UNPKG

@abaplint/core

Version:
112 lines 4.09 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SlowParameterPassing = exports.SlowParameterPassingConf = void 0; const _basic_rule_config_1 = require("./_basic_rule_config"); const issue_1 = require("../issue"); const _irule_1 = require("./_irule"); const _abap_object_1 = require("../objects/_abap_object"); const syntax_1 = require("../abap/5_syntax/syntax"); const _scope_type_1 = require("../abap/5_syntax/_scope_type"); const _reference_1 = require("../abap/5_syntax/_reference"); class SlowParameterPassingConf extends _basic_rule_config_1.BasicRuleConfig { } exports.SlowParameterPassingConf = SlowParameterPassingConf; class SlowParameterPassing { constructor() { this.conf = new SlowParameterPassingConf(); } getMetadata() { return { key: "slow_parameter_passing", title: "Slow Parameter Passing", shortDescription: `Detects slow pass by value passing for methods where parameter is not changed`, extendedInformation: `Method parameters defined in interfaces is not checked`, tags: [_irule_1.RuleTag.Performance], badExample: `CLASS lcl DEFINITION. PUBLIC SECTION. METHODS bar IMPORTING VALUE(sdf) TYPE string. ENDCLASS. CLASS lcl IMPLEMENTATION. METHOD bar. WRITE sdf. ENDMETHOD. ENDCLASS.`, goodExample: `CLASS lcl DEFINITION. PUBLIC SECTION. METHODS bar IMPORTING sdf TYPE string. ENDCLASS. CLASS lcl IMPLEMENTATION. METHOD bar. WRITE sdf. ENDMETHOD. ENDCLASS.`, }; } getConfig() { return this.conf; } setConfig(conf) { this.conf = conf; } initialize(reg) { this.reg = reg; return this; } run(obj) { const issues = []; if (!(obj instanceof _abap_object_1.ABAPObject)) { return []; } const top = new syntax_1.SyntaxLogic(this.reg, obj).run().spaghetti.getTop(); const methods = this.listMethodNodes(top); for (const m of methods) { const vars = m.getData().vars; if (m.getIdentifier().sname.includes("~")) { // skip methods defined in interfaces // todo: checking for just "~" is not correct, there might be ALIASES continue; } for (const v in vars) { const id = vars[v]; if (id.getMeta().includes("pass_by_value" /* IdentifierMeta.PassByValue */) === false) { continue; } else if (this.reg.isFileDependency(id.getFilename()) === true) { continue; } const writes = this.listWritePositions(m, id); if (writes.length === 0) { const message = "Parameter " + id.getName() + " passed by VALUE but not changed"; issues.push(issue_1.Issue.atIdentifier(id, message, this.getMetadata().key, this.getConfig().severity)); } } } return issues; } listWritePositions(node, id) { var _a, _b; const ret = []; for (const v of node.getData().references) { if (v.referenceType === _reference_1.ReferenceType.DataWriteReference && ((_a = v.resolved) === null || _a === void 0 ? void 0 : _a.getFilename()) === id.getFilename() && ((_b = v.resolved) === null || _b === void 0 ? void 0 : _b.getStart().equals(id.getStart()))) { ret.push(v.position.getStart()); } } return ret; } listMethodNodes(node) { const ret = []; if (node.getIdentifier().stype === _scope_type_1.ScopeType.Method) { ret.push(node); } else { for (const c of node.getChildren()) { ret.push(...this.listMethodNodes(c)); } } return ret; } } exports.SlowParameterPassing = SlowParameterPassing; //# sourceMappingURL=slow_parameter_passing.js.map