@abaplint/core 2.85.24 → 2.85.25

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.
@@ -68,7 +68,7 @@ class Registry {
68
68
  }
69
69
  static abaplintVersion() {
70
70
  // magic, see build script "version.sh"
71
- return "2.85.24";
71
+ return "2.85.25";
72
72
  }
73
73
  getDDICReferences() {
74
74
  return this.references;
@@ -44,19 +44,21 @@ Current rules:
44
44
  * CONV is outlined
45
45
  * COND is outlined
46
46
  * REDUCE is outlined
47
+ * SWITCH is outlined
48
+ * APPEND expression is outlined
47
49
  * EMPTY KEY is changed to DEFAULT KEY, opposite of DEFAULT KEY in https://rules.abaplint.org/avoid_use/
48
50
  * CAST changed to ?=
49
51
  * LOOP AT method_call( ) is outlined
50
52
  * VALUE # with structure fields
51
53
  * VALUE # with internal table lines
52
- * Table Expressions[ index ] are outlined
54
+ * Table Expressions are outlined
53
55
  * SELECT INTO @DATA definitions are outlined
54
56
  * Some occurrences of string template formatting option ALPHA changed to function module call
55
57
  * SELECT/INSERT/MODIFY/DELETE/UPDATE "," in field list removed, "@" in source/targets removed
56
58
  * PARTIALLY IMPLEMENTED removed, it can be quick fixed via rule implement_methods
57
59
  * RAISE EXCEPTION ... MESSAGE
58
- * APPEND expression is outlined
59
60
  * Moving with +=, -=, /=, *=, &&= is expanded
61
+ * line_exists and line_index is downported to READ TABLE
60
62
 
61
63
  Only one transformation is applied to a statement at a time, so multiple steps might be required to do the full downport.`,
62
64
  tags: [_irule_1.RuleTag.Experimental, _irule_1.RuleTag.Downport, _irule_1.RuleTag.Quickfix],
@@ -192,6 +194,10 @@ Only one transformation is applied to a statement at a time, so multiple steps m
192
194
  if (found) {
193
195
  return found;
194
196
  }
197
+ found = this.outlineSwitch(high, lowFile, highSyntax);
198
+ if (found) {
199
+ return found;
200
+ }
195
201
  found = this.outlineCast(high, lowFile, highSyntax);
196
202
  if (found) {
197
203
  return found;
@@ -224,7 +230,7 @@ Only one transformation is applied to a statement at a time, so multiple steps m
224
230
  if (found) {
225
231
  return found;
226
232
  }
227
- found = this.replaceLineExists(high, lowFile, highSyntax);
233
+ found = this.replaceLineFunctions(high, lowFile, highSyntax);
228
234
  if (found) {
229
235
  return found;
230
236
  }
@@ -408,16 +414,11 @@ ${indentation}${uniqueName} = ${source.concatTokens()}.\n${indentation}`);
408
414
  return undefined;
409
415
  }
410
416
  replaceTableExpression(node, lowFile, highSyntax) {
411
- var _a;
412
417
  for (const fieldChain of node.findAllExpressionsRecursive(Expressions.FieldChain)) {
413
418
  const tableExpression = fieldChain.findDirectExpression(Expressions.TableExpression);
414
419
  if (tableExpression === undefined) {
415
420
  continue;
416
421
  }
417
- if (tableExpression.getChildren().length > 3) {
418
- // for now, only support the INDEX scenario
419
- continue;
420
- }
421
422
  let pre = "";
422
423
  let startToken = undefined;
423
424
  for (const child of fieldChain.getChildren()) {
@@ -432,11 +433,24 @@ ${indentation}${uniqueName} = ${source.concatTokens()}.\n${indentation}`);
432
433
  if (startToken === undefined) {
433
434
  continue;
434
435
  }
436
+ let condition = "";
437
+ for (const c of tableExpression.getChildren() || []) {
438
+ if (c.getFirstToken().getStr() === "[" || c.getFirstToken().getStr() === "]") {
439
+ continue;
440
+ }
441
+ else if (c.get() instanceof Expressions.ComponentChainSimple && condition === "") {
442
+ condition = "WITH KEY ";
443
+ }
444
+ else if (c.get() instanceof Expressions.Source && condition === "") {
445
+ condition = "INDEX ";
446
+ }
447
+ condition += c.concatTokens() + " ";
448
+ }
435
449
  const uniqueName = this.uniqueName(node.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
436
450
  const indentation = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
437
451
  const firstToken = node.getFirstToken();
438
452
  const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, firstToken.getStart(), `DATA ${uniqueName} LIKE LINE OF ${pre}.
439
- ${indentation}READ TABLE ${pre} INDEX ${(_a = tableExpression.findFirstExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.concatTokens()} INTO ${uniqueName}.
453
+ ${indentation}READ TABLE ${pre} ${condition}INTO ${uniqueName}.
440
454
  ${indentation}IF sy-subrc <> 0.
441
455
  ${indentation} RAISE EXCEPTION TYPE cx_sy_itab_line_not_found.
442
456
  ${indentation}ENDIF.
@@ -735,6 +749,67 @@ ${indentation} output = ${topTarget}.`;
735
749
  }
736
750
  return { body, end };
737
751
  }
752
+ outlineSwitch(node, lowFile, highSyntax) {
753
+ var _a, _b;
754
+ for (const i of node.findAllExpressionsRecursive(Expressions.Source)) {
755
+ const firstToken = i.getFirstToken();
756
+ if (firstToken.getStr().toUpperCase() !== "SWITCH") {
757
+ continue;
758
+ }
759
+ const type = this.findType(i, lowFile, highSyntax);
760
+ if (type === undefined) {
761
+ continue;
762
+ }
763
+ const uniqueName = this.uniqueName(firstToken.getStart(), lowFile.getFilename(), highSyntax);
764
+ const indentation = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
765
+ let body = "";
766
+ let name = "";
767
+ const switchBody = i.findDirectExpression(Expressions.SwitchBody);
768
+ if (switchBody === undefined) {
769
+ continue;
770
+ }
771
+ for (const l of ((_a = switchBody === null || switchBody === void 0 ? void 0 : switchBody.findDirectExpression(Expressions.Let)) === null || _a === void 0 ? void 0 : _a.findDirectExpressions(Expressions.InlineFieldDefinition)) || []) {
772
+ name = l.getFirstToken().getStr();
773
+ body += indentation + `DATA(${name}) = ${(_b = switchBody.findFirstExpression(Expressions.Source)) === null || _b === void 0 ? void 0 : _b.concatTokens()}.\n`;
774
+ }
775
+ body += `DATA ${uniqueName} TYPE ${type}.\n`;
776
+ let firstSource = false;
777
+ let inWhen = false;
778
+ for (const c of switchBody.getChildren()) {
779
+ if (c.get() instanceof Expressions.Source && firstSource === false) {
780
+ body += indentation + `CASE ${c.concatTokens()}.`;
781
+ firstSource = true;
782
+ }
783
+ else if (c instanceof nodes_1.TokenNode && c.concatTokens().toUpperCase() === "THEN") {
784
+ inWhen = true;
785
+ body += ".\n";
786
+ }
787
+ else if (c instanceof nodes_1.TokenNode && c.concatTokens().toUpperCase() === "WHEN") {
788
+ inWhen = false;
789
+ body += `\n${indentation} WHEN `;
790
+ }
791
+ else if (c instanceof nodes_1.TokenNode && c.concatTokens().toUpperCase() === "OR") {
792
+ body += ` OR `;
793
+ }
794
+ else if (c instanceof nodes_1.TokenNode && c.concatTokens().toUpperCase() === "ELSE") {
795
+ inWhen = true;
796
+ body += `\n${indentation} WHEN OTHERS.\n`;
797
+ }
798
+ else if (inWhen === false) {
799
+ body += c.concatTokens();
800
+ }
801
+ else {
802
+ body += indentation + " " + uniqueName + " = " + c.concatTokens() + ".";
803
+ }
804
+ }
805
+ body += "\n" + indentation + "ENDCASE.\n" + indentation;
806
+ const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), body);
807
+ const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, firstToken.getStart(), i.getLastToken().getEnd(), uniqueName);
808
+ const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
809
+ return issue_1.Issue.atToken(lowFile, firstToken, "Downport SWITCH", this.getMetadata().key, this.conf.severity, fix);
810
+ }
811
+ return undefined;
812
+ }
738
813
  outlineReduce(node, lowFile, highSyntax) {
739
814
  var _a;
740
815
  for (const i of node.findAllExpressionsRecursive(Expressions.Source)) {
@@ -1101,12 +1176,13 @@ ${indentation} output = ${topTarget}.`;
1101
1176
  }
1102
1177
  return undefined;
1103
1178
  }
1104
- replaceLineExists(node, lowFile, highSyntax) {
1179
+ replaceLineFunctions(node, lowFile, highSyntax) {
1105
1180
  var _a, _b;
1106
1181
  const spag = highSyntax.spaghetti.lookupPosition(node.getFirstToken().getStart(), lowFile.getFilename());
1107
1182
  for (const r of (spag === null || spag === void 0 ? void 0 : spag.getData().references) || []) {
1183
+ const func = r.position.getName().toUpperCase();
1108
1184
  if (r.referenceType === _reference_1.ReferenceType.BuiltinMethodReference
1109
- && r.position.getName().toUpperCase() === "LINE_EXISTS") {
1185
+ && (func === "LINE_EXISTS" || func === "LINE_INDEX")) {
1110
1186
  const token = r.position.getToken();
1111
1187
  const expression = this.findMethodCallExpression(node, token);
1112
1188
  if (expression === undefined) {
@@ -1120,19 +1196,23 @@ ${indentation} output = ${topTarget}.`;
1120
1196
  else if (c.get() instanceof Expressions.ComponentChainSimple && condition === "") {
1121
1197
  condition = "WITH KEY ";
1122
1198
  }
1199
+ else if (c.get() instanceof Expressions.Source && condition === "") {
1200
+ condition = "INDEX ";
1201
+ }
1123
1202
  condition += c.concatTokens() + " ";
1124
1203
  }
1125
1204
  const tableName = (_b = expression === null || expression === void 0 ? void 0 : expression.findFirstExpression(Expressions.SourceField)) === null || _b === void 0 ? void 0 : _b.concatTokens();
1126
1205
  const uniqueName = this.uniqueName(node.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
1127
1206
  const indentation = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
1207
+ const sy = func === "LINE_EXISTS" ? "sy-subrc" : "sy-tabix";
1128
1208
  const code = `DATA ${uniqueName} LIKE sy-subrc.\n` +
1129
1209
  indentation + `READ TABLE ${tableName} ${condition}TRANSPORTING NO FIELDS.\n` +
1130
- indentation + uniqueName + " = sy-subrc.\n" +
1210
+ indentation + uniqueName + ` = ${sy}.\n` +
1131
1211
  indentation;
1132
1212
  const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), code);
1133
1213
  const start = expression.getFirstToken().getStart();
1134
1214
  const end = expression.getLastToken().getEnd();
1135
- const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, start, end, uniqueName + " = 0");
1215
+ const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, start, end, uniqueName + (func === "LINE_EXISTS" ? " = 0" : ""));
1136
1216
  const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
1137
1217
  return issue_1.Issue.atToken(lowFile, token, "Use BOOLC", this.getMetadata().key, this.conf.severity, fix);
1138
1218
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.85.24",
3
+ "version": "2.85.25",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -50,7 +50,7 @@
50
50
  "@types/mocha": "^9.1.0",
51
51
  "@types/node": "^17.0.21",
52
52
  "chai": "^4.3.6",
53
- "eslint": "^8.9.0",
53
+ "eslint": "^8.10.0",
54
54
  "mocha": "^9.2.1",
55
55
  "c8": "^7.11.0",
56
56
  "source-map-support": "^0.5.21",