@abaplint/cli 2.120.51 → 2.120.53
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 +97 -11
- package/package.json +2 -2
package/build/cli.js
CHANGED
|
@@ -53,6 +53,13 @@ const BUFS = new Set([
|
|
|
53
53
|
CH_DOT, CH_COMMA, CH_COLON, 40 /* ( */, 41 /* ) */, 91 /* [ */,
|
|
54
54
|
93 /* ] */, 43 /* + */, CH_AT
|
|
55
55
|
]);
|
|
56
|
+
// characters that may follow the closing "'", "`" or "|" of a literal, anything else
|
|
57
|
+
// is a syntax error, "There must be a space or equivalent character after ...",
|
|
58
|
+
// note that "(" is allowed, ie. text elements like 'text'(001)
|
|
59
|
+
const AFTER_LITERAL = new Set([
|
|
60
|
+
EOF, CH_SPACE, CH_TAB, CH_NL, CH_DOT, CH_COMMA, CH_COLON, CH_DQUOTE,
|
|
61
|
+
40 /* ( */, 41 /* ) */, 91 /* [ */, 93 /* ] */
|
|
62
|
+
]);
|
|
56
63
|
class Lexer {
|
|
57
64
|
run(file, virtual) {
|
|
58
65
|
this.virtual = virtual;
|
|
@@ -332,7 +339,11 @@ class Lexer {
|
|
|
332
339
|
&& ahead !== CH_BACKTICK
|
|
333
340
|
&& this.buffer.countIsEven(CH_BACKTICK)) {
|
|
334
341
|
// end of ping
|
|
335
|
-
|
|
342
|
+
if (AFTER_LITERAL.has(ahead)) {
|
|
343
|
+
this.add();
|
|
344
|
+
}
|
|
345
|
+
// else: no separator after the literal, keep the buffer so the following
|
|
346
|
+
// characters are glued onto the token, the parser will report the error
|
|
336
347
|
if (ahead === CH_DQUOTE) {
|
|
337
348
|
this.m = ModeComment;
|
|
338
349
|
}
|
|
@@ -345,7 +356,9 @@ class Lexer {
|
|
|
345
356
|
&& (current === CH_PIPE || current === CH_LBRACE)
|
|
346
357
|
&& (stream.prevChar() !== CH_BACKSLASH || (stream.prevPrevChar() === CH_BACKSLASH && stream.prevChar() === CH_BACKSLASH))) {
|
|
347
358
|
// end of template
|
|
348
|
-
|
|
359
|
+
if (current === CH_LBRACE || AFTER_LITERAL.has(ahead)) {
|
|
360
|
+
this.add();
|
|
361
|
+
}
|
|
349
362
|
this.m = ModeNormal;
|
|
350
363
|
}
|
|
351
364
|
else if (this.m === ModeTemplate
|
|
@@ -360,7 +373,9 @@ class Lexer {
|
|
|
360
373
|
&& ahead !== CH_QUOTE
|
|
361
374
|
&& this.buffer.countIsEven(CH_QUOTE)) {
|
|
362
375
|
// end of string
|
|
363
|
-
|
|
376
|
+
if (AFTER_LITERAL.has(ahead)) {
|
|
377
|
+
this.add();
|
|
378
|
+
}
|
|
364
379
|
if (ahead === CH_DQUOTE) {
|
|
365
380
|
this.m = ModeComment;
|
|
366
381
|
}
|
|
@@ -24650,12 +24665,15 @@ class ABAPFileInformationParser {
|
|
|
24650
24665
|
continue;
|
|
24651
24666
|
}
|
|
24652
24667
|
const parameters = this.parseMethodParameters(def);
|
|
24668
|
+
const concatenated = def.concatTokens().toUpperCase();
|
|
24653
24669
|
methods.push({
|
|
24654
24670
|
name: methodName.getStr(),
|
|
24655
24671
|
identifier: new _identifier_1.Identifier(methodName, this.filename),
|
|
24656
24672
|
isRedefinition: def.findDirectExpression(Expressions.Redefinition) !== undefined,
|
|
24657
|
-
isForTesting:
|
|
24658
|
-
isFinal:
|
|
24673
|
+
isForTesting: concatenated.includes(" FOR TESTING"),
|
|
24674
|
+
isFinal: concatenated.includes(" FINAL"),
|
|
24675
|
+
isDefaultIgnore: concatenated.includes(" DEFAULT IGNORE"),
|
|
24676
|
+
isDefaultFail: concatenated.includes(" DEFAULT FAIL"),
|
|
24659
24677
|
isAbstract: def.findDirectExpression(Expressions.Abstract) !== undefined,
|
|
24660
24678
|
isEventHandler: def.findDirectExpression(Expressions.EventHandler) !== undefined,
|
|
24661
24679
|
visibility,
|
|
@@ -34725,6 +34743,7 @@ class Source {
|
|
|
34725
34743
|
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
34726
34744
|
}
|
|
34727
34745
|
this.addIfInferred(node, input, foundType);
|
|
34746
|
+
this.traverseRemainingChildren(children, input);
|
|
34728
34747
|
return foundType;
|
|
34729
34748
|
}
|
|
34730
34749
|
case "REF":
|
|
@@ -34820,11 +34839,15 @@ class Source {
|
|
|
34820
34839
|
}
|
|
34821
34840
|
let hexExpected = false;
|
|
34822
34841
|
let hexNext = false;
|
|
34842
|
+
// an arithmetic operator has been seen, so the operands that follow
|
|
34843
|
+
// determine a calculation type rather than simply replacing the context
|
|
34844
|
+
let arithmetic = false;
|
|
34823
34845
|
while (children.length >= 0) {
|
|
34824
34846
|
if (first instanceof nodes_1.ExpressionNode) {
|
|
34825
34847
|
const get = first.get();
|
|
34826
34848
|
if (get instanceof Expressions.MethodCallChain) {
|
|
34827
|
-
|
|
34849
|
+
const found = method_call_chain_1.MethodCallChain.runSyntax(first, input, targetType);
|
|
34850
|
+
context = arithmetic === true ? this.infer(context, found, true) : found;
|
|
34828
34851
|
if (context === undefined) {
|
|
34829
34852
|
const message = "Method has no RETURNING value";
|
|
34830
34853
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
@@ -34832,18 +34855,19 @@ class Source {
|
|
|
34832
34855
|
}
|
|
34833
34856
|
}
|
|
34834
34857
|
else if (get instanceof Expressions.FieldChain) {
|
|
34835
|
-
|
|
34858
|
+
const found = field_chain_1.FieldChain.runSyntax(first, input, type, allowGenericDeference);
|
|
34859
|
+
context = arithmetic === true ? this.infer(context, found, true) : found;
|
|
34836
34860
|
}
|
|
34837
34861
|
else if (get instanceof Expressions.StringTemplate) {
|
|
34838
34862
|
context = string_template_1.StringTemplate.runSyntax(first, input);
|
|
34839
34863
|
}
|
|
34840
34864
|
else if (get instanceof Expressions.Source) {
|
|
34841
34865
|
const found = Source.runSyntax(first, input);
|
|
34842
|
-
context = this.infer(context, found);
|
|
34866
|
+
context = this.infer(context, found, arithmetic);
|
|
34843
34867
|
}
|
|
34844
34868
|
else if (get instanceof Expressions.Constant) {
|
|
34845
34869
|
const found = constant_1.Constant.runSyntax(first);
|
|
34846
|
-
context = this.infer(context, found);
|
|
34870
|
+
context = this.infer(context, found, arithmetic);
|
|
34847
34871
|
}
|
|
34848
34872
|
else if (get instanceof Expressions.Dereference) {
|
|
34849
34873
|
context = dereference_1.Dereference.runSyntax(first, context, input);
|
|
@@ -34852,6 +34876,7 @@ class Source {
|
|
|
34852
34876
|
context = component_chain_1.ComponentChain.runSyntax(context, first, input);
|
|
34853
34877
|
}
|
|
34854
34878
|
else if (get instanceof Expressions.ArithOperator) {
|
|
34879
|
+
arithmetic = true;
|
|
34855
34880
|
if (first.concatTokens() === "**") {
|
|
34856
34881
|
context = new basic_1.FloatType();
|
|
34857
34882
|
}
|
|
@@ -34898,7 +34923,13 @@ class Source {
|
|
|
34898
34923
|
Source.runSyntax(last, input);
|
|
34899
34924
|
}
|
|
34900
34925
|
}
|
|
34901
|
-
static infer(context, found) {
|
|
34926
|
+
static infer(context, found, arithmetic = false) {
|
|
34927
|
+
if (arithmetic === true) {
|
|
34928
|
+
const calculation = this.calculationType(context, found);
|
|
34929
|
+
if (calculation !== undefined) {
|
|
34930
|
+
return calculation;
|
|
34931
|
+
}
|
|
34932
|
+
}
|
|
34902
34933
|
if (context instanceof basic_1.FloatType && found instanceof basic_1.IntegerType) {
|
|
34903
34934
|
return context;
|
|
34904
34935
|
}
|
|
@@ -34912,6 +34943,56 @@ class Source {
|
|
|
34912
34943
|
return found;
|
|
34913
34944
|
}
|
|
34914
34945
|
}
|
|
34946
|
+
/** The calculation type of an arithmetic expression is the most general of the
|
|
34947
|
+
* operand types. An operand of type c, n, d, t or string is converted into it and
|
|
34948
|
+
* never becomes the result: "lv_f * '0.25'" is a float, not a character field of
|
|
34949
|
+
* length four. Returns undefined when neither operand is numeric, leaving the
|
|
34950
|
+
* decision to the caller. */
|
|
34951
|
+
static calculationType(left, right) {
|
|
34952
|
+
if (left === undefined || right === undefined) {
|
|
34953
|
+
return undefined;
|
|
34954
|
+
}
|
|
34955
|
+
else if (left instanceof basic_1.VoidType || left instanceof unknown_type_1.UnknownType) {
|
|
34956
|
+
// not knowing an operand means not knowing the result
|
|
34957
|
+
return left;
|
|
34958
|
+
}
|
|
34959
|
+
else if (right instanceof basic_1.VoidType || right instanceof unknown_type_1.UnknownType) {
|
|
34960
|
+
return right;
|
|
34961
|
+
}
|
|
34962
|
+
const leftRank = this.numericRank(left);
|
|
34963
|
+
const rightRank = this.numericRank(right);
|
|
34964
|
+
if (leftRank === undefined && rightRank === undefined) {
|
|
34965
|
+
return undefined;
|
|
34966
|
+
}
|
|
34967
|
+
else if (rightRank === undefined) {
|
|
34968
|
+
return left;
|
|
34969
|
+
}
|
|
34970
|
+
else if (leftRank === undefined) {
|
|
34971
|
+
return right;
|
|
34972
|
+
}
|
|
34973
|
+
return leftRank >= rightRank ? left : right;
|
|
34974
|
+
}
|
|
34975
|
+
static numericRank(type) {
|
|
34976
|
+
if (type instanceof basic_1.DecFloat34Type) {
|
|
34977
|
+
return 6;
|
|
34978
|
+
}
|
|
34979
|
+
else if (type instanceof basic_1.DecFloat16Type) {
|
|
34980
|
+
return 5;
|
|
34981
|
+
}
|
|
34982
|
+
else if (type instanceof basic_1.FloatType) {
|
|
34983
|
+
return 4;
|
|
34984
|
+
}
|
|
34985
|
+
else if (type instanceof basic_1.PackedType) {
|
|
34986
|
+
return 3;
|
|
34987
|
+
}
|
|
34988
|
+
else if (type instanceof basic_1.Integer8Type) {
|
|
34989
|
+
return 2;
|
|
34990
|
+
}
|
|
34991
|
+
else if (type instanceof basic_1.IntegerType) {
|
|
34992
|
+
return 1;
|
|
34993
|
+
}
|
|
34994
|
+
return undefined;
|
|
34995
|
+
}
|
|
34915
34996
|
static addIfInferred(node, input, inferredType) {
|
|
34916
34997
|
const basic = new basic_types_1.BasicTypes(input);
|
|
34917
34998
|
const typeExpression = node.findDirectExpression(Expressions.TypeNameOrInfer);
|
|
@@ -70563,7 +70644,7 @@ class Registry {
|
|
|
70563
70644
|
}
|
|
70564
70645
|
static abaplintVersion() {
|
|
70565
70646
|
// magic, see build script "version.js"
|
|
70566
|
-
return "2.120.
|
|
70647
|
+
return "2.120.53";
|
|
70567
70648
|
}
|
|
70568
70649
|
getDDICReferences() {
|
|
70569
70650
|
return this.ddicReferences;
|
|
@@ -84170,6 +84251,11 @@ class ImplementMethods extends _abap_rule_1.ABAPRule {
|
|
|
84170
84251
|
return [idef];
|
|
84171
84252
|
}
|
|
84172
84253
|
for (const m of this.findInterfaceMethods(idef)) {
|
|
84254
|
+
if (m.method.isDefaultIgnore === true || m.method.isDefaultFail === true) {
|
|
84255
|
+
// the interface says an implementation is optional, so asking for one
|
|
84256
|
+
// reports an error where ABAP reports none
|
|
84257
|
+
continue;
|
|
84258
|
+
}
|
|
84173
84259
|
if (this.isAbstract(m, interfaceInfo, def)) {
|
|
84174
84260
|
if (def.isAbstract) {
|
|
84175
84261
|
continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abaplint/cli",
|
|
3
|
-
"version": "2.120.
|
|
3
|
+
"version": "2.120.53",
|
|
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.53",
|
|
43
43
|
"@types/chai": "^4.3.20",
|
|
44
44
|
"@types/minimist": "^1.2.5",
|
|
45
45
|
"@types/mocha": "^10.0.10",
|