@abaplint/core 2.119.44 → 2.119.46

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.
Files changed (77) hide show
  1. package/build/abaplint.d.ts +360 -5
  2. package/build/src/abap/2_statements/expressions/_select_core.js +9 -7
  3. package/build/src/abap/2_statements/expressions/assign_source.js +9 -3
  4. package/build/src/abap/2_statements/expressions/database_table.js +8 -0
  5. package/build/src/abap/2_statements/expressions/select.js +1 -1
  6. package/build/src/abap/2_statements/expressions/select_cte.js +2 -1
  7. package/build/src/abap/2_statements/expressions/sql_client.js +1 -1
  8. package/build/src/abap/2_statements/expressions/sql_from.js +9 -8
  9. package/build/src/abap/2_statements/expressions/sql_from_source.js +2 -1
  10. package/build/src/abap/2_statements/statements/add.js +2 -1
  11. package/build/src/abap/2_statements/statements/assert.js +2 -1
  12. package/build/src/abap/2_statements/statements/assign.js +8 -3
  13. package/build/src/abap/2_statements/statements/at.js +2 -1
  14. package/build/src/abap/2_statements/statements/authority_check.js +2 -1
  15. package/build/src/abap/2_statements/statements/call.js +2 -1
  16. package/build/src/abap/2_statements/statements/call_function.js +1 -1
  17. package/build/src/abap/2_statements/statements/call_transformation.js +2 -1
  18. package/build/src/abap/2_statements/statements/class_deferred.js +2 -1
  19. package/build/src/abap/2_statements/statements/class_definition_load.js +2 -1
  20. package/build/src/abap/2_statements/statements/commit.js +2 -1
  21. package/build/src/abap/2_statements/statements/commit_entities.js +1 -1
  22. package/build/src/abap/2_statements/statements/create_data.js +1 -1
  23. package/build/src/abap/2_statements/statements/create_object.js +1 -1
  24. package/build/src/abap/2_statements/statements/delete_database.js +2 -1
  25. package/build/src/abap/2_statements/statements/delete_internal.js +3 -1
  26. package/build/src/abap/2_statements/statements/divide.js +2 -1
  27. package/build/src/abap/2_statements/statements/endform.js +2 -2
  28. package/build/src/abap/2_statements/statements/endfunction.js +2 -1
  29. package/build/src/abap/2_statements/statements/endwith.js +1 -1
  30. package/build/src/abap/2_statements/statements/export.js +4 -3
  31. package/build/src/abap/2_statements/statements/form.js +2 -1
  32. package/build/src/abap/2_statements/statements/free.js +2 -1
  33. package/build/src/abap/2_statements/statements/function_module.js +2 -1
  34. package/build/src/abap/2_statements/statements/function_pool.js +2 -1
  35. package/build/src/abap/2_statements/statements/get_reference.js +2 -1
  36. package/build/src/abap/2_statements/statements/get_time.js +2 -1
  37. package/build/src/abap/2_statements/statements/import.js +5 -4
  38. package/build/src/abap/2_statements/statements/insert_database.js +2 -1
  39. package/build/src/abap/2_statements/statements/interface_deferred.js +2 -1
  40. package/build/src/abap/2_statements/statements/interface_load.js +2 -1
  41. package/build/src/abap/2_statements/statements/loop.js +1 -1
  42. package/build/src/abap/2_statements/statements/loop_extract.js +2 -1
  43. package/build/src/abap/2_statements/statements/message.js +2 -1
  44. package/build/src/abap/2_statements/statements/method_def.js +8 -4
  45. package/build/src/abap/2_statements/statements/method_implementation.js +3 -1
  46. package/build/src/abap/2_statements/statements/modify_database.js +2 -1
  47. package/build/src/abap/2_statements/statements/multiply.js +2 -1
  48. package/build/src/abap/2_statements/statements/perform.js +1 -1
  49. package/build/src/abap/2_statements/statements/raise.js +2 -1
  50. package/build/src/abap/2_statements/statements/raise_entity_event.js +2 -1
  51. package/build/src/abap/2_statements/statements/raise_event.js +2 -1
  52. package/build/src/abap/2_statements/statements/read_table.js +3 -2
  53. package/build/src/abap/2_statements/statements/rollback.js +2 -1
  54. package/build/src/abap/2_statements/statements/rollback_entities.js +1 -1
  55. package/build/src/abap/2_statements/statements/set_handler.js +2 -1
  56. package/build/src/abap/2_statements/statements/set_locks.js +1 -1
  57. package/build/src/abap/2_statements/statements/static.js +3 -2
  58. package/build/src/abap/2_statements/statements/subtract.js +2 -1
  59. package/build/src/abap/2_statements/statements/test_injection.js +2 -1
  60. package/build/src/abap/2_statements/statements/test_seam.js +1 -1
  61. package/build/src/abap/2_statements/statements/update_database.js +4 -3
  62. package/build/src/abap/2_statements/statements/wait.js +4 -3
  63. package/build/src/abap/2_statements/statements/with.js +1 -1
  64. package/build/src/abap/5_syntax/_current_scope.js +1 -2
  65. package/build/src/abap/5_syntax/expressions/select.js +15 -3
  66. package/build/src/abap/5_syntax/statements/delete_internal.js +4 -3
  67. package/build/src/abap/5_syntax/statements/loop.js +8 -0
  68. package/build/src/abap/5_syntax/statements/modify_internal.js +7 -0
  69. package/build/src/abap/5_syntax/statements/select_loop.js +1 -1
  70. package/build/src/cds/cds_parser.js +8 -8
  71. package/build/src/config.js +24 -15
  72. package/build/src/ddl/ddl_parser.js +2 -2
  73. package/build/src/registry.js +1 -1
  74. package/build/src/rules/index.js +1 -0
  75. package/build/src/rules/sy_read_restriction.js +152 -0
  76. package/build/src/version.js +2 -65
  77. package/package.json +1 -1
@@ -3,9 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Rollback = void 0;
4
4
  const combi_1 = require("../combi");
5
5
  const expressions_1 = require("../expressions");
6
+ const version_1 = require("../../../version");
6
7
  class Rollback {
7
8
  getMatcher() {
8
- return (0, combi_1.seq)("ROLLBACK", (0, combi_1.altPrio)("WORK", expressions_1.DatabaseConnection));
9
+ return (0, combi_1.verNotLang)(version_1.LanguageVersion.KeyUser, (0, combi_1.seq)("ROLLBACK", (0, combi_1.altPrio)("WORK", expressions_1.DatabaseConnection)));
9
10
  }
10
11
  }
11
12
  exports.Rollback = Rollback;
@@ -6,7 +6,7 @@ const version_1 = require("../../../version");
6
6
  class RollbackEntities {
7
7
  getMatcher() {
8
8
  const s = "ROLLBACK ENTITIES";
9
- return (0, combi_1.ver)(version_1.Release.v754, s);
9
+ return (0, combi_1.verNotLang)(version_1.LanguageVersion.KeyUser, (0, combi_1.ver)(version_1.Release.v754, s));
10
10
  }
11
11
  }
12
12
  exports.RollbackEntities = RollbackEntities;
@@ -3,12 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SetHandler = void 0;
4
4
  const combi_1 = require("../combi");
5
5
  const expressions_1 = require("../expressions");
6
+ const version_1 = require("../../../version");
6
7
  class SetHandler {
7
8
  getMatcher() {
8
9
  const activation = (0, combi_1.seq)("ACTIVATION", expressions_1.Source);
9
10
  const fo = (0, combi_1.seq)("FOR", (0, combi_1.altPrio)("ALL INSTANCES", expressions_1.Source));
10
11
  const ret = (0, combi_1.seq)("SET HANDLER", (0, combi_1.plus)(expressions_1.MethodSource), (0, combi_1.optPrio)(fo), (0, combi_1.optPrio)(activation));
11
- return ret;
12
+ return (0, combi_1.verNotLang)(version_1.LanguageVersion.KeyUser, ret);
12
13
  }
13
14
  }
14
15
  exports.SetHandler = SetHandler;
@@ -7,7 +7,7 @@ const version_1 = require("../../../version");
7
7
  class SetLocks {
8
8
  getMatcher() {
9
9
  const s = (0, combi_1.seq)("SET LOCKS OF", expressions_1.SimpleName, "ENTITY", expressions_1.SimpleName, "FROM", expressions_1.Source, "FAILED", expressions_1.Target, "REPORTED", expressions_1.Target);
10
- return (0, combi_1.ver)(version_1.Release.v754, s);
10
+ return (0, combi_1.verNotLang)(version_1.LanguageVersion.KeyUser, (0, combi_1.ver)(version_1.Release.v754, s));
11
11
  }
12
12
  }
13
13
  exports.SetLocks = SetLocks;
@@ -36,12 +36,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.Static = void 0;
37
37
  const combi_1 = require("../combi");
38
38
  const Expressions = __importStar(require("../expressions"));
39
+ const version_1 = require("../../../version");
39
40
  class Static {
40
41
  getMatcher() {
41
42
  const p = (0, combi_1.opt)((0, combi_1.per)(Expressions.Type, Expressions.Value, Expressions.Length, Expressions.Decimals));
42
43
  const type = (0, combi_1.seq)((0, combi_1.opt)(Expressions.ConstantFieldLength), p);
43
- const ret = (0, combi_1.seq)((0, combi_1.alt)("STATIC", "STATICS"), Expressions.DefinitionName, (0, combi_1.optPrio)(Expressions.ConstantFieldLength), (0, combi_1.alt)(type, Expressions.TypeTable));
44
- return ret;
44
+ const body = (0, combi_1.seq)(Expressions.DefinitionName, (0, combi_1.optPrio)(Expressions.ConstantFieldLength), (0, combi_1.alt)(type, Expressions.TypeTable));
45
+ return (0, combi_1.altPrio)((0, combi_1.seq)("STATIC", body), (0, combi_1.verNotLang)(version_1.LanguageVersion.KeyUser, (0, combi_1.seq)("STATICS", body)));
45
46
  }
46
47
  }
47
48
  exports.Static = Static;
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Subtract = void 0;
4
+ const version_1 = require("../../../version");
4
5
  const combi_1 = require("../combi");
5
6
  const expressions_1 = require("../expressions");
6
7
  class Subtract {
7
8
  getMatcher() {
8
9
  const ret = (0, combi_1.seq)("SUBTRACT", expressions_1.Source, "FROM", expressions_1.Target);
9
- return ret;
10
+ return (0, combi_1.verNotLang)(version_1.LanguageVersion.KeyUser, ret);
10
11
  }
11
12
  }
12
13
  exports.Subtract = Subtract;
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TestInjection = void 0;
4
+ const version_1 = require("../../../version");
4
5
  const combi_1 = require("../combi");
5
6
  const expressions_1 = require("../expressions");
6
7
  class TestInjection {
7
8
  getMatcher() {
8
- return (0, combi_1.seq)("TEST-INJECTION", expressions_1.TestSeamName);
9
+ return (0, combi_1.verNotLang)(version_1.LanguageVersion.KeyUser, (0, combi_1.seq)("TEST-INJECTION", expressions_1.TestSeamName));
9
10
  }
10
11
  }
11
12
  exports.TestInjection = TestInjection;
@@ -6,7 +6,7 @@ const expressions_1 = require("../expressions");
6
6
  const version_1 = require("../../../version");
7
7
  class TestSeam {
8
8
  getMatcher() {
9
- return (0, combi_1.ver)(version_1.Release.v750, (0, combi_1.seq)("TEST-SEAM", expressions_1.TestSeamName), { also: combi_1.AlsoIn.OpenABAP });
9
+ return (0, combi_1.verNotLang)(version_1.LanguageVersion.KeyUser, (0, combi_1.ver)(version_1.Release.v750, (0, combi_1.seq)("TEST-SEAM", expressions_1.TestSeamName), { also: combi_1.AlsoIn.OpenABAP }));
10
10
  }
11
11
  }
12
12
  exports.TestSeam = TestSeam;
@@ -1,17 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UpdateDatabase = void 0;
4
+ const version_1 = require("../../../version");
4
5
  const combi_1 = require("../combi");
5
6
  const expressions_1 = require("../expressions");
6
- const version_1 = require("../../../version");
7
+ const version_2 = require("../../../version");
7
8
  class UpdateDatabase {
8
9
  getMatcher() {
9
10
  const parameters = (0, combi_1.seq)(expressions_1.SQLFieldAndValue, (0, combi_1.star)((0, combi_1.seq)((0, combi_1.opt)(","), expressions_1.SQLFieldAndValue)));
10
11
  const set = (0, combi_1.seq)("SET", (0, combi_1.alt)(parameters, expressions_1.Dynamic), (0, combi_1.opt)((0, combi_1.seq)("WHERE", expressions_1.SQLCond)));
11
12
  const indicators = (0, combi_1.seq)("INDICATORS SET STRUCTURE", expressions_1.ComponentName);
12
- const fromTable = (0, combi_1.seq)("FROM", (0, combi_1.opt)("TABLE"), expressions_1.SQLSource, (0, combi_1.opt)((0, combi_1.ver)(version_1.Release.v755, indicators)));
13
+ const fromTable = (0, combi_1.seq)("FROM", (0, combi_1.opt)("TABLE"), expressions_1.SQLSource, (0, combi_1.opt)((0, combi_1.ver)(version_2.Release.v755, indicators)));
13
14
  const ret = (0, combi_1.seq)("UPDATE", expressions_1.DatabaseTable, (0, combi_1.opt)(expressions_1.SQLClient), (0, combi_1.opt)(expressions_1.DatabaseConnection), (0, combi_1.opt)((0, combi_1.alt)(fromTable, set)));
14
- return ret;
15
+ return (0, combi_1.verNotLang)(version_1.LanguageVersion.KeyUser, ret);
15
16
  }
16
17
  }
17
18
  exports.UpdateDatabase = UpdateDatabase;
@@ -1,19 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Wait = void 0;
4
- const combi_1 = require("../combi");
5
4
  const version_1 = require("../../../version");
5
+ const combi_1 = require("../combi");
6
+ const version_2 = require("../../../version");
6
7
  const expressions_1 = require("../expressions");
7
8
  class Wait {
8
9
  getMatcher() {
9
10
  const up = (0, combi_1.seq)("UP TO", expressions_1.Source, "SECONDS");
10
11
  const channels = "MESSAGING CHANNELS";
11
- const push = (0, combi_1.ver)(version_1.Release.v750, "PUSH CHANNELS", { also: combi_1.AlsoIn.OpenABAP });
12
+ const push = (0, combi_1.ver)(version_2.Release.v750, "PUSH CHANNELS", { also: combi_1.AlsoIn.OpenABAP });
12
13
  const tasks = "ASYNCHRONOUS TASKS";
13
14
  const type = (0, combi_1.seq)("FOR", (0, combi_1.per)(channels, push, tasks));
14
15
  const until = (0, combi_1.seq)((0, combi_1.opt)(type), "UNTIL", expressions_1.Cond, (0, combi_1.opt)(up));
15
16
  const ret = (0, combi_1.seq)("WAIT", (0, combi_1.alt)(until, up));
16
- return ret;
17
+ return (0, combi_1.verNotLang)(version_1.LanguageVersion.KeyUser, ret);
17
18
  }
18
19
  }
19
20
  exports.Wait = Wait;
@@ -9,7 +9,7 @@ class With {
9
9
  getMatcher() {
10
10
  const exposing = (0, combi_1.optPrio)((0, combi_1.seq)("WITH", (0, combi_1.altPrio)(new expressions_1.SQLCTEHierarchy(), expressions_1.SQLCTEAssociations)));
11
11
  const cte = (0, combi_1.seq)(expressions_1.WithName, "AS", (0, combi_1.tok)(tokens_1.WParenLeftW), expressions_1.SelectCTE, (0, combi_1.tok)(tokens_1.WParenRightW), exposing);
12
- return (0, combi_1.ver)(version_1.Release.v751, (0, combi_1.seq)("WITH", cte, (0, combi_1.star)((0, combi_1.seq)(",", cte)), expressions_1.Select));
12
+ return (0, combi_1.verNotLang)(version_1.LanguageVersion.KeyUser, (0, combi_1.ver)(version_1.Release.v751, (0, combi_1.seq)("WITH", cte, (0, combi_1.star)((0, combi_1.seq)(",", cte)), expressions_1.Select)));
13
13
  }
14
14
  }
15
15
  exports.With = With;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CurrentScope = void 0;
4
- const version_1 = require("../../version");
5
4
  const _builtin_1 = require("./_builtin");
6
5
  const ddic_1 = require("../../ddic");
7
6
  const position_1 = require("../../position");
@@ -37,7 +36,7 @@ class CurrentScope {
37
36
  }
38
37
  ///////////////////////////
39
38
  getRelease() {
40
- return (0, version_1.versionToABAPRelease)(this.reg.getConfig().getVersion());
39
+ return this.reg.getConfig().getRelease();
41
40
  }
42
41
  getVersion() {
43
42
  return this.reg.getConfig().getVersion();
@@ -50,7 +50,7 @@ const _syntax_input_1 = require("../_syntax_input");
50
50
  const version_1 = require("../../../version");
51
51
  const isSimple = /^\w+$/;
52
52
  class Select {
53
- static runSyntax(node, input, skipImplicitInto = false) {
53
+ static runSyntax(node, input, skipImplicitInto = false, selectLoop = false) {
54
54
  var _a;
55
55
  const token = node.getFirstToken();
56
56
  let from = node.findDirectExpression(Expressions.SQLFrom);
@@ -109,6 +109,14 @@ class Select {
109
109
  sql_source_1.SQLSource.runSyntax(s, input);
110
110
  }
111
111
  for (const up of node.findDirectExpressions(Expressions.SQLUpTo)) {
112
+ if (intoExpression
113
+ && this.isStrictMode(node, input)
114
+ && (selectLoop === false || input.scope.getLanguageVersion() === version_1.LanguageVersion.Cloud)
115
+ && from.getFirstToken().getStart().isBefore(up.getFirstToken().getStart())
116
+ && up.getFirstToken().getStart().isBefore(intoExpression.getFirstToken().getStart())) {
117
+ const message = `The addition "UP TO n ROWS" must only be placed after the INTO/APPENDING clause.`;
118
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, up.getFirstToken(), message));
119
+ }
112
120
  for (const s of up.findDirectExpressions(Expressions.SQLSource)) {
113
121
  sql_source_1.SQLSource.runSyntax(s, input);
114
122
  }
@@ -134,7 +142,7 @@ class Select {
134
142
  input.issues.push((0, _syntax_input_1.syntaxIssue)(input, orderBy.getFirstToken(), message));
135
143
  }
136
144
  }
137
- if (this.isStrictMode(node)) {
145
+ if (this.isStrictMode(node, input)) {
138
146
  this.strictModeChecks(node, input);
139
147
  }
140
148
  if (input.scope.getType() === _scope_type_1.ScopeType.OpenSQL) {
@@ -142,7 +150,11 @@ class Select {
142
150
  }
143
151
  }
144
152
  // there are multiple rules, but gotta start somewhere
145
- static isStrictMode(node) {
153
+ static isStrictMode(node, input) {
154
+ // strict OpenSQL is always required in the cloud language version
155
+ if (input.scope.getLanguageVersion() === version_1.LanguageVersion.Cloud) {
156
+ return true;
157
+ }
146
158
  const into = node.findDirectExpressionsMulti([Expressions.SQLIntoList, Expressions.SQLIntoStructure, Expressions.SQLIntoTable])[0];
147
159
  const where = node.findDirectExpression(Expressions.SQLCond);
148
160
  // INTO is after WHERE
@@ -54,8 +54,9 @@ class DeleteInternal {
54
54
  const localVariable = input.scope.findVariable(target.concatTokens());
55
55
  if (localVariable === undefined && node.getChildren().length === 5 && node.getChildren()[2].concatTokens().toUpperCase() === "FROM") {
56
56
  // it might be a database table
57
- tabl = (_a = input.scope.getDDIC()) === null || _a === void 0 ? void 0 : _a.lookupTableOrView(target.concatTokens());
58
- if (tabl) {
57
+ const found = (_a = input.scope.getDDIC()) === null || _a === void 0 ? void 0 : _a.lookupTableOrView(target.concatTokens());
58
+ if ((found === null || found === void 0 ? void 0 : found.object) !== undefined) {
59
+ tabl = found;
59
60
  input.scope.getDDICReferences().addUsing(input.scope.getParentObj(), { object: tabl.object });
60
61
  }
61
62
  }
@@ -63,7 +64,7 @@ class DeleteInternal {
63
64
  targetType = target_1.Target.runSyntax(target, input);
64
65
  if (node.findDirectTokenByText("TABLE") === undefined
65
66
  && node.findDirectTokenByText("ADJACENT") === undefined
66
- && node.findDirectTokenByText("FROM")
67
+ && (node.findDirectTokenByText("FROM") || node.findDirectTokenByText("INDEX"))
67
68
  && targetType instanceof basic_1.TableType
68
69
  && targetType.getAccessType() === basic_1.TableAccessType.hashed) {
69
70
  const message = "Implicit or explicit index operation on hashed table is not possible";
@@ -99,6 +99,14 @@ class Loop {
99
99
  }
100
100
  const targetConcat = loopTarget === null || loopTarget === void 0 ? void 0 : loopTarget.concatTokens().toUpperCase();
101
101
  const topType = sourceType; // todo: refactor topType vs sourceType vs rowType
102
+ if (topType instanceof basic_1.TableType
103
+ && topType.getAccessType() === basic_1.TableAccessType.hashed
104
+ && node.findDirectTokenByText("USING") === undefined
105
+ && (node.findDirectTokenByText("FROM") || node.findDirectTokenByText("TO"))) {
106
+ const message = "Implicit or explicit index operation on hashed table is not possible";
107
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
108
+ return;
109
+ }
102
110
  if (sourceType instanceof basic_1.TableType) {
103
111
  rowType = sourceType.getRowType();
104
112
  sourceType = rowType;
@@ -58,6 +58,13 @@ class ModifyInternal {
58
58
  // ok
59
59
  }
60
60
  else if (targetType instanceof basic_1.TableType) {
61
+ if (node.findDirectTokenByText("TABLE") === undefined
62
+ && node.findDirectTokenByText("INDEX")
63
+ && targetType.getAccessType() === basic_1.TableAccessType.hashed) {
64
+ const message = "Implicit or explicit index operation on hashed table is not possible";
65
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
66
+ return;
67
+ }
61
68
  if (node.findDirectTokenByText("TABLE")
62
69
  && node.findDirectTokenByText("INDEX")
63
70
  && targetType.isWithHeader() === false) {
@@ -40,7 +40,7 @@ class SelectLoop {
40
40
  runSyntax(node, input) {
41
41
  const s = node.findDirectExpression(Expressions.Select);
42
42
  if (s) {
43
- select_1.Select.runSyntax(s, input);
43
+ select_1.Select.runSyntax(s, input, false, true);
44
44
  }
45
45
  }
46
46
  }
@@ -48,27 +48,27 @@ class CDSParser {
48
48
  }
49
49
  let tokens = cds_lexer_1.CDSLexer.run(file);
50
50
  tokens = tokens.filter(t => !(t instanceof tokens_1.Comment));
51
- let res = combi_1.Combi.run(new Expressions.CDSDefineView(), tokens, version_1.defaultVersion);
51
+ let res = combi_1.Combi.run(new Expressions.CDSDefineView(), tokens, version_1.defaultRelease);
52
52
  if (res === undefined || !(res[0] instanceof nodes_1.ExpressionNode)) {
53
- res = combi_1.Combi.run(new Expressions.CDSDefineAbstract(), tokens, version_1.defaultVersion);
53
+ res = combi_1.Combi.run(new Expressions.CDSDefineAbstract(), tokens, version_1.defaultRelease);
54
54
  }
55
55
  if (res === undefined || !(res[0] instanceof nodes_1.ExpressionNode)) {
56
- res = combi_1.Combi.run(new Expressions.CDSDefineProjection(), tokens, version_1.defaultVersion);
56
+ res = combi_1.Combi.run(new Expressions.CDSDefineProjection(), tokens, version_1.defaultRelease);
57
57
  }
58
58
  if (res === undefined || !(res[0] instanceof nodes_1.ExpressionNode)) {
59
- res = combi_1.Combi.run(new Expressions.CDSAnnotate(), tokens, version_1.defaultVersion);
59
+ res = combi_1.Combi.run(new Expressions.CDSAnnotate(), tokens, version_1.defaultRelease);
60
60
  }
61
61
  if (res === undefined || !(res[0] instanceof nodes_1.ExpressionNode)) {
62
- res = combi_1.Combi.run(new Expressions.CDSDefineCustom(), tokens, version_1.defaultVersion);
62
+ res = combi_1.Combi.run(new Expressions.CDSDefineCustom(), tokens, version_1.defaultRelease);
63
63
  }
64
64
  if (res === undefined || !(res[0] instanceof nodes_1.ExpressionNode)) {
65
- res = combi_1.Combi.run(new Expressions.CDSDefineTableFunction(), tokens, version_1.defaultVersion);
65
+ res = combi_1.Combi.run(new Expressions.CDSDefineTableFunction(), tokens, version_1.defaultRelease);
66
66
  }
67
67
  if (res === undefined || !(res[0] instanceof nodes_1.ExpressionNode)) {
68
- res = combi_1.Combi.run(new Expressions.CDSExtendView(), tokens, version_1.defaultVersion);
68
+ res = combi_1.Combi.run(new Expressions.CDSExtendView(), tokens, version_1.defaultRelease);
69
69
  }
70
70
  if (res === undefined || !(res[0] instanceof nodes_1.ExpressionNode)) {
71
- res = combi_1.Combi.run(new Expressions.CDSDefineHierarchy(), tokens, version_1.defaultVersion);
71
+ res = combi_1.Combi.run(new Expressions.CDSDefineHierarchy(), tokens, version_1.defaultRelease);
72
72
  }
73
73
  if (res === undefined || !(res[0] instanceof nodes_1.ExpressionNode)) {
74
74
  return undefined;
@@ -47,10 +47,7 @@ class Config {
47
47
  for (const rule of sorted) {
48
48
  rules[rule.getMetadata().key] = rule.getConfig();
49
49
  }
50
- let version = version_1.defaultVersion;
51
- if (ver) {
52
- version = ver;
53
- }
50
+ const version = ver;
54
51
  // defaults: dont skip anything, report everything. The user can decide to skip stuff
55
52
  // its difficult to debug errors not being reported
56
53
  const config = {
@@ -158,42 +155,54 @@ class Config {
158
155
  return this.config.syntax;
159
156
  }
160
157
  getRelease() {
161
- return (0, version_1.versionToABAPRelease)(this.getVersion());
158
+ const v = this.config.syntax.version;
159
+ if (v !== undefined && typeof v !== "string") {
160
+ return version_1.Release[v.release];
161
+ }
162
+ if (this.config.global === undefined || v === undefined) {
163
+ return version_1.defaultRelease;
164
+ }
165
+ return (0, version_1.versionToABAPRelease)(v);
162
166
  }
163
167
  getOpenABAP() {
164
168
  return this.config.syntax.openABAP === true;
165
169
  }
166
170
  getVersion() {
167
- if (this.config.global === undefined || this.config.syntax.version === undefined) {
168
- return version_1.defaultVersion;
171
+ const v = this.config.syntax.version;
172
+ if (this.config.global === undefined || v === undefined || typeof v !== "string") {
173
+ return version_1.Version.v816;
169
174
  }
170
- return this.config.syntax.version;
175
+ return v;
171
176
  }
172
177
  getLanguageVersion() {
173
178
  var _a;
179
+ const v = this.config.syntax.version;
180
+ if (v !== undefined && typeof v !== "string") {
181
+ return v.language;
182
+ }
174
183
  return (_a = this.config.syntax.languageVersion) !== null && _a !== void 0 ? _a : version_1.LanguageVersion.Normal;
175
184
  }
176
185
  checkVersion() {
177
- if (this.config.syntax.version === undefined) {
178
- return; // handled in getVersion
186
+ const version = this.config.syntax.version;
187
+ if (version === undefined || typeof version !== "string") {
188
+ return; // undefined handled in getVersion, object form is already explicit
179
189
  }
180
190
  let match = false;
181
191
  const vers = version_1.Version;
182
192
  for (const v in version_1.Version) {
183
- if (vers[v] === this.config.syntax.version) {
193
+ if (vers[v] === version) {
184
194
  match = true;
185
195
  break;
186
196
  }
187
197
  }
188
198
  if (match === false) {
189
- this.config.syntax.version = version_1.defaultVersion;
199
+ this.config.syntax.version = undefined;
190
200
  return;
191
201
  }
192
- if (this.config.syntax.version === version_1.Version.Cloud) {
193
- this.config.syntax.version = version_1.Version.Newest;
202
+ if (version === version_1.Version.Cloud) {
194
203
  this.config.syntax.languageVersion = version_1.LanguageVersion.Cloud;
195
204
  }
196
- else if (this.config.syntax.version === version_1.Version.OpenABAP) {
205
+ else if (version === version_1.Version.OpenABAP) {
197
206
  this.config.syntax.version = version_1.Version.v702;
198
207
  this.config.syntax.openABAP = true;
199
208
  }
@@ -47,9 +47,9 @@ var DDLKind;
47
47
  class DDLParser {
48
48
  parse(file) {
49
49
  const tokens = ddl_lexer_1.DDLLexer.run(file);
50
- let res = combi_1.Combi.run(new Expressions.DDLStructure(), tokens, version_1.defaultVersion);
50
+ let res = combi_1.Combi.run(new Expressions.DDLStructure(), tokens, version_1.defaultRelease);
51
51
  if (res === undefined) {
52
- res = combi_1.Combi.run(new Expressions.DDLTable(), tokens, version_1.defaultVersion);
52
+ res = combi_1.Combi.run(new Expressions.DDLTable(), tokens, version_1.defaultRelease);
53
53
  }
54
54
  if (res === undefined || !(res[0] instanceof nodes_1.ExpressionNode)) {
55
55
  return undefined;
@@ -74,7 +74,7 @@ class Registry {
74
74
  }
75
75
  static abaplintVersion() {
76
76
  // magic, see build script "version.js"
77
- return "2.119.44";
77
+ return "2.119.46";
78
78
  }
79
79
  getDDICReferences() {
80
80
  return this.ddicReferences;
@@ -172,6 +172,7 @@ __exportStar(require("./strict_sql"), exports);
172
172
  __exportStar(require("./superclass_final"), exports);
173
173
  __exportStar(require("./superfluous_value"), exports);
174
174
  __exportStar(require("./sy_modification"), exports);
175
+ __exportStar(require("./sy_read_restriction"), exports);
175
176
  __exportStar(require("./tabl_enhancement_category"), exports);
176
177
  __exportStar(require("./tables_declared_locally"), exports);
177
178
  __exportStar(require("./try_without_catch"), exports);
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SyReadRestriction = exports.SyReadRestrictionConf = void 0;
37
+ const issue_1 = require("../issue");
38
+ const Expressions = __importStar(require("../abap/2_statements/expressions"));
39
+ const _abap_rule_1 = require("./_abap_rule");
40
+ const _basic_rule_config_1 = require("./_basic_rule_config");
41
+ const _irule_1 = require("./_irule");
42
+ const version_1 = require("../version");
43
+ const severity_1 = require("../severity");
44
+ // ABAP Cloud: 17 system fields allowed for reading
45
+ // https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENSYSTEM_FIELDS.html
46
+ const CLOUD_ALLOWED = new Set([
47
+ "SY-BATCH",
48
+ "SY-DBCNT",
49
+ "SY-FDPOS",
50
+ "SY-INDEX",
51
+ "SY-LANGU",
52
+ "SY-MANDT",
53
+ "SY-MSGID",
54
+ "SY-MSGNO",
55
+ "SY-MSGTY",
56
+ "SY-MSGV1",
57
+ "SY-MSGV2",
58
+ "SY-MSGV3",
59
+ "SY-MSGV4",
60
+ "SY-SUBRC",
61
+ "SY-SYSID",
62
+ "SY-TABIX",
63
+ "SY-UNAME",
64
+ ]);
65
+ // ABAP for Key Users: 5 system fields allowed for reading
66
+ const KEYUSER_ALLOWED = new Set([
67
+ "SY-DBCNT",
68
+ "SY-FDPOS",
69
+ "SY-INDEX",
70
+ "SY-SUBRC",
71
+ "SY-TABIX",
72
+ ]);
73
+ class SyReadRestrictionConf extends _basic_rule_config_1.BasicRuleConfig {
74
+ }
75
+ exports.SyReadRestrictionConf = SyReadRestrictionConf;
76
+ class SyReadRestriction extends _abap_rule_1.ABAPRule {
77
+ constructor() {
78
+ super(...arguments);
79
+ this.conf = new SyReadRestrictionConf();
80
+ }
81
+ getMetadata() {
82
+ return {
83
+ key: "sy_read_restriction",
84
+ title: "SY field read restriction",
85
+ shortDescription: `Finds reads of SY fields not allowed in the current language version`,
86
+ extendedInformation: `In ABAP Cloud, only 17 system fields may be read; reads of other fields produce a warning.\n` +
87
+ `In ABAP for Key Users, only 5 system fields may be read:\n` +
88
+ `SY-DBCNT, SY-FDPOS, SY-INDEX, SY-SUBRC, SY-TABIX.\n` +
89
+ `https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENSYSTEM_FIELDS.html`,
90
+ tags: [_irule_1.RuleTag.SingleFile],
91
+ badExample: `lv = sy-uname.`,
92
+ goodExample: `IF sy-subrc = 0. ENDIF.`,
93
+ };
94
+ }
95
+ getConfig() {
96
+ return this.conf;
97
+ }
98
+ setConfig(conf) {
99
+ this.conf = conf;
100
+ }
101
+ runParsed(file, _obj) {
102
+ var _a;
103
+ const issues = [];
104
+ const langVer = this.reg.getConfig().getLanguageVersion();
105
+ if (langVer === version_1.LanguageVersion.Normal) {
106
+ return [];
107
+ }
108
+ const allowed = langVer === version_1.LanguageVersion.KeyUser ? KEYUSER_ALLOWED : CLOUD_ALLOWED;
109
+ const severity = langVer === version_1.LanguageVersion.KeyUser ? this.conf.severity : severity_1.Severity.Warning;
110
+ // Collect tokens that appear in writable Target positions — they're modifications,
111
+ // handled by the sy_modification rule, not this one.
112
+ const writeTokens = new Set();
113
+ for (const t of ((_a = file.getStructure()) === null || _a === void 0 ? void 0 : _a.findAllExpressionsRecursive(Expressions.Target)) || []) {
114
+ const concat = t.concatTokens().toUpperCase();
115
+ if (!concat.startsWith("SY-")) {
116
+ continue;
117
+ }
118
+ writeTokens.add(t.getFirstToken());
119
+ }
120
+ // Walk all tokens looking for the sequence SY - <fieldname>
121
+ const tokens = file.getTokens();
122
+ for (let i = 0; i + 2 < tokens.length; i++) {
123
+ const sy = tokens[i];
124
+ const dash = tokens[i + 1];
125
+ const fld = tokens[i + 2];
126
+ if (sy.getStr().toUpperCase() !== "SY") {
127
+ continue;
128
+ }
129
+ if (dash.getStr() !== "-") {
130
+ continue;
131
+ }
132
+ // Adjacent: no whitespace between the three tokens, on the same row
133
+ if (sy.getEnd().getCol() !== dash.getStart().getCol()
134
+ || dash.getEnd().getCol() !== fld.getStart().getCol()
135
+ || sy.getRow() !== dash.getRow()
136
+ || dash.getRow() !== fld.getRow()) {
137
+ continue;
138
+ }
139
+ if (writeTokens.has(sy)) {
140
+ continue;
141
+ }
142
+ const fieldName = "SY-" + fld.getStr().toUpperCase();
143
+ if (!allowed.has(fieldName)) {
144
+ const message = `SY field "${fieldName}" cannot be read in language version ${langVer}`;
145
+ issues.push(issue_1.Issue.atToken(file, sy, message, this.getMetadata().key, severity));
146
+ }
147
+ }
148
+ return issues;
149
+ }
150
+ }
151
+ exports.SyReadRestriction = SyReadRestriction;
152
+ //# sourceMappingURL=sy_read_restriction.js.map