@abaplint/core 2.86.6 → 2.87.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/abaplint.d.ts +1 -0
- package/build/src/abap/types/method_parameters.js +8 -1
- package/build/src/registry.js +1 -1
- package/build/src/rules/double_space.js +1 -0
- package/build/src/rules/downport.js +22 -1
- package/build/src/rules/index.js +1 -0
- package/build/src/rules/slow_parameter_passing.js +85 -0
- package/build/src/rules/unsecure_fae.js +1 -1
- package/package.json +1 -1
package/build/abaplint.d.ts
CHANGED
|
@@ -2646,6 +2646,7 @@ export declare const enum IdentifierMeta {
|
|
|
2646
2646
|
EventParameter = "event_parameter",
|
|
2647
2647
|
FormParameter = "form_parameter",
|
|
2648
2648
|
ReadOnly = "read_only",
|
|
2649
|
+
PassByValue = "pass_by_value",
|
|
2649
2650
|
InlineDefinition = "inline",
|
|
2650
2651
|
BuiltIn = "built-in",
|
|
2651
2652
|
DDIC = "ddic",
|
|
@@ -163,7 +163,14 @@ class MethodParameters {
|
|
|
163
163
|
if (p === undefined) {
|
|
164
164
|
continue;
|
|
165
165
|
}
|
|
166
|
-
|
|
166
|
+
const extraMeta = [];
|
|
167
|
+
if (opt.concatTokens().toUpperCase().startsWith("VALUE(")) {
|
|
168
|
+
extraMeta.push("pass_by_value" /* PassByValue */);
|
|
169
|
+
}
|
|
170
|
+
else if (meta.includes("importing" /* MethodImporting */)) {
|
|
171
|
+
extraMeta.push("read_only" /* ReadOnly */);
|
|
172
|
+
}
|
|
173
|
+
target.push(new method_param_1.MethodParam().runSyntax(p, scope, this.filename, [...meta, ...extraMeta]));
|
|
167
174
|
if (opt.getLastToken().getStr().toUpperCase() === "OPTIONAL") {
|
|
168
175
|
const name = target[target.length - 1].getName().toUpperCase();
|
|
169
176
|
this.optional.push(name);
|
package/build/src/registry.js
CHANGED
|
@@ -56,6 +56,7 @@ class DoubleSpace extends _abap_rule_1.ABAPRule {
|
|
|
56
56
|
&& !(s.get() instanceof _statement_1.Unknown)
|
|
57
57
|
&& !(s.get() instanceof statements_1.MethodDef)
|
|
58
58
|
&& !(s.get() instanceof _statement_1.MacroCall)
|
|
59
|
+
&& !(s.get() instanceof statements_1.Events)
|
|
59
60
|
&& !(s.get() instanceof _statement_1.MacroContent)) {
|
|
60
61
|
issues = issues.concat(this.checkKeywords(s, file));
|
|
61
62
|
}
|
|
@@ -515,16 +515,29 @@ ${indentation}`);
|
|
|
515
515
|
}
|
|
516
516
|
tableCondition(tableExpression) {
|
|
517
517
|
let condition = "";
|
|
518
|
+
let keyName = "";
|
|
518
519
|
for (const c of tableExpression.getChildren() || []) {
|
|
519
520
|
if (c.getFirstToken().getStr() === "[" || c.getFirstToken().getStr() === "]") {
|
|
520
521
|
continue;
|
|
521
522
|
}
|
|
522
523
|
else if (c.get() instanceof Expressions.ComponentChainSimple && condition === "") {
|
|
523
|
-
|
|
524
|
+
if (keyName === "") {
|
|
525
|
+
condition = "WITH KEY ";
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
condition = "WITH TABLE KEY " + keyName + " COMPONENTS ";
|
|
529
|
+
}
|
|
524
530
|
}
|
|
525
531
|
else if (c.get() instanceof Expressions.Source && condition === "") {
|
|
526
532
|
condition = "INDEX ";
|
|
527
533
|
}
|
|
534
|
+
else if (c instanceof nodes_1.TokenNode && c.getFirstToken().getStr().toUpperCase() === "KEY") {
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
else if (c.get() instanceof Expressions.SimpleName) {
|
|
538
|
+
keyName = c.concatTokens();
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
528
541
|
condition += c.concatTokens() + " ";
|
|
529
542
|
}
|
|
530
543
|
return condition;
|
|
@@ -1143,6 +1156,7 @@ ${indentation} output = ${topTarget}.`;
|
|
|
1143
1156
|
body += indentation + end;
|
|
1144
1157
|
}
|
|
1145
1158
|
const abap = `DATA ${uniqueName} ${type}.\n` +
|
|
1159
|
+
indentation + `CLEAR ${uniqueName}.\n` + // might be called inside a loop
|
|
1146
1160
|
body +
|
|
1147
1161
|
indentation;
|
|
1148
1162
|
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), abap);
|
|
@@ -1311,6 +1325,7 @@ ${indentation} output = ${topTarget}.`;
|
|
|
1311
1325
|
buildCondBody(body, uniqueName, indent, lowFile, highSyntax) {
|
|
1312
1326
|
let code = "";
|
|
1313
1327
|
let first = true;
|
|
1328
|
+
let addElse = true;
|
|
1314
1329
|
for (const c of body.getChildren()) {
|
|
1315
1330
|
if (c instanceof nodes_1.TokenNode) {
|
|
1316
1331
|
switch (c.getFirstToken().getStr().toUpperCase()) {
|
|
@@ -1328,6 +1343,7 @@ ${indentation} output = ${topTarget}.`;
|
|
|
1328
1343
|
break;
|
|
1329
1344
|
case "ELSE":
|
|
1330
1345
|
code += indent + "ELSE.\n";
|
|
1346
|
+
addElse = false;
|
|
1331
1347
|
break;
|
|
1332
1348
|
default:
|
|
1333
1349
|
throw "buildCondBody, unexpected token";
|
|
@@ -1346,6 +1362,11 @@ ${indentation} output = ${topTarget}.`;
|
|
|
1346
1362
|
throw "buildCondBody, unexpected expression, " + c.get().constructor.name;
|
|
1347
1363
|
}
|
|
1348
1364
|
}
|
|
1365
|
+
if (addElse) {
|
|
1366
|
+
// COND might be called inside a loop
|
|
1367
|
+
code += indent + "ELSE.\n";
|
|
1368
|
+
code += indent + ` CLEAR ${uniqueName}.\n`;
|
|
1369
|
+
}
|
|
1349
1370
|
code += indent + "ENDIF.\n";
|
|
1350
1371
|
code += indent;
|
|
1351
1372
|
return code;
|
package/build/src/rules/index.js
CHANGED
|
@@ -129,6 +129,7 @@ __exportStar(require("./selection_screen_naming"), exports);
|
|
|
129
129
|
__exportStar(require("./sequential_blank"), exports);
|
|
130
130
|
__exportStar(require("./short_case"), exports);
|
|
131
131
|
__exportStar(require("./sicf_consistency"), exports);
|
|
132
|
+
__exportStar(require("./slow_parameter_passing"), exports);
|
|
132
133
|
__exportStar(require("./space_before_colon"), exports);
|
|
133
134
|
__exportStar(require("./space_before_dot"), exports);
|
|
134
135
|
__exportStar(require("./sql_escape_host_variables"), exports);
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SlowParameterPassing = exports.SlowParameterPassingConf = void 0;
|
|
4
|
+
const _basic_rule_config_1 = require("./_basic_rule_config");
|
|
5
|
+
const issue_1 = require("../issue");
|
|
6
|
+
const _irule_1 = require("./_irule");
|
|
7
|
+
const _abap_object_1 = require("../objects/_abap_object");
|
|
8
|
+
const syntax_1 = require("../abap/5_syntax/syntax");
|
|
9
|
+
const _scope_type_1 = require("../abap/5_syntax/_scope_type");
|
|
10
|
+
const _reference_1 = require("../abap/5_syntax/_reference");
|
|
11
|
+
class SlowParameterPassingConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
12
|
+
}
|
|
13
|
+
exports.SlowParameterPassingConf = SlowParameterPassingConf;
|
|
14
|
+
class SlowParameterPassing {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.conf = new SlowParameterPassingConf();
|
|
17
|
+
}
|
|
18
|
+
getMetadata() {
|
|
19
|
+
return {
|
|
20
|
+
key: "slow_parameter_passing",
|
|
21
|
+
title: "Slow Parameter Passing",
|
|
22
|
+
shortDescription: `Detects show pass by value passing for methods where parameter is not changed`,
|
|
23
|
+
tags: [_irule_1.RuleTag.Performance],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
getConfig() {
|
|
27
|
+
return this.conf;
|
|
28
|
+
}
|
|
29
|
+
setConfig(conf) {
|
|
30
|
+
this.conf = conf;
|
|
31
|
+
}
|
|
32
|
+
initialize(reg) {
|
|
33
|
+
this.reg = reg;
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
run(obj) {
|
|
37
|
+
const issues = [];
|
|
38
|
+
if (!(obj instanceof _abap_object_1.ABAPObject)) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
const top = new syntax_1.SyntaxLogic(this.reg, obj).run().spaghetti.getTop();
|
|
42
|
+
const methods = this.listMethodNodes(top);
|
|
43
|
+
for (const m of methods) {
|
|
44
|
+
const vars = m.getData().vars;
|
|
45
|
+
for (const v in vars) {
|
|
46
|
+
const id = vars[v];
|
|
47
|
+
if (id.getMeta().includes("pass_by_value" /* PassByValue */) === false) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const writes = this.listWritePositions(m, id);
|
|
51
|
+
if (writes.length === 0) {
|
|
52
|
+
const message = "Parameter passed by VALUE but not changed";
|
|
53
|
+
issues.push(issue_1.Issue.atIdentifier(id, message, this.getMetadata().key, this.getConfig().severity));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return issues;
|
|
58
|
+
}
|
|
59
|
+
listWritePositions(node, id) {
|
|
60
|
+
var _a, _b;
|
|
61
|
+
const ret = [];
|
|
62
|
+
for (const v of node.getData().references) {
|
|
63
|
+
if (v.referenceType === _reference_1.ReferenceType.DataWriteReference
|
|
64
|
+
&& ((_a = v.resolved) === null || _a === void 0 ? void 0 : _a.getFilename()) === id.getFilename()
|
|
65
|
+
&& ((_b = v.resolved) === null || _b === void 0 ? void 0 : _b.getStart().equals(id.getStart()))) {
|
|
66
|
+
ret.push(v.position.getStart());
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return ret;
|
|
70
|
+
}
|
|
71
|
+
listMethodNodes(node) {
|
|
72
|
+
const ret = [];
|
|
73
|
+
if (node.getIdentifier().stype === _scope_type_1.ScopeType.Method) {
|
|
74
|
+
ret.push(node);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
for (const c of node.getChildren()) {
|
|
78
|
+
ret.push(...this.listMethodNodes(c));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return ret;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.SlowParameterPassing = SlowParameterPassing;
|
|
85
|
+
//# sourceMappingURL=slow_parameter_passing.js.map
|
|
@@ -20,7 +20,7 @@ class UnsecureFAE {
|
|
|
20
20
|
title: "Unsecure FAE",
|
|
21
21
|
shortDescription: `Checks for unsecure FAE`,
|
|
22
22
|
extendedInformation: `Issues from rule check_syntax must be fixed before this rule takes effect`,
|
|
23
|
-
tags: [_irule_1.RuleTag.Experimental],
|
|
23
|
+
tags: [_irule_1.RuleTag.Experimental, _irule_1.RuleTag.Performance],
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
getConfig() {
|