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 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 21929x 21929x 21929x 21929x 1x 10966x 10966x 10966x 10966x 10966x 32704x 32704x 32704x 32704x 32704x 32704x 32704x 32704x 10966x 10966x 10688x 10688x 10966x 10966x 258x 258x 10966x 10966x 271x 271x 271x 271x 271x 271x 271x 271x 5963x 5963x 5951x 5951x 12x 12x 5963x 1x 1x 1x 1x 1x 1x 12x 271x 271x 271x 10966x 10966x 1236x 1236x 1236x 360x 353x 353x 360x 3x 3x 360x 1236x 1236x 965x 965x 1236x 1236x 1236x 10966x 10966x | /* 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], }; } 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; } } |