@abaplint/cli 2.120.39 → 2.120.41
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/cli.js +68 -8
- package/package.json +2 -2
package/build/cli.js
CHANGED
|
@@ -26079,6 +26079,21 @@ class CurrentScope {
|
|
|
26079
26079
|
}
|
|
26080
26080
|
this.current.getData().forms.push(...f);
|
|
26081
26081
|
}
|
|
26082
|
+
/** The FORM definitions are built up front, at that point the program level types are not known.
|
|
26083
|
+
* When the FORM statement is traversed it is replaced with one resolved in the scope of the FORM */
|
|
26084
|
+
updateFormDefinition(f) {
|
|
26085
|
+
let search = this.current;
|
|
26086
|
+
while (search !== undefined) {
|
|
26087
|
+
const forms = search.getData().forms;
|
|
26088
|
+
for (let i = 0; i < forms.length; i++) {
|
|
26089
|
+
if (forms[i].equals(f)) {
|
|
26090
|
+
forms[i] = f;
|
|
26091
|
+
return;
|
|
26092
|
+
}
|
|
26093
|
+
}
|
|
26094
|
+
search = search.getParent();
|
|
26095
|
+
}
|
|
26096
|
+
}
|
|
26082
26097
|
addInterfaceDefinition(i) {
|
|
26083
26098
|
if (this.current === undefined) {
|
|
26084
26099
|
return;
|
|
@@ -27025,6 +27040,7 @@ class Procedural {
|
|
|
27025
27040
|
scope: _current_scope_1.CurrentScope.buildDefault(this.reg, obj),
|
|
27026
27041
|
filename: file.getFilename(),
|
|
27027
27042
|
issues: [],
|
|
27043
|
+
deferred: [],
|
|
27028
27044
|
};
|
|
27029
27045
|
for (const found of structure.findAllStructures(Structures.Form)) {
|
|
27030
27046
|
this.scope.addFormDefinitions([new types_1.FormDefinition(found, input)]);
|
|
@@ -36470,6 +36486,7 @@ class FindGlobalDefinitions {
|
|
|
36470
36486
|
filename: file.getFilename(),
|
|
36471
36487
|
scope: _current_scope_1.CurrentScope.buildDefault(this.reg, obj),
|
|
36472
36488
|
issues: [],
|
|
36489
|
+
deferred: [],
|
|
36473
36490
|
};
|
|
36474
36491
|
if (obj instanceof interface_1.Interface) {
|
|
36475
36492
|
const found = struc.findFirstStructure(Structures.Interface);
|
|
@@ -40698,6 +40715,9 @@ class Form {
|
|
|
40698
40715
|
}
|
|
40699
40716
|
input.scope.push(_scope_type_1.ScopeType.Form, name, node.getFirstToken().getStart(), input.filename);
|
|
40700
40717
|
const form = new form_definition_1.FormDefinition(node, input);
|
|
40718
|
+
// the definitions are built up front, before the program level types are known, replace it
|
|
40719
|
+
// with this one, which is resolved in the scope of the FORM
|
|
40720
|
+
input.scope.updateFormDefinition(form);
|
|
40701
40721
|
input.scope.addList(form.getUsingParameters());
|
|
40702
40722
|
input.scope.addList(form.getChangingParameters());
|
|
40703
40723
|
input.scope.addList(form.getTablesParameters());
|
|
@@ -43732,12 +43752,19 @@ class Perform {
|
|
|
43732
43752
|
input.scope.addReference(expr.getFirstToken(), found, _reference_1.ReferenceType.FormReference, input.filename);
|
|
43733
43753
|
////////////////////////////
|
|
43734
43754
|
// check parameters match
|
|
43735
|
-
//
|
|
43736
|
-
|
|
43737
|
-
|
|
43738
|
-
|
|
43739
|
-
|
|
43740
|
-
|
|
43755
|
+
// deferred, the FORM might be defined after the PERFORM, its parameters are only typed
|
|
43756
|
+
// once the FORM statement itself has been traversed
|
|
43757
|
+
input.deferred.push(() => {
|
|
43758
|
+
var _a;
|
|
43759
|
+
// look up again, the definition is replaced when the FORM statement is traversed
|
|
43760
|
+
const def = (_a = input.scope.findFormDefinition(name)) !== null && _a !== void 0 ? _a : found;
|
|
43761
|
+
if (this.checkParameters(node, tables, def.getTablesParameters(), "TABLES", input) === false) {
|
|
43762
|
+
return;
|
|
43763
|
+
}
|
|
43764
|
+
// USING and CHANGING are interchangeable, the actual parameters form a single positional list
|
|
43765
|
+
const formal = def.getUsingParameters().concat(def.getChangingParameters());
|
|
43766
|
+
this.checkParameters(node, using.concat(changing), formal, "USING/CHANGING", input);
|
|
43767
|
+
});
|
|
43741
43768
|
}
|
|
43742
43769
|
// returns false if an issue was reported
|
|
43743
43770
|
checkParameters(node, actual, formal, kind, input) {
|
|
@@ -48388,6 +48415,7 @@ class SyntaxLogic {
|
|
|
48388
48415
|
constructor(reg, object) {
|
|
48389
48416
|
this.reg = reg;
|
|
48390
48417
|
this.issues = [];
|
|
48418
|
+
this.deferred = [];
|
|
48391
48419
|
this.object = object;
|
|
48392
48420
|
}
|
|
48393
48421
|
run() {
|
|
@@ -48401,6 +48429,7 @@ class SyntaxLogic {
|
|
|
48401
48429
|
proc: new _procedural_1.Procedural(this.reg, this.scope),
|
|
48402
48430
|
};
|
|
48403
48431
|
this.issues = [];
|
|
48432
|
+
this.deferred = [];
|
|
48404
48433
|
this.reg.getDDICReferences().clear(this.object);
|
|
48405
48434
|
this.reg.getMSAGReferences().clear(this.object);
|
|
48406
48435
|
if (this.object instanceof objects_1.Program && this.object.isInclude()) {
|
|
@@ -48408,6 +48437,11 @@ class SyntaxLogic {
|
|
|
48408
48437
|
return { issues: [], spaghetti: this.scope.pop(new position_1.Position(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER)) };
|
|
48409
48438
|
}
|
|
48410
48439
|
this.traverseObject();
|
|
48440
|
+
// the FORM definitions are now all traversed, ie. their parameters are typed
|
|
48441
|
+
for (const d of this.deferred) {
|
|
48442
|
+
d();
|
|
48443
|
+
}
|
|
48444
|
+
this.deferred = [];
|
|
48411
48445
|
for (;;) {
|
|
48412
48446
|
const spaghetti = this.scope.pop(new position_1.Position(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER)); // pop built-in scopes
|
|
48413
48447
|
if (spaghetti.getTop().getIdentifier().stype === _scope_type_1.ScopeType.BuiltIn) {
|
|
@@ -48507,6 +48541,7 @@ class SyntaxLogic {
|
|
|
48507
48541
|
scope: this.scope,
|
|
48508
48542
|
filename,
|
|
48509
48543
|
issues: this.issues,
|
|
48544
|
+
deferred: this.deferred,
|
|
48510
48545
|
};
|
|
48511
48546
|
if (stru instanceof Structures.ClassDefinition) {
|
|
48512
48547
|
new class_definition_1.ClassDefinition(node, input);
|
|
@@ -48558,6 +48593,7 @@ class SyntaxLogic {
|
|
|
48558
48593
|
scope: this.scope,
|
|
48559
48594
|
filename,
|
|
48560
48595
|
issues: this.issues,
|
|
48596
|
+
deferred: this.deferred,
|
|
48561
48597
|
};
|
|
48562
48598
|
// todo, refactor
|
|
48563
48599
|
if (s instanceof Statements.Type) {
|
|
@@ -70138,7 +70174,7 @@ class Registry {
|
|
|
70138
70174
|
}
|
|
70139
70175
|
static abaplintVersion() {
|
|
70140
70176
|
// magic, see build script "version.js"
|
|
70141
|
-
return "2.120.
|
|
70177
|
+
return "2.120.41";
|
|
70142
70178
|
}
|
|
70143
70179
|
getDDICReferences() {
|
|
70144
70180
|
return this.ddicReferences;
|
|
@@ -72829,7 +72865,7 @@ const KNOWN_CURR_DATA_ELEMENTS = ["BWERT", "DZWERT"];
|
|
|
72829
72865
|
const RESERVED_ELEMENT_NAMES = ["BEGIN", "NUMBER", "POSITION"];
|
|
72830
72866
|
const MAX_LABEL_LENGTH = 40;
|
|
72831
72867
|
// Annotations which are not supported in CDS view entities
|
|
72832
|
-
const VIEW_ENTITY_FORBIDDEN_ANNOTATIONS = ["Semantics.unitOfMeasure"];
|
|
72868
|
+
const VIEW_ENTITY_FORBIDDEN_ANNOTATIONS = ["Semantics.unitOfMeasure", "Semantics.currencyCode"];
|
|
72833
72869
|
class CDSCheckSyntax {
|
|
72834
72870
|
constructor() {
|
|
72835
72871
|
this.conf = new CDSCheckSyntaxConf();
|
|
@@ -72873,6 +72909,7 @@ Missing objects are only reported when their names match the configured errorNam
|
|
|
72873
72909
|
this.checkFieldAnnotations(tree, ddic, issues, file);
|
|
72874
72910
|
this.checkLabels(tree, issues, file);
|
|
72875
72911
|
this.checkViewEntityAnnotations(tree, issues, file);
|
|
72912
|
+
this.checkSearchable(tree, issues, file);
|
|
72876
72913
|
this.checkReservedNames(tree, issues, file);
|
|
72877
72914
|
this.checkFields(tree, sources, object, issues, file);
|
|
72878
72915
|
return issues;
|
|
@@ -73094,6 +73131,29 @@ Missing objects are only reported when their names match the configured errorNam
|
|
|
73094
73131
|
}
|
|
73095
73132
|
}
|
|
73096
73133
|
}
|
|
73134
|
+
checkSearchable(tree, issues, file) {
|
|
73135
|
+
let searchable;
|
|
73136
|
+
for (const annotation of tree.findAllExpressionsRecursive(expressions_1.CDSAnnotation)) {
|
|
73137
|
+
const normalized = annotation.concatTokens().replace(/\s/g, "").toUpperCase().replace(/^@</, "@");
|
|
73138
|
+
if (this.hasSearchAnnotation(normalized, "defaultSearchElement")) {
|
|
73139
|
+
return;
|
|
73140
|
+
}
|
|
73141
|
+
else if (searchable === undefined && this.hasSearchAnnotation(normalized, "searchable")) {
|
|
73142
|
+
searchable = annotation;
|
|
73143
|
+
}
|
|
73144
|
+
}
|
|
73145
|
+
if (searchable !== undefined) {
|
|
73146
|
+
const message = "@Search.defaultSearchElement: true required on at least one element " +
|
|
73147
|
+
"when @Search.searchable: true";
|
|
73148
|
+
issues.push(issue_1.Issue.atToken(file, searchable.getFirstToken(), message, this.getMetadata().key, this.conf.severity));
|
|
73149
|
+
}
|
|
73150
|
+
}
|
|
73151
|
+
hasSearchAnnotation(normalized, name) {
|
|
73152
|
+
if (normalized.startsWith("@SEARCH") === false) {
|
|
73153
|
+
return false;
|
|
73154
|
+
}
|
|
73155
|
+
return new RegExp("[.{,]" + name.toUpperCase() + ":TRUE").test(normalized);
|
|
73156
|
+
}
|
|
73097
73157
|
checkReservedNames(tree, issues, file) {
|
|
73098
73158
|
var _a, _b;
|
|
73099
73159
|
for (const element of tree.findAllExpressionsRecursive(expressions_1.CDSElement)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abaplint/cli",
|
|
3
|
-
"version": "2.120.
|
|
3
|
+
"version": "2.120.41",
|
|
4
4
|
"description": "abaplint - Command Line Interface",
|
|
5
5
|
"funding": "https://github.com/sponsors/larshp",
|
|
6
6
|
"bin": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"homepage": "https://abaplint.org",
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@abaplint/core": "^2.120.
|
|
42
|
+
"@abaplint/core": "^2.120.41",
|
|
43
43
|
"@types/chai": "^4.3.20",
|
|
44
44
|
"@types/minimist": "^1.2.5",
|
|
45
45
|
"@types/mocha": "^10.0.10",
|