@abaplint/core 2.120.38 → 2.120.40

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.
@@ -1612,6 +1612,9 @@ export declare class CurrentScope {
1612
1612
  addExtraLikeTypeNamed(name: string, type: TypedIdentifier | undefined): void;
1613
1613
  addClassDefinition(c: IClassDefinition): void;
1614
1614
  addFormDefinitions(f: readonly IFormDefinition[]): void;
1615
+ /** The FORM definitions are built up front, at that point the program level types are not known.
1616
+ * When the FORM statement is traversed it is replaced with one resolved in the scope of the FORM */
1617
+ updateFormDefinition(f: IFormDefinition): void;
1615
1618
  addInterfaceDefinition(i: IInterfaceDefinition): void;
1616
1619
  addNamedIdentifier(name: string, identifier: TypedIdentifier): void;
1617
1620
  addNamedIdentifierToParent(name: string, identifier: TypedIdentifier): void;
@@ -7872,11 +7875,15 @@ declare type SyntaxInput = {
7872
7875
  scope: CurrentScope;
7873
7876
  filename: string;
7874
7877
  issues: Issue[];
7878
+ /** checks which can only run once the full object has been traversed, eg. PERFORM parameters,
7879
+ * the FORM might be defined after the PERFORM */
7880
+ deferred: (() => void)[];
7875
7881
  };
7876
7882
 
7877
7883
  export declare class SyntaxLogic {
7878
7884
  private currentFile;
7879
7885
  private issues;
7886
+ private deferred;
7880
7887
  private readonly object;
7881
7888
  private readonly reg;
7882
7889
  private scope;
@@ -107,6 +107,21 @@ class CurrentScope {
107
107
  }
108
108
  this.current.getData().forms.push(...f);
109
109
  }
110
+ /** The FORM definitions are built up front, at that point the program level types are not known.
111
+ * When the FORM statement is traversed it is replaced with one resolved in the scope of the FORM */
112
+ updateFormDefinition(f) {
113
+ let search = this.current;
114
+ while (search !== undefined) {
115
+ const forms = search.getData().forms;
116
+ for (let i = 0; i < forms.length; i++) {
117
+ if (forms[i].equals(f)) {
118
+ forms[i] = f;
119
+ return;
120
+ }
121
+ }
122
+ search = search.getParent();
123
+ }
124
+ }
110
125
  addInterfaceDefinition(i) {
111
126
  if (this.current === undefined) {
112
127
  return;
@@ -59,6 +59,7 @@ class Procedural {
59
59
  scope: _current_scope_1.CurrentScope.buildDefault(this.reg, obj),
60
60
  filename: file.getFilename(),
61
61
  issues: [],
62
+ deferred: [],
62
63
  };
63
64
  for (const found of structure.findAllStructures(Structures.Form)) {
64
65
  this.scope.addFormDefinitions([new types_1.FormDefinition(found, input)]);
@@ -151,6 +151,7 @@ class FindGlobalDefinitions {
151
151
  filename: file.getFilename(),
152
152
  scope: _current_scope_1.CurrentScope.buildDefault(this.reg, obj),
153
153
  issues: [],
154
+ deferred: [],
154
155
  };
155
156
  if (obj instanceof interface_1.Interface) {
156
157
  const found = struc.findFirstStructure(Structures.Interface);
@@ -20,6 +20,9 @@ class Form {
20
20
  }
21
21
  input.scope.push(_scope_type_1.ScopeType.Form, name, node.getFirstToken().getStart(), input.filename);
22
22
  const form = new form_definition_1.FormDefinition(node, input);
23
+ // the definitions are built up front, before the program level types are known, replace it
24
+ // with this one, which is resolved in the scope of the FORM
25
+ input.scope.updateFormDefinition(form);
23
26
  input.scope.addList(form.getUsingParameters());
24
27
  input.scope.addList(form.getChangingParameters());
25
28
  input.scope.addList(form.getTablesParameters());
@@ -92,12 +92,19 @@ class Perform {
92
92
  input.scope.addReference(expr.getFirstToken(), found, _reference_1.ReferenceType.FormReference, input.filename);
93
93
  ////////////////////////////
94
94
  // check parameters match
95
- // USING and CHANGING are interchangeable, the actual parameters form a single positional list
96
- if (this.checkParameters(node, tables, found.getTablesParameters(), "TABLES", input) === false) {
97
- return;
98
- }
99
- const formal = found.getUsingParameters().concat(found.getChangingParameters());
100
- this.checkParameters(node, using.concat(changing), formal, "USING/CHANGING", input);
95
+ // deferred, the FORM might be defined after the PERFORM, its parameters are only typed
96
+ // once the FORM statement itself has been traversed
97
+ input.deferred.push(() => {
98
+ var _a;
99
+ // look up again, the definition is replaced when the FORM statement is traversed
100
+ const def = (_a = input.scope.findFormDefinition(name)) !== null && _a !== void 0 ? _a : found;
101
+ if (this.checkParameters(node, tables, def.getTablesParameters(), "TABLES", input) === false) {
102
+ return;
103
+ }
104
+ // USING and CHANGING are interchangeable, the actual parameters form a single positional list
105
+ const formal = def.getUsingParameters().concat(def.getChangingParameters());
106
+ this.checkParameters(node, using.concat(changing), formal, "USING/CHANGING", input);
107
+ });
101
108
  }
102
109
  // returns false if an issue was reported
103
110
  checkParameters(node, actual, formal, kind, input) {
@@ -64,22 +64,8 @@ class SelectOption {
64
64
  return;
65
65
  }
66
66
  const nameChain = node.findFirstExpression(Expressions.FieldChain);
67
- let found = new basic_types_1.BasicTypes(input).resolveLikeName(nameChain);
67
+ const found = new basic_types_1.BasicTypes(input).resolveLikeName(nameChain);
68
68
  if (found) {
69
- if (found instanceof basic_1.StructureType) {
70
- let length = 0;
71
- for (const c of found.getComponents()) {
72
- if (c.type instanceof basic_1.CharacterType) {
73
- length += c.type.getLength();
74
- }
75
- }
76
- if (length === 0) {
77
- found = basic_1.VoidType.get("Selectoption, fallback");
78
- }
79
- else {
80
- found = new basic_1.CharacterType(length);
81
- }
82
- }
83
69
  const stru = new basic_1.StructureType([
84
70
  { name: "SIGN", type: new basic_1.CharacterType(1) },
85
71
  { name: "OPTION", type: new basic_1.CharacterType(2) },
@@ -337,6 +337,7 @@ class SyntaxLogic {
337
337
  constructor(reg, object) {
338
338
  this.reg = reg;
339
339
  this.issues = [];
340
+ this.deferred = [];
340
341
  this.object = object;
341
342
  }
342
343
  run() {
@@ -350,6 +351,7 @@ class SyntaxLogic {
350
351
  proc: new _procedural_1.Procedural(this.reg, this.scope),
351
352
  };
352
353
  this.issues = [];
354
+ this.deferred = [];
353
355
  this.reg.getDDICReferences().clear(this.object);
354
356
  this.reg.getMSAGReferences().clear(this.object);
355
357
  if (this.object instanceof objects_1.Program && this.object.isInclude()) {
@@ -357,6 +359,11 @@ class SyntaxLogic {
357
359
  return { issues: [], spaghetti: this.scope.pop(new position_1.Position(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER)) };
358
360
  }
359
361
  this.traverseObject();
362
+ // the FORM definitions are now all traversed, ie. their parameters are typed
363
+ for (const d of this.deferred) {
364
+ d();
365
+ }
366
+ this.deferred = [];
360
367
  for (;;) {
361
368
  const spaghetti = this.scope.pop(new position_1.Position(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER)); // pop built-in scopes
362
369
  if (spaghetti.getTop().getIdentifier().stype === _scope_type_1.ScopeType.BuiltIn) {
@@ -456,6 +463,7 @@ class SyntaxLogic {
456
463
  scope: this.scope,
457
464
  filename,
458
465
  issues: this.issues,
466
+ deferred: this.deferred,
459
467
  };
460
468
  if (stru instanceof Structures.ClassDefinition) {
461
469
  new class_definition_1.ClassDefinition(node, input);
@@ -507,6 +515,7 @@ class SyntaxLogic {
507
515
  scope: this.scope,
508
516
  filename,
509
517
  issues: this.issues,
518
+ deferred: this.deferred,
510
519
  };
511
520
  // todo, refactor
512
521
  if (s instanceof Statements.Type) {
@@ -75,7 +75,7 @@ class Registry {
75
75
  }
76
76
  static abaplintVersion() {
77
77
  // magic, see build script "version.js"
78
- return "2.120.38";
78
+ return "2.120.40";
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.38",
3
+ "version": "2.120.40",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",