All files / src/rules use_new.ts

96% Statements 96/100
84.37% Branches 27/32
100% Functions 7/7
96% Lines 96/100

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 1001x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 11088x 11088x 11088x 11088x 33130x 33130x 33130x 33130x 33130x 33130x 33130x 33130x 33130x 33130x 33130x 33130x 33130x 33130x 11088x 11088x 8x 8x 11088x 11088x 10568x 10568x 11088x 11088x 244x 244x 11088x 11088x 280x 280x 280x 20x 20x 260x 260x 280x     260x 280x 1416x 13x 1x 13x 1x 12x 2x 2x 13x 13x 1x 1x 8x 8x 8x 8x 8x 1416x 260x 260x 260x 11088x 11088x 8x 8x     8x 8x 8x 8x 8x 6x 6x 8x 8x 8x 8x 8x 11088x
import {Issue} from "../issue";
import * as Statements from "../abap/2_statements/statements";
import * as Expressions from "../abap/2_statements/expressions";
import {ABAPRule} from "./_abap_rule";
import {BasicRuleConfig} from "./_basic_rule_config";
import {Dynamic, ParameterListExceptions, Target} from "../abap/2_statements/expressions";
import {LanguageVersion, Release, releaseAtLeast} from "../version";
import {IRuleMetadata, RuleTag} from "./_irule";
import {EditHelper, IEdit} from "../edit_helper";
import {StatementNode} from "../abap/nodes";
import {ABAPFile} from "../abap/abap_file";
import {ABAPObject} from "../objects/_abap_object";
 
export class UseNewConf extends BasicRuleConfig {
}
 
export class UseNew extends ABAPRule {
  private conf = new UseNewConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "use_new",
      title: "Use NEW",
      shortDescription: `Checks for deprecated CREATE OBJECT statements.`,
      extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-new-to-create-object
 
If the target variable is referenced in the CREATE OBJECT statement, no errors are issued
 
Applicable from v740sp02 and up`,
      badExample: `CREATE OBJECT ref.`,
      goodExample: `ref = NEW #( ).`,
      tags: [RuleTag.Upport, RuleTag.Styleguide, RuleTag.Quickfix, RuleTag.SingleFile],
    };
  }
 
  private getMessage(): string {
    return "Use NEW #( ) to instantiate object.";
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: UseNewConf) {
    this.conf = conf;
  }
 
  public runParsed(file: ABAPFile, obj: ABAPObject) {
    const issues: Issue[] = [];
 
    if (obj.getType() === "INTF") {
      return [];
    }
 
    if (!releaseAtLeast(this.reg.getConfig().getRelease(), Release.v740sp02)
        && this.reg.getConfig().getLanguageVersion() !== LanguageVersion.Cloud) {
      return [];
    }
 
    for (const statement of file.getStatements()) {
      if (statement.get() instanceof Statements.CreateObject) {
        if (statement.findFirstExpression(Dynamic)) {
          continue;
        } else if (statement.findDirectExpression(ParameterListExceptions)) {
          continue;
        } else if (statement.findDirectTokenByText("AREA")) {
          continue;
        }
        const target = statement.findDirectExpression(Target)?.concatTokens() + "->";
        if (statement.concatTokens().includes(target)) {
          continue;
        }
 
        const fix = this.buildFix(file, statement);
        const issue = Issue.atPosition(file, statement.getStart(), this.getMessage(), this.getMetadata().key, this.conf.severity, fix);
        issues.push(issue);
      }
    }
 
    return issues;
  }
 
  private buildFix(file: ABAPFile, statement: StatementNode): IEdit | undefined {
    const target = statement.findDirectExpression(Expressions.Target)?.concatTokens();
    if (target === undefined) {
      return undefined;
    }
    const parameters = statement.findDirectExpression(Expressions.ParameterListS);
    const param = parameters ? parameters.concatTokens() + " " : "";
 
    let type = statement.findDirectExpression(Expressions.ClassName)?.getFirstToken().getStr();
    if (type === undefined) {
      type = "#";
    }
 
    const string = `${target} = NEW ${type}( ${param}).`;
 
    return EditHelper.replaceRange(file, statement.getStart(), statement.getEnd(), string);
  }
}