@abaplint/core 2.93.16 → 2.93.18
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/abap/2_statements/expressions/for.js +1 -1
- package/build/src/abap/5_syntax/expressions/for.js +3 -0
- package/build/src/abap/5_syntax/expressions/inline_field_definition.js +2 -1
- package/build/src/abap/5_syntax/expressions/reduce_body.js +11 -2
- package/build/src/abap/5_syntax/expressions/value_body.js +9 -6
- package/build/src/registry.js +1 -1
- package/build/src/rules/downport.js +58 -11
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ class For extends combi_1.Expression {
|
|
|
14
14
|
const then = (0, combi_1.seq)("THEN", _1.Source);
|
|
15
15
|
const whil = (0, combi_1.seq)((0, combi_1.altPrio)("UNTIL", "WHILE"), _1.Cond);
|
|
16
16
|
const itera = (0, combi_1.seq)(_1.InlineFieldDefinition, (0, combi_1.opt)(then), whil);
|
|
17
|
-
const groupBy = (0, combi_1.seq)("GROUP BY", field_chain_1.FieldChain);
|
|
17
|
+
const groupBy = (0, combi_1.seq)("GROUP BY", (0, combi_1.alt)(field_chain_1.FieldChain, (0, combi_1.seq)("(", (0, combi_1.plus)(_1.LoopGroupByComponent), ")")));
|
|
18
18
|
const groups = (0, combi_1.ver)(version_1.Version.v740sp08, (0, combi_1.seq)("GROUPS", field_chain_1.FieldChain, "OF", _1.Target, "IN", _1.Source, (0, combi_1.optPrio)(groupBy)));
|
|
19
19
|
const f = (0, combi_1.seq)("FOR", (0, combi_1.alt)(itera, inn, groups), (0, combi_1.optPrio)(_1.Let));
|
|
20
20
|
return (0, combi_1.ver)(version_1.Version.v740sp05, f);
|
|
@@ -10,12 +10,14 @@ const component_cond_1 = require("./component_cond");
|
|
|
10
10
|
const cond_1 = require("./cond");
|
|
11
11
|
class For {
|
|
12
12
|
runSyntax(node, scope, filename) {
|
|
13
|
+
let scoped = false;
|
|
13
14
|
const inlineLoop = node.findDirectExpressions(Expressions.InlineLoopDefinition);
|
|
14
15
|
const inlineField = node.findAllExpressions(Expressions.InlineFieldDefinition);
|
|
15
16
|
const addScope = inlineLoop.length > 0 || inlineField.length > 0;
|
|
16
17
|
if (addScope) {
|
|
17
18
|
// this scope is popped in parent expressions
|
|
18
19
|
scope.push(_scope_type_1.ScopeType.For, "FOR", node.getFirstToken().getStart(), filename);
|
|
20
|
+
scoped = true;
|
|
19
21
|
}
|
|
20
22
|
for (const s of inlineLoop) {
|
|
21
23
|
new inline_loop_definition_1.InlineLoopDefinition().runSyntax(s, scope, filename);
|
|
@@ -32,6 +34,7 @@ class For {
|
|
|
32
34
|
for (const s of node.findDirectExpressions(Expressions.Cond)) {
|
|
33
35
|
new cond_1.Cond().runSyntax(s, scope, filename);
|
|
34
36
|
}
|
|
37
|
+
return scoped;
|
|
35
38
|
}
|
|
36
39
|
}
|
|
37
40
|
exports.For = For;
|
|
@@ -13,7 +13,7 @@ class InlineFieldDefinition {
|
|
|
13
13
|
let type = undefined;
|
|
14
14
|
const field = (_a = node.findDirectExpression(Expressions.Field)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
15
15
|
if (field === undefined) {
|
|
16
|
-
return;
|
|
16
|
+
return undefined;
|
|
17
17
|
}
|
|
18
18
|
const source = node.findDirectExpression(Expressions.Source);
|
|
19
19
|
if (source) {
|
|
@@ -33,6 +33,7 @@ class InlineFieldDefinition {
|
|
|
33
33
|
const identifier = new _typed_identifier_1.TypedIdentifier(field, filename, type, ["inline" /* IdentifierMeta.InlineDefinition */]);
|
|
34
34
|
scope.addReference(field, identifier, _reference_1.ReferenceType.DataWriteReference, filename);
|
|
35
35
|
scope.addIdentifier(identifier);
|
|
36
|
+
return type;
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
exports.InlineFieldDefinition = InlineFieldDefinition;
|
|
@@ -19,8 +19,12 @@ class ReduceBody {
|
|
|
19
19
|
if (letNode) {
|
|
20
20
|
scoped = new let_1.Let().runSyntax(letNode, scope, filename);
|
|
21
21
|
}
|
|
22
|
+
let first = undefined;
|
|
22
23
|
for (const i of node.findDirectExpressions(Expressions.InlineFieldDefinition)) {
|
|
23
|
-
new inline_field_definition_1.InlineFieldDefinition().runSyntax(i, scope, filename);
|
|
24
|
+
const found = new inline_field_definition_1.InlineFieldDefinition().runSyntax(i, scope, filename);
|
|
25
|
+
if (found && first === undefined) {
|
|
26
|
+
first = found;
|
|
27
|
+
}
|
|
24
28
|
}
|
|
25
29
|
for (const forNode of node.findDirectExpressions(Expressions.For) || []) {
|
|
26
30
|
new for_1.For().runSyntax(forNode, scope, filename);
|
|
@@ -37,7 +41,12 @@ class ReduceBody {
|
|
|
37
41
|
while (scope.getType() === _scope_type_1.ScopeType.For) {
|
|
38
42
|
scope.pop(node.getLastToken().getEnd());
|
|
39
43
|
}
|
|
40
|
-
|
|
44
|
+
if (first) {
|
|
45
|
+
return first;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
return new unknown_type_1.UnknownType("todo, ReduceBody");
|
|
49
|
+
}
|
|
41
50
|
}
|
|
42
51
|
}
|
|
43
52
|
exports.ReduceBody = ReduceBody;
|
|
@@ -6,20 +6,23 @@ const for_1 = require("./for");
|
|
|
6
6
|
const source_1 = require("./source");
|
|
7
7
|
const let_1 = require("./let");
|
|
8
8
|
const field_assignment_1 = require("./field_assignment");
|
|
9
|
-
const _scope_type_1 = require("../_scope_type");
|
|
10
9
|
const basic_1 = require("../../types/basic");
|
|
11
10
|
class ValueBody {
|
|
12
11
|
runSyntax(node, scope, filename, targetType) {
|
|
13
12
|
if (node === undefined) {
|
|
14
13
|
return targetType;
|
|
15
14
|
}
|
|
15
|
+
let forScopes = 0;
|
|
16
16
|
for (const forNode of node.findDirectExpressions(Expressions.For) || []) {
|
|
17
|
-
new for_1.For().runSyntax(forNode, scope, filename);
|
|
17
|
+
const scoped = new for_1.For().runSyntax(forNode, scope, filename);
|
|
18
|
+
if (scoped === true) {
|
|
19
|
+
forScopes++;
|
|
20
|
+
}
|
|
18
21
|
}
|
|
19
|
-
let
|
|
22
|
+
let letScoped = false;
|
|
20
23
|
const letNode = node.findDirectExpression(Expressions.Let);
|
|
21
24
|
if (letNode) {
|
|
22
|
-
|
|
25
|
+
letScoped = new let_1.Let().runSyntax(letNode, scope, filename);
|
|
23
26
|
}
|
|
24
27
|
for (const s of node.findDirectExpressions(Expressions.FieldAssignment)) {
|
|
25
28
|
new field_assignment_1.FieldAssignment().runSyntax(s, scope, filename, targetType);
|
|
@@ -52,10 +55,10 @@ class ValueBody {
|
|
|
52
55
|
new source_1.Source().runSyntax(s, scope, filename);
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
|
-
if (
|
|
58
|
+
if (letScoped === true) {
|
|
56
59
|
scope.pop(node.getLastToken().getEnd());
|
|
57
60
|
}
|
|
58
|
-
|
|
61
|
+
for (let i = 0; i < forScopes; i++) {
|
|
59
62
|
scope.pop(node.getLastToken().getEnd());
|
|
60
63
|
}
|
|
61
64
|
if ((targetType === null || targetType === void 0 ? void 0 : targetType.isGeneric()) && type) {
|
package/build/src/registry.js
CHANGED
|
@@ -222,6 +222,10 @@ Only one transformation is applied to a statement at a time, so multiple steps m
|
|
|
222
222
|
if (found) {
|
|
223
223
|
return found;
|
|
224
224
|
}
|
|
225
|
+
found = this.downportCorrespondingSimple(high, lowFile);
|
|
226
|
+
if (found) {
|
|
227
|
+
return found;
|
|
228
|
+
}
|
|
225
229
|
found = this.downportRef(low, high, lowFile, highSyntax);
|
|
226
230
|
if (found) {
|
|
227
231
|
return found;
|
|
@@ -873,6 +877,28 @@ ${indentation}RAISE EXCEPTION ${uniqueName2}.`;
|
|
|
873
877
|
const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
|
|
874
878
|
return issue_1.Issue.atToken(lowFile, high.getFirstToken(), "Downport, call function parameter", this.getMetadata().key, this.conf.severity, fix);
|
|
875
879
|
}
|
|
880
|
+
downportCorrespondingSimple(high, lowFile) {
|
|
881
|
+
var _a;
|
|
882
|
+
if (!(high.get() instanceof Statements.Move)
|
|
883
|
+
|| high.getChildren().length !== 4
|
|
884
|
+
|| high.getChildren()[2].getFirstToken().getStr().toUpperCase() !== "CORRESPONDING") {
|
|
885
|
+
return undefined;
|
|
886
|
+
}
|
|
887
|
+
const target = high.findDirectExpression(Expressions.Target);
|
|
888
|
+
if (target === undefined) {
|
|
889
|
+
console.dir("sdf1");
|
|
890
|
+
return undefined;
|
|
891
|
+
}
|
|
892
|
+
const sourceRef = (_a = high.findFirstExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.findFirstExpression(Expressions.CorrespondingBody);
|
|
893
|
+
if (sourceRef === undefined || sourceRef.getChildren().length !== 1) {
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
const code = `MOVE-CORRESPONDING ${sourceRef.concatTokens()} TO ${target.concatTokens()}`;
|
|
897
|
+
const start = high.getFirstToken().getStart();
|
|
898
|
+
const end = high.getLastToken().getStart();
|
|
899
|
+
const fix = edit_helper_1.EditHelper.replaceRange(lowFile, start, end, code);
|
|
900
|
+
return issue_1.Issue.atToken(lowFile, high.getFirstToken(), "Downport, simple CORRESPONDING move", this.getMetadata().key, this.conf.severity, fix);
|
|
901
|
+
}
|
|
876
902
|
downportRefSimple(high, lowFile) {
|
|
877
903
|
var _a;
|
|
878
904
|
if (!(high.get() instanceof Statements.Move)
|
|
@@ -895,7 +921,7 @@ ${indentation}RAISE EXCEPTION ${uniqueName2}.`;
|
|
|
895
921
|
return issue_1.Issue.atToken(lowFile, high.getFirstToken(), "Downport, simple REF move", this.getMetadata().key, this.conf.severity, fix);
|
|
896
922
|
}
|
|
897
923
|
downportLoopGroup(high, lowFile, highSyntax, highFile) {
|
|
898
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
924
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
899
925
|
if (!(high.get() instanceof Statements.Loop)) {
|
|
900
926
|
return undefined;
|
|
901
927
|
}
|
|
@@ -907,6 +933,7 @@ ${indentation}RAISE EXCEPTION ${uniqueName2}.`;
|
|
|
907
933
|
const loopSourceName = ((_b = high.findFirstExpression(Expressions.SimpleSource2)) === null || _b === void 0 ? void 0 : _b.concatTokens()) || "nameNotFound";
|
|
908
934
|
const loopTargetName = ((_c = high.findFirstExpression(Expressions.TargetField)) === null || _c === void 0 ? void 0 : _c.concatTokens()) || "nameNotFound";
|
|
909
935
|
const groupTarget = ((_d = group.findDirectExpression(Expressions.LoopGroupByTarget)) === null || _d === void 0 ? void 0 : _d.concatTokens()) || "";
|
|
936
|
+
const isReference = (_e = high.findFirstExpression(Expressions.LoopTarget)) === null || _e === void 0 ? void 0 : _e.concatTokens().toUpperCase().startsWith("REFERENCE INTO ");
|
|
910
937
|
let loopSourceRowType = "typeNotFound";
|
|
911
938
|
const spag = highSyntax.spaghetti.lookupPosition(high.getFirstToken().getStart(), lowFile.getFilename());
|
|
912
939
|
if (spag !== undefined) {
|
|
@@ -921,8 +948,8 @@ ${indentation}RAISE EXCEPTION ${uniqueName2}.`;
|
|
|
921
948
|
let groupCountName = undefined;
|
|
922
949
|
for (const c of group.findAllExpressions(Expressions.LoopGroupByComponent)) {
|
|
923
950
|
const name = c.findFirstExpression(Expressions.ComponentName);
|
|
924
|
-
let type = ((
|
|
925
|
-
if ((
|
|
951
|
+
let type = ((_f = c.findFirstExpression(Expressions.Source)) === null || _f === void 0 ? void 0 : _f.concatTokens()) || "todo";
|
|
952
|
+
if ((_g = c.concatTokens()) === null || _g === void 0 ? void 0 : _g.toUpperCase().endsWith(" = GROUP SIZE")) {
|
|
926
953
|
type = "i";
|
|
927
954
|
groupCountName = name === null || name === void 0 ? void 0 : name.concatTokens();
|
|
928
955
|
}
|
|
@@ -939,29 +966,31 @@ ${indentation}RAISE EXCEPTION ${uniqueName2}.`;
|
|
|
939
966
|
END OF ${groupTargetName}type.
|
|
940
967
|
DATA ${groupTargetName}tab TYPE STANDARD TABLE OF ${groupTargetName}type WITH DEFAULT KEY.
|
|
941
968
|
DATA ${uniqueName} LIKE LINE OF ${groupTargetName}tab.
|
|
942
|
-
LOOP AT ${loopSourceName} ${(
|
|
969
|
+
LOOP AT ${loopSourceName} ${(_h = high.findFirstExpression(Expressions.LoopTarget)) === null || _h === void 0 ? void 0 : _h.concatTokens()}.
|
|
943
970
|
READ TABLE ${groupTargetName}tab ASSIGNING FIELD-SYMBOL(<${uniqueFS}>) WITH KEY ${condition}.
|
|
944
|
-
IF sy-subrc = 0
|
|
945
|
-
|
|
946
|
-
|
|
971
|
+
IF sy-subrc = 0.\n`;
|
|
972
|
+
if (groupCountName !== undefined) {
|
|
973
|
+
code += ` <${uniqueFS}>-${groupCountName} = <${uniqueFS}>-${groupCountName} + 1.\n`;
|
|
974
|
+
}
|
|
975
|
+
code += ` INSERT ${loopTargetName}${isReference ? "->*" : ""} INTO TABLE <${uniqueFS}>-items.
|
|
947
976
|
ELSE.\n`;
|
|
948
977
|
code += ` CLEAR ${uniqueName}.\n`;
|
|
949
978
|
for (const c of group.findAllExpressions(Expressions.LoopGroupByComponent)) {
|
|
950
979
|
code += ` ${uniqueName}-${c.concatTokens().replace("GROUP SIZE", "1")}.\n`;
|
|
951
980
|
}
|
|
952
|
-
code += ` INSERT ${loopTargetName}->* INTO TABLE ${uniqueName}-items.\n`;
|
|
981
|
+
code += ` INSERT ${loopTargetName}${isReference ? "->*" : ""} INTO TABLE ${uniqueName}-items.\n`;
|
|
953
982
|
code += ` INSERT ${uniqueName} INTO TABLE ${groupTargetName}tab.\n`;
|
|
954
983
|
code += `ENDIF.
|
|
955
984
|
ENDLOOP.
|
|
956
985
|
LOOP AT ${groupTargetName}tab ${groupTarget}.`;
|
|
957
986
|
let fix = edit_helper_1.EditHelper.replaceRange(lowFile, high.getFirstToken().getStart(), high.getLastToken().getEnd(), code);
|
|
958
|
-
for (const l of ((
|
|
987
|
+
for (const l of ((_j = highFile.getStructure()) === null || _j === void 0 ? void 0 : _j.findAllStructures(Structures.Loop)) || []) {
|
|
959
988
|
// make sure to find the correct/current loop statement
|
|
960
989
|
if (l.findDirectStatement(Statements.Loop) !== high) {
|
|
961
990
|
continue;
|
|
962
991
|
}
|
|
963
992
|
for (const loop of l.findAllStatements(Statements.Loop)) {
|
|
964
|
-
if ((
|
|
993
|
+
if ((_k = loop.concatTokens()) === null || _k === void 0 ? void 0 : _k.toUpperCase().startsWith("LOOP AT GROUP ")) {
|
|
965
994
|
const subLoopSource = loop.findFirstExpression(Expressions.SimpleSource2);
|
|
966
995
|
if (subLoopSource === undefined) {
|
|
967
996
|
continue;
|
|
@@ -1362,8 +1391,26 @@ ${indentation} output = ${topTarget}.`;
|
|
|
1362
1391
|
from = from ? " FROM " + from : "";
|
|
1363
1392
|
let to = (_j = forLoop.findExpressionAfterToken("TO")) === null || _j === void 0 ? void 0 : _j.concatTokens();
|
|
1364
1393
|
to = to ? " TO " + to : "";
|
|
1394
|
+
let gby = "";
|
|
1395
|
+
for (const lg of forLoop.findDirectExpressions(Expressions.LoopGroupByComponent)) {
|
|
1396
|
+
if (gby !== "") {
|
|
1397
|
+
gby += " ";
|
|
1398
|
+
}
|
|
1399
|
+
gby = lg.concatTokens();
|
|
1400
|
+
}
|
|
1401
|
+
if (gby !== "") {
|
|
1402
|
+
gby = " GROUP BY ( " + gby + " )";
|
|
1403
|
+
}
|
|
1404
|
+
const groups = forLoop.findExpressionAfterToken("GROUPS");
|
|
1405
|
+
if (groups) {
|
|
1406
|
+
gby += " INTO DATA(" + groups.concatTokens() + ")";
|
|
1407
|
+
}
|
|
1408
|
+
let inGroup = "";
|
|
1409
|
+
if (forLoop.concatTokens().toUpperCase().includes(" IN GROUP ")) {
|
|
1410
|
+
inGroup = "-items";
|
|
1411
|
+
}
|
|
1365
1412
|
// todo, also backup sy-index / sy-tabix here?
|
|
1366
|
-
body += indentation + `LOOP AT ${loopSource} INTO DATA(${loopTargetField})${from}${to}${cond}.\n`;
|
|
1413
|
+
body += indentation + `LOOP AT ${loopSource}${inGroup} INTO DATA(${loopTargetField})${from}${to}${cond}${gby}.\n`;
|
|
1367
1414
|
if (indexInto) {
|
|
1368
1415
|
body += indentation + " DATA(" + indexInto + ") = sy-tabix.\n";
|
|
1369
1416
|
}
|