All files / src/rules invalid_table_index.ts

97.46% Statements 77/79
90.47% Branches 19/21
100% Functions 5/5
97.46% Lines 77/79

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 801x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 10343x 10343x 10343x 10343x 30860x 30860x 30860x 30860x 30860x 30860x 30860x 30860x 30860x 30860x 30860x 10343x 10343x 9830x 9830x 10343x 10343x 241x 241x 10343x 10343x 256x 256x 256x 256x 12x 12x 244x 244x 256x 2x 2x 2x 2x     2x 1x 1x 1x 1x 1x 2x 244x 256x 3x 2x 3x 3x 1x 1x 3x 1x 1x 1x 1x 1x 3x 244x 244x 244x 10343x  
import {Issue} from "../issue";
import * as Expressions from "../abap/2_statements/expressions";
import {ABAPRule} from "./_abap_rule";
import {BasicRuleConfig} from "./_basic_rule_config";
import {IRuleMetadata, RuleTag} from "./_irule";
import {ABAPFile} from "../abap/abap_file";
import {EditHelper} from "../edit_helper";
import {ReadTable} from "../abap/2_statements/statements";
 
 
export class InvalidTableIndexConf extends BasicRuleConfig {
}
 
export class InvalidTableIndex extends ABAPRule {
  private conf = new InvalidTableIndexConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "invalid_table_index",
      title: "Invalid Table Index",
      shortDescription: `Issues error for constant table index zero, as ABAP starts from 1`,
      tags: [RuleTag.SingleFile, RuleTag.Quickfix],
      badExample: `DATA(first) = table[ 0 ].
READ TABLE gt_stack ASSIGNING <ls_stack> INDEX 0.`,
      goodExample: `DATA(first) = table[ 1 ].
READ TABLE gt_stack ASSIGNING <ls_stack> INDEX 1.`,
    };
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: InvalidTableIndexConf) {
    this.conf = conf;
  }
 
  public runParsed(file: ABAPFile) {
    const issues: Issue[] = [];
 
    const stru = file.getStructure();
    if (stru === undefined) {
      return issues; // parser error
    }
 
    const expr = stru.findAllExpressionsRecursive(Expressions.TableExpression);
    for (const e of expr) {
      const token = e.findDirectExpression(Expressions.Source)
        ?.findDirectExpression(Expressions.Constant)
        ?.findFirstExpression(Expressions.Integer)?.getFirstToken();
      if (token === undefined) {
        continue;
      }
      if (token.getStr() === "0") {
        const message = "Table index starts from 1";
        const fix = EditHelper.replaceToken(file, token, "1");
        const issue = Issue.atToken(file, token, message, this.getMetadata().key, this.conf.severity, fix);
        issues.push(issue);
      }
    }
 
    for (const rt of stru.findAllStatements(ReadTable)) {
      const token = rt.findExpressionAfterToken("INDEX")
        ?.findDirectExpression(Expressions.Constant)
        ?.findFirstExpression(Expressions.Integer)?.getFirstToken();
      if (token === undefined) {
        continue;
      }
      if (token.getStr() === "0") {
        const message = "Table index starts from 1";
        const fix = EditHelper.replaceToken(file, token, "1");
        const issue = Issue.atToken(file, token, message, this.getMetadata().key, this.conf.severity, fix);
        issues.push(issue);
      }
    }
 
    return issues;
  }
}