@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.
- package/build/src/registry.js +1 -1
- package/build/src/rules/downport.js +93 -13
- package/package.json +2 -2
package/build/src/registry.js
CHANGED
|
@@ -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
|
|
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.
|
|
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}
|
|
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
|
-
|
|
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
|
-
&&
|
|
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 +
|
|
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.
|
|
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.
|
|
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",
|