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 22005x 22005x 22005x 22005x 1x 11004x 11004x 11004x 11004x 11004x 32816x 32816x 32816x 32816x 32816x 32816x 32816x 32816x 11004x 11004x 10724x 10724x 11004x 11004x 260x 260x 11004x 11004x 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 11004x 11004x 1244x 1244x 1244x 361x 354x 354x 361x 3x 3x 361x 1244x 1244x 971x 971x 1244x 1244x 1244x 11004x 11004x | /* 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; } } |