@abaplint/core 2.115.28 → 2.116.1
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/src/cds/cds_lexer.js +15 -2
- package/build/src/cds/expressions/cds_aggregate.js +6 -3
- package/build/src/cds/expressions/cds_annotation.js +3 -3
- package/build/src/cds/expressions/cds_annotation_array.js +1 -1
- package/build/src/cds/expressions/cds_annotation_object.js +1 -1
- package/build/src/cds/expressions/cds_annotation_simple.js +6 -1
- package/build/src/cds/expressions/cds_arithmetics.js +3 -2
- package/build/src/cds/expressions/cds_as.js +3 -1
- package/build/src/cds/expressions/cds_association.js +13 -1
- package/build/src/cds/expressions/cds_cardinality.js +6 -4
- package/build/src/cds/expressions/cds_case.js +7 -3
- package/build/src/cds/expressions/cds_composition.js +7 -1
- package/build/src/cds/expressions/cds_condition.js +6 -4
- package/build/src/cds/expressions/cds_define_abstract.js +1 -1
- package/build/src/cds/expressions/cds_define_custom.js +1 -1
- package/build/src/cds/expressions/cds_define_hierarchy.js +3 -3
- package/build/src/cds/expressions/cds_define_projection.js +1 -1
- package/build/src/cds/expressions/cds_define_table_function.js +1 -1
- package/build/src/cds/expressions/cds_define_view.js +1 -1
- package/build/src/cds/expressions/cds_element.js +8 -2
- package/build/src/cds/expressions/cds_extend_view.js +1 -1
- package/build/src/cds/expressions/cds_function.js +16 -1
- package/build/src/cds/expressions/cds_integer.js +5 -1
- package/build/src/cds/expressions/cds_join.js +11 -2
- package/build/src/cds/expressions/cds_prefixed_name.js +17 -6
- package/build/src/cds/expressions/cds_select.js +3 -2
- package/build/src/cds/expressions/cds_source.js +6 -3
- package/build/src/cds/expressions/cds_string.js +10 -5
- package/build/src/cds/expressions/cds_type.js +1 -1
- package/build/src/cds/expressions/cds_with_parameters.js +1 -1
- package/build/src/objects/data_definition.js +21 -6
- package/build/src/registry.js +1 -1
- package/build/src/rules/aff_and_xml.js +57 -0
- package/build/src/rules/definitions_top.js +2 -2
- package/build/src/rules/fm_global_parameters_obsolete.js +1 -1
- package/build/src/rules/index.js +1 -0
- package/package.json +5 -5
|
@@ -56,7 +56,7 @@ class CDSLexer {
|
|
|
56
56
|
let row = 1;
|
|
57
57
|
let col = 1;
|
|
58
58
|
let build = "";
|
|
59
|
-
const stream = new Stream(file.getRaw().replace(/\r/g, "").replace(/\u00a0/g, " "));
|
|
59
|
+
const stream = new Stream(file.getRaw().replace(/\r/g, "").replace(/\u00a0/g, " ").replace(/\u000b/g, " "));
|
|
60
60
|
let next = "";
|
|
61
61
|
while (stream.length() > 0) {
|
|
62
62
|
const prev = next;
|
|
@@ -67,7 +67,17 @@ class CDSLexer {
|
|
|
67
67
|
if (mode === Mode.String) {
|
|
68
68
|
build += next;
|
|
69
69
|
if (next === "'" && nextNext === "'") {
|
|
70
|
-
// escaped single quote, continue string
|
|
70
|
+
// escaped single quote (doubled), continue string
|
|
71
|
+
build += stream.takeNext();
|
|
72
|
+
col++;
|
|
73
|
+
}
|
|
74
|
+
else if (next === "\\" && nextNext === "\\") {
|
|
75
|
+
// escaped backslash (e.g. '\\' in ltrim/rtrim calls), consume both chars
|
|
76
|
+
build += stream.takeNext();
|
|
77
|
+
col++;
|
|
78
|
+
}
|
|
79
|
+
else if (next === "\\" && nextNext === "'") {
|
|
80
|
+
// backslash-escaped single quote, continue string
|
|
71
81
|
build += stream.takeNext();
|
|
72
82
|
col++;
|
|
73
83
|
}
|
|
@@ -113,6 +123,8 @@ class CDSLexer {
|
|
|
113
123
|
else if (mode === Mode.Default && next === "/" && nextNext === "*") {
|
|
114
124
|
mode = Mode.MultiLineComment;
|
|
115
125
|
build = result.add(build, row, col, mode);
|
|
126
|
+
stream.takeNext(); // consume the '*' so it doesn't become prev for '*/' detection
|
|
127
|
+
col++;
|
|
116
128
|
continue;
|
|
117
129
|
}
|
|
118
130
|
switch (next) {
|
|
@@ -140,6 +152,7 @@ class CDSLexer {
|
|
|
140
152
|
case ")":
|
|
141
153
|
case "[":
|
|
142
154
|
case "]":
|
|
155
|
+
case "!":
|
|
143
156
|
case "=":
|
|
144
157
|
case "<":
|
|
145
158
|
case ">":
|
|
@@ -5,9 +5,12 @@ const _1 = require(".");
|
|
|
5
5
|
const combi_1 = require("../../abap/2_statements/combi");
|
|
6
6
|
class CDSAggregate extends combi_1.Expression {
|
|
7
7
|
getRunnable() {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
// CDSPrefixedName handles dotted paths with path filters e.g. a._Assoc[filter].Field
|
|
9
|
+
// CDSArithmetics handles expressions like sum(A + B), max(A * 100)
|
|
10
|
+
// fieldAsType handles avg(field AS type) / sum(field AS type) — SAP inline type coercion
|
|
11
|
+
const fieldAsType = (0, combi_1.seq)(_1.CDSPrefixedName, "AS", _1.CDSType);
|
|
12
|
+
const value = (0, combi_1.altPrio)(_1.CDSArithmetics, _1.CDSCast, _1.CDSCase, _1.CDSFunction, fieldAsType, _1.CDSPrefixedName, _1.CDSString, "*");
|
|
13
|
+
return (0, combi_1.seq)((0, combi_1.altPrio)("MAX", "MIN", "SUM", "AVG", "COUNT"), "(", (0, combi_1.optPrio)((0, combi_1.altPrio)("DISTINCT", "ALL")), value, ")");
|
|
11
14
|
}
|
|
12
15
|
}
|
|
13
16
|
exports.CDSAggregate = CDSAggregate;
|
|
@@ -7,9 +7,9 @@ const cds_annotation_array_1 = require("./cds_annotation_array");
|
|
|
7
7
|
class CDSAnnotation extends combi_1.Expression {
|
|
8
8
|
getRunnable() {
|
|
9
9
|
const nameWithSlash = (0, combi_1.seq)((0, combi_1.regex)(/^\w+$/), (0, combi_1.star)((0, combi_1.seq)("/", (0, combi_1.regex)(/^\w+$/))));
|
|
10
|
-
// Support both "@Name" (single token)
|
|
11
|
-
const annotationStart = (0, combi_1.alt)((0, combi_1.regex)(/^@\w+$/), (0, combi_1.seq)("@", (0, combi_1.regex)(/^\w+$/)));
|
|
12
|
-
return (0, combi_1.seq)(annotationStart, (0, combi_1.star)((0, combi_1.seq)(".", nameWithSlash)), (0, combi_1.
|
|
10
|
+
// Support both "@Name" (single token), "@ Name" (two tokens), and "@< Name" (inline backward annotation)
|
|
11
|
+
const annotationStart = (0, combi_1.alt)((0, combi_1.regex)(/^@\w+$/), (0, combi_1.seq)("@", (0, combi_1.regex)(/^\w+$/)), (0, combi_1.seq)("@", "<", (0, combi_1.regex)(/^\w+$/)));
|
|
12
|
+
return (0, combi_1.seq)(annotationStart, (0, combi_1.star)((0, combi_1.seq)(".", nameWithSlash)), (0, combi_1.optPrio)((0, combi_1.seq)(":", (0, combi_1.alt)(cds_annotation_array_1.CDSAnnotationArray, _1.CDSAnnotationObject, _1.CDSAnnotationSimple))));
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
exports.CDSAnnotation = CDSAnnotation;
|
|
@@ -7,7 +7,7 @@ const cds_annotation_simple_1 = require("./cds_annotation_simple");
|
|
|
7
7
|
class CDSAnnotationArray extends combi_1.Expression {
|
|
8
8
|
getRunnable() {
|
|
9
9
|
const value = (0, combi_1.alt)(cds_annotation_simple_1.CDSAnnotationSimple, _1.CDSAnnotationObject, CDSAnnotationArray);
|
|
10
|
-
const valueList = (0, combi_1.seq)("[", value, (0, combi_1.
|
|
10
|
+
const valueList = (0, combi_1.seq)("[", value, (0, combi_1.star)((0, combi_1.seq)(",", value)), "]");
|
|
11
11
|
return valueList;
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -8,7 +8,7 @@ class CDSAnnotationObject extends combi_1.Expression {
|
|
|
8
8
|
getRunnable() {
|
|
9
9
|
const value = (0, combi_1.seq)(":", (0, combi_1.alt)(CDSAnnotationObject, _1.CDSAnnotationArray, cds_annotation_simple_1.CDSAnnotationSimple));
|
|
10
10
|
const namedot = (0, combi_1.seq)(_1.CDSName, (0, combi_1.star)((0, combi_1.seq)(".", _1.CDSName)));
|
|
11
|
-
const valueNested = (0, combi_1.seq)("{", namedot, (0, combi_1.
|
|
11
|
+
const valueNested = (0, combi_1.seq)("{", namedot, (0, combi_1.optPrio)(value), (0, combi_1.star)((0, combi_1.seq)(",", namedot, (0, combi_1.optPrio)(value))), "}");
|
|
12
12
|
return valueNested;
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -2,10 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CDSAnnotationSimple = void 0;
|
|
4
4
|
const _1 = require(".");
|
|
5
|
+
const cds_prefixed_name_1 = require("./cds_prefixed_name");
|
|
5
6
|
const combi_1 = require("../../abap/2_statements/combi");
|
|
6
7
|
class CDSAnnotationSimple extends combi_1.Expression {
|
|
7
8
|
getRunnable() {
|
|
8
|
-
const
|
|
9
|
+
const ident = (0, combi_1.regex)(/^[\w_]+$/);
|
|
10
|
+
// #(expr) where expr can be: identifier, dotted path, string, or concatenation with +
|
|
11
|
+
const hashArg = (0, combi_1.altPrio)(_1.CDSString, cds_prefixed_name_1.CDSPrefixedName, ident);
|
|
12
|
+
const hashExpr = (0, combi_1.seq)(hashArg, (0, combi_1.starPrio)((0, combi_1.seq)("+", hashArg)));
|
|
13
|
+
const value = (0, combi_1.altPrio)(_1.CDSString, "true", "false", "null", (0, combi_1.seq)("-", (0, combi_1.regex)(/^\d+$/), ".", (0, combi_1.regex)(/^\d+$/)), (0, combi_1.seq)("-", (0, combi_1.regex)(/^\d+$/)), (0, combi_1.seq)((0, combi_1.regex)(/^\d+$/), ".", (0, combi_1.regex)(/^\d+$/)), (0, combi_1.regex)(/^\d+$/), (0, combi_1.seq)("#", "(", hashExpr, ")"), (0, combi_1.regex)(/^#[\w_]+$/));
|
|
9
14
|
return value;
|
|
10
15
|
}
|
|
11
16
|
}
|
|
@@ -28,10 +28,11 @@ class CDSArithmetics extends combi_1.Expression {
|
|
|
28
28
|
// Unary operator prefix, e.g. -field, +field
|
|
29
29
|
const unary = (0, combi_1.altPrio)("-", "+");
|
|
30
30
|
const unaryExpression = (0, combi_1.seq)(unary, val);
|
|
31
|
-
// An operand is
|
|
31
|
+
// An operand is a paren, unary-prefixed value, or bare value.
|
|
32
|
+
// Including unaryExpression allows "A + + B" and "A + -B" patterns.
|
|
32
33
|
// CDSArithParen = "(" altPrio(CDSArithmetics, CDSArithParen, val) ")" — separate singleton that
|
|
33
34
|
// can recursively contain itself, enabling deeply nested parentheses without infinite recursion.
|
|
34
|
-
const operand = (0, combi_1.altPrio)(_1.CDSArithParen, val);
|
|
35
|
+
const operand = (0, combi_1.altPrio)(_1.CDSArithParen, unaryExpression, val);
|
|
35
36
|
const operatorValue = (0, combi_1.seq)(operator, operand);
|
|
36
37
|
// Main form: operand op operand op ... (leading term may itself be a paren)
|
|
37
38
|
const withOperators = (0, combi_1.seq)(operand, (0, combi_1.plusPrio)(operatorValue));
|
|
@@ -5,7 +5,9 @@ const _1 = require(".");
|
|
|
5
5
|
const combi_1 = require("../../abap/2_statements/combi");
|
|
6
6
|
class CDSAs extends combi_1.Expression {
|
|
7
7
|
getRunnable() {
|
|
8
|
-
|
|
8
|
+
const redirected = (0, combi_1.seq)(": REDIRECTED TO", (0, combi_1.optPrio)((0, combi_1.altPrio)("PARENT", "COMPOSITION CHILD")), _1.CDSName);
|
|
9
|
+
const colonType = (0, combi_1.seq)(":", (0, combi_1.altPrio)(_1.CDSType, _1.CDSName, "LOCALIZED"));
|
|
10
|
+
return (0, combi_1.seq)("AS", _1.CDSName, (0, combi_1.optPrio)((0, combi_1.altPrio)(redirected, colonType)));
|
|
9
11
|
}
|
|
10
12
|
}
|
|
11
13
|
exports.CDSAs = CDSAs;
|
|
@@ -6,7 +6,19 @@ const combi_1 = require("../../abap/2_statements/combi");
|
|
|
6
6
|
const cds_cardinality_1 = require("./cds_cardinality");
|
|
7
7
|
class CDSAssociation extends combi_1.Expression {
|
|
8
8
|
getRunnable() {
|
|
9
|
-
|
|
9
|
+
// Text cardinality: "to exact one", "to one", "to many" — no brackets
|
|
10
|
+
const textCardinality = (0, combi_1.seq)((0, combi_1.opt)("EXACT"), (0, combi_1.altPrio)("ONE", "MANY"));
|
|
11
|
+
// Numeric cardinality: any non-negative integer or * (e.g. [0..1], [1..2], [0..*])
|
|
12
|
+
const cardNum = (0, combi_1.altPrio)((0, combi_1.regex)(/^\d+$/), "*");
|
|
13
|
+
const numericCardinality = (0, combi_1.seq)("[", cardNum, (0, combi_1.optPrio)((0, combi_1.seq)(".", ".", cardNum)), "]");
|
|
14
|
+
// Text-based OF form: "association of one to many Target on ..." — text cardinality includes "TO"
|
|
15
|
+
const ofTextSide = (0, combi_1.altPrio)((0, combi_1.seq)("EXACT", "ONE"), "ONE", "MANY");
|
|
16
|
+
const ofTextForm = (0, combi_1.seq)("ASSOCIATION", "OF", ofTextSide, "TO", ofTextSide, _1.CDSRelation, "ON", _1.CDSCondition);
|
|
17
|
+
// Numeric OF form: "association of [0..1] to Target on ..."
|
|
18
|
+
const ofNumericForm = (0, combi_1.seq)("ASSOCIATION", "OF", numericCardinality, "TO", _1.CDSRelation, "ON", _1.CDSCondition);
|
|
19
|
+
// "association [0..1] to Target as _Alias on condition" — standard form
|
|
20
|
+
const standardForm = (0, combi_1.seq)("ASSOCIATION", (0, combi_1.optPrio)(cds_cardinality_1.CDSCardinality), "TO", (0, combi_1.opt)((0, combi_1.altPrio)(textCardinality, "PARENT")), _1.CDSRelation, "ON", _1.CDSCondition, (0, combi_1.opt)((0, combi_1.seq)("WITH", "DEFAULT", "FILTER", _1.CDSCondition)));
|
|
21
|
+
return (0, combi_1.altPrio)(ofTextForm, ofNumericForm, standardForm);
|
|
10
22
|
}
|
|
11
23
|
}
|
|
12
24
|
exports.CDSAssociation = CDSAssociation;
|
|
@@ -4,10 +4,12 @@ exports.CDSCardinality = void 0;
|
|
|
4
4
|
const combi_1 = require("../../abap/2_statements/combi");
|
|
5
5
|
class CDSCardinality extends combi_1.Expression {
|
|
6
6
|
getRunnable() {
|
|
7
|
-
|
|
8
|
-
const num = (0, combi_1.
|
|
9
|
-
const
|
|
10
|
-
|
|
7
|
+
// Numeric cardinality: any non-negative integer or * (e.g. [0..1], [1..2], [0..*])
|
|
8
|
+
const num = (0, combi_1.altPrio)((0, combi_1.regex)(/^\d+$/), "*");
|
|
9
|
+
const numeric = (0, combi_1.seq)("[", num, (0, combi_1.optPrio)((0, combi_1.seq)(".", ".", num)), "]");
|
|
10
|
+
const textNum = (0, combi_1.altPrio)("ONE", "MANY");
|
|
11
|
+
const text = (0, combi_1.seq)(textNum, "TO", textNum);
|
|
12
|
+
return (0, combi_1.altPrio)(numeric, text);
|
|
11
13
|
}
|
|
12
14
|
}
|
|
13
15
|
exports.CDSCardinality = CDSCardinality;
|
|
@@ -5,9 +5,13 @@ const _1 = require(".");
|
|
|
5
5
|
const combi_1 = require("../../abap/2_statements/combi");
|
|
6
6
|
class CDSCase extends combi_1.Expression {
|
|
7
7
|
getRunnable() {
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
// caseParen: explicit "( case ... end )" alternative placed BEFORE CDSArithmetics.
|
|
9
|
+
// This avoids CDSArithmetics trying ( case ... end ) as an operand (partial match + fail),
|
|
10
|
+
// which causes 2^N backtracking for N levels of nested parenthesized CASE expressions.
|
|
11
|
+
// CDSArithmetics is still tried after for arithmetic like (-1)*Amount or (2*A)-B.
|
|
12
|
+
const caseParen = (0, combi_1.seq)("(", CDSCase, ")");
|
|
13
|
+
const value = (0, combi_1.altPrio)(_1.CDSString, CDSCase, caseParen, _1.CDSArithmetics, _1.CDSCast, _1.CDSAggregate, _1.CDSArithParen, _1.CDSFunction, _1.CDSInteger, _1.CDSPrefixedName);
|
|
14
|
+
const simple = (0, combi_1.seq)((0, combi_1.altPrio)(_1.CDSArithmetics, _1.CDSArithParen, _1.CDSAggregate, _1.CDSFunction, _1.CDSPrefixedName), (0, combi_1.plusPrio)((0, combi_1.seq)("WHEN", value, "THEN", value)));
|
|
11
15
|
const complex = (0, combi_1.plusPrio)((0, combi_1.seq)("WHEN", _1.CDSCondition, "THEN", value));
|
|
12
16
|
return (0, combi_1.seq)("CASE", (0, combi_1.altPrio)(complex, simple), (0, combi_1.optPrio)((0, combi_1.seq)("ELSE", value)), "END");
|
|
13
17
|
}
|
|
@@ -6,7 +6,13 @@ const combi_1 = require("../../abap/2_statements/combi");
|
|
|
6
6
|
const cds_cardinality_1 = require("./cds_cardinality");
|
|
7
7
|
class CDSComposition extends combi_1.Expression {
|
|
8
8
|
getRunnable() {
|
|
9
|
-
|
|
9
|
+
const num = (0, combi_1.altPrio)("ONE", "MANY");
|
|
10
|
+
// Text cardinality after OF: "of exact one to many", "of one to many", or bare "of many" / "of one"
|
|
11
|
+
const textCardinality = (0, combi_1.altPrio)((0, combi_1.seq)((0, combi_1.opt)("EXACT"), num, "TO", num), (0, combi_1.seq)((0, combi_1.opt)("EXACT"), num));
|
|
12
|
+
// Numeric cardinality [n..m] before OF: any non-negative integer or *
|
|
13
|
+
const cardNum = (0, combi_1.altPrio)((0, combi_1.regex)(/^\d+$/), "*");
|
|
14
|
+
const numericCardinality = (0, combi_1.seq)("[", cardNum, (0, combi_1.optPrio)((0, combi_1.seq)(".", ".", cardNum)), "]");
|
|
15
|
+
return (0, combi_1.seq)("COMPOSITION", (0, combi_1.optPrio)(numericCardinality), "OF", (0, combi_1.opt)((0, combi_1.altPrio)(cds_cardinality_1.CDSCardinality, textCardinality)), _1.CDSRelation);
|
|
10
16
|
}
|
|
11
17
|
}
|
|
12
18
|
exports.CDSComposition = CDSComposition;
|
|
@@ -6,20 +6,22 @@ const combi_1 = require("../../abap/2_statements/combi");
|
|
|
6
6
|
const cds_integer_1 = require("./cds_integer");
|
|
7
7
|
class CDSCondition extends combi_1.Expression {
|
|
8
8
|
getRunnable() {
|
|
9
|
-
|
|
9
|
+
// CDSArithmetics before CDSCast/CDSFunction so cast(A)-cast(B) is handled as arithmetic, not two separate casts
|
|
10
|
+
// CDSCase allows nested case expressions on either side of a comparison
|
|
11
|
+
const left = (0, combi_1.altPrio)(_1.CDSString, _1.CDSArithmetics, _1.CDSCast, _1.CDSFunction, _1.CDSAggregate, _1.CDSCase, _1.CDSArithParen, _1.CDSPrefixedName);
|
|
10
12
|
const nonLikeOperators = (0, combi_1.altPrio)("=", (0, combi_1.seq)("!", "="), (0, combi_1.seq)("<", ">"), (0, combi_1.seq)(">", "="), (0, combi_1.seq)("<", "="), "<", ">");
|
|
11
13
|
const likeOperators = (0, combi_1.altPrio)("LIKE", "NOT LIKE");
|
|
12
14
|
// Right side of comparison: simple values first, then parenthesized, then full arithmetic last.
|
|
13
15
|
// CDSArithmetics is last to avoid triggering CDSPrefixedName→CDSCondition→CDSArithmetics cycle.
|
|
14
16
|
const right = (0, combi_1.altPrio)(_1.CDSArithParen, left, cds_integer_1.CDSInteger, _1.CDSArithmetics);
|
|
15
17
|
// ESCAPE is only valid with LIKE/NOT LIKE, not with other comparison operators.
|
|
16
|
-
const compare = (0, combi_1.altPrio)((0, combi_1.seq)(likeOperators, right, (0, combi_1.
|
|
18
|
+
const compare = (0, combi_1.altPrio)((0, combi_1.seq)(likeOperators, right, (0, combi_1.optPrio)((0, combi_1.seq)("ESCAPE", _1.CDSString))), (0, combi_1.seq)(nonLikeOperators, right));
|
|
17
19
|
const is = (0, combi_1.seq)("IS", (0, combi_1.optPrio)("NOT"), (0, combi_1.altPrio)("INITIAL", "NULL"));
|
|
18
|
-
const between = (0, combi_1.seq)("BETWEEN", left, "AND", left);
|
|
20
|
+
const between = (0, combi_1.seq)((0, combi_1.altPrio)("NOT BETWEEN", "BETWEEN"), left, "AND", left);
|
|
19
21
|
const condition = (0, combi_1.seq)((0, combi_1.optPrio)("NOT"), left, (0, combi_1.altPrio)(compare, is, between));
|
|
20
22
|
const paren = (0, combi_1.seq)("(", CDSCondition, ")");
|
|
21
23
|
const notParen = (0, combi_1.seq)("NOT", paren);
|
|
22
|
-
return (0, combi_1.seq)((0, combi_1.altPrio)(condition, notParen, paren), (0, combi_1.
|
|
24
|
+
return (0, combi_1.seq)((0, combi_1.altPrio)(condition, notParen, paren), (0, combi_1.star)((0, combi_1.seq)((0, combi_1.altPrio)("AND", "OR"), (0, combi_1.altPrio)(condition, notParen, paren))));
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
27
|
exports.CDSCondition = CDSCondition;
|
|
@@ -6,7 +6,7 @@ const combi_1 = require("../../abap/2_statements/combi");
|
|
|
6
6
|
const cds_name_1 = require("./cds_name");
|
|
7
7
|
class CDSDefineAbstract extends combi_1.Expression {
|
|
8
8
|
getRunnable() {
|
|
9
|
-
const field = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.
|
|
9
|
+
const field = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.optPrio)((0, combi_1.str)("KEY")), cds_name_1.CDSName, ":", _1.CDSType, ";");
|
|
10
10
|
const compsiOrAssoci = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), cds_name_1.CDSName, ":", (0, combi_1.alt)(_1.CDSComposition, _1.CDSAssociation), ";");
|
|
11
11
|
return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), "DEFINE", (0, combi_1.opt)("ROOT"), "ABSTRACT", "ENTITY", cds_name_1.CDSName, (0, combi_1.str)("{"), (0, combi_1.plus)((0, combi_1.alt)(field, compsiOrAssoci)), (0, combi_1.str)("}"), (0, combi_1.opt)(";"));
|
|
12
12
|
}
|
|
@@ -7,7 +7,7 @@ const cds_name_1 = require("./cds_name");
|
|
|
7
7
|
const cds_type_1 = require("./cds_type");
|
|
8
8
|
class CDSDefineCustom extends combi_1.Expression {
|
|
9
9
|
getRunnable() {
|
|
10
|
-
const field = (0, combi_1.seq)((0, combi_1.
|
|
10
|
+
const field = (0, combi_1.seq)((0, combi_1.optPrio)((0, combi_1.str)("KEY")), cds_name_1.CDSName, ":", cds_type_1.CDSType, ";");
|
|
11
11
|
const compsiOrAssoci = (0, combi_1.seq)(cds_name_1.CDSName, ":", (0, combi_1.alt)(_1.CDSComposition, _1.CDSAssociation), ";");
|
|
12
12
|
return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.str)("DEFINE"), (0, combi_1.opt)((0, combi_1.str)("ROOT")), (0, combi_1.str)("CUSTOM ENTITY"), cds_name_1.CDSName, (0, combi_1.opt)(_1.CDSWithParameters), (0, combi_1.str)("{"), (0, combi_1.plus)((0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.alt)(field, compsiOrAssoci))), (0, combi_1.str)("}"), (0, combi_1.opt)(";"));
|
|
13
13
|
}
|
|
@@ -5,12 +5,12 @@ const _1 = require(".");
|
|
|
5
5
|
const combi_1 = require("../../abap/2_statements/combi");
|
|
6
6
|
class CDSDefineHierarchy extends combi_1.Expression {
|
|
7
7
|
getRunnable() {
|
|
8
|
-
const field = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.
|
|
8
|
+
const field = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.optPrio)("KEY"), _1.CDSPrefixedName, (0, combi_1.optPrio)(_1.CDSAs));
|
|
9
9
|
const sortDirection = (0, combi_1.altPrio)("ASCENDING", "DESCENDING");
|
|
10
|
-
const siblingsOrderField = (0, combi_1.seq)(_1.CDSPrefixedName, (0, combi_1.
|
|
10
|
+
const siblingsOrderField = (0, combi_1.seq)(_1.CDSPrefixedName, (0, combi_1.optPrio)(sortDirection));
|
|
11
11
|
const siblingsOrder = (0, combi_1.seq)("SIBLINGS", "ORDER", "BY", siblingsOrderField, (0, combi_1.star)((0, combi_1.seq)(",", siblingsOrderField)));
|
|
12
12
|
const directory = (0, combi_1.seq)("DIRECTORY", _1.CDSName, "FILTER", "BY", _1.CDSCondition);
|
|
13
|
-
const hierarchyBody = (0, combi_1.seq)("SOURCE", _1.CDSName, (0, combi_1.opt)(_1.CDSParametersSelect), "CHILD", "TO", "PARENT", "ASSOCIATION", _1.CDSName, (0, combi_1.opt)(directory), (0, combi_1.opt)((0, combi_1.seq)("START", "WHERE", _1.CDSCondition)), (0, combi_1.opt)(siblingsOrder), (0, combi_1.opt)((0, combi_1.seq)("NODETYPE", _1.CDSName)), (0, combi_1.opt)((0, combi_1.seq)("MULTIPLE", "PARENTS", "ALLOWED")), (0, combi_1.opt)((0, combi_1.seq)("ORPHANS", (0, combi_1.altPrio)("IGNORE", "ROOT"))), (0, combi_1.opt)((0, combi_1.seq)("CYCLES", "BREAKUP")), (0, combi_1.opt)((0, combi_1.seq)("CACHE", (0, combi_1.altPrio)("FORCE", "NONE", "EMPTY"))));
|
|
13
|
+
const hierarchyBody = (0, combi_1.seq)("SOURCE", _1.CDSName, (0, combi_1.opt)(_1.CDSParametersSelect), "CHILD", "TO", "PARENT", "ASSOCIATION", _1.CDSName, (0, combi_1.opt)(directory), (0, combi_1.opt)((0, combi_1.seq)("START", "WHERE", _1.CDSCondition)), (0, combi_1.opt)(siblingsOrder), (0, combi_1.opt)((0, combi_1.seq)("NODETYPE", _1.CDSName)), (0, combi_1.opt)((0, combi_1.seq)("DEPTH", _1.CDSInteger)), (0, combi_1.opt)((0, combi_1.seq)("MULTIPLE", "PARENTS", (0, combi_1.altPrio)("NOT ALLOWED", "ALLOWED"))), (0, combi_1.opt)((0, combi_1.seq)("ORPHANS", (0, combi_1.altPrio)("IGNORE", "ROOT"))), (0, combi_1.opt)((0, combi_1.seq)("CYCLES", "BREAKUP")), (0, combi_1.opt)((0, combi_1.seq)("CACHE", (0, combi_1.altPrio)("FORCE", "NONE", "EMPTY", "OFF"))));
|
|
14
14
|
return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), "DEFINE", "HIERARCHY", _1.CDSName, (0, combi_1.opt)(_1.CDSWithParameters), "AS", "PARENT", "CHILD", "HIERARCHY", "(", hierarchyBody, ")", "{", (0, combi_1.seq)(field, (0, combi_1.star)((0, combi_1.seq)(",", field))), "}", (0, combi_1.opt)(";"));
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -6,7 +6,7 @@ const __1 = require("../..");
|
|
|
6
6
|
const combi_1 = require("../../abap/2_statements/combi");
|
|
7
7
|
class CDSDefineProjection extends combi_1.Expression {
|
|
8
8
|
getRunnable() {
|
|
9
|
-
return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), "DEFINE", (0, combi_1.opt)("ROOT"), "VIEW", (0, combi_1.ver)(__1.Version.v755, (0, combi_1.opt)("ENTITY")), _1.CDSName, (0, combi_1.opt)(_1.CDSProviderContract), "AS PROJECTION ON", _1.CDSName, (0, combi_1.opt)(_1.CDSAs), (0, combi_1.str)("{"), (0, combi_1.
|
|
9
|
+
return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), "DEFINE", (0, combi_1.opt)("ROOT"), (0, combi_1.opt)("TRANSIENT"), "VIEW", (0, combi_1.ver)(__1.Version.v755, (0, combi_1.opt)("ENTITY")), _1.CDSName, (0, combi_1.opt)(_1.CDSProviderContract), (0, combi_1.opt)(_1.CDSWithParameters), "AS PROJECTION ON", _1.CDSName, (0, combi_1.opt)(_1.CDSParametersSelect), (0, combi_1.opt)(_1.CDSAs), (0, combi_1.star)(_1.CDSAssociation), (0, combi_1.str)("{"), (0, combi_1.seq)(_1.CDSElement, (0, combi_1.star)((0, combi_1.seq)(",", _1.CDSElement)), (0, combi_1.opt)(",")), (0, combi_1.str)("}"), (0, combi_1.opt)(_1.CDSWhere), (0, combi_1.opt)(";"));
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
exports.CDSDefineProjection = CDSDefineProjection;
|
|
@@ -7,7 +7,7 @@ const cds_name_1 = require("./cds_name");
|
|
|
7
7
|
class CDSDefineTableFunction extends combi_1.Expression {
|
|
8
8
|
getRunnable() {
|
|
9
9
|
const methodName = (0, combi_1.seq)(cds_name_1.CDSName, "=", ">", cds_name_1.CDSName);
|
|
10
|
-
return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.str)("DEFINE TABLE FUNCTION"), cds_name_1.CDSName, (0, combi_1.optPrio)(_1.CDSWithParameters), (0, combi_1.str)("RETURNS {"), (0, combi_1.plus)((0, combi_1.seq)((0, combi_1.optPrio)("KEY"), cds_name_1.CDSName, ":", _1.CDSType, ";")), (0, combi_1.str)("} IMPLEMENTED BY METHOD"), methodName, (0, combi_1.opt)(";"));
|
|
10
|
+
return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.str)("DEFINE TABLE FUNCTION"), cds_name_1.CDSName, (0, combi_1.optPrio)(_1.CDSWithParameters), (0, combi_1.str)("RETURNS {"), (0, combi_1.plus)((0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.optPrio)("KEY"), cds_name_1.CDSName, ":", _1.CDSType, ";")), (0, combi_1.str)("} IMPLEMENTED BY METHOD"), methodName, (0, combi_1.opt)(";"));
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
exports.CDSDefineTableFunction = CDSDefineTableFunction;
|
|
@@ -10,7 +10,7 @@ const cds_with_parameters_1 = require("./cds_with_parameters");
|
|
|
10
10
|
class CDSDefineView extends combi_1.Expression {
|
|
11
11
|
getRunnable() {
|
|
12
12
|
const columnAlias = (0, combi_1.seq)("(", cds_name_1.CDSName, (0, combi_1.star)((0, combi_1.seq)(",", cds_name_1.CDSName)), ")");
|
|
13
|
-
return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), "DEFINE", (0, combi_1.opt)("ROOT"), "VIEW", (0, combi_1.ver)(__1.Version.v755, (0, combi_1.opt)("ENTITY")), cds_name_1.CDSName, (0, combi_1.opt)(columnAlias), (0, combi_1.opt)(cds_with_parameters_1.CDSWithParameters), "AS", cds_select_1.CDSSelect, (0, combi_1.opt)(";"));
|
|
13
|
+
return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.opt)("DEFINE"), (0, combi_1.opt)("ROOT"), "VIEW", (0, combi_1.ver)(__1.Version.v755, (0, combi_1.opt)("ENTITY")), cds_name_1.CDSName, (0, combi_1.opt)(columnAlias), (0, combi_1.opt)(cds_with_parameters_1.CDSWithParameters), "AS", cds_select_1.CDSSelect, (0, combi_1.opt)(";"));
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
exports.CDSDefineView = CDSDefineView;
|
|
@@ -8,10 +8,16 @@ const cds_cast_1 = require("./cds_cast");
|
|
|
8
8
|
class CDSElement extends combi_1.Expression {
|
|
9
9
|
getRunnable() {
|
|
10
10
|
const redirected = (0, combi_1.seq)(": REDIRECTED TO", (0, combi_1.optPrio)((0, combi_1.altPrio)("PARENT", "COMPOSITION CHILD")), _1.CDSName);
|
|
11
|
-
const colonThing = (0, combi_1.seq)(":", (0, combi_1.
|
|
11
|
+
const colonThing = (0, combi_1.seq)(":", (0, combi_1.altPrio)(_1.CDSType, _1.CDSName, "LOCALIZED"));
|
|
12
12
|
// $extension.* — extension field wildcard
|
|
13
13
|
const extensionWildcard = (0, combi_1.seq)("$extension", ".", "*");
|
|
14
|
-
|
|
14
|
+
const body = (0, combi_1.altPrio)(extensionWildcard, _1.CDSArithmetics, _1.CDSAggregate, _1.CDSString, _1.CDSArithParen, _1.CDSFunction, cds_cast_1.CDSCast, _1.CDSCase, (0, combi_1.seq)("(", _1.CDSCase, ")"), (0, combi_1.seq)(_1.CDSPrefixedName, (0, combi_1.optPrio)(cds_as_1.CDSAs), (0, combi_1.optPrio)((0, combi_1.altPrio)(redirected, colonThing))), _1.CDSInteger);
|
|
15
|
+
// KEY/VIRTUAL keyword handling via altPrio:
|
|
16
|
+
// - Try keyword form first: if keyword consumed but body fails (e.g. "virtual.Field"),
|
|
17
|
+
// altPrio backtracks to plain body (which handles "virtual" as a datasource alias prefix).
|
|
18
|
+
// - This gives exactly 1 state in all cases (no exponential blowup from opt()).
|
|
19
|
+
const elementBody = (0, combi_1.altPrio)((0, combi_1.seq)((0, combi_1.altPrio)("KEY", "VIRTUAL"), body), body);
|
|
20
|
+
return (0, combi_1.seq)((0, combi_1.starPrio)(_1.CDSAnnotation), elementBody, (0, combi_1.optPrio)(cds_as_1.CDSAs));
|
|
15
21
|
}
|
|
16
22
|
}
|
|
17
23
|
exports.CDSElement = CDSElement;
|
|
@@ -6,7 +6,7 @@ const combi_1 = require("../../abap/2_statements/combi");
|
|
|
6
6
|
const cds_name_1 = require("./cds_name");
|
|
7
7
|
class CDSExtendView extends combi_1.Expression {
|
|
8
8
|
getRunnable() {
|
|
9
|
-
const namedot = (0, combi_1.seq)(cds_name_1.CDSName, (0, combi_1.
|
|
9
|
+
const namedot = (0, combi_1.seq)(cds_name_1.CDSName, (0, combi_1.optPrio)((0, combi_1.seq)(".", cds_name_1.CDSName)), (0, combi_1.optPrio)(_1.CDSAs));
|
|
10
10
|
const valueNested = (0, combi_1.seq)("{", namedot, (0, combi_1.star)((0, combi_1.seq)(",", namedot)), "}");
|
|
11
11
|
return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.str)("EXTEND VIEW"), (0, combi_1.opt)((0, combi_1.str)("ENTITY")), cds_name_1.CDSName, (0, combi_1.str)("WITH"), (0, combi_1.opt)(cds_name_1.CDSName), valueNested, (0, combi_1.opt)(";"));
|
|
12
12
|
}
|
|
@@ -12,6 +12,7 @@ class CDSFunction extends combi_1.Expression {
|
|
|
12
12
|
const dats_add_months = (0, combi_1.seq)("DATS_ADD_MONTHS", "(", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ")");
|
|
13
13
|
const dats_days_between = (0, combi_1.seq)("DATS_DAYS_BETWEEN", "(", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ")");
|
|
14
14
|
const dats_is_valid = (0, combi_1.seq)("DATS_IS_VALID", "(", _1.CDSFunctionInput, ")");
|
|
15
|
+
const tims_is_valid = (0, combi_1.seq)("TIMS_IS_VALID", "(", _1.CDSFunctionInput, ")");
|
|
15
16
|
const substring = (0, combi_1.seq)("SUBSTRING", "(", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ")");
|
|
16
17
|
const bintohex = (0, combi_1.seq)("BINTOHEX", "(", _1.CDSFunctionInput, ")");
|
|
17
18
|
const hextobin = (0, combi_1.seq)("HEXTOBIN", "(", _1.CDSFunctionInput, ")");
|
|
@@ -29,6 +30,7 @@ class CDSFunction extends combi_1.Expression {
|
|
|
29
30
|
const dats_tims_to_tstmp = (0, combi_1.seq)("DATS_TIMS_TO_TSTMP", "(", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ")");
|
|
30
31
|
const tstmp_is_valid = (0, combi_1.seq)("TSTMP_IS_VALID", "(", _1.CDSFunctionInput, ")");
|
|
31
32
|
const tstmp_current_utctimestamp = (0, combi_1.seq)("TSTMP_CURRENT_UTCTIMESTAMP", "(", ")");
|
|
33
|
+
const utcl_current = (0, combi_1.seq)("UTCL_CURRENT", "(", ")");
|
|
32
34
|
const tstmp_seconds_between = (0, combi_1.seq)("TSTMP_SECONDS_BETWEEN", "(", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ")");
|
|
33
35
|
const tstmp_add_seconds = (0, combi_1.seq)("TSTMP_ADD_SECONDS", "(", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ")");
|
|
34
36
|
const abap_system_timezone = (0, combi_1.seq)("ABAP_SYSTEM_TIMEZONE", "(", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ")");
|
|
@@ -44,12 +46,25 @@ class CDSFunction extends combi_1.Expression {
|
|
|
44
46
|
const left = (0, combi_1.seq)("LEFT", "(", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ")");
|
|
45
47
|
const right = (0, combi_1.seq)("RIGHT", "(", _1.CDSFunctionInput, ",", _1.CDSFunctionInput, ")");
|
|
46
48
|
const fltp_to_dec = (0, combi_1.seq)("FLTP_TO_DEC", "(", _1.CDSFunctionInput, "AS", _1.CDSType, ")");
|
|
49
|
+
const curr_to_decfloat_amount = (0, combi_1.seq)("CURR_TO_DECFLOAT_AMOUNT", "(", _1.CDSFunctionInput, ")");
|
|
47
50
|
const conversionInput = (0, combi_1.seq)(_1.CDSName, "=", ">", _1.CDSFunctionInput);
|
|
48
51
|
const conversionInputs = (0, combi_1.seq)(conversionInput, (0, combi_1.starPrio)((0, combi_1.seq)(",", conversionInput)));
|
|
49
52
|
const unitConversion = (0, combi_1.seq)("UNIT_CONVERSION", "(", conversionInputs, ")");
|
|
50
53
|
const currencyConversion = (0, combi_1.seq)("CURRENCY_CONVERSION", "(", conversionInputs, ")");
|
|
51
54
|
const decimalShift = (0, combi_1.seq)("DECIMAL_SHIFT", "(", conversionInputs, ")");
|
|
52
|
-
|
|
55
|
+
const ratioOf = (0, combi_1.seq)("RATIO_OF", "(", conversionInputs, ")");
|
|
56
|
+
const replaceRegexpr = (0, combi_1.seq)("REPLACE_REGEXPR", "(", conversionInputs, ")");
|
|
57
|
+
const matchesRegexpr = (0, combi_1.seq)("MATCHES_REGEXPR", "(", conversionInputs, ")");
|
|
58
|
+
const occurrencesRegexpr = (0, combi_1.seq)("OCCURRENCES_REGEXPR", "(", conversionInputs, ")");
|
|
59
|
+
const substrRegexpr = (0, combi_1.seq)("SUBSTR_REGEXPR", "(", conversionInputs, ")");
|
|
60
|
+
const locateRegexpr = (0, combi_1.seq)("LOCATE_REGEXPR", "(", conversionInputs, ")");
|
|
61
|
+
// Generic fallback: user-defined/extension functions like GET_NUMERIC_VALUE(arg).
|
|
62
|
+
// Use a regex that excludes CDS keywords that would otherwise be matched by CDSName.
|
|
63
|
+
// Must contain at least one underscore to distinguish from keywords (e.g. GET_NUMERIC_VALUE).
|
|
64
|
+
const extFuncName = (0, combi_1.regex)(/^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$/i);
|
|
65
|
+
const genericArgs = (0, combi_1.seq)(_1.CDSFunctionInput, (0, combi_1.starPrio)((0, combi_1.seq)(",", _1.CDSFunctionInput)));
|
|
66
|
+
const genericFunc = (0, combi_1.seq)(extFuncName, "(", genericArgs, ")");
|
|
67
|
+
return (0, combi_1.altPrio)(substring, coalesce, tstmp_to_dats, concat, tstmp_to_tims, upper, lower, abs, ceil, floor, round, div, division, concat_with_space, dats_is_valid, tims_is_valid, dats_days_between, tstmp_add_seconds, tstmp_seconds_between, tstmp_current_utctimestamp, tstmp_is_valid, utcl_current, abap_system_timezone, abap_user_timezone, bintohex, hextobin, dats_add_days, dats_add_months, tstmp_to_dst, dats_tims_to_tstmp, mod, left, right, lpad, rpad, instr, length, ltrim, rtrim, replace, unitConversion, currencyConversion, decimalShift, fltp_to_dec, ratioOf, replaceRegexpr, matchesRegexpr, occurrencesRegexpr, substrRegexpr, locateRegexpr, curr_to_decfloat_amount, genericFunc);
|
|
53
68
|
}
|
|
54
69
|
}
|
|
55
70
|
exports.CDSFunction = CDSFunction;
|
|
@@ -7,7 +7,11 @@ class CDSInteger extends combi_1.Expression {
|
|
|
7
7
|
const digits = (0, combi_1.regex)(/^\d+$/);
|
|
8
8
|
// Decimal numbers like 100.00 are lexed as 3 tokens: "100" "." "00"
|
|
9
9
|
const decimal = (0, combi_1.seq)(digits, ".", digits);
|
|
10
|
-
|
|
10
|
+
// Scientific notation like 0.0000000000000000E+00 is lexed as:
|
|
11
|
+
// "0" "." "0000000000000000E" "+" "00" (mantissa ends with E, sign, exponent)
|
|
12
|
+
const mantissa = (0, combi_1.regex)(/^\d+E$/i);
|
|
13
|
+
const sciNotation = (0, combi_1.seq)(digits, ".", mantissa, (0, combi_1.altPrio)("+", "-"), digits);
|
|
14
|
+
return (0, combi_1.seq)((0, combi_1.opt)("-"), (0, combi_1.altPrio)(sciNotation, decimal, digits));
|
|
11
15
|
}
|
|
12
16
|
}
|
|
13
17
|
exports.CDSInteger = CDSInteger;
|
|
@@ -6,13 +6,22 @@ const combi_1 = require("../../abap/2_statements/combi");
|
|
|
6
6
|
const cds_condition_1 = require("./cds_condition");
|
|
7
7
|
class CDSJoin extends combi_1.Expression {
|
|
8
8
|
getRunnable() {
|
|
9
|
-
const
|
|
9
|
+
const cardSide = (0, combi_1.altPrio)("EXACT ONE", "ONE", "MANY");
|
|
10
|
+
// LEFT OUTER [card TO card] — structured to cover all combinations
|
|
11
|
+
const leftOuterCard = (0, combi_1.seq)("LEFT OUTER", cardSide, "TO", cardSide);
|
|
12
|
+
const leftOuterToCard = (0, combi_1.seq)("LEFT OUTER TO", (0, combi_1.altPrio)("EXACT ONE", "ONE", "MANY"));
|
|
13
|
+
// INNER [card TO card]
|
|
14
|
+
const innerCard = (0, combi_1.seq)("INNER", cardSide, "TO", cardSide);
|
|
15
|
+
const innerToCard = (0, combi_1.seq)("INNER TO", (0, combi_1.altPrio)("EXACT ONE", "ONE", "MANY"));
|
|
16
|
+
const joinTypes = (0, combi_1.optPrio)((0, combi_1.altPrio)(leftOuterCard, leftOuterToCard, "LEFT OUTER", innerCard, innerToCard, "INNER", "CROSS", "RIGHT OUTER"));
|
|
10
17
|
const cond = (0, combi_1.seq)(_1.CDSSource, "ON", cds_condition_1.CDSCondition);
|
|
11
18
|
const foo = (0, combi_1.altPrio)((0, combi_1.seq)("(", cond, ")"), cond);
|
|
12
19
|
// Parenthesized join sub-expression: JOIN (src innerJOIN src ON cond) ON outerCond
|
|
13
20
|
const innerJoin = (0, combi_1.seq)(joinTypes, "JOIN", (0, combi_1.altPrio)((0, combi_1.seq)("(", cond, ")"), cond));
|
|
14
21
|
const parenJoinChain = (0, combi_1.seq)("(", _1.CDSSource, (0, combi_1.star)(innerJoin), ")", "ON", cds_condition_1.CDSCondition);
|
|
15
|
-
|
|
22
|
+
// Inline nested join: JOIN src [JOIN src ON cond]* ON outerCond
|
|
23
|
+
const inlineChain = (0, combi_1.seq)(_1.CDSSource, (0, combi_1.star)((0, combi_1.seq)(joinTypes, "JOIN", _1.CDSSource, "ON", cds_condition_1.CDSCondition)), "ON", cds_condition_1.CDSCondition);
|
|
24
|
+
return (0, combi_1.seq)(joinTypes, "JOIN", (0, combi_1.altPrio)(parenJoinChain, inlineChain, foo, _1.CDSSource));
|
|
16
25
|
}
|
|
17
26
|
}
|
|
18
27
|
exports.CDSJoin = CDSJoin;
|
|
@@ -17,15 +17,26 @@ class CDSPrefixedName extends combi_1.Expression {
|
|
|
17
17
|
// [condition] — filter condition only
|
|
18
18
|
const joinType = (0, combi_1.altPrio)("LEFT OUTER", "INNER", "CROSS");
|
|
19
19
|
const joinRedirect = (0, combi_1.seq)("[", joinType, "]");
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
20
|
+
// Cardinality spec: integer or * (e.g. [*:inner], [1:inner])
|
|
21
|
+
const cardSpec = (0, combi_1.altPrio)(cds_integer_1.CDSInteger, "*");
|
|
22
|
+
const cardinalityJoin = (0, combi_1.seq)("[", cardSpec, ":", joinType, "]");
|
|
23
|
+
// [1: left outer where condition] — cardinality + join-type + WHERE filter
|
|
24
|
+
const cardinalityJoinWhere = (0, combi_1.seq)("[", cardSpec, ":", joinType, "WHERE", cds_condition_1.CDSCondition, "]");
|
|
25
|
+
// [left outer where condition] — join-type + WHERE filter (no cardinality prefix)
|
|
26
|
+
const joinWhere = (0, combi_1.seq)("[", joinType, "WHERE", cds_condition_1.CDSCondition, "]");
|
|
27
|
+
// Text cardinality forms: [to one: cond], [to many: cond]
|
|
28
|
+
const textCard = (0, combi_1.altPrio)("TO ONE", "TO MANY");
|
|
29
|
+
const textCardFilter = (0, combi_1.seq)("[", textCard, ":", cds_condition_1.CDSCondition, "]");
|
|
30
|
+
// Numeric range cardinality: [0..1: cond], [1..1: cond], [0..*: cond], [n..m: cond]
|
|
31
|
+
const cardNum = (0, combi_1.altPrio)(cds_integer_1.CDSInteger, "*");
|
|
32
|
+
const rangeCard = (0, combi_1.seq)(cds_integer_1.CDSInteger, ".", ".", cardNum);
|
|
33
|
+
const rangeCardFilter = (0, combi_1.seq)("[", rangeCard, ":", cds_condition_1.CDSCondition, "]");
|
|
34
|
+
const pathFilter = (0, combi_1.altPrio)(cardinalityJoinWhere, joinWhere, cardinalityJoin, joinRedirect, textCardFilter, rangeCardFilter, (0, combi_1.seq)("[", cardSpec, ":", cds_condition_1.CDSCondition, "]"), (0, combi_1.seq)("[", cds_condition_1.CDSCondition, "]"));
|
|
24
35
|
// Each dotted segment may have its own path filter: A[cond].B[cond].C
|
|
25
36
|
// The final segment may also be a string literal: #enum.'value'
|
|
26
37
|
// A segment may have a parameterized call: _Assoc( P_Key : value ) or _Assoc[filter]
|
|
27
|
-
const segment = (0, combi_1.seq)(".", (0, combi_1.altPrio)(cds_string_1.CDSString, cds_name_1.CDSName), (0, combi_1.
|
|
28
|
-
return (0, combi_1.seq)(cds_name_1.CDSName, (0, combi_1.
|
|
38
|
+
const segment = (0, combi_1.seq)(".", (0, combi_1.altPrio)(cds_string_1.CDSString, cds_name_1.CDSName), (0, combi_1.optPrio)((0, combi_1.altPrio)(cds_parameters_select_1.CDSParametersSelect, cds_parameters_1.CDSParameters)), (0, combi_1.optPrio)(pathFilter));
|
|
39
|
+
return (0, combi_1.seq)(cds_name_1.CDSName, (0, combi_1.optPrio)((0, combi_1.altPrio)(cds_parameters_1.CDSParameters, cds_parameters_select_1.CDSParametersSelect)), (0, combi_1.optPrio)(pathFilter), (0, combi_1.star)(segment));
|
|
29
40
|
}
|
|
30
41
|
}
|
|
31
42
|
exports.CDSPrefixedName = CDSPrefixedName;
|
|
@@ -9,9 +9,10 @@ class CDSSelect extends combi_1.Expression {
|
|
|
9
9
|
getRunnable() {
|
|
10
10
|
const fields = (0, combi_1.seq)((0, combi_1.star)((0, combi_1.seq)(_1.CDSElement, ",")), _1.CDSElement);
|
|
11
11
|
const distinct = (0, combi_1.str)("DISTINCT");
|
|
12
|
-
|
|
12
|
+
// elem (,elem)* [,] — handles separator commas and optional trailing comma
|
|
13
|
+
const elementList = (0, combi_1.seq)(_1.CDSElement, (0, combi_1.star)((0, combi_1.seq)(",", _1.CDSElement)), (0, combi_1.opt)(","));
|
|
13
14
|
const elements = (0, combi_1.seq)((0, combi_1.str)("{"), (0, combi_1.altPrio)("*", elementList), (0, combi_1.str)("}"));
|
|
14
|
-
return (0, combi_1.seq)("SELECT", (0, combi_1.optPrio)(distinct), (0, combi_1.opt)((0, combi_1.altPrio)("*", fields)), "FROM", _1.CDSSource, (0, combi_1.star)(cds_join_1.CDSJoin), (0, combi_1.star)((0, combi_1.altPrio)(_1.CDSComposition, cds_association_1.CDSAssociation)), (0, combi_1.opt)(elements), (0, combi_1.optPrio)(_1.CDSWhere), (0, combi_1.optPrio)(_1.CDSGroupBy), (0, combi_1.optPrio)(_1.CDSHaving), (0, combi_1.optPrio)((0, combi_1.seq)("UNION", (0, combi_1.optPrio)("ALL"), CDSSelect)));
|
|
15
|
+
return (0, combi_1.seq)("SELECT", (0, combi_1.optPrio)(distinct), (0, combi_1.opt)((0, combi_1.altPrio)("*", fields)), "FROM", _1.CDSSource, (0, combi_1.star)(cds_join_1.CDSJoin), (0, combi_1.star)((0, combi_1.altPrio)(_1.CDSComposition, cds_association_1.CDSAssociation)), (0, combi_1.opt)(elements), (0, combi_1.optPrio)(_1.CDSWhere), (0, combi_1.optPrio)(_1.CDSGroupBy), (0, combi_1.optPrio)(_1.CDSHaving), (0, combi_1.optPrio)((0, combi_1.altPrio)((0, combi_1.seq)("UNION", (0, combi_1.optPrio)("ALL"), CDSSelect), (0, combi_1.seq)("EXCEPT", CDSSelect), (0, combi_1.seq)("INTERSECT", CDSSelect))));
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
exports.CDSSelect = CDSSelect;
|
|
@@ -5,9 +5,12 @@ const _1 = require(".");
|
|
|
5
5
|
const combi_1 = require("../../abap/2_statements/combi");
|
|
6
6
|
class CDSSource extends combi_1.Expression {
|
|
7
7
|
getRunnable() {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
8
|
+
// Static where filter in FROM: SomeTable [Field = 'Value']
|
|
9
|
+
const staticFilter = (0, combi_1.seq)("[", _1.CDSCondition, "]");
|
|
10
|
+
const singleSource = (0, combi_1.seq)(_1.CDSName, (0, combi_1.optPrio)(_1.CDSParametersSelect), (0, combi_1.optPrio)(staticFilter), (0, combi_1.opt)((0, combi_1.altPrio)(_1.CDSAs, _1.CDSName)));
|
|
11
|
+
// FROM ( src [JOIN src ON cond]* ) — parenthesized join chain, arbitrarily nested
|
|
12
|
+
// CDSSource is self-referential here to handle: (((T1 join T2) join T3) join T4)
|
|
13
|
+
const parenSource = (0, combi_1.seq)("(", (0, combi_1.altPrio)(CDSSource, singleSource), (0, combi_1.star)(_1.CDSJoin), ")");
|
|
11
14
|
return (0, combi_1.altPrio)(parenSource, singleSource);
|
|
12
15
|
}
|
|
13
16
|
}
|
|
@@ -4,11 +4,16 @@ exports.CDSString = void 0;
|
|
|
4
4
|
const combi_1 = require("../../abap/2_statements/combi");
|
|
5
5
|
class CDSString extends combi_1.Expression {
|
|
6
6
|
getRunnable() {
|
|
7
|
-
// Allow any character except unescaped single quote;
|
|
8
|
-
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
|
|
7
|
+
// Allow any character except unescaped single quote; escape sequences:
|
|
8
|
+
// '' — escaped single quote (doubling)
|
|
9
|
+
// \' — escaped single quote (backslash form)
|
|
10
|
+
// \\ — escaped backslash (e.g. '\\' in ltrim/rtrim calls)
|
|
11
|
+
// \x — other backslash sequences not followed by '
|
|
12
|
+
const reg = (0, combi_1.regex)(/^'(?:[^'\\]|''|\\'|\\\\|\\(?!'))*'$/);
|
|
13
|
+
// Typed literal: abap.int4'1', abap.char'X', abap.numc(3)'123', etc.
|
|
14
|
+
// Lexed as tokens: abap, ., typename, 'value'
|
|
15
|
+
const abapTypeName = (0, combi_1.regex)(/^(?:int[1-9]|sstring|char|numc|dats|tims|fltp|decfloat\d+|dec|string|raw|xstring|clnt|lang|unit|cuky|curr|quan|d|t|p|n|c|x|f)$/i);
|
|
16
|
+
const abap = (0, combi_1.seq)("abap", ".", abapTypeName, (0, combi_1.optPrio)((0, combi_1.seq)("(", (0, combi_1.regex)(/^\d+$/), ")")), reg);
|
|
12
17
|
return (0, combi_1.altPrio)(abap, reg);
|
|
13
18
|
}
|
|
14
19
|
}
|
|
@@ -6,7 +6,7 @@ const combi_1 = require("../../abap/2_statements/combi");
|
|
|
6
6
|
class CDSType extends combi_1.Expression {
|
|
7
7
|
getRunnable() {
|
|
8
8
|
const decimals = (0, combi_1.seq)(",", (0, combi_1.regex)(/\d+/));
|
|
9
|
-
return (0, combi_1.seq)(_1.CDSName, (0, combi_1.
|
|
9
|
+
return (0, combi_1.seq)(_1.CDSName, (0, combi_1.optPrio)((0, combi_1.seq)(".", _1.CDSName)), (0, combi_1.optPrio)((0, combi_1.seq)("(", (0, combi_1.regex)(/\d+/), (0, combi_1.optPrio)(decimals), ")")));
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
exports.CDSType = CDSType;
|
|
@@ -5,7 +5,7 @@ const _1 = require(".");
|
|
|
5
5
|
const combi_1 = require("../../abap/2_statements/combi");
|
|
6
6
|
class CDSWithParameters extends combi_1.Expression {
|
|
7
7
|
getRunnable() {
|
|
8
|
-
const param = (0, combi_1.seq)((0, combi_1.
|
|
8
|
+
const param = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), _1.CDSName, ":", _1.CDSType, (0, combi_1.star)(_1.CDSAnnotation));
|
|
9
9
|
return (0, combi_1.seq)("WITH PARAMETERS", param, (0, combi_1.star)((0, combi_1.seq)(",", param)));
|
|
10
10
|
}
|
|
11
11
|
}
|
|
@@ -173,15 +173,22 @@ class DataDefinition extends _abstract_object_1.AbstractObject {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
findSourcesAndRelations(tree) {
|
|
176
|
-
var _a, _b, _c, _d, _e
|
|
176
|
+
var _a, _b, _c, _d, _e;
|
|
177
177
|
for (const e of tree.findAllExpressions(expressions_1.CDSSource)) {
|
|
178
178
|
const name = ((_a = e.getFirstChild()) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase().replace(/ /g, "")) || "ERROR";
|
|
179
179
|
const as = (_c = (_b = e.findDirectExpression(expressions_1.CDSAs)) === null || _b === void 0 ? void 0 : _b.findDirectExpression(expressions_1.CDSName)) === null || _c === void 0 ? void 0 : _c.concatTokens().toUpperCase();
|
|
180
180
|
this.parsedData.sources.push({ name, as });
|
|
181
181
|
}
|
|
182
182
|
for (const e of tree.findAllExpressions(expressions_1.CDSRelation)) {
|
|
183
|
-
|
|
184
|
-
|
|
183
|
+
// For namespace-prefixed names like /PF1/C_VH_TRANSTYPE, getFirstToken() only yields "/".
|
|
184
|
+
// Collect all tokens NOT part of the CDSAs child to reconstruct the full name.
|
|
185
|
+
const asNode = e.findDirectExpression(expressions_1.CDSAs);
|
|
186
|
+
const asTokenSet = new Set(asNode ? asNode.getTokens().map(t => `${t.getStart().getRow()}:${t.getStart().getCol()}`) : []);
|
|
187
|
+
const name = e.getTokens()
|
|
188
|
+
.filter(t => !asTokenSet.has(`${t.getStart().getRow()}:${t.getStart().getCol()}`))
|
|
189
|
+
.map(t => t.getStr())
|
|
190
|
+
.join("") || "ERROR";
|
|
191
|
+
const as = (_d = asNode === null || asNode === void 0 ? void 0 : asNode.findDirectExpression(expressions_1.CDSName)) === null || _d === void 0 ? void 0 : _d.getFirstToken().getStr();
|
|
185
192
|
this.parsedData.relations.push({ name, as });
|
|
186
193
|
}
|
|
187
194
|
for (const e of tree.findAllExpressions(expressions_1.CDSAssociation)) {
|
|
@@ -189,10 +196,18 @@ class DataDefinition extends _abstract_object_1.AbstractObject {
|
|
|
189
196
|
if (j === undefined) {
|
|
190
197
|
continue;
|
|
191
198
|
}
|
|
192
|
-
|
|
193
|
-
|
|
199
|
+
// CDSRelation: seq(opt(/NS/), entityName, opt(CDSAs))
|
|
200
|
+
// For namespace-prefixed names like /PF1/C_VH_TRANSTYPE, getFirstToken() only yields "/"
|
|
201
|
+
// Collect all tokens that are NOT part of the CDSAs child to reconstruct the full name
|
|
202
|
+
const asNode = j.findDirectExpression(expressions_1.CDSAs);
|
|
203
|
+
const asTokenSet = new Set(asNode ? asNode.getTokens().map(t => `${t.getStart().getRow()}:${t.getStart().getCol()}`) : []);
|
|
204
|
+
const name = j.getTokens()
|
|
205
|
+
.filter(t => !asTokenSet.has(`${t.getStart().getRow()}:${t.getStart().getCol()}`))
|
|
206
|
+
.map(t => t.getStr())
|
|
207
|
+
.join("") || "ERROR";
|
|
208
|
+
const as = (_e = asNode === null || asNode === void 0 ? void 0 : asNode.findDirectExpression(expressions_1.CDSName)) === null || _e === void 0 ? void 0 : _e.getFirstToken().getStr();
|
|
194
209
|
this.parsedData.associations.push({
|
|
195
|
-
name: name
|
|
210
|
+
name: name,
|
|
196
211
|
as: as,
|
|
197
212
|
});
|
|
198
213
|
}
|
package/build/src/registry.js
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AFFAndXML = exports.AFFAndXMLConf = void 0;
|
|
4
|
+
const issue_1 = require("../issue");
|
|
5
|
+
const _irule_1 = require("./_irule");
|
|
6
|
+
const _basic_rule_config_1 = require("./_basic_rule_config");
|
|
7
|
+
class AFFAndXMLConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
8
|
+
}
|
|
9
|
+
exports.AFFAndXMLConf = AFFAndXMLConf;
|
|
10
|
+
class AFFAndXML {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.conf = new AFFAndXMLConf();
|
|
13
|
+
}
|
|
14
|
+
getMetadata() {
|
|
15
|
+
return {
|
|
16
|
+
key: "aff_and_xml",
|
|
17
|
+
title: "AFF and XML",
|
|
18
|
+
shortDescription: `Checks for objects that have both AFF (.json) and XML (.xml) files`,
|
|
19
|
+
extendedInformation: `If an object has both an ABAP file format JSON file and an XML file, the XML file should be removed`,
|
|
20
|
+
tags: [_irule_1.RuleTag.Syntax],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
getConfig() {
|
|
24
|
+
return this.conf;
|
|
25
|
+
}
|
|
26
|
+
setConfig(conf) {
|
|
27
|
+
this.conf = conf;
|
|
28
|
+
}
|
|
29
|
+
initialize(_reg) {
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
run(obj) {
|
|
33
|
+
const files = obj.getFiles();
|
|
34
|
+
let hasJSON = false;
|
|
35
|
+
let hasXML = false;
|
|
36
|
+
const type = obj.getType().toLowerCase();
|
|
37
|
+
for (const file of files) {
|
|
38
|
+
const filename = file.getFilename().toLowerCase();
|
|
39
|
+
if (filename.endsWith("." + type + ".json")) {
|
|
40
|
+
hasJSON = true;
|
|
41
|
+
}
|
|
42
|
+
else if (filename.endsWith("." + type + ".xml")) {
|
|
43
|
+
hasXML = true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (hasJSON && hasXML) {
|
|
47
|
+
const xmlFile = obj.getXMLFile();
|
|
48
|
+
if (xmlFile) {
|
|
49
|
+
const message = "Object has both AFF JSON and XML files, remove the XML";
|
|
50
|
+
return [issue_1.Issue.atRow(xmlFile, 1, message, this.getMetadata().key, this.conf.severity)];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.AFFAndXML = AFFAndXML;
|
|
57
|
+
//# sourceMappingURL=aff_and_xml.js.map
|
|
@@ -30,11 +30,11 @@ class DefinitionsTop extends _abap_rule_1.ABAPRule {
|
|
|
30
30
|
shortDescription: `Checks that definitions are placed at the beginning of METHODs, FORMs and FUNCTIONs.`,
|
|
31
31
|
extendedInformation: `https://docs.abapopenchecks.org/checks/17/`,
|
|
32
32
|
tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Quickfix],
|
|
33
|
-
badExample: `
|
|
33
|
+
badExample: `FORM foo.
|
|
34
34
|
WRITE 'hello'.
|
|
35
35
|
DATA int TYPE i.
|
|
36
36
|
ENDFORM.`,
|
|
37
|
-
goodExample: `
|
|
37
|
+
goodExample: `FORM foo.
|
|
38
38
|
DATA int TYPE i.
|
|
39
39
|
WRITE 'hello'.
|
|
40
40
|
ENDFORM.`,
|
|
@@ -16,7 +16,7 @@ class FMGlobalParametersObsolete {
|
|
|
16
16
|
return {
|
|
17
17
|
key: "fm_global_parameters_obsolete",
|
|
18
18
|
title: "FM Global Parameters Obsolete",
|
|
19
|
-
shortDescription: `Check for function modules with global
|
|
19
|
+
shortDescription: `Check for function modules with global parameters`,
|
|
20
20
|
extendedInformation: `https://help.sap.com/doc/abapdocu_750_index_htm/7.50/en-US/abenglobal_parameters_obsolete.htm`,
|
|
21
21
|
tags: [],
|
|
22
22
|
};
|
package/build/src/rules/index.js
CHANGED
|
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./7bit_ascii"), exports);
|
|
18
18
|
__exportStar(require("./abapdoc"), exports);
|
|
19
19
|
__exportStar(require("./add_test_attributes"), exports);
|
|
20
|
+
__exportStar(require("./aff_and_xml"), exports);
|
|
20
21
|
__exportStar(require("./align_parameters"), exports);
|
|
21
22
|
__exportStar(require("./align_pseudo_comments"), exports);
|
|
22
23
|
__exportStar(require("./align_type_expressions"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abaplint/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.116.1",
|
|
4
4
|
"description": "abaplint - Core API",
|
|
5
5
|
"main": "build/src/index.js",
|
|
6
6
|
"typings": "build/abaplint.d.ts",
|
|
@@ -50,20 +50,20 @@
|
|
|
50
50
|
},
|
|
51
51
|
"homepage": "https://abaplint.org",
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@microsoft/api-extractor": "^7.57.
|
|
53
|
+
"@microsoft/api-extractor": "^7.57.7",
|
|
54
54
|
"@types/chai": "^4.3.20",
|
|
55
55
|
"@types/mocha": "^10.0.10",
|
|
56
|
-
"@types/node": "^24.
|
|
56
|
+
"@types/node": "^24.12.0",
|
|
57
57
|
"chai": "^4.5.0",
|
|
58
58
|
"eslint": "^9.39.2",
|
|
59
59
|
"mocha": "^11.7.5",
|
|
60
60
|
"c8": "^11.0.0",
|
|
61
61
|
"source-map-support": "^0.5.21",
|
|
62
|
-
"ts-json-schema-generator": "
|
|
62
|
+
"ts-json-schema-generator": "^2.9.0",
|
|
63
63
|
"typescript": "^5.9.3"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"fast-xml-parser": "^5.3
|
|
66
|
+
"fast-xml-parser": "^5.5.3",
|
|
67
67
|
"json5": "^2.2.3",
|
|
68
68
|
"vscode-languageserver-types": "^3.17.5"
|
|
69
69
|
}
|