@abaplint/core 2.91.10 → 2.91.13

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.
@@ -5,6 +5,7 @@ const combi_1 = require("../combi");
5
5
  const _1 = require(".");
6
6
  const field_chain_1 = require("./field_chain");
7
7
  const type_table_key_1 = require("./type_table_key");
8
+ const version_1 = require("../../../version");
8
9
  class TypeTable extends combi_1.Expression {
9
10
  getRunnable() {
10
11
  const header = "WITH HEADER LINE";
@@ -15,9 +16,10 @@ class TypeTable extends combi_1.Expression {
15
16
  const rangeLike = (0, combi_1.seq)("RANGE OF", _1.SimpleFieldChain, (0, combi_1.opt)(header), (0, combi_1.opt)(initial));
16
17
  const typetable = (0, combi_1.seq)(normal1, (0, combi_1.alt)((0, combi_1.opt)((0, combi_1.per)(header, initial, (0, combi_1.plusPrio)(type_table_key_1.TypeTableKey))), (0, combi_1.seq)((0, combi_1.plus)(type_table_key_1.TypeTableKey), (0, combi_1.optPrio)(initial))));
17
18
  const occurs = (0, combi_1.seq)("OCCURS", _1.Integer);
19
+ const derived = (0, combi_1.ver)(version_1.Version.v754, (0, combi_1.seq)("TABLE FOR", (0, combi_1.altPrio)("CREATE", "FAILED", "LOCK", "ACTION IMPORT", "UPDATE", "READ RESULT", "ACTION RESULT"), _1.TypeName));
18
20
  const oldType = (0, combi_1.seq)((0, combi_1.opt)("REF TO"), _1.TypeName, (0, combi_1.alt)((0, combi_1.seq)(occurs, (0, combi_1.opt)(header)), header));
19
21
  const oldLike = (0, combi_1.seq)((0, combi_1.opt)("REF TO"), field_chain_1.FieldChain, (0, combi_1.alt)((0, combi_1.seq)(occurs, (0, combi_1.opt)(header)), header));
20
- const ret = (0, combi_1.altPrio)((0, combi_1.seq)(occurs, (0, combi_1.opt)(header)), (0, combi_1.seq)("LIKE", (0, combi_1.alt)(oldLike, likeType, rangeLike)), (0, combi_1.seq)("TYPE", (0, combi_1.alt)(oldType, typetable, rangeType)));
22
+ const ret = (0, combi_1.altPrio)((0, combi_1.seq)(occurs, (0, combi_1.opt)(header)), (0, combi_1.seq)("LIKE", (0, combi_1.alt)(oldLike, likeType, rangeLike)), (0, combi_1.seq)("TYPE", (0, combi_1.alt)(oldType, typetable, rangeType, derived)));
21
23
  return ret;
22
24
  }
23
25
  }
@@ -105,7 +105,8 @@ class StatementParser {
105
105
  for (let statement of wa.statements) {
106
106
  // dont use CALL METHOD, when executing lazy, it easily gives a Move for the last statment if lazy logic is evaluated
107
107
  if (statement.get() instanceof _statement_1.Unknown
108
- && statement.concatTokens().toUpperCase().startsWith("CALL METHOD ") === false) {
108
+ && statement.concatTokens().toUpperCase().startsWith("CALL METHOD ") === false
109
+ && statement.concatTokens().toUpperCase().startsWith("CALL FUNCTION ") === false) {
109
110
  for (const { first, second } of this.buildSplits(statement.getTokens())) {
110
111
  if (second.length === 1) {
111
112
  continue; // probably punctuation
@@ -10,12 +10,13 @@ class MethodDef {
10
10
  const parameters = (0, combi_1.seq)((0, combi_1.optPrio)((0, combi_1.altPrio)("FINAL", def, expressions_1.Abstract)), (0, combi_1.optPrio)(expressions_1.MethodDefImporting), (0, combi_1.optPrio)(expressions_1.MethodDefExporting), (0, combi_1.optPrio)(expressions_1.MethodDefChanging), (0, combi_1.optPrio)(expressions_1.MethodDefReturning), (0, combi_1.optPrio)((0, combi_1.altPrio)(expressions_1.MethodDefRaising, expressions_1.MethodDefExceptions)));
11
11
  const testing = (0, combi_1.seq)((0, combi_1.optPrio)(expressions_1.Abstract), "FOR TESTING", (0, combi_1.optPrio)((0, combi_1.altPrio)(expressions_1.MethodDefRaising, expressions_1.MethodDefExceptions)));
12
12
  // todo, this is only from version something
13
- const tableFunction = (0, combi_1.seq)("FOR TABLE FUNCTION", (0, combi_1.regex)(/^\w+?$/));
13
+ const tableFunction = (0, combi_1.seq)("TABLE FUNCTION", (0, combi_1.regex)(/^\w+?$/));
14
14
  // todo, this is only from version something
15
- const ddl = "FOR DDL OBJECT OPTIONS CDS SESSION CLIENT REQUIRED";
15
+ const ddl = "DDL OBJECT OPTIONS CDS SESSION CLIENT REQUIRED";
16
+ const behavior = (0, combi_1.altPrio)((0, combi_1.seq)("VALIDATE ON SAVE IMPORTING", expressions_1.MethodParamName, "FOR", expressions_1.TypeName), (0, combi_1.seq)("MODIFY IMPORTING", expressions_1.MethodParamName, "FOR ACTION", expressions_1.TypeName, "RESULT", expressions_1.MethodParamName), (0, combi_1.seq)("FEATURES IMPORTING", expressions_1.MethodParamName, "REQUEST", expressions_1.NamespaceSimpleName, "FOR", expressions_1.NamespaceSimpleName, "RESULT", expressions_1.MethodParamName), (0, combi_1.seq)("DETERMINE ON MODIFY IMPORTING", expressions_1.MethodParamName, "FOR", expressions_1.TypeName));
16
17
  // todo, this is only from version something
17
18
  const amdp = "AMDP OPTIONS CDS SESSION CLIENT current";
18
- const ret = (0, combi_1.seq)((0, combi_1.altPrio)("CLASS-METHODS", "METHODS"), expressions_1.MethodName, (0, combi_1.alt)((0, combi_1.seq)((0, combi_1.optPrio)(expressions_1.Abstract), expressions_1.EventHandler), parameters, testing, tableFunction, ddl, amdp, "NOT AT END OF MODE", (0, combi_1.optPrio)(expressions_1.Redefinition)));
19
+ const ret = (0, combi_1.seq)((0, combi_1.altPrio)("CLASS-METHODS", "METHODS"), expressions_1.MethodName, (0, combi_1.alt)((0, combi_1.seq)((0, combi_1.optPrio)(expressions_1.Abstract), expressions_1.EventHandler), parameters, testing, (0, combi_1.seq)("FOR", (0, combi_1.alt)(tableFunction, ddl, behavior)), amdp, "NOT AT END OF MODE", (0, combi_1.optPrio)(expressions_1.Redefinition)));
19
20
  return ret;
20
21
  }
21
22
  }
@@ -68,7 +68,7 @@ class Registry {
68
68
  }
69
69
  static abaplintVersion() {
70
70
  // magic, see build script "version.sh"
71
- return "2.91.10";
71
+ return "2.91.13";
72
72
  }
73
73
  getDDICReferences() {
74
74
  return this.references;
@@ -19,7 +19,9 @@ class CDSLegacyView {
19
19
  title: "CDS Legacy View",
20
20
  shortDescription: `Identify CDS Legacy Views`,
21
21
  // eslint-disable-next-line max-len
22
- extendedInformation: `https://blogs.sap.com/2021/10/16/a-new-generation-of-cds-views-how-to-migrate-your-cds-views-to-cds-view-entities/
22
+ extendedInformation: `Use DEFINE VIEW ENTITY instead of DEFINE VIEW
23
+
24
+ https://blogs.sap.com/2021/10/16/a-new-generation-of-cds-views-how-to-migrate-your-cds-views-to-cds-view-entities/
23
25
 
24
26
  v755 and up`,
25
27
  tags: [_irule_1.RuleTag.SingleFile],
@@ -188,7 +188,7 @@ Only one transformation is applied to a statement at a time, so multiple steps m
188
188
  if (found) {
189
189
  return found;
190
190
  }
191
- found = this.stringTemplateAlpha(high, lowFile);
191
+ found = this.stringTemplateAlpha(high, lowFile, highSyntax);
192
192
  if (found) {
193
193
  return found;
194
194
  }
@@ -200,6 +200,18 @@ Only one transformation is applied to a statement at a time, so multiple steps m
200
200
  if (found) {
201
201
  return found;
202
202
  }
203
+ found = this.downportRefSimple(high, lowFile);
204
+ if (found) {
205
+ return found;
206
+ }
207
+ found = this.downportRef(high, lowFile, highSyntax);
208
+ if (found) {
209
+ return found;
210
+ }
211
+ found = this.callFunctionParameterSimple(high, lowFile, highSyntax);
212
+ if (found) {
213
+ return found;
214
+ }
203
215
  found = this.moveWithTableTarget(low, high, lowFile, highSyntax);
204
216
  if (found) {
205
217
  return found;
@@ -272,6 +284,10 @@ Only one transformation is applied to a statement at a time, so multiple steps m
272
284
  if (found) {
273
285
  return found;
274
286
  }
287
+ found = this.getReference(high, lowFile, highSyntax);
288
+ if (found) {
289
+ return found;
290
+ }
275
291
  found = this.replaceContains(high, lowFile, highSyntax);
276
292
  if (found) {
277
293
  return found;
@@ -779,6 +795,71 @@ ${indentation}RAISE EXCEPTION ${uniqueName2}.`;
779
795
  }
780
796
  return undefined;
781
797
  }
798
+ callFunctionParameterSimple(high, lowFile, highSyntax) {
799
+ if (!(high.get() instanceof Statements.CallFunction)) {
800
+ return undefined;
801
+ }
802
+ let found = undefined;
803
+ for (const p of high.findAllExpressions(Expressions.FunctionExportingParameter)) {
804
+ found = p.findDirectExpression(Expressions.Source);
805
+ if (found && (found.findDirectExpression(Expressions.FieldChain)
806
+ || found.findDirectExpression(Expressions.Constant)
807
+ || found.findDirectExpression(Expressions.TextElement))) {
808
+ // its actually simple, ok
809
+ found = undefined;
810
+ }
811
+ else if (found !== undefined) {
812
+ break;
813
+ }
814
+ }
815
+ if (found === undefined) {
816
+ return undefined;
817
+ }
818
+ const uniqueName = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
819
+ const code = `DATA(${uniqueName}) = ${found.concatTokens()}.\n`;
820
+ const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getFirstToken().getStart(), code);
821
+ const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, found.getFirstToken().getStart(), found.getLastToken().getEnd(), uniqueName);
822
+ const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
823
+ return issue_1.Issue.atToken(lowFile, high.getFirstToken(), "Downport, call function parameter", this.getMetadata().key, this.conf.severity, fix);
824
+ }
825
+ downportRefSimple(high, lowFile) {
826
+ var _a;
827
+ if (!(high.get() instanceof Statements.Move)
828
+ || high.getChildren().length !== 4
829
+ || high.getChildren()[2].getFirstToken().getStr().toUpperCase() !== "REF") {
830
+ return undefined;
831
+ }
832
+ const target = high.findDirectExpression(Expressions.Target);
833
+ if (target === undefined) {
834
+ return undefined;
835
+ }
836
+ const sourceRef = (_a = high.findFirstExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.findDirectExpression(Expressions.Source);
837
+ if (sourceRef === undefined || sourceRef.getChildren().length !== 1) {
838
+ return;
839
+ }
840
+ const code = `GET REFERENCE OF ${sourceRef.concatTokens()} INTO ${target.concatTokens()}`;
841
+ const start = high.getFirstToken().getStart();
842
+ const end = high.getLastToken().getStart();
843
+ const fix = edit_helper_1.EditHelper.replaceRange(lowFile, start, end, code);
844
+ return issue_1.Issue.atToken(lowFile, high.getFirstToken(), "Downport, simple REF move", this.getMetadata().key, this.conf.severity, fix);
845
+ }
846
+ downportRef(high, lowFile, highSyntax) {
847
+ let found = undefined;
848
+ for (const s of high.findAllExpressionsRecursive(Expressions.Source)) {
849
+ if (s.getFirstToken().getStr().toUpperCase() === "REF") {
850
+ found = s;
851
+ }
852
+ }
853
+ if (found === undefined) {
854
+ return undefined;
855
+ }
856
+ const uniqueName = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
857
+ const code = `DATA(${uniqueName}) = ${found.concatTokens()}.\n`;
858
+ const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getFirstToken().getStart(), code);
859
+ const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, found.getFirstToken().getStart(), found.getLastToken().getEnd(), uniqueName);
860
+ const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
861
+ return issue_1.Issue.atToken(lowFile, high.getFirstToken(), "Downport, REF", this.getMetadata().key, this.conf.severity, fix);
862
+ }
782
863
  moveWithSimpleValue(high, lowFile) {
783
864
  if (!(high.get() instanceof Statements.Move)
784
865
  || high.getChildren().length !== 4) {
@@ -927,7 +1008,7 @@ ${indentation}${uniqueName}`;
927
1008
  return issue_1.Issue.atToken(lowFile, high.getFirstToken(), "Expand operator", this.getMetadata().key, this.conf.severity, fix);
928
1009
  }
929
1010
  // must be very simple string templates, like "|{ ls_line-no ALPHA = IN }|"
930
- stringTemplateAlpha(node, lowFile) {
1011
+ stringTemplateAlpha(node, lowFile, highSyntax) {
931
1012
  var _a, _b, _c;
932
1013
  if (!(node.get() instanceof Statements.Move)) {
933
1014
  return undefined;
@@ -936,8 +1017,13 @@ ${indentation}${uniqueName}`;
936
1017
  if (topSource === undefined || topSource.getChildren().length !== 1) {
937
1018
  return undefined;
938
1019
  }
939
- const child = topSource.getFirstChild();
1020
+ let top = true;
1021
+ let child = topSource.getFirstChild();
940
1022
  if (!(child.get() instanceof Expressions.StringTemplate)) {
1023
+ child = child.findFirstExpression(Expressions.StringTemplate);
1024
+ top = false;
1025
+ }
1026
+ if (child === undefined || !(child.get() instanceof Expressions.StringTemplate)) {
941
1027
  return undefined;
942
1028
  }
943
1029
  const templateTokens = child.getChildren();
@@ -962,13 +1048,28 @@ ${indentation}${uniqueName}`;
962
1048
  const indentation = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
963
1049
  const source = (_b = templateSource === null || templateSource === void 0 ? void 0 : templateSource.findDirectExpression(Expressions.Source)) === null || _b === void 0 ? void 0 : _b.concatTokens();
964
1050
  const topTarget = (_c = node.findDirectExpression(Expressions.Target)) === null || _c === void 0 ? void 0 : _c.concatTokens();
965
- const code = `CALL FUNCTION '${functionName}'
1051
+ const uniqueName = this.uniqueName(node.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
1052
+ if (top === false) {
1053
+ const code = `DATA ${uniqueName} TYPE string.
1054
+ ${indentation}CALL FUNCTION '${functionName}'
1055
+ ${indentation} EXPORTING
1056
+ ${indentation} input = ${source}
1057
+ ${indentation} IMPORTING
1058
+ ${indentation} output = ${uniqueName}.\n`;
1059
+ const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), code);
1060
+ const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, child.getFirstToken().getStart(), child.getLastToken().getEnd(), uniqueName);
1061
+ const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
1062
+ return issue_1.Issue.atToken(lowFile, node.getFirstToken(), "Downport ALPHA", this.getMetadata().key, this.conf.severity, fix);
1063
+ }
1064
+ else {
1065
+ const code = `CALL FUNCTION '${functionName}'
966
1066
  ${indentation} EXPORTING
967
1067
  ${indentation} input = ${source}
968
1068
  ${indentation} IMPORTING
969
1069
  ${indentation} output = ${topTarget}.`;
970
- const fix = edit_helper_1.EditHelper.replaceRange(lowFile, node.getFirstToken().getStart(), node.getLastToken().getEnd(), code);
971
- return issue_1.Issue.atToken(lowFile, node.getFirstToken(), "Downport ALPHA", this.getMetadata().key, this.conf.severity, fix);
1070
+ const fix = edit_helper_1.EditHelper.replaceRange(lowFile, node.getFirstToken().getStart(), node.getLastToken().getEnd(), code);
1071
+ return issue_1.Issue.atToken(lowFile, node.getFirstToken(), "Downport ALPHA", this.getMetadata().key, this.conf.severity, fix);
1072
+ }
972
1073
  }
973
1074
  outlineLoopInput(node, lowFile, highSyntax) {
974
1075
  if (!(node.get() instanceof Statements.Loop)) {
@@ -1643,6 +1744,26 @@ ${indentation} output = ${topTarget}.`;
1643
1744
  }
1644
1745
  return undefined;
1645
1746
  }
1747
+ getReference(node, lowFile, _highSyntax) {
1748
+ var _a, _b, _c;
1749
+ if (!(node.get() instanceof Statements.GetReference)) {
1750
+ return undefined;
1751
+ }
1752
+ const inline = (_a = node.findDirectExpression(Expressions.Target)) === null || _a === void 0 ? void 0 : _a.findDirectExpression(Expressions.InlineData);
1753
+ if (inline === undefined) {
1754
+ return undefined;
1755
+ }
1756
+ const targetName = (_b = inline.findDirectExpression(Expressions.TargetField)) === null || _b === void 0 ? void 0 : _b.concatTokens();
1757
+ const sourceName = (_c = node.findDirectExpression(Expressions.Source)) === null || _c === void 0 ? void 0 : _c.concatTokens();
1758
+ if (targetName === undefined || sourceName === undefined) {
1759
+ return undefined;
1760
+ }
1761
+ const code = `DATA ${targetName} LIKE REF TO ${sourceName}.\n`;
1762
+ const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), code);
1763
+ const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, inline.getFirstToken().getStart(), inline.getLastToken().getEnd(), targetName);
1764
+ const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
1765
+ return issue_1.Issue.atToken(lowFile, inline.getFirstToken(), "Downport, outline DATA ref", this.getMetadata().key, this.conf.severity, fix);
1766
+ }
1646
1767
  replaceContains(node, lowFile, highSyntax) {
1647
1768
  const spag = highSyntax.spaghetti.lookupPosition(node.getFirstToken().getStart(), lowFile.getFilename());
1648
1769
  // only downport if its an single method call condition
@@ -1734,8 +1855,10 @@ ${indentation} output = ${topTarget}.`;
1734
1855
  const target = node.findDirectExpression(Expressions.Target);
1735
1856
  const found = source === null || source === void 0 ? void 0 : source.findFirstExpression(Expressions.NewObject);
1736
1857
  // must be at top level of the source for quickfix to work(todo: handle more scenarios)
1737
- // todo, assumption: the target is not an inline definition
1738
- if (target && found && source.concatTokens() === found.concatTokens()) {
1858
+ if (target
1859
+ && found
1860
+ && source.concatTokens() === found.concatTokens()
1861
+ && target.findDirectExpression(Expressions.InlineData) === undefined) {
1739
1862
  const abap = this.newParameters(found, target.concatTokens(), highSyntax, lowFile);
1740
1863
  if (abap !== undefined) {
1741
1864
  fix = edit_helper_1.EditHelper.replaceRange(lowFile, node.getFirstToken().getStart(), node.getLastToken().getEnd(), abap);
@@ -65,8 +65,7 @@ class XMLConsistency {
65
65
  else if (name !== obj.getName().toUpperCase()) {
66
66
  issues.push(issue_1.Issue.atRow(file, 1, "Name in XML does not match object", this.getMetadata().key, this.conf.severity));
67
67
  }
68
- else if (obj.getDefinition() === undefined
69
- || ((_b = obj.getDefinition()) === null || _b === void 0 ? void 0 : _b.getName().toUpperCase()) !== name.toUpperCase()) {
68
+ else if (obj.getDefinition() !== undefined && ((_b = obj.getDefinition()) === null || _b === void 0 ? void 0 : _b.getName().toUpperCase()) !== name.toUpperCase()) {
70
69
  issues.push(issue_1.Issue.atRow(file, 1, "Interface matching XML name not found in ABAP file", this.getMetadata().key, this.conf.severity));
71
70
  }
72
71
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.91.10",
3
+ "version": "2.91.13",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "homepage": "https://abaplint.org",
47
47
  "devDependencies": {
48
- "@microsoft/api-extractor": "^7.28.4",
48
+ "@microsoft/api-extractor": "^7.28.6",
49
49
  "@types/chai": "^4.3.1",
50
50
  "@types/mocha": "^9.1.1",
51
51
  "@types/node": "^18.0.6",