All files / src/rules exporting.ts

98.98% Statements 98/99
96% Branches 24/25
100% Functions 7/7
98.98% Lines 98/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 1x 9362x 9362x 9362x 9362x 9362x 27931x 27931x 27931x 27931x 27931x 27931x 27931x 27931x 27931x 27931x 27931x 27931x 9362x 9362x 7x 7x 9362x 9362x 251x 251x 251x 19x 19x 232x 251x 1289x 1289x 1289x 26x 2x 2x 2x   26x 24x 24x 26x 1289x 232x 232x 232x 9362x 9362x 8898x 8898x 9362x 9362x 216x 216x 9362x 9362x 24x 24x 15x 15x 9x 24x 1x 1x 8x 8x 8x 8x 8x 8x 24x 24x 24x 7x 7x 7x 7x 7x 7x 7x 1x 1x 1x 9362x 9362x 9362x
import {Issue} from "../issue";
import {IRuleMetadata, RuleTag} from "./_irule";
import {ABAPRule} from "./_abap_rule";
import {BasicRuleConfig} from "./_basic_rule_config";
import {MethodParameters, MethodCallBody, MethodCall} from "../abap/2_statements/expressions";
import {ExpressionNode} from "../abap/nodes";
import {EditHelper} from "../edit_helper";
import {ABAPFile} from "../abap/abap_file";
import {ABAPObject} from "../objects/_abap_object";
 
export class ExportingConf extends BasicRuleConfig {
}
 
export class Exporting extends ABAPRule {
 
  private conf = new ExportingConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "exporting",
      title: "EXPORTING can be omitted",
      shortDescription: `Detects EXPORTING statements which can be omitted.`,
      badExample: `call_method( EXPORTING foo = bar ).`,
      goodExample: `call_method( foo = bar ).`,
      extendedInformation:
`https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#omit-the-optional-keyword-exporting
https://docs.abapopenchecks.org/checks/30/`,
      tags: [RuleTag.Styleguide, RuleTag.Quickfix, RuleTag.SingleFile],
    };
  }
 
  private getMessage(): string {
    return "The EXPORTING keyword can be omitted";
  }
 
  public runParsed(file: ABAPFile, obj: ABAPObject) {
    let issues: Issue[] = [];
 
    if (obj.getType() === "INTF") {
      return [];
    }
 
    for (const statement of file.getStatements()) {
      const expressions = statement.findAllExpressionsMulti([MethodCallBody, MethodCall]);
 
      for (const b of expressions) {
        if (b.get() instanceof MethodCallBody) {
          if (b.getFirstToken().getStr() !== "(") {
            continue;
          }
          issues = issues.concat(this.check(b, file));
        } else if (b.get() instanceof MethodCall) {
          issues = issues.concat(this.check(b, file));
        }
      }
    }
 
    return issues;
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: ExportingConf) {
    this.conf = conf;
  }
 
  private check(node: ExpressionNode, file: ABAPFile): Issue[] {
    const e = node.findFirstExpression(MethodParameters);
    if (e === undefined) {
      return [];
    }
 
    if (e.getFirstToken().getStr().toUpperCase() !== "EXPORTING") {
      return [];
    }
 
    const tokens = e.getDirectTokens();
    const strings = tokens.map(t => t.getStr().toUpperCase());
 
    if (strings[0] === "EXPORTING"
          && strings.includes("IMPORTING") === false
          && strings.includes("RECEIVING") === false
          && strings.includes("EXCEPTIONS") === false
          && strings.includes("CHANGING") === false) {
 
      const next = e.getAllTokens()[1];
      const fix = EditHelper.deleteRange(file, tokens[0].getStart(), next.getStart());
 
      const issue = Issue.atToken(file, tokens[0], this.getMessage(), this.getMetadata().key, this.conf.severity, fix);
      return [issue];
    }
 
    return [];
  }
 
 
}