@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.
@@ -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
- target.push(new method_param_1.MethodParam().runSyntax(p, scope, this.filename, meta));
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);
@@ -68,7 +68,7 @@ class Registry {
68
68
  }
69
69
  static abaplintVersion() {
70
70
  // magic, see build script "version.sh"
71
- return "2.86.6";
71
+ return "2.87.0";
72
72
  }
73
73
  getDDICReferences() {
74
74
  return this.references;
@@ -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
- condition = "WITH KEY ";
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;
@@ -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() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.86.6",
3
+ "version": "2.87.0",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",