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 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 22043x 22043x 22043x 22043x 1x 11023x 11023x 11023x 11023x 11023x 32923x 32923x 32923x 32923x 32923x 32923x 32923x 32923x 32923x 32923x 32923x 32923x 32923x 32923x 11023x 11023x 10768x 10768x 11023x 11023x 244x 244x 11023x 11023x 266x 266x 266x 266x 266x 266x 266x 266x 6002x 6002x 5990x 5990x 12x 12x 6002x 1x 1x 1x 1x 1x 1x 12x 266x 266x 266x 11023x 11023x 1212x 1212x 1212x 390x 383x 383x 390x 3x 3x 390x 1212x 1212x 946x 946x 1212x 1212x 1212x 11023x 11023x | /* eslint-disable max-len */
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 {SyntaxLogic} from "../abap/5_syntax/syntax";
import {ABAPObject} from "../objects/_abap_object";
import {ISpaghettiScopeNode} from "../abap/5_syntax/_spaghetti_scope";
import {ReferenceType} from "../abap/5_syntax/_reference";
import {MethodDefinition} from "../abap/types";
import {Position} from "../position";
export class StaticCallViaInstanceConf extends BasicRuleConfig {
/** Allow in test class includes */
public allowInTestclassIncludes?: boolean = false;
}
export class StaticCallViaInstance extends ABAPRule {
private conf = new StaticCallViaInstanceConf();
public getMetadata(): IRuleMetadata {
return {
key: "static_call_via_instance",
title: "Static call via instance variable",
shortDescription: `Static method call via instance variable`,
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#dont-call-static-methods-through-instance-variables`,
tags: [RuleTag.Styleguide],
badExample: `METHOD run.
NEW lcl_helper( )->static_method( ).
ENDMETHOD.`,
goodExample: `METHOD run.
lcl_helper=>static_method( ).
ENDMETHOD.`,
};
}
public getConfig() {
return this.conf;
}
public setConfig(conf: StaticCallViaInstanceConf) {
this.conf = conf;
}
public runParsed(file: ABAPFile, obj: ABAPObject): Issue[] {
const issues: Issue[] = [];
if (this.getConfig().allowInTestclassIncludes === true && file.getFilename().includes(".testclasses.")) {
return [];
}
const staticMethodCalls = this.listMethodCalls(file.getFilename(), new SyntaxLogic(this.reg, obj).run().spaghetti.getTop());
const tokens = file.getTokens();
for (let i = 0; i < tokens.length - 1; i++) {
const token = tokens[i];
if (token.getStr() !== "->") {
continue;
}
const next = tokens[i + 1];
for (const s of staticMethodCalls) {
if (s.equals(next!.getStart())) {
const message = "Avoid calling static method via instance";
issues.push(Issue.atToken(file, token, message, this.getMetadata().key));
break;
}
}
}
return issues;
}
private listMethodCalls(filename: string, node: ISpaghettiScopeNode): Position[] {
const ret: Position[] = [];
for (const r of node.getData().references) {
if (r.referenceType !== ReferenceType.MethodReference || r.position.getFilename() !== filename) {
continue;
}
if (r.resolved instanceof MethodDefinition && r.resolved.isStatic() === true) {
ret.push(r.position.getStart());
}
}
for (const child of node.getChildren()) {
ret.push(...this.listMethodCalls(filename, child));
}
return ret;
}
}
|