All files / src/rules check_text_elements.ts

98.03% Statements 100/102
88.88% Branches 24/27
100% Functions 6/6
98.03% Lines 100/102

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 1021x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 8934x 8934x 8934x 8934x 8934x 8934x 60551x 60551x 60551x 60551x 60551x 60551x 8934x 8934x 8485x 8485x 8934x 8934x 202x 202x 8934x 8934x 215x 215x 215x 215x 8934x 8934x 270x 49x 49x 221x 221x 221x 270x 226x 226x 12x 12x 214x 214x 214x 214x 214x 214x 214x 226x 12x 12x 12x 12x 12x 12x 12x     12x 214x 226x 12x 6x 6x 6x 1x 1x 1x 6x 6x 6x 6x 6x 6x 6x 4x 4x 6x 1x 1x 6x 5x 2x 2x 6x 12x 214x 221x 221x 221x 8934x 8934x
import {IRule} from "./_irule";
import {Issue} from "../issue";
import {BasicRuleConfig} from "./_basic_rule_config";
import * as Expressions from "../abap/2_statements/expressions";
import {ABAPObject, ITextElements} from "../objects/_abap_object";
import {IObject} from "../objects/_iobject";
import {IRegistry} from "../_iregistry";
import {IncludeGraph} from "../utils/include_graph";
 
export class CheckTextElementsConf extends BasicRuleConfig {
}
 
export class CheckTextElements implements IRule {
  private reg: IRegistry;
  private conf = new CheckTextElementsConf();
  private graph: IncludeGraph;
 
  public getMetadata() {
    return {
      key: "check_text_elements",
      title: "Check text elements",
      shortDescription: `Check text elements exists or matches code`,
    };
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: CheckTextElementsConf) {
    this.conf = conf;
  }
 
  public initialize(reg: IRegistry) {
    this.reg = reg;
    this.graph = new IncludeGraph(this.reg);
    return this;
  }
 
  public run(obj: IObject): Issue[] {
    if (!(obj instanceof ABAPObject)) {
      return [];
    }
 
    const output: Issue[] = [];
 
    for (const file of obj.getABAPFiles()) {
      const stru = file.getStructure();
      if (stru === undefined) {
        continue;
      }
 
      let texts: ITextElements;
      let mainName: string | undefined = undefined;
 
      const expressions = stru.findAllExpressionsMulti([Expressions.TextElement, Expressions.TextElementString]);
 
      // optimize: no need to find main and texts if there are no expressions to check
      if (expressions.length > 0) {
        const mains = this.graph.listMainForInclude(file.getFilename());
        if (mains.length === 1) {
// todo, this only checks the first main
          mainName = mains[0];
          const main1 = this.reg.findObjectForFile(this.reg.getFileByName(mains[0])!)! as ABAPObject;
          texts = main1.getTexts();
        } else {
          texts = obj.getTexts();
        }
      }
 
      for (const e of expressions) {
        if (e.get() instanceof Expressions.TextElement) {
          const token = e.findFirstExpression(Expressions.TextElementKey)!.getFirstToken();
          const key = token.getStr().toUpperCase();
          if (texts![key] === undefined) {
            const message = `Text element "${key}" not found` + (mainName ? ", " + mainName : "");
            output.push(Issue.atToken(file, token, message, this.getMetadata().key, this.conf.severity));
          }
        } else {
          // its a Expressions.TextElementString
          const token = e.findFirstExpression(Expressions.TextElementKey)!.getFirstToken();
          const code = e.getFirstToken().getStr();
          const key = token.getStr().toUpperCase();
          let found = texts![key];
          if (found && code.startsWith("'")) {
            found = found.replace(/'/g, "''");
          }
          if (found === undefined) {
            const message = `Text element "${key}" not found` + (mainName ? ", " + mainName : "");
            output.push(Issue.atToken(file, token, message, this.getMetadata().key, this.conf.severity));
          } else if (code !== "'" + found + "'"
              && code !== "`" + found + "`") {
            output.push(Issue.atToken(file, token, "Text does not match text element", this.getMetadata().key, this.conf.severity));
          }
        }
      }
    }
 
    return output;
  }
 
}