@abaplint/core 2.120.28 → 2.120.30

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.
@@ -2,10 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Color = void 0;
4
4
  const combi_1 = require("../combi");
5
- const source_1 = require("./source");
5
+ const simple_source3_1 = require("./simple_source3");
6
6
  class Color extends combi_1.Expression {
7
7
  getRunnable() {
8
- const eq = (0, combi_1.seq)("=", source_1.Source);
8
+ const eq = (0, combi_1.seq)("=", simple_source3_1.SimpleSource3);
9
9
  const integers = (0, combi_1.altPrio)("1", "2", "3", "4", "5", "6", "7");
10
10
  const texts = (0, combi_1.altPrio)("COL_BACKGROUND", "COL_HEADING", "COL_NORMAL", "COL_TOTAL", "COL_KEY", "COL_POSITIVE", "COL_NEGATIVE", "COL_GROUP");
11
11
  const value = (0, combi_1.alt)(eq, (0, combi_1.altPrio)("ON", "OFF", "COLOR OFF", (0, combi_1.altPrio)(integers, texts)));
@@ -171,6 +171,31 @@ class ObjectOriented {
171
171
  }
172
172
  return ret;
173
173
  }
174
+ // does the supplied class have friendship with "friendName"?
175
+ // note that interfaces of the friend, and subclasses of the friend also have friendship
176
+ hasFriendship(cd, friendName) {
177
+ var _a;
178
+ const friends = cd.getFriends().map(f => f.toUpperCase());
179
+ const isFriend = (name) => friends.includes(name.toUpperCase()) || this.scope.isLocalFriend(cd.getName(), name);
180
+ if (isFriend(friendName)) {
181
+ return true;
182
+ }
183
+ const friendDefinition = this.scope.findClassDefinition(friendName);
184
+ if (friendDefinition === undefined) {
185
+ return false;
186
+ }
187
+ if (this.findInterfaces(friendDefinition).some(i => friends.includes(i.name.toUpperCase()))) {
188
+ return true;
189
+ }
190
+ let sup = friendDefinition.getSuperClass();
191
+ while (sup !== undefined) {
192
+ if (isFriend(sup)) {
193
+ return true;
194
+ }
195
+ sup = (_a = this.scope.findClassDefinition(sup)) === null || _a === void 0 ? void 0 : _a.getSuperClass();
196
+ }
197
+ return false;
198
+ }
174
199
  searchEvent(def, name) {
175
200
  if (def === undefined || name === undefined) {
176
201
  return undefined;
@@ -567,6 +567,9 @@ class TypeUtils {
567
567
  console.dir(source);
568
568
  console.dir(target);
569
569
  */
570
+ if (source instanceof basic_1.UTCLongType || target instanceof basic_1.UTCLongType) {
571
+ return this.isUTCLongAssignable(source, target);
572
+ }
570
573
  if (target instanceof basic_1.TableType) {
571
574
  if (target.isWithHeader()) {
572
575
  return this.isAssignable(source, target.getRowType());
@@ -718,6 +721,33 @@ class TypeUtils {
718
721
  }
719
722
  return true;
720
723
  }
724
+ // utclong can only be converted to and from character like types
725
+ isUTCLongAssignable(source, target) {
726
+ if (this.isGenericOrVoid(source) || this.isGenericOrVoid(target)) {
727
+ return true;
728
+ }
729
+ else if (source instanceof basic_1.UTCLongType && target instanceof basic_1.UTCLongType) {
730
+ return true;
731
+ }
732
+ else if (source instanceof basic_1.UTCLongType) {
733
+ return this.isTextLike(target);
734
+ }
735
+ return this.isTextLike(source);
736
+ }
737
+ isGenericOrVoid(type) {
738
+ return type instanceof basic_1.VoidType
739
+ || type instanceof basic_1.AnyType
740
+ || type instanceof basic_1.DataType
741
+ || type instanceof basic_1.UnknownType;
742
+ }
743
+ isTextLike(type) {
744
+ return type instanceof basic_1.CharacterType
745
+ || type instanceof basic_1.StringType
746
+ || type instanceof basic_1.CLikeType
747
+ || type instanceof basic_1.CSequenceType
748
+ || type instanceof cgeneric_type_1.CGenericType
749
+ || type instanceof basic_1.SimpleType;
750
+ }
721
751
  }
722
752
  exports.TypeUtils = TypeUtils;
723
753
  //# sourceMappingURL=_type_utils.js.map
@@ -50,6 +50,7 @@ const types_1 = require("../types");
50
50
  const expressions_1 = require("../2_statements/expressions");
51
51
  const _builtin_1 = require("./_builtin");
52
52
  const position_1 = require("../../position");
53
+ const _syntax_input_1 = require("./_syntax_input");
53
54
  class BasicTypes {
54
55
  constructor(input) {
55
56
  this.input = input;
@@ -990,6 +991,13 @@ class BasicTypes {
990
991
  }
991
992
  const chain = val.findFirstExpression(Expressions.SimpleFieldChain);
992
993
  if (chain) {
994
+ // todo, hardcoded for now, should be a generic check that the chain is a constant
995
+ const concat = chain.concatTokens().toUpperCase();
996
+ if (concat === "SY-DATUM" || concat === "SY-UZEIT") {
997
+ const message = "VALUE, " + concat.toLowerCase() + " is not a constant";
998
+ this.input.issues.push((0, _syntax_input_1.syntaxIssue)(this.input, chain.getFirstToken(), message));
999
+ return undefined;
1000
+ }
993
1001
  return this.resolveConstantValue(chain);
994
1002
  }
995
1003
  throw new Error("findValue, unexpected");
@@ -47,6 +47,8 @@ const _reference_1 = require("../_reference");
47
47
  const component_name_1 = require("./component_name");
48
48
  const attribute_name_1 = require("./attribute_name");
49
49
  const _syntax_input_1 = require("../_syntax_input");
50
+ const visibility_1 = require("../../4_file_information/visibility");
51
+ const class_definition_1 = require("../../types/class_definition");
50
52
  class MethodCallChain {
51
53
  static runSyntax(node, input, targetType) {
52
54
  var _a, _b;
@@ -95,6 +97,12 @@ class MethodCallChain {
95
97
  input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, message));
96
98
  return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
97
99
  }
100
+ const notVisible = method ? this.checkVisibility(method, def, foundDef, input) : undefined;
101
+ if (notVisible !== undefined) {
102
+ const message = `Method "${methodName}" is ${notVisible} and cannot be accessed`;
103
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, message));
104
+ return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
105
+ }
98
106
  const voidedName = context instanceof basic_1.VoidType ? context.getVoided() : undefined;
99
107
  const extra = helper.methodReferenceExtras(foundDef, className || voidedName);
100
108
  input.scope.addReference(methodToken, method, _reference_1.ReferenceType.MethodReference, input.filename, extra);
@@ -137,6 +145,47 @@ class MethodCallChain {
137
145
  return context;
138
146
  }
139
147
  //////////////////////////////////////
148
+ // returns the visibility as text if the method cannot be accessed from the current scope
149
+ static checkVisibility(method, def, foundDef, input) {
150
+ var _a, _b, _c;
151
+ const visibility = method.getVisibility();
152
+ if (visibility === visibility_1.Visibility.Public || foundDef === undefined) {
153
+ return undefined;
154
+ }
155
+ else if (!(foundDef instanceof class_definition_1.ClassDefinition)) {
156
+ // interface members are always public
157
+ return undefined;
158
+ }
159
+ const name = foundDef.getName().toUpperCase();
160
+ const enclosing = (_a = input.scope.getEnclosingClassName()) === null || _a === void 0 ? void 0 : _a.toUpperCase();
161
+ if (enclosing === undefined || enclosing === name) {
162
+ return undefined;
163
+ }
164
+ // friendship with the class used at the call site also gives access to inherited members
165
+ const helper = new _object_oriented_1.ObjectOriented(input.scope);
166
+ const visited = [];
167
+ let current = def instanceof class_definition_1.ClassDefinition ? def : foundDef;
168
+ while (current !== undefined && visited.includes(current.getName().toUpperCase()) === false) {
169
+ visited.push(current.getName().toUpperCase());
170
+ if (helper.hasFriendship(current, enclosing)) {
171
+ return undefined;
172
+ }
173
+ const sup = current.getSuperClass();
174
+ current = sup === undefined ? undefined : input.scope.findClassDefinition(sup);
175
+ }
176
+ if (visibility === visibility_1.Visibility.Protected) {
177
+ // subclasses can access protected members
178
+ let sup = (_b = input.scope.findClassDefinition(enclosing)) === null || _b === void 0 ? void 0 : _b.getSuperClass();
179
+ while (sup !== undefined) {
180
+ if (sup.toUpperCase() === name) {
181
+ return undefined;
182
+ }
183
+ sup = (_c = input.scope.findClassDefinition(sup)) === null || _c === void 0 ? void 0 : _c.getSuperClass();
184
+ }
185
+ return "protected";
186
+ }
187
+ return "private";
188
+ }
140
189
  static findTop(first, input, targetType) {
141
190
  var _a;
142
191
  if (first.get() instanceof Expressions.ClassName) {
@@ -39,6 +39,7 @@ const basic_1 = require("../../types/basic");
39
39
  const _syntax_input_1 = require("../_syntax_input");
40
40
  const sql_set_op_group_1 = require("./sql_set_op_group");
41
41
  const sql_source_1 = require("./sql_source");
42
+ const RANGE_COMPONENTS = ["SIGN", "OPTION", "LOW", "HIGH"];
42
43
  class SQLIn {
43
44
  static runSyntax(node, input) {
44
45
  const setop = node.findDirectExpression(Expressions.SQLSetOpGroup);
@@ -58,6 +59,12 @@ class SQLIn {
58
59
  input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
59
60
  return;
60
61
  }
62
+ if (intype instanceof basic_1.TableType && this.isRangeRow(intype.getRowType()) === false) {
63
+ const name = insource.concatTokens().replace(/^@/, "").replace(/\[\]$/, "");
64
+ const message = `row structure of ${name} is not correct`;
65
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
66
+ return;
67
+ }
61
68
  }
62
69
  return;
63
70
  }
@@ -68,6 +75,16 @@ class SQLIn {
68
75
  sql_source_1.SQLSource.runSyntax(s, input);
69
76
  }
70
77
  }
78
+ // "IN itab" expects a ranges table, ie. the row must have SIGN, OPTION, LOW and HIGH
79
+ static isRangeRow(rowType) {
80
+ if (rowType instanceof basic_1.VoidType || rowType instanceof basic_1.UnknownType || rowType instanceof basic_1.AnyType) {
81
+ return true;
82
+ }
83
+ else if (!(rowType instanceof basic_1.StructureType)) {
84
+ return false;
85
+ }
86
+ return RANGE_COMPONENTS.every(c => rowType.getComponentByName(c) !== undefined);
87
+ }
71
88
  }
72
89
  exports.SQLIn = SQLIn;
73
90
  //# sourceMappingURL=sql_in.js.map
@@ -151,7 +151,7 @@ class CreateObject {
151
151
  this.validateParameters(cdef, node, input);
152
152
  }
153
153
  static checkInstantiationAllowed(cdef, input) {
154
- var _a, _b, _c;
154
+ var _a, _b;
155
155
  const createVis = cdef.getCreateVisibility();
156
156
  if (createVis === visibility_1.Visibility.Public) {
157
157
  return undefined;
@@ -164,34 +164,17 @@ class CreateObject {
164
164
  if (enclosingClass.toUpperCase() === cdef.getName().toUpperCase()) {
165
165
  return undefined;
166
166
  }
167
- if (cdef.getFriends().some(f => f.toUpperCase() === enclosingClass.toUpperCase()) ||
168
- input.scope.isLocalFriend(cdef.getName(), enclosingClass)) {
167
+ if (new _object_oriented_1.ObjectOriented(input.scope).hasFriendship(cdef, enclosingClass)) {
169
168
  return undefined;
170
169
  }
171
- const enclosingDefinition = input.scope.findClassDefinition(enclosingClass);
172
- if (enclosingDefinition !== undefined) {
173
- const implementedInterfaces = new _object_oriented_1.ObjectOriented(input.scope).findInterfaces(enclosingDefinition);
174
- if (cdef.getFriends().some(friend => implementedInterfaces.some(implemented => implemented.name.toUpperCase() === friend.toUpperCase()))) {
175
- return undefined;
176
- }
177
- }
178
- // subclasses of friends also have friendship
179
- let enclosingSup = enclosingDefinition === null || enclosingDefinition === void 0 ? void 0 : enclosingDefinition.getSuperClass();
180
- while (enclosingSup !== undefined) {
181
- if (cdef.getFriends().some(f => f.toUpperCase() === enclosingSup.toUpperCase()) ||
182
- input.scope.isLocalFriend(cdef.getName(), enclosingSup)) {
183
- return undefined;
184
- }
185
- enclosingSup = (_a = input.scope.findClassDefinition(enclosingSup)) === null || _a === void 0 ? void 0 : _a.getSuperClass();
186
- }
187
170
  if (createVis === visibility_1.Visibility.Protected) {
188
171
  // subclasses are also allowed
189
- let sup = (_b = input.scope.findClassDefinition(enclosingClass)) === null || _b === void 0 ? void 0 : _b.getSuperClass();
172
+ let sup = (_a = input.scope.findClassDefinition(enclosingClass)) === null || _a === void 0 ? void 0 : _a.getSuperClass();
190
173
  while (sup !== undefined) {
191
174
  if (sup.toUpperCase() === cdef.getName().toUpperCase()) {
192
175
  return undefined;
193
176
  }
194
- sup = (_c = input.scope.findClassDefinition(sup)) === null || _c === void 0 ? void 0 : _c.getSuperClass();
177
+ sup = (_b = input.scope.findClassDefinition(sup)) === null || _b === void 0 ? void 0 : _b.getSuperClass();
195
178
  }
196
179
  }
197
180
  return cdef.getName() + " cannot be instantiated, class is defined as " +
@@ -39,6 +39,7 @@ const source_1 = require("../expressions/source");
39
39
  const dynamic_1 = require("../expressions/dynamic");
40
40
  const database_table_1 = require("../expressions/database_table");
41
41
  const _check_database_fields_1 = require("../expressions/_check_database_fields");
42
+ const sql_in_1 = require("../expressions/sql_in");
42
43
  class DeleteDatabase {
43
44
  runSyntax(node, input) {
44
45
  for (const s of node.findAllExpressions(Expressions.Source)) {
@@ -50,6 +51,12 @@ class DeleteDatabase {
50
51
  for (const d of node.findAllExpressions(Expressions.Dynamic)) {
51
52
  dynamic_1.Dynamic.runSyntax(d, input);
52
53
  }
54
+ for (const compare of node.findAllExpressions(Expressions.SQLCompare)) {
55
+ const sqlin = compare.findDirectExpression(Expressions.SQLIn);
56
+ if (sqlin !== undefined) {
57
+ sql_in_1.SQLIn.runSyntax(sqlin, input);
58
+ }
59
+ }
53
60
  const dbtab = node.findFirstExpression(Expressions.DatabaseTable);
54
61
  if (dbtab !== undefined) {
55
62
  const dbSource = database_table_1.DatabaseTable.runSyntax(dbtab, input);
@@ -7,13 +7,17 @@ const expressions_1 = require("../../2_statements/expressions");
7
7
  const _syntax_input_1 = require("../_syntax_input");
8
8
  class Form {
9
9
  runSyntax(node, input) {
10
- var _a;
11
- const name = (_a = node.findDirectExpression(expressions_1.FormName)) === null || _a === void 0 ? void 0 : _a.concatTokens();
12
- if (name === undefined) {
10
+ const nameExpression = node.findDirectExpression(expressions_1.FormName);
11
+ const name = nameExpression === null || nameExpression === void 0 ? void 0 : nameExpression.concatTokens();
12
+ if (nameExpression === undefined || name === undefined) {
13
13
  const message = "Form, could not find name";
14
14
  input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
15
15
  return;
16
16
  }
17
+ if (name.length > 30) {
18
+ const message = "FORM name longer than 30 characters";
19
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, nameExpression.getFirstToken(), message));
20
+ }
17
21
  input.scope.push(_scope_type_1.ScopeType.Form, name, node.getFirstToken().getStart(), input.filename);
18
22
  const form = new form_definition_1.FormDefinition(node, input);
19
23
  input.scope.addList(form.getUsingParameters());
@@ -38,7 +38,7 @@ const Expressions = __importStar(require("../../2_statements/expressions"));
38
38
  const source_1 = require("../expressions/source");
39
39
  class Format {
40
40
  runSyntax(node, input) {
41
- for (const s of node.findAllExpressions(Expressions.Source)) {
41
+ for (const s of node.findAllExpressionsMulti([Expressions.Source, Expressions.SimpleSource3])) {
42
42
  source_1.Source.runSyntax(s, input);
43
43
  }
44
44
  }
@@ -62,6 +62,11 @@ class Parameter {
62
62
  input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
63
63
  return;
64
64
  }
65
+ if (this.hasUserCommand(node) && this.hasLength(node)) {
66
+ const message = "USER-COMMAND and LENGTH not possible together";
67
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
68
+ return;
69
+ }
65
70
  const bfound = new basic_types_1.BasicTypes(input).parseType(node);
66
71
  if (bfound) {
67
72
  input.scope.addIdentifier(new _typed_identifier_1.TypedIdentifier(nameToken, input.filename, bfound));
@@ -73,6 +78,30 @@ class Parameter {
73
78
  const magicToken = new tokens_1.Identifier(nameToken.getStart(), magicName);
74
79
  input.scope.addIdentifier(new _typed_identifier_1.TypedIdentifier(magicToken, input.filename, basic_1.VoidType.get("PARAMETER-MAGIC")));
75
80
  }
81
+ // "USER-COMMAND" is lexed as three tokens
82
+ hasUserCommand(node) {
83
+ const tokens = node.getTokens();
84
+ for (let i = 0; i < tokens.length - 2; i++) {
85
+ if (tokens[i].getStr().toUpperCase() === "USER"
86
+ && tokens[i + 1].getStr() === "-"
87
+ && tokens[i + 2].getStr().toUpperCase() === "COMMAND") {
88
+ return true;
89
+ }
90
+ }
91
+ return false;
92
+ }
93
+ // "VISIBLE LENGTH" is not the same as "LENGTH"
94
+ hasLength(node) {
95
+ var _a;
96
+ const tokens = node.getTokens();
97
+ for (let i = 0; i < tokens.length; i++) {
98
+ if (tokens[i].getStr().toUpperCase() === "LENGTH"
99
+ && ((_a = tokens[i - 1]) === null || _a === void 0 ? void 0 : _a.getStr().toUpperCase()) !== "VISIBLE") {
100
+ return true;
101
+ }
102
+ }
103
+ return false;
104
+ }
76
105
  }
77
106
  exports.Parameter = Parameter;
78
107
  //# sourceMappingURL=parameter.js.map
@@ -75,7 +75,7 @@ class Registry {
75
75
  }
76
76
  static abaplintVersion() {
77
77
  // magic, see build script "version.js"
78
- return "2.120.28";
78
+ return "2.120.30";
79
79
  }
80
80
  getDDICReferences() {
81
81
  return this.ddicReferences;
@@ -14,6 +14,11 @@ class CDSCheckSyntaxConf extends _basic_rule_config_1.BasicRuleConfig {
14
14
  exports.CDSCheckSyntaxConf = CDSCheckSyntaxConf;
15
15
  const KNOWN_QUAN_DATA_ELEMENTS = ["MENGE_D"];
16
16
  const KNOWN_CURR_DATA_ELEMENTS = ["BWERT", "DZWERT"];
17
+ // Reserved names, cannot be used as element names, see DDIC table TRESE
18
+ const RESERVED_ELEMENT_NAMES = ["BEGIN", "NUMBER", "POSITION"];
19
+ const MAX_LABEL_LENGTH = 40;
20
+ // Annotations which are not supported in CDS view entities
21
+ const VIEW_ENTITY_FORBIDDEN_ANNOTATIONS = ["Semantics.unitOfMeasure"];
17
22
  class CDSCheckSyntax {
18
23
  constructor() {
19
24
  this.conf = new CDSCheckSyntaxConf();
@@ -55,6 +60,9 @@ Missing objects are only reported when their names match the configured errorNam
55
60
  this.checkTypes(tree, ddic, issues, file);
56
61
  this.checkRootProjection(tree, ddic, issues, file);
57
62
  this.checkFieldAnnotations(tree, ddic, issues, file);
63
+ this.checkLabels(tree, issues, file);
64
+ this.checkViewEntityAnnotations(tree, issues, file);
65
+ this.checkReservedNames(tree, issues, file);
58
66
  this.checkFields(tree, sources, object, issues, file);
59
67
  return issues;
60
68
  }
@@ -239,6 +247,62 @@ Missing objects are only reported when their names match the configured errorNam
239
247
  || a.toUpperCase().includes("@SEMANTICS:{CURRENCYCODE:TRUE"));
240
248
  }
241
249
  }
250
+ checkLabels(tree, issues, file) {
251
+ for (const annotation of tree.findAllExpressionsRecursive(expressions_1.CDSAnnotation)) {
252
+ const concatenated = annotation.concatTokens();
253
+ if (/@\s*<?\s*EndUserText/i.test(concatenated) === false) {
254
+ continue;
255
+ }
256
+ const expression = /label\s*:\s*'((?:[^']|'')*)'/gi;
257
+ let match = expression.exec(concatenated);
258
+ while (match !== null) {
259
+ const label = match[1].replace(/''/g, "'");
260
+ if (label.length > MAX_LABEL_LENGTH) {
261
+ const message = `CDS label is ${label.length} characters, maximum is ${MAX_LABEL_LENGTH}`;
262
+ issues.push(issue_1.Issue.atToken(file, annotation.getFirstToken(), message, this.getMetadata().key, this.conf.severity));
263
+ }
264
+ match = expression.exec(concatenated);
265
+ }
266
+ }
267
+ }
268
+ checkViewEntityAnnotations(tree, issues, file) {
269
+ const view = tree.findFirstExpression(expressions_1.CDSDefineView);
270
+ if (view === undefined || view.findDirectTokenByText("ENTITY") === undefined) {
271
+ return;
272
+ }
273
+ for (const annotation of tree.findAllExpressionsRecursive(expressions_1.CDSAnnotation)) {
274
+ const normalized = annotation.concatTokens().replace(/\s/g, "").toUpperCase().replace(/^@</, "@");
275
+ for (const forbidden of VIEW_ENTITY_FORBIDDEN_ANNOTATIONS) {
276
+ const upper = forbidden.toUpperCase();
277
+ if (normalized.startsWith("@" + upper) === false
278
+ && normalized.startsWith("@" + upper.replace(".", ":{")) === false) {
279
+ continue;
280
+ }
281
+ const message = `Annotation ${forbidden} is not allowed in view entities`;
282
+ issues.push(issue_1.Issue.atToken(file, annotation.getFirstToken(), message, this.getMetadata().key, this.conf.severity));
283
+ }
284
+ }
285
+ }
286
+ checkReservedNames(tree, issues, file) {
287
+ var _a, _b;
288
+ for (const element of tree.findAllExpressionsRecursive(expressions_1.CDSElement)) {
289
+ if (element.findDirectTokenByText("INCLUDE") !== undefined) {
290
+ continue;
291
+ }
292
+ let nameNode = (_a = element.findDirectExpression(expressions_1.CDSAs)) === null || _a === void 0 ? void 0 : _a.findDirectExpression(expressions_1.CDSName);
293
+ if (nameNode === undefined) {
294
+ const names = ((_b = element.findDirectExpression(expressions_1.CDSPrefixedName)) === null || _b === void 0 ? void 0 : _b.findDirectExpressions(expressions_1.CDSName)) || [];
295
+ nameNode = names[names.length - 1];
296
+ }
297
+ if (nameNode === undefined) {
298
+ continue;
299
+ }
300
+ const name = this.name(nameNode);
301
+ if (RESERVED_ELEMENT_NAMES.includes(name.toUpperCase())) {
302
+ issues.push(issue_1.Issue.atToken(file, nameNode.getFirstToken(), `CDS element name "${name}" is reserved`, this.getMetadata().key, this.conf.severity));
303
+ }
304
+ }
305
+ }
242
306
  checkFields(tree, sources, object, issues, file) {
243
307
  var _a;
244
308
  const associationNames = new Set();
@@ -83,6 +83,7 @@ class CloudTypes {
83
83
  || obj instanceof Objects.BehaviorDefinition
84
84
  || obj instanceof Objects.BusinessCatalog
85
85
  || obj instanceof Objects.BusinessCatalogAppAssignment
86
+ || obj instanceof Objects.BusinessConfigurationMaintenanceObject
86
87
  || obj instanceof Objects.CDSMetadataExtension
87
88
  || obj instanceof Objects.Class
88
89
  || obj instanceof Objects.CDSType
@@ -99,11 +100,13 @@ class CloudTypes {
99
100
  || obj instanceof Objects.EventBinding
100
101
  || obj instanceof Objects.EventConsumer
101
102
  || obj instanceof Objects.FunctionGroup
103
+ || obj instanceof Objects.GatewayODataGroupAndAssignment
102
104
  || obj instanceof Objects.HttpService
103
105
  || obj instanceof Objects.IAMApp
104
106
  || obj instanceof Objects.InboundService
105
107
  || obj instanceof Objects.Interface
106
108
  || obj instanceof Objects.LockObject
109
+ || obj instanceof Objects.MaintenanceAndTransportObject
107
110
  || obj instanceof Objects.MessageClass
108
111
  || obj instanceof Objects.NumberRange
109
112
  || obj instanceof Objects.OutboundService
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.120.28",
3
+ "version": "2.120.30",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",