@abaplint/core 2.120.35 → 2.120.37
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.
- package/build/abaplint.d.ts +1 -0
- package/build/src/abap/5_syntax/_type_utils.js +23 -0
- package/build/src/abap/5_syntax/basic_types.js +16 -3
- package/build/src/abap/5_syntax/expressions/form_param.js +1 -1
- package/build/src/abap/5_syntax/statements/perform.js +5 -1
- package/build/src/abap/types/form_definition.js +2 -1
- package/build/src/registry.js +1 -1
- package/package.json +1 -1
package/build/abaplint.d.ts
CHANGED
|
@@ -3559,6 +3559,7 @@ export declare const enum IdentifierMeta {
|
|
|
3559
3559
|
FunctionModuleTables = "function_module_tables",
|
|
3560
3560
|
EventParameter = "event_parameter",
|
|
3561
3561
|
FormParameter = "form_parameter",
|
|
3562
|
+
FormParameterStructure = "form_parameter_structure",
|
|
3562
3563
|
ReadOnly = "read_only",
|
|
3563
3564
|
Tables = "tables",
|
|
3564
3565
|
Abstract = "abstract",
|
|
@@ -575,6 +575,29 @@ class TypeUtils {
|
|
|
575
575
|
}
|
|
576
576
|
return this.isAssignable(source, target);
|
|
577
577
|
}
|
|
578
|
+
// Typing with the classic STRUCTURE addition, ie. "FORM foo USING bar STRUCTURE zkey",
|
|
579
|
+
// is not a compatibility check: ABAP only checks the fragment view up to the end of the
|
|
580
|
+
// formal structure, so the actual parameter is allowed to be longer. For TABLES parameters
|
|
581
|
+
// the table key is not part of the check at all.
|
|
582
|
+
isAssignableStructureTyping(source, target, node) {
|
|
583
|
+
if (source instanceof basic_1.StructureType && target instanceof basic_1.StructureType) {
|
|
584
|
+
const sourceComponents = source.getComponents();
|
|
585
|
+
const targetComponents = target.getComponents();
|
|
586
|
+
if (sourceComponents.length < targetComponents.length) {
|
|
587
|
+
return false;
|
|
588
|
+
}
|
|
589
|
+
for (let i = 0; i < targetComponents.length; i++) {
|
|
590
|
+
if (this.isAssignableStrict(sourceComponents[i].type, targetComponents[i].type) === false) {
|
|
591
|
+
return false;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
return true;
|
|
595
|
+
}
|
|
596
|
+
else if (source instanceof basic_1.TableType && target instanceof basic_1.TableType) {
|
|
597
|
+
return this.isAssignableStructureTyping(source.getRowType(), target.getRowType());
|
|
598
|
+
}
|
|
599
|
+
return this.isAssignableStrict(source, target, node);
|
|
600
|
+
}
|
|
578
601
|
isAssignable(source, target) {
|
|
579
602
|
if (source === undefined || target === undefined) {
|
|
580
603
|
return true;
|
|
@@ -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
|
-
|
|
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
|
-
|
|
555
|
+
row = type.getRowType();
|
|
550
556
|
}
|
|
551
557
|
else if (type instanceof Types.VoidType) {
|
|
552
|
-
|
|
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();
|
|
@@ -31,7 +31,7 @@ class FormParam {
|
|
|
31
31
|
else {
|
|
32
32
|
type = new basic_1.UnknownType("todo, FORM STRUCTURES typing");
|
|
33
33
|
}
|
|
34
|
-
return new _typed_identifier_1.TypedIdentifier(nameToken, input.filename, type, ["form_parameter" /* IdentifierMeta.FormParameter */]);
|
|
34
|
+
return new _typed_identifier_1.TypedIdentifier(nameToken, input.filename, type, ["form_parameter" /* IdentifierMeta.FormParameter */, "form_parameter_structure" /* IdentifierMeta.FormParameterStructure */]);
|
|
35
35
|
}
|
|
36
36
|
if (node.getChildren().length === 1 && nameToken) {
|
|
37
37
|
// untyped FORM parameter
|
|
@@ -113,7 +113,11 @@ class Perform {
|
|
|
113
113
|
continue;
|
|
114
114
|
}
|
|
115
115
|
const parameter = formal[i];
|
|
116
|
-
|
|
116
|
+
const structureTyping = parameter.getMeta().includes("form_parameter_structure" /* IdentifierMeta.FormParameterStructure */);
|
|
117
|
+
const assignable = structureTyping
|
|
118
|
+
? typeUtils.isAssignableStructureTyping(type, parameter.getType(), source)
|
|
119
|
+
: typeUtils.isAssignableStrict(type, parameter.getType(), source);
|
|
120
|
+
if (assignable === false) {
|
|
117
121
|
const message = `PERFORM parameter type not compatible, ${parameter.getName()}`;
|
|
118
122
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, source.getFirstToken(), message));
|
|
119
123
|
return false;
|
|
@@ -90,7 +90,8 @@ class FormDefinition extends _identifier_1.Identifier {
|
|
|
90
90
|
else if (!(type instanceof basic_1.UnknownType) && !(type instanceof basic_1.VoidType)) {
|
|
91
91
|
type = new basic_1.UnknownType("FORM TABLES type must be table type");
|
|
92
92
|
}
|
|
93
|
-
|
|
93
|
+
// keep the meta from FormParam, so STRUCTURE typing can be recognized later
|
|
94
|
+
ret.push(new _typed_identifier_1.TypedIdentifier(p.getToken(), input.filename, type, p.getMeta()));
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
97
|
return ret;
|
package/build/src/registry.js
CHANGED