@abaplint/core
Version:
abaplint - Core API
112 lines • 4.09 kB
JavaScript
;
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