@abaplint/core 2.120.34 → 2.120.36

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.
@@ -429,6 +429,8 @@ declare class Attributes implements IAttributes {
429
429
  private parse;
430
430
  private parseSection;
431
431
  private parseAlias;
432
+ /** does the component exist in the interface, or in one of its aliases or included interfaces? */
433
+ private existsInInterface;
432
434
  private parseAttribute;
433
435
  }
434
436
 
@@ -533,7 +533,7 @@ class BasicTypes {
533
533
  return Types.VoidType.get((_f = node.findFirstExpression(Expressions.TypeStructure)) === null || _f === void 0 ? void 0 : _f.concatTokens());
534
534
  }
535
535
  else if (text.startsWith("LIKE LINE OF ")) {
536
- const name = (_g = node.findFirstExpression(Expressions.FieldChain)) === null || _g === void 0 ? void 0 : _g.concatTokens();
536
+ let name = (_g = node.findFirstExpression(Expressions.FieldChain)) === null || _g === void 0 ? void 0 : _g.concatTokens();
537
537
  let e = node.findFirstExpression(Expressions.Type);
538
538
  if (e === undefined) {
539
539
  e = node.findFirstExpression(Expressions.FormParamType);
@@ -541,19 +541,32 @@ class BasicTypes {
541
541
  if (e === undefined) {
542
542
  e = node.findFirstExpression(Expressions.FieldChain);
543
543
  }
544
+ if (e === undefined) {
545
+ // old style, eg "LIKE LINE OF tab OCCURS 0 WITH HEADER LINE", it is parsed as TypeName
546
+ e = typeName;
547
+ name = typeName === null || typeName === void 0 ? void 0 : typeName.concatTokens();
548
+ }
544
549
  const type = this.resolveLikeName(e, false);
550
+ let row = undefined;
545
551
  if (type === undefined) {
546
552
  return new Types.UnknownType("Type error, could not resolve \"" + name + "\", parseType");
547
553
  }
548
554
  else if (type instanceof Types.TableType) {
549
- return type.getRowType();
555
+ row = type.getRowType();
550
556
  }
551
557
  else if (type instanceof Types.VoidType) {
552
- return type;
558
+ row = type;
553
559
  }
554
560
  else {
555
561
  return new Types.UnknownType("Type error, not a table type " + name);
556
562
  }
563
+ if (this.isOccurs(node)) {
564
+ return new Types.TableType(row, {
565
+ withHeader: text.includes(" WITH HEADER LINE"),
566
+ keyType: Types.TableKeyType.default
567
+ }, qualifiedName);
568
+ }
569
+ return row;
557
570
  }
558
571
  else if (text.startsWith("LIKE REF TO ")) {
559
572
  const name = (_h = node.findFirstExpression(Expressions.FieldChain)) === null || _h === void 0 ? void 0 : _h.concatTokens();
@@ -52,6 +52,7 @@ const constants_1 = require("../5_syntax/structures/constants");
52
52
  const type_definitions_1 = require("./type_definitions");
53
53
  const types_1 = require("../5_syntax/structures/types");
54
54
  const type_1 = require("../5_syntax/statements/type");
55
+ const _syntax_input_1 = require("../5_syntax/_syntax_input");
55
56
  const _reference_1 = require("../5_syntax/_reference");
56
57
  const alias_1 = require("./alias");
57
58
  class Attributes {
@@ -273,6 +274,13 @@ class Attributes {
273
274
  if (foundAttribute) {
274
275
  input.scope.addNamedIdentifier(aliasName.getStr(), foundAttribute);
275
276
  }
277
+ const component = compName.split("~")[1];
278
+ if (foundType === undefined
279
+ && foundAttribute === undefined
280
+ && this.existsInInterface(idef, component, input, []) === false) {
281
+ const message = "Component " + component + " not found in interface " + idef.getName();
282
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, compToken, message));
283
+ }
276
284
  }
277
285
  else if (this.declaredInterfaces.includes(name.toUpperCase()) || input.scope.getDDIC().inErrorNamespace(name) === false) {
278
286
  input.scope.addReference(compToken, undefined, _reference_1.ReferenceType.ObjectOrientedVoidReference, input.filename);
@@ -282,6 +290,33 @@ class Attributes {
282
290
  }
283
291
  }
284
292
  }
293
+ /** does the component exist in the interface, or in one of its aliases or included interfaces? */
294
+ existsInInterface(idef, component, input, visited) {
295
+ const upperName = idef.getName().toUpperCase();
296
+ if (visited.includes(upperName)) {
297
+ return false;
298
+ }
299
+ visited.push(upperName);
300
+ const upper = component.toUpperCase();
301
+ if (idef.getTypeDefinitions().getByName(component) !== undefined
302
+ || idef.getAttributes().findByName(component) !== undefined
303
+ || idef.getMethodDefinitions().getByName(component) !== undefined
304
+ || idef.getEvents().some(e => e.getName().toUpperCase() === upper)
305
+ || idef.getAliases().some(a => a.getName().toUpperCase() === upper)) {
306
+ return true;
307
+ }
308
+ for (const i of idef.getImplementing()) {
309
+ const sub = input.scope.findInterfaceDefinition(i.name);
310
+ if (sub === undefined) {
311
+ // voided or not found, assume the component exists
312
+ return true;
313
+ }
314
+ else if (this.existsInInterface(sub, component, input, visited)) {
315
+ return true;
316
+ }
317
+ }
318
+ return false;
319
+ }
285
320
  parseAttribute(node, visibility, input) {
286
321
  let found = undefined;
287
322
  const s = node.get();
@@ -75,7 +75,7 @@ class Registry {
75
75
  }
76
76
  static abaplintVersion() {
77
77
  // magic, see build script "version.js"
78
- return "2.120.34";
78
+ return "2.120.36";
79
79
  }
80
80
  getDDICReferences() {
81
81
  return this.ddicReferences;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.120.34",
3
+ "version": "2.120.36",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",