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 22431x 22431x 22431x 22431x 1x 11217x 11217x 11217x 11217x 11217x 33488x 33488x 33488x 33488x 33488x 33488x 33488x 33488x 11217x 11217x 10970x 10970x 11217x 11217x 227x 227x 11217x 11217x 240x 240x 240x 240x 240x 240x 240x 240x 5566x 5566x 5554x 5554x 12x 12x 5566x 1x 1x 1x 1x 1x 1x 12x 240x 240x 240x 11217x 11217x 1122x 1122x 1122x 376x 369x 369x 376x 3x 3x 376x 1122x 1122x 882x 882x 1122x 1122x 1122x 11217x 11217x | /* 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; } } |