@abaplint/core 2.91.26 → 2.91.29

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.
@@ -1869,6 +1869,7 @@ declare namespace Expressions {
1869
1869
  LoopGroupByComponent,
1870
1870
  LoopGroupByTarget,
1871
1871
  LoopGroupBy,
1872
+ LoopTarget,
1872
1873
  MacroName,
1873
1874
  MessageClass_2 as MessageClass,
1874
1875
  MessageNumber,
@@ -3559,6 +3560,10 @@ declare class LoopGroupByTarget extends Expression {
3559
3560
  getRunnable(): IStatementRunnable;
3560
3561
  }
3561
3562
 
3563
+ declare class LoopTarget extends Expression {
3564
+ getRunnable(): IStatementRunnable;
3565
+ }
3566
+
3562
3567
  declare class MacroName extends Expression {
3563
3568
  getRunnable(): IStatementRunnable;
3564
3569
  }
@@ -99,6 +99,7 @@ __exportStar(require("./let"), exports);
99
99
  __exportStar(require("./loop_group_by_component"), exports);
100
100
  __exportStar(require("./loop_group_by_target"), exports);
101
101
  __exportStar(require("./loop_group_by"), exports);
102
+ __exportStar(require("./loop_target"), exports);
102
103
  __exportStar(require("./macro_name"), exports);
103
104
  __exportStar(require("./message_class"), exports);
104
105
  __exportStar(require("./message_number"), exports);
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LoopTarget = void 0;
4
+ const combi_1 = require("../combi");
5
+ const _1 = require(".");
6
+ class LoopTarget extends combi_1.Expression {
7
+ getRunnable() {
8
+ const into = (0, combi_1.seq)((0, combi_1.opt)("REFERENCE"), "INTO", _1.Target);
9
+ const assigning = (0, combi_1.seq)("ASSIGNING", _1.FSTarget);
10
+ const target = (0, combi_1.alt)((0, combi_1.seq)((0, combi_1.alt)(into, assigning), (0, combi_1.optPrio)("CASTING")), "TRANSPORTING NO FIELDS");
11
+ return target;
12
+ }
13
+ }
14
+ exports.LoopTarget = LoopTarget;
15
+ //# sourceMappingURL=loop_target.js.map
@@ -9,14 +9,11 @@ const loop_group_by_1 = require("../expressions/loop_group_by");
9
9
  class Loop {
10
10
  getMatcher() {
11
11
  const where = (0, combi_1.seq)("WHERE", (0, combi_1.alt)(expressions_1.ComponentCond, expressions_1.Dynamic));
12
- const into = (0, combi_1.seq)((0, combi_1.opt)("REFERENCE"), "INTO", expressions_1.Target);
13
- const assigning = (0, combi_1.seq)("ASSIGNING", expressions_1.FSTarget);
14
12
  const group = (0, combi_1.ver)(version_1.Version.v740sp08, (0, combi_1.seq)("GROUP BY", loop_group_by_1.LoopGroupBy));
15
- const target = (0, combi_1.alt)((0, combi_1.seq)((0, combi_1.alt)(into, assigning), (0, combi_1.optPrio)("CASTING")), "TRANSPORTING NO FIELDS");
16
13
  const from = (0, combi_1.seq)("FROM", expressions_1.Source);
17
14
  const to = (0, combi_1.seq)("TO", expressions_1.Source);
18
15
  const usingKey = (0, combi_1.seq)("USING KEY", (0, combi_1.altPrio)(expressions_1.SimpleName, expressions_1.Dynamic));
19
- const options = (0, combi_1.per)(target, from, to, where, usingKey, group);
16
+ const options = (0, combi_1.per)(expressions_1.LoopTarget, from, to, where, usingKey, group);
20
17
  const at = (0, combi_1.seq)("AT", (0, combi_1.opt)((0, combi_1.seq)("SCREEN", (0, combi_1.fail)())), (0, combi_1.opt)((0, combi_1.ver)(version_1.Version.v740sp08, "GROUP")), (0, combi_1.alt)(simple_source2_1.SimpleSource2, (0, combi_1.ver)(version_1.Version.v740sp02, expressions_1.Source)), (0, combi_1.opt)(options));
21
18
  return (0, combi_1.seq)("LOOP", (0, combi_1.opt)(at));
22
19
  }
@@ -6,6 +6,7 @@ const basic_types_1 = require("../basic_types");
6
6
  const Expressions = require("../../2_statements/expressions");
7
7
  const basic_1 = require("../../types/basic");
8
8
  const _scope_type_1 = require("../_scope_type");
9
+ const type_table_key_1 = require("./type_table_key");
9
10
  class TypeTable {
10
11
  runSyntax(node, scope, filename, qualifiedNamePrefix) {
11
12
  // todo, input is currently the statement, but should be the expression?
@@ -25,10 +26,16 @@ class TypeTable {
25
26
  qualifiedName = scope.getName() + "=>" + qualifiedName;
26
27
  }
27
28
  }
28
- const type = new basic_types_1.BasicTypes(filename, scope).parseTable(node, qualifiedName);
29
+ let type = new basic_types_1.BasicTypes(filename, scope).parseTable(node, qualifiedName);
29
30
  if (type === undefined) {
30
31
  return new _typed_identifier_1.TypedIdentifier(name, filename, new basic_1.UnknownType("TableType, fallback"));
31
32
  }
33
+ for (const tt of node.findAllExpressions(Expressions.TypeTableKey)) {
34
+ const error = new type_table_key_1.TypeTableKey().runSyntax(tt, type);
35
+ if (error) {
36
+ type = error;
37
+ }
38
+ }
32
39
  return new _typed_identifier_1.TypedIdentifier(name, filename, type);
33
40
  }
34
41
  }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TypeTableKey = void 0;
4
+ const Expressions = require("../../2_statements/expressions");
5
+ const basic_1 = require("../../types/basic");
6
+ class TypeTableKey {
7
+ runSyntax(node, type) {
8
+ if (type instanceof basic_1.TableType) {
9
+ const rowType = type.getRowType();
10
+ if (rowType instanceof basic_1.StructureType) {
11
+ for (const c of node.findAllExpressions(Expressions.FieldSub)) {
12
+ const concat = c.concatTokens();
13
+ if (concat.includes("-") === false // todo, properly check sub fields
14
+ && rowType.getComponentByName(concat) === undefined
15
+ && concat.toUpperCase() !== "TABLE_LINE") {
16
+ return new basic_1.UnknownType(`Field ${concat} not part of structure`);
17
+ }
18
+ }
19
+ }
20
+ }
21
+ return undefined;
22
+ }
23
+ }
24
+ exports.TypeTableKey = TypeTableKey;
25
+ //# sourceMappingURL=type_table_key.js.map
@@ -14,7 +14,8 @@ const dynamic_1 = require("../expressions/dynamic");
14
14
  const loop_group_by_1 = require("../expressions/loop_group_by");
15
15
  class Loop {
16
16
  runSyntax(node, scope, filename) {
17
- let target = node.findDirectExpression(Expressions.Target);
17
+ const loopTarget = node.findDirectExpression(Expressions.LoopTarget);
18
+ let target = loopTarget === null || loopTarget === void 0 ? void 0 : loopTarget.findDirectExpression(Expressions.Target);
18
19
  const targetType = target ? new target_1.Target().runSyntax(target, scope, filename) : undefined;
19
20
  if (target === undefined) {
20
21
  target = node.findDirectExpression(Expressions.FSTarget);
@@ -58,7 +59,7 @@ class Loop {
58
59
  new inline_fs_1.InlineFS().runSyntax(inlinefs, scope, filename, sourceType);
59
60
  }
60
61
  else {
61
- const fstarget = node.findDirectExpression(Expressions.FSTarget);
62
+ const fstarget = loopTarget === null || loopTarget === void 0 ? void 0 : loopTarget.findDirectExpression(Expressions.FSTarget);
62
63
  if (fstarget) {
63
64
  new fstarget_1.FSTarget().runSyntax(fstarget, scope, filename, sourceType);
64
65
  }
@@ -68,7 +68,7 @@ class Registry {
68
68
  }
69
69
  static abaplintVersion() {
70
70
  // magic, see build script "version.sh"
71
- return "2.91.26";
71
+ return "2.91.29";
72
72
  }
73
73
  getDDICReferences() {
74
74
  return this.references;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Downport = exports.DownportConf = void 0;
4
+ /* eslint-disable max-len */
4
5
  const Statements = require("../abap/2_statements/statements");
5
6
  const Expressions = require("../abap/2_statements/expressions");
6
7
  const Structures = require("../abap/3_structures/structures");
@@ -200,6 +201,10 @@ Only one transformation is applied to a statement at a time, so multiple steps m
200
201
  if (found) {
201
202
  return found;
202
203
  }
204
+ found = this.assignWithTable(high, lowFile);
205
+ if (found) {
206
+ return found;
207
+ }
203
208
  found = this.downportRefSimple(high, lowFile);
204
209
  if (found) {
205
210
  return found;
@@ -865,7 +870,7 @@ ${indentation}RAISE EXCEPTION ${uniqueName2}.`;
865
870
  return issue_1.Issue.atToken(lowFile, high.getFirstToken(), "Downport, simple REF move", this.getMetadata().key, this.conf.severity, fix);
866
871
  }
867
872
  downportLoopGroup(high, lowFile, highSyntax, highFile) {
868
- var _a, _b, _c, _d, _e, _f, _g, _h;
873
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
869
874
  if (!(high.get() instanceof Statements.Loop)) {
870
875
  return undefined;
871
876
  }
@@ -886,32 +891,52 @@ ${indentation}RAISE EXCEPTION ${uniqueName2}.`;
886
891
  loopSourceRowType = tt.getRowType().getQualifiedName() || "typeNotFound";
887
892
  }
888
893
  }
889
- let code = `TYPES: BEGIN OF ${groupTargetName}#type,\n`;
894
+ let code = `TYPES: BEGIN OF ${groupTargetName}type,\n`;
895
+ let condition = "";
896
+ let groupCountName = undefined;
890
897
  for (const c of group.findAllExpressions(Expressions.LoopGroupByComponent)) {
891
898
  const name = c.findFirstExpression(Expressions.ComponentName);
892
899
  let type = ((_e = c.findFirstExpression(Expressions.Source)) === null || _e === void 0 ? void 0 : _e.concatTokens()) || "todo";
893
900
  if ((_f = c.concatTokens()) === null || _f === void 0 ? void 0 : _f.toUpperCase().endsWith(" = GROUP SIZE")) {
894
901
  type = "i";
902
+ groupCountName = name === null || name === void 0 ? void 0 : name.concatTokens();
895
903
  }
896
904
  else {
905
+ condition += c.concatTokens();
897
906
  type = type.replace(loopTargetName, loopSourceRowType);
898
907
  type = type.replace("->", "-");
899
908
  }
900
- code += ` ${name === null || name === void 0 ? void 0 : name.concatTokens()} TYPE ${type},\n`;
909
+ code += ` ${name === null || name === void 0 ? void 0 : name.concatTokens()} TYPE ${type},\n`;
910
+ }
911
+ const uniqueName = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
912
+ const uniqueFS = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
913
+ code += ` items LIKE ${loopSourceName},
914
+ END OF ${groupTargetName}type.
915
+ DATA ${groupTargetName}tab TYPE STANDARD TABLE OF ${groupTargetName}type WITH DEFAULT KEY.
916
+ DATA ${uniqueName} LIKE LINE OF ${groupTargetName}tab.
917
+ LOOP AT ${loopSourceName} ${(_g = high.findFirstExpression(Expressions.LoopTarget)) === null || _g === void 0 ? void 0 : _g.concatTokens()}.
918
+ READ TABLE ${groupTargetName}tab ASSIGNING FIELD-SYMBOL(<${uniqueFS}>) WITH KEY ${condition}.
919
+ IF sy-subrc = 0.
920
+ <${uniqueFS}>-${groupCountName} = <${uniqueFS}>-${groupCountName} + 1.
921
+ INSERT ${loopTargetName}->* INTO TABLE <${uniqueFS}>-items.
922
+ ELSE.\n`;
923
+ code += ` CLEAR ${uniqueName}.\n`;
924
+ for (const c of group.findAllExpressions(Expressions.LoopGroupByComponent)) {
925
+ code += ` ${uniqueName}-${c.concatTokens().replace("GROUP SIZE", "1")}.\n`;
901
926
  }
902
- code += ` items LIKE ${loopSourceName},
903
- END OF ${groupTargetName}#type.
904
- DATA ${groupTargetName}#tab TYPE STANDARD TABLE OF ${groupTargetName}#type WITH DEFAULT KEY.
905
- * todo, aggregation code here
906
- LOOP AT ${groupTargetName}#tab ${groupTarget}.`;
927
+ code += ` INSERT ${loopTargetName}->* INTO TABLE ${uniqueName}-items.\n`;
928
+ code += ` INSERT ${uniqueName} INTO TABLE ${groupTargetName}tab.\n`;
929
+ code += `ENDIF.
930
+ ENDLOOP.
931
+ LOOP AT ${groupTargetName}tab ${groupTarget}.`;
907
932
  let fix = edit_helper_1.EditHelper.replaceRange(lowFile, high.getFirstToken().getStart(), high.getLastToken().getEnd(), code);
908
- for (const l of ((_g = highFile.getStructure()) === null || _g === void 0 ? void 0 : _g.findAllStructures(Structures.Loop)) || []) {
933
+ for (const l of ((_h = highFile.getStructure()) === null || _h === void 0 ? void 0 : _h.findAllStructures(Structures.Loop)) || []) {
909
934
  // make sure to find the correct/current loop statement
910
935
  if (l.findDirectStatement(Statements.Loop) !== high) {
911
936
  continue;
912
937
  }
913
938
  for (const loop of l.findAllStatements(Statements.Loop)) {
914
- if ((_h = loop.concatTokens()) === null || _h === void 0 ? void 0 : _h.toUpperCase().startsWith("LOOP AT GROUP ")) {
939
+ if ((_j = loop.concatTokens()) === null || _j === void 0 ? void 0 : _j.toUpperCase().startsWith("LOOP AT GROUP ")) {
915
940
  const subLoopSource = loop.findFirstExpression(Expressions.SimpleSource2);
916
941
  if (subLoopSource === undefined) {
917
942
  continue;
@@ -943,6 +968,30 @@ LOOP AT ${groupTargetName}#tab ${groupTarget}.`;
943
968
  const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
944
969
  return issue_1.Issue.atToken(lowFile, high.getFirstToken(), "Downport, REF", this.getMetadata().key, this.conf.severity, fix);
945
970
  }
971
+ assignWithTable(high, lowFile) {
972
+ var _a;
973
+ if (!(high.get() instanceof Statements.Assign)
974
+ || high.getChildren().length !== 5) {
975
+ return undefined;
976
+ }
977
+ const fieldChain = (_a = high.findDirectExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.findDirectExpression(Expressions.FieldChain);
978
+ if ((fieldChain === null || fieldChain === void 0 ? void 0 : fieldChain.getChildren().length) !== 2) {
979
+ return undefined;
980
+ }
981
+ const tableExpression = fieldChain === null || fieldChain === void 0 ? void 0 : fieldChain.getChildren()[1];
982
+ if (!(tableExpression.get() instanceof Expressions.TableExpression)
983
+ || !(tableExpression instanceof nodes_1.ExpressionNode)) {
984
+ return undefined;
985
+ }
986
+ const index = tableExpression.findDirectExpression(Expressions.Source);
987
+ if (index === undefined) {
988
+ return undefined;
989
+ }
990
+ const fsTarget = high.findDirectExpression(Expressions.FSTarget);
991
+ const code = `READ TABLE ${fieldChain === null || fieldChain === void 0 ? void 0 : fieldChain.getChildren()[0].concatTokens()} INDEX ${index.concatTokens()} ASSIGNING ${fsTarget === null || fsTarget === void 0 ? void 0 : fsTarget.concatTokens()}.`;
992
+ const fix = edit_helper_1.EditHelper.replaceRange(lowFile, high.getFirstToken().getStart(), high.getLastToken().getEnd(), code);
993
+ return issue_1.Issue.atToken(lowFile, high.getFirstToken(), "Downport, ASSIGN table expr", this.getMetadata().key, this.conf.severity, fix);
994
+ }
946
995
  moveWithSimpleValue(high, lowFile) {
947
996
  if (!(high.get() instanceof Statements.Move)
948
997
  || high.getChildren().length !== 4) {
@@ -1176,7 +1225,7 @@ ${indentation} output = ${topTarget}.`;
1176
1225
  return issue_1.Issue.atToken(lowFile, node.getFirstToken(), "Outline LOOP input", this.getMetadata().key, this.conf.severity, fix);
1177
1226
  }
1178
1227
  outlineLoopTarget(node, lowFile, _highSyntax) {
1179
- var _a, _b, _c, _d, _e;
1228
+ var _a, _b, _c, _d, _e, _f, _g;
1180
1229
  // also allows outlining of voided types
1181
1230
  if (!(node.get() instanceof Statements.Loop)) {
1182
1231
  return undefined;
@@ -1190,18 +1239,18 @@ ${indentation} output = ${topTarget}.`;
1190
1239
  return undefined;
1191
1240
  }
1192
1241
  const indentation = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
1193
- const dataTarget = (_b = node.findDirectExpression(Expressions.Target)) === null || _b === void 0 ? void 0 : _b.findDirectExpression(Expressions.InlineData);
1242
+ const dataTarget = (_c = (_b = node.findDirectExpression(Expressions.LoopTarget)) === null || _b === void 0 ? void 0 : _b.findDirectExpression(Expressions.Target)) === null || _c === void 0 ? void 0 : _c.findDirectExpression(Expressions.InlineData);
1194
1243
  if (dataTarget) {
1195
- const targetName = ((_c = dataTarget.findDirectExpression(Expressions.TargetField)) === null || _c === void 0 ? void 0 : _c.concatTokens()) || "DOWNPORT_ERROR";
1244
+ const targetName = ((_d = dataTarget.findDirectExpression(Expressions.TargetField)) === null || _d === void 0 ? void 0 : _d.concatTokens()) || "DOWNPORT_ERROR";
1196
1245
  const code = `DATA ${targetName} LIKE LINE OF ${sourceName}.\n${indentation}`;
1197
1246
  const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), code);
1198
1247
  const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, dataTarget.getFirstToken().getStart(), dataTarget.getLastToken().getEnd(), targetName);
1199
1248
  const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
1200
1249
  return issue_1.Issue.atToken(lowFile, node.getFirstToken(), "Outline LOOP data target", this.getMetadata().key, this.conf.severity, fix);
1201
1250
  }
1202
- const fsTarget = (_d = node.findDirectExpression(Expressions.FSTarget)) === null || _d === void 0 ? void 0 : _d.findDirectExpression(Expressions.InlineFS);
1251
+ const fsTarget = (_f = (_e = node.findDirectExpression(Expressions.LoopTarget)) === null || _e === void 0 ? void 0 : _e.findDirectExpression(Expressions.FSTarget)) === null || _f === void 0 ? void 0 : _f.findDirectExpression(Expressions.InlineFS);
1203
1252
  if (fsTarget) {
1204
- const targetName = ((_e = fsTarget.findDirectExpression(Expressions.TargetFieldSymbol)) === null || _e === void 0 ? void 0 : _e.concatTokens()) || "DOWNPORT_ERROR";
1253
+ const targetName = ((_g = fsTarget.findDirectExpression(Expressions.TargetFieldSymbol)) === null || _g === void 0 ? void 0 : _g.concatTokens()) || "DOWNPORT_ERROR";
1205
1254
  const code = `FIELD-SYMBOLS ${targetName} LIKE LINE OF ${sourceName}.\n${indentation}`;
1206
1255
  const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), code);
1207
1256
  const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, fsTarget.getFirstToken().getStart(), fsTarget.getLastToken().getEnd(), targetName);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.91.26",
3
+ "version": "2.91.29",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -45,10 +45,10 @@
45
45
  },
46
46
  "homepage": "https://abaplint.org",
47
47
  "devDependencies": {
48
- "@microsoft/api-extractor": "^7.29.0",
49
- "@types/chai": "^4.3.1",
48
+ "@microsoft/api-extractor": "^7.29.2",
49
+ "@types/chai": "^4.3.3",
50
50
  "@types/mocha": "^9.1.1",
51
- "@types/node": "^18.6.4",
51
+ "@types/node": "^18.7.2",
52
52
  "chai": "^4.3.6",
53
53
  "eslint": "^8.21.0",
54
54
  "mocha": "^10.0.0",