All files / src/rules exporting.ts

98.99% Statements 98/99
95.83% Branches 23/24
100% Functions 7/7
98.99% 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 7654x 7654x 7654x 7654x 7654x 22822x 22822x 22822x 22822x 22822x 22822x 22822x 22822x 22822x 22822x 22822x 22822x 7654x 7654x 7x 7x 7654x 7654x 169x 169x 169x 10x 10x 159x 169x 813x 813x 813x 20x 2x 2x 2x   20x 18x 18x 20x 813x 159x 159x 159x 7654x 7654x 7346x 7346x 7654x 7654x 139x 139x 7654x 7654x 18x 18x 9x 9x 9x 18x 1x 1x 8x 8x 8x 8x 8x 8x 18x 18x 18x 7x 7x 7x 7x 7x 7x 7x 1x 1x 1x 7654x 7654x 7654x
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 [];
  }
 
 
}