All files / src/rules check_text_elements.ts

100% Statements 99/99
92.59% Branches 25/27
100% Functions 6/6
100% Lines 99/99

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 991x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 7665x 7665x 7665x 7665x 7665x 7665x 22817x 22817x 22817x 22817x 22817x 22817x 7665x 7665x 7346x 7346x 7665x 7665x 139x 139x 7665x 7665x 152x 152x 152x 152x 7665x 7665x 178x 20x 20x 158x 158x 158x 178x 162x 162x 12x 12x 150x 150x 150x 150x 150x 162x 139x 139x 139x 139x 162x 11x 11x 150x 150x 150x 162x 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 150x 158x 158x 158x 7665x 7665x
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 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();
      }
 
      const expressions = stru.findAllExpressionsMulti([Expressions.TextElement, Expressions.TextElementString]);
 
      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;
  }
 
}