@sap/cds-compiler 3.1.2 → 3.4.0
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 +101 -3
- package/bin/cdsc.js +4 -2
- package/doc/CHANGELOG_BETA.md +35 -0
- package/lib/api/main.js +153 -29
- package/lib/api/validate.js +8 -3
- package/lib/base/dictionaries.js +6 -6
- package/lib/base/error.js +2 -2
- package/lib/base/keywords.js +106 -24
- package/lib/base/message-registry.js +177 -79
- package/lib/base/messages.js +78 -57
- package/lib/base/model.js +2 -1
- package/lib/checks/actionsFunctions.js +1 -1
- package/lib/checks/annotationsOData.js +2 -2
- package/lib/checks/arrayOfs.js +15 -7
- package/lib/checks/cdsPersistence.js +1 -1
- package/lib/checks/checkForTypes.js +53 -0
- package/lib/checks/defaultValues.js +4 -2
- package/lib/checks/elements.js +81 -6
- package/lib/checks/foreignKeys.js +12 -13
- package/lib/checks/invalidTarget.js +10 -11
- package/lib/checks/managedInType.js +21 -15
- package/lib/checks/nullableKeys.js +1 -1
- package/lib/checks/onConditions.js +9 -9
- package/lib/checks/parameters.js +23 -0
- package/lib/checks/queryNoDbArtifacts.js +1 -1
- package/lib/checks/selectItems.js +1 -1
- package/lib/checks/sql-snippets.js +12 -10
- package/lib/checks/types.js +2 -2
- package/lib/checks/utils.js +17 -7
- package/lib/checks/validator.js +36 -14
- package/lib/compiler/assert-consistency.js +21 -13
- package/lib/compiler/builtins.js +8 -0
- package/lib/compiler/checks.js +57 -40
- package/lib/compiler/define.js +139 -69
- package/lib/compiler/extend.js +319 -50
- package/lib/compiler/finalize-parse-cdl.js +14 -9
- package/lib/compiler/kick-start.js +2 -35
- package/lib/compiler/populate.js +111 -68
- package/lib/compiler/propagator.js +5 -3
- package/lib/compiler/resolve.js +71 -108
- package/lib/compiler/shared.js +82 -54
- package/lib/compiler/tweak-assocs.js +26 -14
- package/lib/compiler/utils.js +13 -2
- package/lib/edm/annotations/genericTranslation.js +10 -7
- package/lib/edm/csn2edm.js +11 -11
- package/lib/edm/edm.js +17 -9
- package/lib/edm/edmPreprocessor.js +53 -30
- package/lib/edm/edmUtils.js +7 -2
- package/lib/gen/Dictionary.json +14 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +3 -2
- package/lib/gen/languageParser.js +4312 -4186
- package/lib/inspect/inspectModelStatistics.js +1 -1
- package/lib/inspect/inspectPropagation.js +23 -9
- package/lib/json/csnVersion.js +13 -13
- package/lib/json/from-csn.js +161 -172
- package/lib/json/to-csn.js +70 -10
- package/lib/language/.eslintrc.json +4 -0
- package/lib/language/antlrParser.js +8 -11
- package/lib/language/docCommentParser.js +1 -2
- package/lib/language/errorStrategy.js +54 -27
- package/lib/language/genericAntlrParser.js +140 -93
- package/lib/language/language.g4 +57 -33
- package/lib/language/multiLineStringParser.js +75 -63
- package/lib/main.d.ts +3 -6
- package/lib/main.js +1 -0
- package/lib/model/.eslintrc.json +13 -0
- package/lib/model/api.js +4 -2
- package/lib/model/csnRefs.js +78 -50
- package/lib/model/csnUtils.js +272 -222
- package/lib/model/enrichCsn.js +41 -31
- package/lib/model/revealInternalProperties.js +61 -57
- package/lib/model/sortViews.js +35 -31
- package/lib/modelCompare/compare.js +52 -18
- package/lib/modelCompare/filter.js +83 -0
- package/lib/optionProcessor.js +10 -1
- package/lib/render/manageConstraints.js +11 -7
- package/lib/render/toCdl.js +151 -106
- package/lib/render/toHdbcds.js +8 -6
- package/lib/render/toRename.js +4 -4
- package/lib/render/toSql.js +17 -7
- package/lib/render/utils/common.js +27 -9
- package/lib/render/utils/sql.js +5 -5
- package/lib/sql-identifier.js +7 -0
- package/lib/transform/db/applyTransformations.js +32 -3
- package/lib/transform/db/assertUnique.js +27 -38
- package/lib/transform/db/expansion.js +92 -41
- package/lib/transform/db/flattening.js +1 -1
- package/lib/transform/db/temporal.js +3 -1
- package/lib/transform/db/transformExists.js +8 -2
- package/lib/transform/db/views.js +42 -13
- package/lib/transform/draft/db.js +2 -2
- package/lib/transform/forOdataNew.js +10 -7
- package/lib/transform/{forHanaNew.js → forRelationalDB.js} +18 -12
- package/lib/transform/localized.js +29 -20
- package/lib/transform/odata/toFinalBaseType.js +8 -11
- package/lib/transform/odata/typesExposure.js +2 -1
- package/lib/transform/parseExpr.js +245 -0
- package/lib/transform/transformUtilsNew.js +122 -51
- package/lib/transform/translateAssocsToJoins.js +17 -16
- package/lib/utils/moduleResolve.js +5 -5
- package/lib/utils/objectUtils.js +3 -3
- package/lib/utils/term.js +5 -5
- package/package.json +2 -2
- package/share/messages/anno-duplicate-unrelated-layer.md +6 -6
- package/share/messages/check-proper-type-of.md +4 -4
- package/share/messages/check-proper-type.md +2 -2
- package/share/messages/duplicate-autoexposed.md +4 -4
- package/share/messages/extend-repeated-intralayer.md +4 -5
- package/share/messages/extend-unrelated-layer.md +4 -4
- package/share/messages/message-explanations.json +3 -1
- package/share/messages/redirected-to-ambiguous.md +7 -6
- package/share/messages/redirected-to-complex.md +63 -0
- package/share/messages/redirected-to-unrelated.md +6 -5
- package/share/messages/rewrite-not-supported.md +4 -4
- package/share/messages/{syntax-expected-integer.md → syntax-expecting-integer.md} +4 -4
- package/share/messages/wildcard-excluding-one.md +37 -0
package/lib/model/csnRefs.js
CHANGED
|
@@ -59,6 +59,13 @@
|
|
|
59
59
|
// delete `s` and then still expects inspectRef() to be able to resolve a
|
|
60
60
|
// reference `['s', 'x']`.
|
|
61
61
|
|
|
62
|
+
// There are currently 3 (SQL) backend issues for which we provide a workaround:
|
|
63
|
+
//
|
|
64
|
+
// - function `resolvePath`: issue with argument `arg` being falsy
|
|
65
|
+
// - function `artifactRef`: issue with non-string ref without definition
|
|
66
|
+
// - function `initColumnElement`: issue with column which is neither `*` nor
|
|
67
|
+
// a `ref` with sibling `inline`, but still has no corresponding element
|
|
68
|
+
|
|
62
69
|
// The functions in this module also use an internal cache. The second call of
|
|
63
70
|
// inspectRef() in the following example might lead to a wrong result or an
|
|
64
71
|
// exception if the assignment to `inspectRef` is not uncommented:
|
|
@@ -164,8 +171,8 @@
|
|
|
164
171
|
// - _effectiveType on def/member/items: cached result of effectiveType()
|
|
165
172
|
// - _origin on def/member/items: the "prototype"
|
|
166
173
|
// - $origin on def/member/items: whether implicit _origin refs have been set for direct members
|
|
167
|
-
// - _parent:
|
|
168
|
-
//
|
|
174
|
+
// - _parent: currently just use to allow ref to `up_` in anonymous aspect
|
|
175
|
+
// for managed compositions
|
|
169
176
|
// - _env on non-string path item: environment provided by the ref so far,
|
|
170
177
|
// next path item is element in it
|
|
171
178
|
// - _ref on non-string `type` or `from` ref, or on alias: the referred def/elem
|
|
@@ -181,7 +188,7 @@
|
|
|
181
188
|
|
|
182
189
|
const BUILTIN_TYPE = {};
|
|
183
190
|
const { locationString } = require('../base/location');
|
|
184
|
-
const { ModelError, CompilerAssertion } = require(
|
|
191
|
+
const { ModelError, CompilerAssertion } = require('../base/error');
|
|
185
192
|
|
|
186
193
|
// Properties in which artifact or members are defined - next property in the
|
|
187
194
|
// "csnPath" is the name or index of that property; 'args' (its value can be a
|
|
@@ -207,7 +214,7 @@ const referenceSemantics = {
|
|
|
207
214
|
excluding: { lexical: false, dynamic: 'source' },
|
|
208
215
|
expand: { lexical: justDollar, dynamic: 'expand' }, // ...using baseEnv
|
|
209
216
|
inline: { lexical: justDollar, dynamic: 'inline' }, // ...using baseEnv
|
|
210
|
-
ref_where: { lexical: justDollar
|
|
217
|
+
ref_where: { lexical: justDollar, dynamic: 'ref-target' }, // ...using baseEnv
|
|
211
218
|
on: { lexical: justDollar, dynamic: 'query' }, // assoc defs, redirected to
|
|
212
219
|
// there are also 'on_join' and 'on_mixin' with default semantics
|
|
213
220
|
orderBy_ref: { lexical: query => query, dynamic: 'query' },
|
|
@@ -216,7 +223,7 @@ const referenceSemantics = {
|
|
|
216
223
|
// refs in ORDER BY expr in UNION not really allowed - only with table alias (of outer queries) or $self
|
|
217
224
|
orderBy_set_expr: { lexical: query => query.$next, dynamic: false },
|
|
218
225
|
// default: { lexical: query => query, dynamic: 'source' }
|
|
219
|
-
}
|
|
226
|
+
};
|
|
220
227
|
|
|
221
228
|
function justDollar() {
|
|
222
229
|
return null;
|
|
@@ -234,23 +241,23 @@ function csnRefs( csn, universalReady ) {
|
|
|
234
241
|
initDefinition( art );
|
|
235
242
|
}
|
|
236
243
|
// Functions which set the new `baseEnv`:
|
|
237
|
-
resolveRef.expandInline = function
|
|
244
|
+
resolveRef.expandInline = function resolveExpandInline( ref, ...args ) {
|
|
238
245
|
return cached( ref, '_env', () => navigationEnv( resolveRef( ref, ...args ).art ) );
|
|
239
|
-
}
|
|
240
|
-
resolveRef.ref_where = function
|
|
246
|
+
};
|
|
247
|
+
resolveRef.ref_where = function resolveRefWhere( pathItem, baseRef, ...args ) {
|
|
241
248
|
return cached( pathItem, '_env', () => {
|
|
242
249
|
resolveRef( baseRef, ...args ); // sets _env cache for non-string ref items
|
|
243
250
|
return getCache( pathItem, '_env' );
|
|
244
251
|
} );
|
|
245
|
-
}
|
|
252
|
+
};
|
|
246
253
|
return {
|
|
247
254
|
effectiveType,
|
|
248
255
|
artifactRef,
|
|
249
256
|
getOrigin,
|
|
250
257
|
inspectRef,
|
|
251
258
|
queryOrMain,
|
|
252
|
-
getColumn:
|
|
253
|
-
getElement:
|
|
259
|
+
getColumn: elem => getCache( elem, '_column' ),
|
|
260
|
+
getElement: col => getCache( col, '_element' ),
|
|
254
261
|
initDefinition,
|
|
255
262
|
targetAspect,
|
|
256
263
|
__getCache_forEnrichCsnDebugging: obj => cache.get( obj ),
|
|
@@ -330,7 +337,7 @@ function csnRefs( csn, universalReady ) {
|
|
|
330
337
|
// Backend bug workaround, TODO: delete next 2 lines
|
|
331
338
|
if (notFound !== undefined)
|
|
332
339
|
return notFound;
|
|
333
|
-
throw new ModelError( `Unknown artifact reference: ${typeof ref !== 'string' ? JSON.stringify(ref.ref) : ref}` );
|
|
340
|
+
throw new ModelError( `Unknown artifact reference: ${ typeof ref !== 'string' ? JSON.stringify(ref.ref) : ref }` );
|
|
334
341
|
}
|
|
335
342
|
|
|
336
343
|
function artifactPathRef( ref ) {
|
|
@@ -364,9 +371,9 @@ function csnRefs( csn, universalReady ) {
|
|
|
364
371
|
// 3. user-induced redirection (in 'cast') with explicit foreign keys
|
|
365
372
|
// 4. original provided association def inside $origin with explicit foreign keys
|
|
366
373
|
// (outside $origin like 2)
|
|
367
|
-
const targetName = refCtx !== 'keys_origin' && art.target
|
|
368
|
-
|
|
369
|
-
|
|
374
|
+
const targetName = refCtx !== 'keys_origin' && art.target ||
|
|
375
|
+
art.$origin && art.$origin.target ||
|
|
376
|
+
art.cast.target;
|
|
370
377
|
const target = csn.definitions[targetName];
|
|
371
378
|
initDefinition( target );
|
|
372
379
|
return target;
|
|
@@ -387,8 +394,8 @@ function csnRefs( csn, universalReady ) {
|
|
|
387
394
|
const { $location } = art;
|
|
388
395
|
const location = $location &&
|
|
389
396
|
(typeof $location === 'string' ? $location : locationString( $location ));
|
|
390
|
-
const def = Object.keys( art ).join('+') + (location ?
|
|
391
|
-
throw new Error( `Inspecting non-initialized CSN node {${def}}` );
|
|
397
|
+
const def = Object.keys( art ).join('+') + (location ? `:${ location }` : '');
|
|
398
|
+
throw new Error( `Inspecting non-initialized CSN node {${ def }}` );
|
|
392
399
|
}
|
|
393
400
|
const step = getCache( art, '$origin$step' );
|
|
394
401
|
if (!step)
|
|
@@ -428,7 +435,7 @@ function csnRefs( csn, universalReady ) {
|
|
|
428
435
|
return effectiveType( art ).items;
|
|
429
436
|
if (step.target)
|
|
430
437
|
return targetAspect( effectiveType( art ) );
|
|
431
|
-
throw Error( `Illegal navigation step ${ Object.keys(step)[0]}` );
|
|
438
|
+
throw Error( `Illegal navigation step ${ Object.keys(step)[0] }` );
|
|
432
439
|
}
|
|
433
440
|
|
|
434
441
|
function effectiveArtFor( art, property ) {
|
|
@@ -529,16 +536,17 @@ function csnRefs( csn, universalReady ) {
|
|
|
529
536
|
return resolvePath( path, csn.definitions[head], null, 'global', semantics.assoc );
|
|
530
537
|
|
|
531
538
|
|
|
532
|
-
|
|
539
|
+
const qcache = query && cache.get( query.projection || query );
|
|
533
540
|
// first the lexical scopes (due to query hierarchy) and $magic: ---------
|
|
534
541
|
if (semantics.lexical !== false) {
|
|
535
542
|
const tryAlias = path.length > 1 || ref.expand || ref.inline;
|
|
536
543
|
let ncache = qcache && (semantics.lexical ? semantics.lexical( qcache ) : qcache);
|
|
537
544
|
while (ncache) {
|
|
538
545
|
const alias = tryAlias && ncache.$aliases[head];
|
|
539
|
-
if (alias)
|
|
546
|
+
if (alias) {
|
|
540
547
|
return resolvePath( path, alias._select || alias._ref, null,
|
|
541
548
|
'alias', ncache.$queryNumber );
|
|
549
|
+
}
|
|
542
550
|
const mixin = ncache._select.mixin && ncache._select.mixin[head];
|
|
543
551
|
if (mixin && {}.hasOwnProperty.call( ncache._select.mixin, head )) {
|
|
544
552
|
setCache( mixin, '_parent', qcache._select );
|
|
@@ -559,8 +567,14 @@ function csnRefs( csn, universalReady ) {
|
|
|
559
567
|
const target = assocTarget( parent, refCtx );
|
|
560
568
|
return resolvePath( path, target.elements[head], target, 'target' );
|
|
561
569
|
}
|
|
562
|
-
if (baseEnv)
|
|
563
|
-
|
|
570
|
+
if (baseEnv) { // ref-target (filter condition), expand, inline
|
|
571
|
+
if (semantics.dynamic !== 'query')
|
|
572
|
+
return resolvePath( path, baseEnv.elements[head], baseEnv, semantics.dynamic );
|
|
573
|
+
// in an ON condition of an association inside inner expand/inline:
|
|
574
|
+
const elemParent = getCache( parent, '_element' );
|
|
575
|
+
if (elemParent) // expand in expand
|
|
576
|
+
return resolvePath( path, elemParent.elements[head], null, 'query' );
|
|
577
|
+
}
|
|
564
578
|
if (!query) { // outside queries - TODO: items?
|
|
565
579
|
let art = parent.elements[head];
|
|
566
580
|
// Ref to up_ in anonymous aspect
|
|
@@ -582,11 +596,11 @@ function csnRefs( csn, universalReady ) {
|
|
|
582
596
|
const alias = qcache.$aliases[name];
|
|
583
597
|
const found = alias.elements[head];
|
|
584
598
|
if (found)
|
|
585
|
-
return resolvePath( path, found, alias._ref, 'source', name )
|
|
599
|
+
return resolvePath( path, found, alias._ref, 'source', name );
|
|
586
600
|
}
|
|
587
601
|
}
|
|
588
602
|
// console.log(query.SELECT,qcache,qcache.$next,main)
|
|
589
|
-
throw new ModelError
|
|
603
|
+
throw new ModelError( `Path item 0=${ head } refers to nothing, refCtx: ${ refCtx }` );
|
|
590
604
|
}
|
|
591
605
|
|
|
592
606
|
/**
|
|
@@ -601,7 +615,7 @@ function csnRefs( csn, universalReady ) {
|
|
|
601
615
|
const links = path.map( (_v, idx) => ({ idx }) );
|
|
602
616
|
// TODO: backends should be changed to enable uncommenting:
|
|
603
617
|
// if (!art) // does not work with test3/Associations/KeylessManagedAssociation/
|
|
604
|
-
// throw new ModelError
|
|
618
|
+
// throw new ModelError( `Path item 0=${ pathId( path[0] ) } refers to nothing, scope: ${ scope }`);
|
|
605
619
|
links[0].art = art;
|
|
606
620
|
for (let i = 1; i < links.length; ++i) { // yes, starting at 1, links[0] is set above
|
|
607
621
|
parent = navigationEnv( art, staticAssoc );
|
|
@@ -610,9 +624,9 @@ function csnRefs( csn, universalReady ) {
|
|
|
610
624
|
setCache( path[i - 1], '_env', parent );
|
|
611
625
|
art = parent.elements[pathId( path[i] )];
|
|
612
626
|
if (!art) {
|
|
613
|
-
const env = links[i - 1]
|
|
627
|
+
const { env } = links[i - 1];
|
|
614
628
|
const loc = env.name && env.name.$location || env.$location;
|
|
615
|
-
throw new ModelError
|
|
629
|
+
throw new ModelError( `Path item ${ i }=${ pathId( path[i] ) } on ${ locationString( loc ) } refers to nothing` );
|
|
616
630
|
}
|
|
617
631
|
links[i].art = art;
|
|
618
632
|
}
|
|
@@ -626,11 +640,15 @@ function csnRefs( csn, universalReady ) {
|
|
|
626
640
|
parent = null;
|
|
627
641
|
}
|
|
628
642
|
if (typeof last !== 'string')
|
|
629
|
-
setCache( last, '_env', env )
|
|
643
|
+
setCache( last, '_env', env );
|
|
630
644
|
}
|
|
631
645
|
return (extraInfo && scope !== 'global')
|
|
632
|
-
? {
|
|
633
|
-
|
|
646
|
+
? {
|
|
647
|
+
links, art, parent, scope, $env: extraInfo,
|
|
648
|
+
}
|
|
649
|
+
: {
|
|
650
|
+
links, art, parent, scope,
|
|
651
|
+
};
|
|
634
652
|
}
|
|
635
653
|
|
|
636
654
|
/**
|
|
@@ -649,7 +667,7 @@ function csnRefs( csn, universalReady ) {
|
|
|
649
667
|
if (query.ref) { // ref in from
|
|
650
668
|
// console.log('SQ:',query,cache.get(query))
|
|
651
669
|
const as = query.as || implicitAs( query.ref );
|
|
652
|
-
const _ref = cached( query, '_from', artifactFromRef )
|
|
670
|
+
const _ref = cached( query, '_from', artifactFromRef );
|
|
653
671
|
getCache( fromSelect, '$aliases' )[as] = { _ref, elements: _ref.elements, _parent: query };
|
|
654
672
|
}
|
|
655
673
|
else {
|
|
@@ -749,8 +767,9 @@ function csnRefs( csn, universalReady ) {
|
|
|
749
767
|
hidden = {};
|
|
750
768
|
cache.set( obj, hidden );
|
|
751
769
|
}
|
|
752
|
-
else if (hidden[prop] !== undefined)
|
|
770
|
+
else if (hidden[prop] !== undefined) {
|
|
753
771
|
return hidden[prop];
|
|
772
|
+
}
|
|
754
773
|
const val = calc( obj );
|
|
755
774
|
hidden[prop] = val;
|
|
756
775
|
return val;
|
|
@@ -759,7 +778,7 @@ function csnRefs( csn, universalReady ) {
|
|
|
759
778
|
|
|
760
779
|
// Return value of a query SELECT for the query node, or the main artifact,
|
|
761
780
|
// i.e. a value with an `elements` property.
|
|
762
|
-
// TODO: only used in
|
|
781
|
+
// TODO: only used in forRelationalDB - move somewhere else
|
|
763
782
|
/**
|
|
764
783
|
* @param {object} query node (object with SET or SELECT property)
|
|
765
784
|
* @param {object} main definition
|
|
@@ -830,7 +849,7 @@ function traverseFrom( from, fromSelect, parentQuery, callback ) {
|
|
|
830
849
|
|
|
831
850
|
function traverseExpr( expr, parentQuery, callback ) {
|
|
832
851
|
if (expr.SELECT || expr.SET)
|
|
833
|
-
traverseQuery( expr, null, parentQuery, callback )
|
|
852
|
+
traverseQuery( expr, null, parentQuery, callback );
|
|
834
853
|
for (const prop of [ 'args', 'xpr' ]) {
|
|
835
854
|
// all properties which could have sub queries (directly or indirectly),
|
|
836
855
|
const val = expr[prop];
|
|
@@ -842,7 +861,7 @@ function traverseExpr( expr, parentQuery, callback ) {
|
|
|
842
861
|
}
|
|
843
862
|
|
|
844
863
|
function traverseDef( node, parent, kind, name, callback ) {
|
|
845
|
-
callback
|
|
864
|
+
callback( node, parent, kind, name );
|
|
846
865
|
if (node.params) {
|
|
847
866
|
for (const n of Object.keys( node.params ))
|
|
848
867
|
traverseType( node.params[n], node, 'param', n, callback );
|
|
@@ -852,32 +871,32 @@ function traverseDef( node, parent, kind, name, callback ) {
|
|
|
852
871
|
traverseType( node, true, kind, name, callback );
|
|
853
872
|
if (node.actions) {
|
|
854
873
|
for (const n of Object.keys( node.actions ))
|
|
855
|
-
traverseDef( node.actions[n], node, 'action', n, callback )
|
|
874
|
+
traverseDef( node.actions[n], node, 'action', n, callback );
|
|
856
875
|
}
|
|
857
876
|
}
|
|
858
877
|
|
|
859
878
|
function traverseType( node, parent, kind, name, callback ) {
|
|
860
879
|
if (parent !== true)
|
|
861
|
-
callback
|
|
880
|
+
callback( node, parent, kind, name );
|
|
862
881
|
const target = targetAspect( node );
|
|
863
882
|
if (target && typeof target === 'object' && target.elements) {
|
|
864
|
-
callback
|
|
883
|
+
callback( target, node, 'target', true );
|
|
865
884
|
node = target;
|
|
866
885
|
}
|
|
867
886
|
else if (node.items) {
|
|
868
887
|
let items = 0;
|
|
869
888
|
while (node.items) {
|
|
870
|
-
callback
|
|
889
|
+
callback( node.items, node, 'items', ++items );
|
|
871
890
|
node = node.items;
|
|
872
891
|
}
|
|
873
892
|
}
|
|
874
893
|
if (node.elements) {
|
|
875
894
|
for (const n of Object.keys( node.elements ))
|
|
876
|
-
traverseDef( node.elements[n], node, 'element', n, callback )
|
|
895
|
+
traverseDef( node.elements[n], node, 'element', n, callback );
|
|
877
896
|
}
|
|
878
897
|
if (node.enum) {
|
|
879
898
|
for (const n of Object.keys( node.enum ))
|
|
880
|
-
traverseDef( node.enum[n], node, 'enum', n, callback )
|
|
899
|
+
traverseDef( node.enum[n], node, 'enum', n, callback );
|
|
881
900
|
}
|
|
882
901
|
}
|
|
883
902
|
|
|
@@ -901,14 +920,19 @@ function startCsnPath( csnPath, csn ) {
|
|
|
901
920
|
const head = csnPath[0];
|
|
902
921
|
if (typeof head !== 'string') {
|
|
903
922
|
const { main, parent, art } = head;
|
|
904
|
-
return {
|
|
923
|
+
return {
|
|
924
|
+
index: 1, main, parent, art,
|
|
925
|
+
};
|
|
905
926
|
}
|
|
906
|
-
if (csnPath.length < 2 || csnPath[0] !== 'definitions')
|
|
907
|
-
throw new CompilerAssertion( 'References outside definitions not supported yet');
|
|
908
|
-
const art = csn
|
|
909
|
-
return {
|
|
927
|
+
if (csnPath.length < 2 || csnPath[0] !== 'definitions' && csnPath[0] !== 'vocabularies')
|
|
928
|
+
throw new CompilerAssertion( 'References outside definitions and vocabularies not supported yet');
|
|
929
|
+
const art = csn[csnPath[0]][csnPath[1]];
|
|
930
|
+
return {
|
|
931
|
+
index: 2, main: art, parent: null, art,
|
|
932
|
+
};
|
|
910
933
|
}
|
|
911
934
|
|
|
935
|
+
|
|
912
936
|
/**
|
|
913
937
|
* @param {CSN.Path} csnPath
|
|
914
938
|
* @param {CSN.Model} csn
|
|
@@ -917,12 +941,15 @@ function startCsnPath( csnPath, csn ) {
|
|
|
917
941
|
function analyseCsnPath( csnPath, csn, resolve ) {
|
|
918
942
|
/** @type {object} */
|
|
919
943
|
let query = null;
|
|
944
|
+
/** @type {any} */
|
|
920
945
|
let refCtx = null;
|
|
921
946
|
/** @type {boolean|string|number} */
|
|
922
947
|
let isName = false;
|
|
923
948
|
let baseRef = null;
|
|
924
949
|
let baseEnv = null;
|
|
925
|
-
let {
|
|
950
|
+
let {
|
|
951
|
+
index, main, parent, art,
|
|
952
|
+
} = startCsnPath( csnPath, csn );
|
|
926
953
|
let obj = art;
|
|
927
954
|
|
|
928
955
|
for (; index < csnPath.length; index++) {
|
|
@@ -951,7 +978,9 @@ function analyseCsnPath( csnPath, csn, resolve ) {
|
|
|
951
978
|
}
|
|
952
979
|
else if (artifactProperties.includes( String(prop) )) {
|
|
953
980
|
if (refCtx === 'target' || refCtx === 'targetAspect') { // with 'elements'
|
|
954
|
-
|
|
981
|
+
// $self refers to the anonymous aspect
|
|
982
|
+
main = obj;
|
|
983
|
+
art = obj;
|
|
955
984
|
parent = null;
|
|
956
985
|
}
|
|
957
986
|
isName = prop;
|
|
@@ -981,8 +1010,7 @@ function analyseCsnPath( csnPath, csn, resolve ) {
|
|
|
981
1010
|
baseEnv = resolve.expandInline( obj, refCtx, main, query, parent, baseEnv );
|
|
982
1011
|
refCtx = prop;
|
|
983
1012
|
}
|
|
984
|
-
|
|
985
|
-
isName = prop;
|
|
1013
|
+
isName = prop;
|
|
986
1014
|
}
|
|
987
1015
|
else if (prop === 'on') {
|
|
988
1016
|
if (refCtx === 'from')
|