All files / src/rules unnecessary_chaining.ts

96.03% Statements 97/101
94.59% Branches 35/37
100% Functions 6/6
96.03% Lines 97/101

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 29364x 29364x 29364x 29364x 29364x 1x 14683x 14683x 14683x 14683x 14683x 43934x 43934x 43934x 43934x 43934x 43934x 43934x 43934x 43934x 43934x 14683x 14683x 14421x 14421x 14683x 14683x 264x 264x 14683x 14683x 302x 302x 302x 58x 58x 58x 1x 1x 58x 301x 301x 302x     301x 301x 302x 1663x 1663x 1467x 1467x 196x 196x 196x 1663x 2x 2x 2x 196x 196x 196x 1663x 3x 3x 3x 196x 1663x 1663x 1663x 122x 1663x 48x 48x 26x 26x 26x 26x 26x 26x 1663x     1663x 301x 301x 301x 14683x 14683x  
import {Issue} from "../issue";
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 {Comment} from "../abap/2_statements/statements/_statement";
import {StatementNode} from "../abap/nodes";
import {ABAPObject} from "../objects/_abap_object";
import {Class} from "../objects";
import {DDIC} from "../ddic";
 
export class UnnecessaryChainingConf extends BasicRuleConfig {
  public maxIssuesPerFile: number | undefined = 10;
  /** Ignore global exception classes */
  public ignoreExceptions: boolean = true;
}
 
export class UnnecessaryChaining extends ABAPRule {
 
  private conf = new UnnecessaryChainingConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "unnecessary_chaining",
      title: "Unnecessary Chaining",
      shortDescription: `Find unnecessary chaining, all statements are checked`,
      extendedInformation: ``,
      tags: [RuleTag.SingleFile, RuleTag.Quickfix],
      badExample: `WRITE: bar.`,
      goodExample: `WRITE bar.`,
    };
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: UnnecessaryChainingConf) {
    this.conf = conf;
  }
 
  public runParsed(file: ABAPFile, obj: ABAPObject) {
    const issues: Issue[] = [];
 
    if (obj instanceof Class) {
      const definition = obj.getClassDefinition();
      const ddic = new DDIC(this.reg);
      if (this.conf.ignoreExceptions === true && ddic.isException(definition, obj)) {
        return issues;
      }
    }
 
    let max = this.getConfig().maxIssuesPerFile;
    if (max === undefined || max < 1) {
      max = 10;
    }
 
    const statements = file.getStatements();
    for (let i = 0; i < statements.length; i++) {
      const colon = statements[i].getColon();
      if (colon === undefined) {
        continue;
      }
 
      let j = 1;
      let nextStatement = statements[i + j];
      while (nextStatement?.get() instanceof Comment) {
        j++;
        nextStatement = statements[i + j];
      }
 
      j = 1;
      let prevStatement: StatementNode | undefined = statements[i - j];
      while (prevStatement?.get() instanceof Comment) {
        j++;
        prevStatement = statements[i - j];
      }
 
      const next = nextStatement?.getColon();
      const prev = prevStatement?.getColon();
      if (next !== undefined && colon.getStart().equals(next.getStart())) {
        continue;
      } else if (prev !== undefined && colon.getStart().equals(prev.getStart())) {
        continue;
      }
 
      const fix = EditHelper.deleteRange(file, colon.getStart(), colon.getEnd());
      const message = "Unnecessary chaining";
      const issue = Issue.atToken(file, colon, message, this.getMetadata().key, this.conf.severity, fix);
      issues.push(issue);
 
      if (issues.length >= max) {
        break;
      }
    }
 
    return issues;
  }
 
}