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 21997x 21997x 21997x 21997x 1x 11000x 11000x 11000x 11000x 11000x 32804x 32804x 32804x 32804x 32804x 32804x 32804x 32804x 11000x 11000x 10720x 10720x 11000x 11000x 260x 260x 11000x 11000x 273x 273x 273x 273x 273x 273x 273x 273x 6009x 6009x 5997x 5997x 12x 12x 6009x 1x 1x 1x 1x 1x 1x 12x 273x 273x 273x 11000x 11000x 1244x 1244x 1244x 361x 354x 354x 361x 3x 3x 361x 1244x 1244x 971x 971x 1244x 1244x 1244x 11000x 11000x | /* 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; } } |