@sap/cds-compiler 2.13.8 → 2.15.6
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/CHANGELOG.md +128 -4
- package/bin/cdsc.js +112 -37
- package/lib/api/main.js +63 -22
- package/lib/api/options.js +2 -3
- package/lib/api/validate.js +6 -6
- package/lib/base/message-registry.js +100 -17
- package/lib/base/messages.js +85 -64
- package/lib/base/optionProcessorHelper.js +19 -0
- package/lib/checks/annotationsOData.js +11 -32
- package/lib/checks/arrayOfs.js +1 -34
- package/lib/checks/validator.js +2 -4
- package/lib/compiler/assert-consistency.js +1 -0
- package/lib/compiler/base.js +1 -0
- package/lib/compiler/builtins.js +11 -0
- package/lib/compiler/checks.js +22 -70
- package/lib/compiler/define.js +59 -11
- package/lib/compiler/extend.js +20 -3
- package/lib/compiler/finalize-parse-cdl.js +26 -20
- package/lib/compiler/index.js +75 -26
- package/lib/compiler/populate.js +36 -17
- package/lib/compiler/propagator.js +4 -1
- package/lib/compiler/resolve.js +104 -16
- package/lib/compiler/shared.js +61 -27
- package/lib/compiler/tweak-assocs.js +7 -1
- package/lib/edm/annotations/genericTranslation.js +93 -21
- package/lib/edm/csn2edm.js +216 -98
- package/lib/edm/edm.js +305 -226
- package/lib/edm/edmPreprocessor.js +499 -423
- package/lib/edm/edmUtils.js +22 -22
- package/lib/gen/Dictionary.json +98 -22
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +3 -1
- package/lib/gen/languageParser.js +4636 -4368
- package/lib/json/csnVersion.js +10 -11
- package/lib/json/from-csn.js +3 -2
- package/lib/json/to-csn.js +0 -2
- package/lib/language/docCommentParser.js +2 -2
- package/lib/language/genericAntlrParser.js +47 -2
- package/lib/language/language.g4 +59 -27
- package/lib/main.d.ts +19 -1
- package/lib/main.js +6 -0
- package/lib/model/csnRefs.js +33 -6
- package/lib/model/csnUtils.js +193 -75
- package/lib/model/enrichCsn.js +1 -0
- package/lib/model/revealInternalProperties.js +2 -2
- package/lib/modelCompare/compare.js +6 -6
- package/lib/optionProcessor.js +62 -26
- package/lib/render/toCdl.js +844 -679
- package/lib/render/toHdbcds.js +189 -243
- package/lib/render/toSql.js +180 -198
- package/lib/render/utils/common.js +131 -15
- package/lib/transform/db/.eslintrc.json +1 -1
- package/lib/transform/db/associations.js +2 -2
- package/lib/transform/db/constraints.js +3 -1
- package/lib/transform/db/expansion.js +15 -10
- package/lib/transform/db/flattening.js +94 -64
- package/lib/transform/db/transformExists.js +7 -7
- package/lib/transform/db/views.js +6 -3
- package/lib/transform/forHanaNew.js +43 -26
- package/lib/transform/forOdataNew.js +43 -42
- package/lib/transform/localized.js +12 -7
- package/lib/transform/odata/toFinalBaseType.js +8 -6
- package/lib/transform/odata/typesExposure.js +145 -197
- package/lib/transform/transformUtilsNew.js +9 -12
- package/lib/transform/translateAssocsToJoins.js +5 -1
- package/lib/transform/universalCsn/coreComputed.js +5 -3
- package/lib/transform/universalCsn/universalCsnEnricher.js +27 -5
- package/lib/utils/moduleResolve.js +13 -6
- package/package.json +1 -1
- package/share/messages/message-explanations.json +2 -1
- package/share/messages/syntax-expected-integer.md +37 -0
- package/lib/transform/odata/attachPath.js +0 -96
- package/lib/transform/odata/expandStructKeysInAssociations.js +0 -59
- package/lib/transform/odata/generateForeignKeyElements.js +0 -261
- package/lib/transform/odata/referenceFlattener.js +0 -296
- package/lib/transform/odata/sortByAssociationDependency.js +0 -105
- package/lib/transform/odata/structuralPath.js +0 -72
- package/lib/transform/odata/structureFlattener.js +0 -171
package/lib/json/csnVersion.js
CHANGED
|
@@ -15,18 +15,17 @@
|
|
|
15
15
|
// 0.1.99 : Like 0.1.0, but with new-style CSN
|
|
16
16
|
// 0.2 : same as 0.1.99, but with new top-level properties: $version, meta
|
|
17
17
|
|
|
18
|
-
// Use literal version constants intentionally and not number intervals to
|
|
18
|
+
// Use literal version constants intentionally and not number intervals to
|
|
19
19
|
// record all published version strings of the core compiler.
|
|
20
|
-
const newCSNVersions = [
|
|
20
|
+
const newCSNVersions = [ '0.1.99', '0.2', '0.2.0', '1.0', '2.0' ];
|
|
21
21
|
// checks if new-csn is requested via the options of already specified in the CSN
|
|
22
22
|
// default: old-style
|
|
23
23
|
function isNewCSN(csn, options) {
|
|
24
|
-
if( (options && options.newCsn ===
|
|
24
|
+
if ( (options && options.newCsn === false) ||
|
|
25
25
|
(csn.version && !newCSNVersions.includes(csn.version.csn)) ||
|
|
26
26
|
(csn.$version && !newCSNVersions.includes(csn.$version)))
|
|
27
|
-
{
|
|
28
27
|
return false;
|
|
29
|
-
|
|
28
|
+
|
|
30
29
|
return true;
|
|
31
30
|
}
|
|
32
31
|
|
|
@@ -34,18 +33,18 @@ function checkCSNVersion(csn, options) {
|
|
|
34
33
|
if (!isNewCSN(csn, options)) {
|
|
35
34
|
// the new transformer works only with new CSN
|
|
36
35
|
const { makeMessageFunction } = require('../base/messages');
|
|
37
|
-
const { error,
|
|
36
|
+
const { error, throwWithAnyError } = makeMessageFunction(csn, options);
|
|
38
37
|
|
|
39
38
|
let errStr = 'CSN Version not supported, version tag: "';
|
|
40
|
-
errStr +=
|
|
41
|
-
errStr += (options.newCsn !== undefined) ?
|
|
39
|
+
errStr += `${ csn.version && csn.version.csn ? csn.version.csn : (csn.$version ? csn.$version : 'not available') }"`;
|
|
40
|
+
errStr += (options.newCsn !== undefined) ? `, options.newCsn: ${ options.newCsn }` : '';
|
|
42
41
|
|
|
43
42
|
error(null, null, errStr);
|
|
44
|
-
|
|
43
|
+
throwWithAnyError();
|
|
45
44
|
}
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
module.exports = {
|
|
49
48
|
isNewCSN,
|
|
50
|
-
checkCSNVersion
|
|
51
|
-
}
|
|
49
|
+
checkCSNVersion,
|
|
50
|
+
};
|
package/lib/json/from-csn.js
CHANGED
|
@@ -152,7 +152,8 @@ const schemaClasses = {
|
|
|
152
152
|
msgId: 'syntax-csn-expected-column',
|
|
153
153
|
defaultKind: '$column',
|
|
154
154
|
validKinds: [], // pseudo kind '$column'
|
|
155
|
-
|
|
155
|
+
// A column with only as+cast.type is a new association
|
|
156
|
+
requires: [ 'ref', 'as', 'xpr', 'val', '#', 'func', 'list', 'SELECT', 'SET', 'expand' ],
|
|
156
157
|
schema: {
|
|
157
158
|
xpr: {
|
|
158
159
|
class: 'condition',
|
|
@@ -197,7 +198,7 @@ const schema = compileSchema( {
|
|
|
197
198
|
dictionaryOf: definition,
|
|
198
199
|
defaultKind: 'enum',
|
|
199
200
|
validKinds: [ 'enum' ],
|
|
200
|
-
inKind: [ 'element', 'type', 'param', 'annotation', 'annotate' ],
|
|
201
|
+
inKind: [ 'element', 'type', 'param', 'annotation', 'annotate', 'extend' ],
|
|
201
202
|
},
|
|
202
203
|
elements: {
|
|
203
204
|
dictionaryOf: definition,
|
package/lib/json/to-csn.js
CHANGED
|
@@ -36,14 +36,14 @@ function parseDocComment(comment) {
|
|
|
36
36
|
else if (lines.length === 2) {
|
|
37
37
|
// Comment that is essentially just a header + footer.
|
|
38
38
|
// First line, i.e. header, is always trimmed from left.
|
|
39
|
-
lines[0] = lines[0].
|
|
39
|
+
lines[0] = lines[0].trimStart();
|
|
40
40
|
|
|
41
41
|
// If the second line starts with an asterisk then remove it.
|
|
42
42
|
// Otherwise trim all whitespace.
|
|
43
43
|
if ((/^\s*[*]/.test(lines[1])))
|
|
44
44
|
lines[1] = removeFence(lines[1]);
|
|
45
45
|
else
|
|
46
|
-
lines[1] = lines[1].
|
|
46
|
+
lines[1] = lines[1].trimStart();
|
|
47
47
|
}
|
|
48
48
|
else {
|
|
49
49
|
const firstNonEmptyLine = lines.find((line, index) => index !== 0 && /[^\s]/.test(line)) || '';
|
|
@@ -93,7 +93,9 @@ GenericAntlrParser.prototype = Object.assign(
|
|
|
93
93
|
setMaxCardinality,
|
|
94
94
|
pushIdent,
|
|
95
95
|
handleComposition,
|
|
96
|
+
associationInSelectItem,
|
|
96
97
|
reportExpandInline,
|
|
98
|
+
checkTypeFacet,
|
|
97
99
|
notSupportedYet,
|
|
98
100
|
csnParseOnly,
|
|
99
101
|
disallowElementExtension,
|
|
@@ -594,11 +596,11 @@ function numberLiteral( token, sign, text = token.text ) {
|
|
|
594
596
|
location.endCol = endCol;
|
|
595
597
|
text = sign.text + text;
|
|
596
598
|
}
|
|
599
|
+
|
|
597
600
|
const num = Number.parseFloat( text || '0' ); // not Number.parseInt() !
|
|
598
601
|
if (!Number.isSafeInteger(num)) {
|
|
599
602
|
if (sign == null) {
|
|
600
|
-
this.error( 'syntax-
|
|
601
|
-
'An integer number is expected here' );
|
|
603
|
+
this.error( 'syntax-expected-integer', token, { '#': !text.match(/^[0-9]*$/) ? 'normal' : 'unsafe'} );
|
|
602
604
|
}
|
|
603
605
|
else if (text !== `${num}`) {
|
|
604
606
|
return { literal: 'number', val: text, location };
|
|
@@ -902,6 +904,31 @@ function handleComposition( cardinality, isComposition ) {
|
|
|
902
904
|
this.excludeExpected( [ [ "'}'", 'COMPOSITIONofBRACE' ], brace1, ...manyOne ] );
|
|
903
905
|
}
|
|
904
906
|
|
|
907
|
+
function associationInSelectItem( art ) {
|
|
908
|
+
const isPath = art.value.path && art.value.path.length
|
|
909
|
+
const isIdentifier = isPath && art.value.path.length === 1;
|
|
910
|
+
if (isIdentifier) {
|
|
911
|
+
if (!art.name) {
|
|
912
|
+
art.name = art.value.path[0];
|
|
913
|
+
} else {
|
|
914
|
+
// Use alias if provided, i.e. ignore art.value.path.
|
|
915
|
+
this.error( 'query-unexpected-alias', art.name.location, {},
|
|
916
|
+
'Unexpected alias for association' );
|
|
917
|
+
}
|
|
918
|
+
delete art.value;
|
|
919
|
+
} else {
|
|
920
|
+
const loc = isPath ? art.value.path[1].location : art.value.location;
|
|
921
|
+
// If neither path nor alias are present, `query-req-name` is emitted in `populate.js`.
|
|
922
|
+
if (isPath || art.name) {
|
|
923
|
+
this.error( 'query-expected-identifier', loc, { '#': 'assoc' } );
|
|
924
|
+
if (isPath) {
|
|
925
|
+
art.name = art.value.path[art.value.path.length - 1];
|
|
926
|
+
}
|
|
927
|
+
delete art.value;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
905
932
|
function reportExpandInline( clauseName ) {
|
|
906
933
|
let token = this.getCurrentToken();
|
|
907
934
|
// improve error location when using "inline" `.{…}` after ref (arguments and
|
|
@@ -913,6 +940,24 @@ function reportExpandInline( clauseName ) {
|
|
|
913
940
|
'Unexpected nested $(PROP), can only be used after a reference' );
|
|
914
941
|
}
|
|
915
942
|
|
|
943
|
+
function checkTypeFacet( art, argIdent ) {
|
|
944
|
+
const id = argIdent.id;
|
|
945
|
+
if (id === 'length' || id === 'scale' || id === 'precision' || id === 'srid') {
|
|
946
|
+
if (art[id] !== undefined) {
|
|
947
|
+
this.error( 'syntax-duplicate-argument', argIdent.location,
|
|
948
|
+
{ '#': 'duplicate', code: id } );
|
|
949
|
+
this.error( 'syntax-duplicate-argument', art[id].location,
|
|
950
|
+
{ '#': 'duplicate', code: id } );
|
|
951
|
+
}
|
|
952
|
+
return true;
|
|
953
|
+
|
|
954
|
+
} else {
|
|
955
|
+
this.error( 'syntax-duplicate-argument', argIdent.location,
|
|
956
|
+
{ '#': 'unknown', code: id } );
|
|
957
|
+
return false;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
|
|
916
961
|
module.exports = {
|
|
917
962
|
genericAntlrParser: GenericAntlrParser,
|
|
918
963
|
};
|
package/lib/language/language.g4
CHANGED
|
@@ -1279,7 +1279,7 @@ selectItemDef[ outer ] locals[ annos = [] ]
|
|
|
1279
1279
|
;
|
|
1280
1280
|
|
|
1281
1281
|
selectItemDefBody[ outer, annos ] returns[ art = {} ]
|
|
1282
|
-
@after{ /* #ATN
|
|
1282
|
+
@after{ /* #ATN 2 */ this.attachLocation($art); }
|
|
1283
1283
|
:
|
|
1284
1284
|
(
|
|
1285
1285
|
e=expression
|
|
@@ -1335,6 +1335,12 @@ selectItemDefBody[ outer, annos ] returns[ art = {} ]
|
|
|
1335
1335
|
| typeRefOptArgs[ $art ] // TODO: annos here?
|
|
1336
1336
|
{ this.docComment( $annos ); }
|
|
1337
1337
|
annotationAssignment_ll1[ $annos ]*
|
|
1338
|
+
|
|
|
1339
|
+
typeAssociationBase[ $art, false ]
|
|
1340
|
+
// #ATN: path could start with MANY or ONE - make sure a token follows in same rule!
|
|
1341
|
+
( typeToMany[ $art ] | typeToOne[ $art ] | simplePath[ $art.target, 'artref' ] )
|
|
1342
|
+
typeAssociationCont[ $art ]?
|
|
1343
|
+
{ this.associationInSelectItem( $art ); }
|
|
1338
1344
|
)
|
|
1339
1345
|
)?
|
|
1340
1346
|
;
|
|
@@ -1592,26 +1598,7 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1592
1598
|
{ $art.type = {}; }
|
|
1593
1599
|
simplePath[ $art.type, 'artref' ]
|
|
1594
1600
|
(
|
|
1595
|
-
|
|
1596
|
-
head=Number
|
|
1597
|
-
{ $art['$'+'typeArgs'] = [ this.numberLiteral( $head ) ]; }
|
|
1598
|
-
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
1599
|
-
(
|
|
1600
|
-
v=VARIABLE
|
|
1601
|
-
{ $art['$'+'typeArgs'].push(
|
|
1602
|
-
{ literal: 'string', val: 'variable', location: this.tokenLocation($v) } );
|
|
1603
|
-
}
|
|
1604
|
-
|
|
|
1605
|
-
f=FLOATING
|
|
1606
|
-
{ $art['$'+'typeArgs'].push(
|
|
1607
|
-
{ literal: 'string', val: 'floating', location: this.tokenLocation($f) } );
|
|
1608
|
-
}
|
|
1609
|
-
|
|
|
1610
|
-
tail=Number
|
|
1611
|
-
{ $art['$'+'typeArgs'].push( this.numberLiteral( $tail ) ); }
|
|
1612
|
-
)
|
|
1613
|
-
)*
|
|
1614
|
-
')'
|
|
1601
|
+
typeRefArgs[ $art ]
|
|
1615
1602
|
{ this.docComment( $annos ); }
|
|
1616
1603
|
annotationAssignment_ll1[ $annos ]*
|
|
1617
1604
|
(
|
|
@@ -1855,7 +1842,19 @@ typeRefOptArgs[ art ]
|
|
|
1855
1842
|
:
|
|
1856
1843
|
simplePath[ $art.type, 'artref' ]
|
|
1857
1844
|
(
|
|
1858
|
-
|
|
1845
|
+
typeRefArgs[ $art ]
|
|
1846
|
+
|
|
|
1847
|
+
':'
|
|
1848
|
+
{ $art.type.scope = $art.type.path.length; }
|
|
1849
|
+
simplePath[ $art.type, 'ref']
|
|
1850
|
+
)?
|
|
1851
|
+
;
|
|
1852
|
+
|
|
1853
|
+
typeRefArgs[ art ]
|
|
1854
|
+
:
|
|
1855
|
+
paren='('
|
|
1856
|
+
(
|
|
1857
|
+
// unnamed arguments
|
|
1859
1858
|
head=Number
|
|
1860
1859
|
{ $art['$'+'typeArgs'] = [ this.numberLiteral( $head ) ]; }
|
|
1861
1860
|
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
@@ -1874,14 +1873,45 @@ typeRefOptArgs[ art ]
|
|
|
1874
1873
|
{ $art['$'+'typeArgs'].push( this.numberLiteral( $tail ) ); }
|
|
1875
1874
|
)
|
|
1876
1875
|
)*
|
|
1877
|
-
')'
|
|
1878
1876
|
|
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1877
|
+
// named arguments
|
|
1878
|
+
typeNamedArg[ $art ]
|
|
1879
|
+
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
1880
|
+
typeNamedArg[ $art ]
|
|
1881
|
+
)*
|
|
1882
|
+
)
|
|
1883
|
+
')'
|
|
1884
|
+
;
|
|
1885
|
+
|
|
1886
|
+
typeNamedArg[ art ] locals[ arg = '' ]
|
|
1887
|
+
:
|
|
1888
|
+
name=ident['paramname']
|
|
1889
|
+
':'
|
|
1890
|
+
{ if (this.checkTypeFacet( $art, $name.id ))
|
|
1891
|
+
$arg = $name.id.id;
|
|
1892
|
+
}
|
|
1893
|
+
(
|
|
1894
|
+
val=Number
|
|
1895
|
+
{ if ($arg && $art && $name.id) {
|
|
1896
|
+
$art[$arg] = this.numberLiteral( $val );
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
|
|
|
1900
|
+
v=VARIABLE
|
|
1901
|
+
{ if ($arg && $art && $name.id) {
|
|
1902
|
+
$art[$arg] = { literal: 'string', val: 'variable', location: this.tokenLocation($v) };
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
|
|
|
1906
|
+
f=FLOATING
|
|
1907
|
+
{ if ($arg && $art && $name.id) {
|
|
1908
|
+
$art[$arg] = { literal: 'string', val: 'floating', location: this.tokenLocation($f) };
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
)
|
|
1883
1912
|
;
|
|
1884
1913
|
|
|
1914
|
+
|
|
1885
1915
|
// Queries -------------------------------------------------------------------
|
|
1886
1916
|
|
|
1887
1917
|
queryExpression returns[ query ] // QLSubqueryComplex, SubqueryComplex
|
|
@@ -2241,6 +2271,7 @@ conditionAnd returns [ cond ] locals [ args = [], andl = [] ]
|
|
|
2241
2271
|
( and=AND c2=conditionTerm { $args.push($c2.cond); $andl.push(this.valueWithTokenLocation( 'and', $and )) } )*
|
|
2242
2272
|
;
|
|
2243
2273
|
|
|
2274
|
+
// Note: New operators need to be added to functionExpressionOperatorsRequireParentheses[] in toCdl.js.
|
|
2244
2275
|
conditionTerm returns [ cond ]
|
|
2245
2276
|
@after{
|
|
2246
2277
|
if ($cond) { this.attachLocation($cond); } else { $cond = $expr.expr; }
|
|
@@ -2288,6 +2319,7 @@ conditionTerm returns [ cond ]
|
|
|
2288
2319
|
)? // optional: for conditions in parentheses
|
|
2289
2320
|
;
|
|
2290
2321
|
|
|
2322
|
+
// Note: New operators need to be added to functionExpressionOperatorsRequireParentheses[] in toCdl.js.
|
|
2291
2323
|
predicate[ cond, negated ]
|
|
2292
2324
|
// As an alternative, we could have a `negated` properties for the operations
|
|
2293
2325
|
// `isNull`(!), `in`, `between` and `like` (or produce the same AST as for
|
package/lib/main.d.ts
CHANGED
|
@@ -81,6 +81,11 @@ declare namespace compiler {
|
|
|
81
81
|
* use this frontend as the fallback parser.
|
|
82
82
|
*/
|
|
83
83
|
fallbackParser?: string | 'cdl' | 'csn'
|
|
84
|
+
/**
|
|
85
|
+
* Where to find `@sap/cds/` packages. This string, if set, is used as
|
|
86
|
+
* the prefix for SAP CDS packages / CDS files.
|
|
87
|
+
*/
|
|
88
|
+
cdsHome?: string
|
|
84
89
|
/**
|
|
85
90
|
* Option for {@link compileSources}. If set, all objects inside the
|
|
86
91
|
* provided sources dictionary are interpreted as XSN structures instead
|
|
@@ -895,7 +900,20 @@ declare namespace compiler {
|
|
|
895
900
|
* The functions in `userFunctions` are usually transformer functions, which
|
|
896
901
|
* change the input CSN destructively.
|
|
897
902
|
*/
|
|
898
|
-
export function traverseCsn(userFunctions: Record<string, Function>, csn: object|any[]);
|
|
903
|
+
export function traverseCsn(userFunctions: Record<string, Function>, csn: object|any[]): void;
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* CSN Model related functions.
|
|
907
|
+
*/
|
|
908
|
+
export namespace model {
|
|
909
|
+
/**
|
|
910
|
+
* Returns true if the given definition name is in a reserved namespace such as `cds.*`
|
|
911
|
+
* but not `cds.foundation.*`.
|
|
912
|
+
*
|
|
913
|
+
* @param definitionName Top-level definition name of the artifact.
|
|
914
|
+
*/
|
|
915
|
+
function isInReservedNamespace(definitionName: string): boolean;
|
|
916
|
+
}
|
|
899
917
|
|
|
900
918
|
/**
|
|
901
919
|
* @private
|
package/lib/main.js
CHANGED
|
@@ -25,6 +25,7 @@ const parseLanguage = require('./language/antlrParser');
|
|
|
25
25
|
const { parseX, compileX, compileSyncX, compileSourcesX, InvocationError } = require('./compiler');
|
|
26
26
|
const { fns } = require('./compiler/shared');
|
|
27
27
|
const define = require('./compiler/define');
|
|
28
|
+
const { isInReservedNamespace } = require("./compiler/builtins");
|
|
28
29
|
const finalizeParseCdl = require('./compiler/finalize-parse-cdl');
|
|
29
30
|
|
|
30
31
|
// The compiler version (taken from package.json)
|
|
@@ -148,4 +149,9 @@ module.exports = {
|
|
|
148
149
|
// it, you MUST talk with us - there can be potential incompatibilities with
|
|
149
150
|
// new releases (even having the same major version):
|
|
150
151
|
$lsp: { parse: parseX, compile: compileX, getArtifactName: a => a.name },
|
|
152
|
+
|
|
153
|
+
// CSN Model related functionality
|
|
154
|
+
model: {
|
|
155
|
+
isInReservedNamespace,
|
|
156
|
+
},
|
|
151
157
|
};
|
package/lib/model/csnRefs.js
CHANGED
|
@@ -442,7 +442,11 @@ function csnRefs( csn, universalReady ) {
|
|
|
442
442
|
const queries = cached( main, '$queries', allQueries );
|
|
443
443
|
for (const qcache of queries || []) {
|
|
444
444
|
const { _select } = qcache;
|
|
445
|
-
|
|
445
|
+
const { elements } = _select;
|
|
446
|
+
if (elements) {
|
|
447
|
+
for (const n of Object.keys( elements ))
|
|
448
|
+
traverseDef( elements[n], _select, 'element', n, initNode );
|
|
449
|
+
}
|
|
446
450
|
if (_select.mixin) {
|
|
447
451
|
for (const n of Object.keys( _select.mixin ))
|
|
448
452
|
setCache( _select.mixin[n], '_parent', _select ); // relevant initNode() part
|
|
@@ -453,7 +457,13 @@ function csnRefs( csn, universalReady ) {
|
|
|
453
457
|
|
|
454
458
|
function initNode( art, parent, kind, name ) {
|
|
455
459
|
setCache( art, '_parent', parent );
|
|
456
|
-
if (
|
|
460
|
+
if (kind === 'target') {
|
|
461
|
+
// Prevent re-initialization of anonymous aspect with initDefinition():
|
|
462
|
+
// (that would be with parent: null which would be wrong)
|
|
463
|
+
setCache( art, '$queries', null );
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
if (art.type || !kind) // with type, top-level, query or mixin
|
|
457
467
|
return;
|
|
458
468
|
const { $origin } = art;
|
|
459
469
|
if (typeof $origin === 'object') // null, […], {…}
|
|
@@ -547,8 +557,19 @@ function csnRefs( csn, universalReady ) {
|
|
|
547
557
|
}
|
|
548
558
|
if (baseEnv) // ref-target (filter condition), expand, inline
|
|
549
559
|
return resolvePath( path, baseEnv.elements[head], baseEnv, semantics.dynamic );
|
|
550
|
-
if (!query)
|
|
551
|
-
|
|
560
|
+
if (!query) { // outside queries - TODO: items?
|
|
561
|
+
let art = parent.elements[head];
|
|
562
|
+
// Ref to up_ in anonymous aspect
|
|
563
|
+
if (!art && head === 'up_') {
|
|
564
|
+
const up = getCache( parent, '_parent' );
|
|
565
|
+
const target = up && typeof up.target === 'string' && csn.definitions[up.target];
|
|
566
|
+
if (target && target.elements) {
|
|
567
|
+
initDefinition( target );
|
|
568
|
+
art = target.elements.up_;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return resolvePath( path, art, parent, 'parent' );
|
|
572
|
+
}
|
|
552
573
|
|
|
553
574
|
if (semantics.dynamic === 'query')
|
|
554
575
|
// TODO: for ON condition in expand, would need to use cached _element
|
|
@@ -703,6 +724,11 @@ function csnRefs( csn, universalReady ) {
|
|
|
703
724
|
hidden = {};
|
|
704
725
|
cache.set( obj, hidden );
|
|
705
726
|
}
|
|
727
|
+
// TODO: we might keep the following with --test-mode
|
|
728
|
+
// if (hidden[prop] !== undefined) {
|
|
729
|
+
// console.log('RS:',prop,hidden[prop],val,obj)
|
|
730
|
+
// throw Error('RESET')
|
|
731
|
+
// }
|
|
706
732
|
hidden[prop] = val;
|
|
707
733
|
return val;
|
|
708
734
|
}
|
|
@@ -818,7 +844,7 @@ function traverseDef( node, parent, kind, name, callback ) {
|
|
|
818
844
|
}
|
|
819
845
|
if (node.returns)
|
|
820
846
|
traverseType( node.returns, node, 'returns', true, callback );
|
|
821
|
-
traverseType( node,
|
|
847
|
+
traverseType( node, true, kind, name, callback );
|
|
822
848
|
if (node.actions) {
|
|
823
849
|
for (const n of Object.keys( node.actions ))
|
|
824
850
|
traverseDef( node.actions[n], node, 'action', n, callback )
|
|
@@ -826,7 +852,8 @@ function traverseDef( node, parent, kind, name, callback ) {
|
|
|
826
852
|
}
|
|
827
853
|
|
|
828
854
|
function traverseType( node, parent, kind, name, callback ) {
|
|
829
|
-
|
|
855
|
+
if (parent !== true)
|
|
856
|
+
callback ( node, parent, kind, name );
|
|
830
857
|
const target = targetAspect( node );
|
|
831
858
|
if (target && typeof target === 'object' && target.elements) {
|
|
832
859
|
callback ( target, node, 'target', true );
|