@sap/cds-compiler 4.9.4 → 5.0.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 +66 -0
- package/bin/cds_remove_invalid_whitespace.js +2 -1
- package/bin/cdsc.js +15 -11
- package/bin/cdshi.js +1 -0
- package/doc/CHANGELOG_BETA.md +7 -0
- package/lib/api/main.js +6 -18
- package/lib/api/options.js +3 -11
- package/lib/api/trace.js +0 -1
- package/lib/base/builtins.js +1 -0
- package/lib/base/location.js +4 -1
- package/lib/base/message-registry.js +29 -29
- package/lib/base/messages.js +22 -26
- package/lib/base/model.js +0 -2
- package/lib/base/node-helpers.js +0 -1
- package/lib/checks/enricher.js +1 -5
- package/lib/checks/structuredAnnoExpressions.js +30 -0
- package/lib/checks/validator.js +8 -0
- package/lib/compiler/assert-consistency.js +4 -1
- package/lib/compiler/base.js +1 -1
- package/lib/compiler/builtins.js +18 -2
- package/lib/compiler/checks.js +2 -5
- package/lib/compiler/define.js +7 -7
- package/lib/compiler/extend.js +68 -33
- package/lib/compiler/generate.js +1 -1
- package/lib/compiler/index.js +23 -6
- package/lib/compiler/lsp-api.js +501 -2
- package/lib/compiler/populate.js +2 -2
- package/lib/compiler/propagator.js +1 -4
- package/lib/compiler/resolve.js +2 -15
- package/lib/compiler/shared.js +112 -31
- package/lib/compiler/tweak-assocs.js +2 -16
- package/lib/compiler/utils.js +2 -1
- package/lib/compiler/xsn-model.js +4 -0
- package/lib/edm/annotations/genericTranslation.js +95 -42
- package/lib/edm/csn2edm.js +16 -4
- package/lib/edm/edm.js +2 -3
- package/lib/edm/edmAnnoPreprocessor.js +1 -2
- package/lib/edm/edmPreprocessor.js +1 -7
- package/lib/gen/Dictionary.json +29 -2
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +2 -1
- package/lib/gen/languageParser.js +4995 -4817
- package/lib/json/csnVersion.js +1 -1
- package/lib/json/from-csn.js +4 -7
- package/lib/json/to-csn.js +23 -12
- package/lib/language/antlrParser.js +2 -2
- package/lib/language/errorStrategy.js +0 -1
- package/lib/language/genericAntlrParser.js +35 -12
- package/lib/language/multiLineStringParser.js +3 -2
- package/lib/language/textUtils.js +1 -0
- package/lib/main.d.ts +28 -9
- package/lib/main.js +7 -4
- package/lib/model/csnRefs.js +20 -4
- package/lib/model/csnUtils.js +0 -2
- package/lib/model/revealInternalProperties.js +1 -1
- package/lib/modelCompare/compare.js +1 -1
- package/lib/optionProcessor.js +28 -9
- package/lib/render/manageConstraints.js +1 -1
- package/lib/render/toCdl.js +36 -7
- package/lib/render/toSql.js +1 -0
- package/lib/render/utils/common.js +12 -9
- package/lib/render/utils/stringEscapes.js +1 -0
- package/lib/transform/db/applyTransformations.js +13 -8
- package/lib/transform/db/associations.js +62 -54
- package/lib/transform/db/expansion.js +1 -6
- package/lib/transform/db/flattening.js +89 -111
- package/lib/transform/db/temporal.js +3 -4
- package/lib/transform/db/views.js +0 -1
- package/lib/transform/draft/odata.js +51 -3
- package/lib/transform/effective/annotations.js +3 -2
- package/lib/transform/effective/flattening.js +135 -0
- package/lib/transform/effective/main.js +6 -6
- package/lib/transform/effective/types.js +13 -9
- package/lib/transform/forOdata.js +0 -2
- package/lib/transform/forRelationalDB.js +0 -19
- package/lib/transform/localized.js +7 -8
- package/lib/transform/odata/flattening.js +39 -31
- package/lib/transform/odata/typesExposure.js +5 -17
- package/lib/transform/transformUtils.js +1 -1
- package/lib/transform/translateAssocsToJoins.js +21 -3
- package/lib/utils/file.js +13 -7
- package/lib/utils/moduleResolve.js +59 -8
- package/lib/utils/term.js +3 -2
- package/package.json +7 -3
- package/share/messages/message-explanations.json +2 -0
- package/share/messages/type-unexpected-foreign-keys.md +52 -0
- package/share/messages/type-unexpected-on-condition.md +52 -0
package/lib/compiler/shared.js
CHANGED
|
@@ -19,7 +19,6 @@ const {
|
|
|
19
19
|
isAssocToPrimaryKeys,
|
|
20
20
|
artifactRefLocation,
|
|
21
21
|
} = require('./utils');
|
|
22
|
-
const { isBetaEnabled } = require('../base/model');
|
|
23
22
|
|
|
24
23
|
const $inferred = Symbol.for( 'cds.$inferred' );
|
|
25
24
|
const $location = Symbol.for( 'cds.$location' );
|
|
@@ -56,13 +55,14 @@ function fns( model ) {
|
|
|
56
55
|
lexical: userBlock,
|
|
57
56
|
dynamic: modelDefinitions,
|
|
58
57
|
notFound: undefinedForAnnotate,
|
|
58
|
+
accept: extendableArtifact,
|
|
59
59
|
},
|
|
60
60
|
extend: {
|
|
61
61
|
isMainRef: 'no-generated',
|
|
62
62
|
lexical: userBlock,
|
|
63
63
|
dynamic: modelDefinitions,
|
|
64
64
|
notFound: undefinedDefinition,
|
|
65
|
-
accept:
|
|
65
|
+
accept: extendableArtifact,
|
|
66
66
|
},
|
|
67
67
|
_extensions: {
|
|
68
68
|
isMainRef: 'all',
|
|
@@ -163,7 +163,7 @@ function fns( model ) {
|
|
|
163
163
|
param: paramSemantics,
|
|
164
164
|
},
|
|
165
165
|
'limit-offset': 'limit-rows',
|
|
166
|
-
// general element references
|
|
166
|
+
// general element / variable references --------------------------------------
|
|
167
167
|
where: {
|
|
168
168
|
lexical: tableAliasesAndSelf,
|
|
169
169
|
dollar: true,
|
|
@@ -279,7 +279,7 @@ function fns( model ) {
|
|
|
279
279
|
annotation: { // annotation assignments
|
|
280
280
|
lexical: justDollarAliases,
|
|
281
281
|
dollar: true,
|
|
282
|
-
dynamic:
|
|
282
|
+
dynamic: parentElementsOrKeys,
|
|
283
283
|
navigation: assocOnNavigation,
|
|
284
284
|
noDep: true,
|
|
285
285
|
notFound: undefinedParentElement,
|
|
@@ -298,6 +298,7 @@ function fns( model ) {
|
|
|
298
298
|
}),
|
|
299
299
|
},
|
|
300
300
|
// TODO: introduce some kind of inheritance
|
|
301
|
+
// used by xpr-rewrite.js to resolve rewritten path roots.
|
|
301
302
|
annoRewrite: { // annotation assignments
|
|
302
303
|
lexical: justDollarAliases,
|
|
303
304
|
dollar: true,
|
|
@@ -323,6 +324,7 @@ function fns( model ) {
|
|
|
323
324
|
resolveTypeArgumentsUnchecked, // TODO: move to some other file
|
|
324
325
|
resolvePathRoot,
|
|
325
326
|
resolvePath,
|
|
327
|
+
resolveDefinitionName,
|
|
326
328
|
checkExpr,
|
|
327
329
|
checkOnCondition,
|
|
328
330
|
navigationEnv,
|
|
@@ -405,6 +407,7 @@ function fns( model ) {
|
|
|
405
407
|
|
|
406
408
|
const s = referenceSemantics[expected];
|
|
407
409
|
const semantics = (typeof s === 'string') ? referenceSemantics[s] : s;
|
|
410
|
+
semantics.name = expected;
|
|
408
411
|
|
|
409
412
|
const r = getPathRoot( ref, semantics, origUser );
|
|
410
413
|
const root = r && acceptPathRoot( r, ref, semantics, origUser );
|
|
@@ -512,6 +515,25 @@ function fns( model ) {
|
|
|
512
515
|
artifact.$typeArgs = undefined;
|
|
513
516
|
}
|
|
514
517
|
|
|
518
|
+
// Resolve the n-1 path steps before the definition name for LSP.
|
|
519
|
+
function resolveDefinitionName( art ) {
|
|
520
|
+
const path = art?.name?.path;
|
|
521
|
+
if (!art || art._main || !path || path.length <= 1)
|
|
522
|
+
return;
|
|
523
|
+
|
|
524
|
+
// Don't resolve paths in an annotation as a definition!
|
|
525
|
+
const definitions = art.kind === 'annotation' ? model.vocabularies : model.definitions;
|
|
526
|
+
|
|
527
|
+
let name = art.name.id;
|
|
528
|
+
if (art.kind === 'namespace') // namespace-statements are ref-only.
|
|
529
|
+
setArtifactLink( path[path.length - 1], definitions[name] || false );
|
|
530
|
+
|
|
531
|
+
for (let i = path.length - 1; i > 0; --i) {
|
|
532
|
+
name = name.substring(0, name.length - path[i].id.length - 1);
|
|
533
|
+
setArtifactLink( path[i - 1], definitions[name] || false );
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
515
537
|
function getPathRoot( { path, scope, location }, semantics, user ) {
|
|
516
538
|
// TODO: use string value of isMainRef?
|
|
517
539
|
const head = path[0];
|
|
@@ -524,8 +546,11 @@ function fns( model ) {
|
|
|
524
546
|
ruser = ruser._outer;
|
|
525
547
|
|
|
526
548
|
// Handle expand/inline, `type of`, :param, global (internally for CDL):
|
|
527
|
-
if (user._pathHead && !semantics.isMainRef) // in expand/inline
|
|
549
|
+
if (user._pathHead && !semantics.isMainRef) { // in expand/inline
|
|
550
|
+
const { name } = semantics;
|
|
528
551
|
semantics = semantics.nestedColumn();
|
|
552
|
+
semantics.name = name;
|
|
553
|
+
}
|
|
529
554
|
if (typeof scope === 'string') { // typeOf, param, global
|
|
530
555
|
semantics = semantics?.[scope] && semantics[scope]( ruser, path, location, semantics );
|
|
531
556
|
if (!semantics) {
|
|
@@ -563,10 +588,13 @@ function fns( model ) {
|
|
|
563
588
|
if (r)
|
|
564
589
|
return setArtifactLink( head, r );
|
|
565
590
|
|
|
566
|
-
if (!semantics.dollar)
|
|
591
|
+
if (!semantics.dollar) {
|
|
567
592
|
valid.push( dynamicDict );
|
|
568
|
-
|
|
569
|
-
|
|
593
|
+
}
|
|
594
|
+
else {
|
|
595
|
+
valid.push( removeInvalidMagicVariables( model.$magicVariables.elements, semantics ),
|
|
596
|
+
removeDollarNames( dynamicDict ) );
|
|
597
|
+
}
|
|
570
598
|
// TODO: streamline function arguments (probably: user, path, semantics )
|
|
571
599
|
const undef = semantics.notFound?.( user._user || user, head, valid, dynamicDict,
|
|
572
600
|
!isMainRef && user._user && user._artifact,
|
|
@@ -629,7 +657,6 @@ function fns( model ) {
|
|
|
629
657
|
// simple 'ref-undefined-art'/'ref-undefined-def' - TODO: which we
|
|
630
658
|
// could "change" to this message at the end of compile():
|
|
631
659
|
error( 'ref-unexpected-autoexposed', [ item.location, user ], { art },
|
|
632
|
-
// eslint-disable-next-line max-len
|
|
633
660
|
'An auto-exposed entity can\'t be referred to - expose entity $(ART) explicitly' );
|
|
634
661
|
return null; // continuation semantics: like “not found”
|
|
635
662
|
}
|
|
@@ -663,9 +690,13 @@ function fns( model ) {
|
|
|
663
690
|
// Do not accept a lonely table alias and `$projection`
|
|
664
691
|
// TODO: test table alias and mixin named `$projection`
|
|
665
692
|
if (path.length !== 1 || user.expand || user.inline) {
|
|
666
|
-
|
|
667
|
-
|
|
693
|
+
if (semantics.rewriteProjectionToSelf &&
|
|
694
|
+
art.kind === '$self' && path[0].id === '$projection') {
|
|
695
|
+
// Rewrite $projection to $self
|
|
668
696
|
path[0].id = '$self';
|
|
697
|
+
warning( 'ref-expecting-$self', [ path[0].location, user ],
|
|
698
|
+
{ code: '$projection', newcode: '$self' });
|
|
699
|
+
}
|
|
669
700
|
return art.name?.$inferred !== '$internal'; // not a compiler-generated internal alias
|
|
670
701
|
}
|
|
671
702
|
|
|
@@ -725,7 +756,14 @@ function fns( model ) {
|
|
|
725
756
|
message( 'ref-obsolete-parameters', [ head.location, user ],
|
|
726
757
|
{ code: `$parameters.${ id }`, newcode: `:${ id }` },
|
|
727
758
|
'Obsolete $(CODE) - replace by $(NEWCODE)' );
|
|
728
|
-
|
|
759
|
+
return art;
|
|
760
|
+
}
|
|
761
|
+
case 'builtin': {
|
|
762
|
+
if (art.name.id === '$at') {
|
|
763
|
+
warning( 'ref-deprecated-variable', [ head.location, user ],
|
|
764
|
+
{ code: '$at', newcode: '$valid' },
|
|
765
|
+
'$(CODE) is deprecated; use $(NEWCODE) instead' );
|
|
766
|
+
}
|
|
729
767
|
return art;
|
|
730
768
|
}
|
|
731
769
|
default:
|
|
@@ -868,6 +906,13 @@ function fns( model ) {
|
|
|
868
906
|
return environment( useParent ? user._parent : user );
|
|
869
907
|
}
|
|
870
908
|
|
|
909
|
+
function parentElementsOrKeys( user ) {
|
|
910
|
+
// annotations on foreign keys only ever have access to their keys (except of course via $self)
|
|
911
|
+
if (user.kind === 'key')
|
|
912
|
+
return user._parent?.foreignKeys || Object.create( null );
|
|
913
|
+
return parentElements( user );
|
|
914
|
+
}
|
|
915
|
+
|
|
871
916
|
function queryElements( user ) {
|
|
872
917
|
return environment( user );
|
|
873
918
|
}
|
|
@@ -1113,11 +1158,11 @@ function fns( model ) {
|
|
|
1113
1158
|
// TODO: if it becomes non-configurable, we can omit this warning
|
|
1114
1159
|
let id = pathName( path );
|
|
1115
1160
|
let head = path[0]._artifact || { _parent: art };
|
|
1116
|
-
// eslint-disable-next-line no-cond-assign
|
|
1117
1161
|
while ((head = head?._parent) && head.kind === 'builtin')
|
|
1118
1162
|
id = `${ head.name.id }.${ id }`;
|
|
1119
1163
|
const msgId = (art.$uncheckedElements) ? 'ref-unknown-var' : 'ref-undefined-var';
|
|
1120
|
-
signalNotFound( msgId, [ item.location, user ],
|
|
1164
|
+
signalNotFound( msgId, [ item.location, user ],
|
|
1165
|
+
removeInvalidMagicVariables( valid, semantics ), { id }, semantics );
|
|
1121
1166
|
}
|
|
1122
1167
|
else if (art.kind === 'aspect' && !art.name) { // anonymous target aspect - TODO: still?
|
|
1123
1168
|
signalNotFound( 'ref-undefined-element', [ item.location, user ], valid,
|
|
@@ -1199,9 +1244,16 @@ function fns( model ) {
|
|
|
1199
1244
|
: acceptElemOrVar( art, user, ref );
|
|
1200
1245
|
}
|
|
1201
1246
|
|
|
1202
|
-
function acceptElemOrVar( art, user, ref ) {
|
|
1247
|
+
function acceptElemOrVar( art, user, ref, semantics ) {
|
|
1203
1248
|
const { path } = ref;
|
|
1204
1249
|
if (art.kind === 'builtin') {
|
|
1250
|
+
if (art.$onlyInExprCtx && !art.$onlyInExprCtx.includes(semantics.name)) {
|
|
1251
|
+
error( 'ref-unexpected-var', [ ref.location, user ], {
|
|
1252
|
+
'#': art.$onlyInExprCtx[0], name: pathName( path ),
|
|
1253
|
+
});
|
|
1254
|
+
return null;
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1205
1257
|
if (user.expand || user.inline) {
|
|
1206
1258
|
const location = (user.expand || user.inline)[$location];
|
|
1207
1259
|
const code = (user.expand) ? '{ ‹expand› }' : '.{ ‹inline› }';
|
|
@@ -1234,16 +1286,19 @@ function fns( model ) {
|
|
|
1234
1286
|
return art;
|
|
1235
1287
|
}
|
|
1236
1288
|
|
|
1237
|
-
|
|
1289
|
+
/**
|
|
1290
|
+
* Returns true, if the artifact is a _real_ artifact that can be used for `extend`/`annotate`.
|
|
1291
|
+
*/
|
|
1292
|
+
function extendableArtifact( art, user, ref ) {
|
|
1238
1293
|
if (art.kind !== 'namespace')
|
|
1239
1294
|
return art;
|
|
1240
|
-
// For compatibility (≤v4), we accept `extend Unknown` without elements/actions/includes
|
|
1241
|
-
// In v5, only allow `extend with definitions`.
|
|
1242
|
-
if (!isBetaEnabled( model.options, 'v5preview' ) &&
|
|
1243
|
-
!(user.elements || user.actions || user.includes))
|
|
1244
|
-
return art;
|
|
1245
1295
|
const { location } = ref.path[ref.path.length - 1];
|
|
1246
|
-
|
|
1296
|
+
if (user.kind === 'extend' && !(user.elements || user.actions || user.includes))
|
|
1297
|
+
return art; // allow `extend with definitions` and empty extends
|
|
1298
|
+
|
|
1299
|
+
// for `annotate`, handle "namespaces" just like unknown artifacts: only emit a warning
|
|
1300
|
+
signalNotFound( user.kind === 'annotate' ? 'ext-undefined-def' : 'ref-undefined-def',
|
|
1301
|
+
[ location, user ], null, { art } );
|
|
1247
1302
|
return false;
|
|
1248
1303
|
}
|
|
1249
1304
|
|
|
@@ -1459,7 +1514,7 @@ function fns( model ) {
|
|
|
1459
1514
|
// console.log('NAV:',expr.path.map(r=>r.id),self)
|
|
1460
1515
|
if (self || self == null && columnRefStartsWithSelf( user )) {
|
|
1461
1516
|
checkOnlyForeignKeyNavigation( user, expr.path, 0, 'self-' );
|
|
1462
|
-
checkNoUnmanaged( expr, user, 'self-unmanaged' );
|
|
1517
|
+
checkNoUnmanaged( expr, user, true, 'self-unmanaged' );
|
|
1463
1518
|
}
|
|
1464
1519
|
// TODO: set navigation dependencies later to avoid both ref-cyclic and
|
|
1465
1520
|
// ref-invalid-navigation/ref-unexpected-assoc
|
|
@@ -1469,18 +1524,20 @@ function fns( model ) {
|
|
|
1469
1524
|
const { path } = expr;
|
|
1470
1525
|
if (!path)
|
|
1471
1526
|
return;
|
|
1472
|
-
|
|
1527
|
+
const self = path?.[0]?._navigation?.kind !== '$tableAlias';
|
|
1528
|
+
if (self)
|
|
1473
1529
|
checkOnlyForeignKeyNavigation( user, expr.path );
|
|
1474
|
-
checkNoUnmanaged( expr, user );
|
|
1530
|
+
checkNoUnmanaged( expr, user, self );
|
|
1475
1531
|
}
|
|
1476
1532
|
|
|
1477
1533
|
function checkRefInQuery( expr, exprCtx, user ) {
|
|
1478
1534
|
const { path } = expr;
|
|
1479
1535
|
if (!path)
|
|
1480
1536
|
return;
|
|
1481
|
-
|
|
1537
|
+
const self = pathStartsWithSelf( expr );
|
|
1538
|
+
if (self)
|
|
1482
1539
|
checkOnlyForeignKeyNavigation( user, expr.path, 0, 'self-' );
|
|
1483
|
-
checkNoUnmanaged( expr, user );
|
|
1540
|
+
checkNoUnmanaged( expr, user, self );
|
|
1484
1541
|
}
|
|
1485
1542
|
|
|
1486
1543
|
function checkExpandInlineRef( art, user, ref ) {
|
|
@@ -1523,10 +1580,10 @@ function fns( model ) {
|
|
|
1523
1580
|
}
|
|
1524
1581
|
const index = userTargetElementPathIndex( user, path );
|
|
1525
1582
|
checkOnlyForeignKeyNavigation( user, path, index );
|
|
1526
|
-
|
|
1583
|
+
const last = path[path.length - 1];
|
|
1584
|
+
if (!last.where && ref._artifact?.on) { // filter already complained about
|
|
1527
1585
|
const target = index > 0 && index < path.length && ref._artifact?.target;
|
|
1528
1586
|
const msg = (target?._artifact === user._main) ? 'self' : 'unmanaged';
|
|
1529
|
-
const last = path[path.length - 1];
|
|
1530
1587
|
error( 'ref-unexpected-assoc', [ last.location, user ],
|
|
1531
1588
|
{ '#': msg, code: '= $self' } );
|
|
1532
1589
|
}
|
|
@@ -1614,6 +1671,16 @@ function fns( model ) {
|
|
|
1614
1671
|
index = checkCoveredByForeignKey( assoc, path, index, user, msgPrefix );
|
|
1615
1672
|
}
|
|
1616
1673
|
assoc = path[index]?._artifact;
|
|
1674
|
+
if (assoc?.target) {
|
|
1675
|
+
// testing this above is not enough: we would not complain about $self
|
|
1676
|
+
// assoc filter at end of ref with expand/inline. We might also move the
|
|
1677
|
+
// unmanaged test above to here.
|
|
1678
|
+
if (path[index]?.where) {
|
|
1679
|
+
error( 'ref-unexpected-assoc', [ path[index].location, user ],
|
|
1680
|
+
{ '#': `${ msgPrefix }with-filter`, alias: '$self' } );
|
|
1681
|
+
return;
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1617
1684
|
}
|
|
1618
1685
|
}
|
|
1619
1686
|
|
|
@@ -1635,7 +1702,6 @@ function fns( model ) {
|
|
|
1635
1702
|
const txt = index >= path.length
|
|
1636
1703
|
? 'complete'
|
|
1637
1704
|
: (isAssocToPrimaryKeys( assoc ) ? 'keys' : 'std');
|
|
1638
|
-
// eslint-disable-next-line max-len
|
|
1639
1705
|
error( 'ref-invalid-navigation', [ last.location, user ], {
|
|
1640
1706
|
'#': msgPrefix + txt, art: assoc, name: last.id, alias: '$self',
|
|
1641
1707
|
}, {
|
|
@@ -1653,10 +1719,12 @@ function fns( model ) {
|
|
|
1653
1719
|
return path.length;
|
|
1654
1720
|
}
|
|
1655
1721
|
|
|
1656
|
-
function checkNoUnmanaged( ref, user, messageVariant = 'unmanaged' ) {
|
|
1722
|
+
function checkNoUnmanaged( ref, user, self, messageVariant = 'unmanaged' ) {
|
|
1657
1723
|
if (ref._artifact?.on && !ref.$expected) {
|
|
1658
1724
|
const { path } = ref;
|
|
1659
1725
|
const last = path[path.length - 1];
|
|
1726
|
+
if (self && last.where) // already complained about filter
|
|
1727
|
+
return;
|
|
1660
1728
|
error( 'ref-unexpected-assoc', [ last.location, user ],
|
|
1661
1729
|
{ '#': messageVariant, alias: '$self' } );
|
|
1662
1730
|
}
|
|
@@ -1745,6 +1813,19 @@ function fns( model ) {
|
|
|
1745
1813
|
}
|
|
1746
1814
|
}
|
|
1747
1815
|
|
|
1816
|
+
function removeInvalidMagicVariables( variables, semantics ) {
|
|
1817
|
+
if (Array.isArray(variables))
|
|
1818
|
+
return variables.map(variable => removeInvalidMagicVariables( variable, semantics ));
|
|
1819
|
+
|
|
1820
|
+
const valid = Object.create(null);
|
|
1821
|
+
for (const name in variables) {
|
|
1822
|
+
const variable = variables[name];
|
|
1823
|
+
if (!variable.$onlyInExprCtx || variable.$onlyInExprCtx.includes( semantics.name ))
|
|
1824
|
+
valid[name] = variable;
|
|
1825
|
+
}
|
|
1826
|
+
return valid;
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1748
1829
|
function removeDollarNames( dict ) {
|
|
1749
1830
|
const r = Object.create( null );
|
|
1750
1831
|
for (const name in dict) {
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
const {
|
|
6
6
|
forEachGeneric,
|
|
7
7
|
forEachInOrder,
|
|
8
|
-
isBetaEnabled,
|
|
9
8
|
} = require('../base/model');
|
|
10
9
|
const { dictLocation, weakLocation, weakRefLocation } = require('../base/location');
|
|
11
10
|
|
|
@@ -45,8 +44,6 @@ function tweakAssocs( model ) {
|
|
|
45
44
|
firstProjectionForPath,
|
|
46
45
|
});
|
|
47
46
|
|
|
48
|
-
const isV5preview = isBetaEnabled( model.options, 'v5preview' );
|
|
49
|
-
|
|
50
47
|
// Phase 5: rewrite associations
|
|
51
48
|
model._entities.forEach( rewriteArtifact );
|
|
52
49
|
// Think hard whether an on condition rewrite can lead to a new cyclic
|
|
@@ -111,9 +108,7 @@ function tweakAssocs( model ) {
|
|
|
111
108
|
info( 'assoc-target-not-in-service', loc,
|
|
112
109
|
{ target, '#': (elem._main.query ? 'select' : 'define') }, {
|
|
113
110
|
std: 'Target $(TARGET) of association is outside any service', // not used
|
|
114
|
-
// eslint-disable-next-line max-len
|
|
115
111
|
define: 'Target $(TARGET) of explicitly defined association is outside any service',
|
|
116
|
-
// eslint-disable-next-line max-len
|
|
117
112
|
select: 'Target $(TARGET) of explicitly selected association is outside any service',
|
|
118
113
|
} );
|
|
119
114
|
}
|
|
@@ -129,7 +124,7 @@ function tweakAssocs( model ) {
|
|
|
129
124
|
}
|
|
130
125
|
|
|
131
126
|
function rewriteAssociationCheck( element ) {
|
|
132
|
-
const elem = element.items || element; // TODO
|
|
127
|
+
const elem = element.items || element; // TODO v6: nested items
|
|
133
128
|
if (elem.elements)
|
|
134
129
|
forEachGeneric( elem, 'elements', rewriteAssociationCheck );
|
|
135
130
|
if (!elem.target)
|
|
@@ -236,7 +231,7 @@ function tweakAssocs( model ) {
|
|
|
236
231
|
}
|
|
237
232
|
|
|
238
233
|
function rewriteAssociation( element ) {
|
|
239
|
-
let elem = element.items || element; // TODO
|
|
234
|
+
let elem = element.items || element; // TODO v6: nested items
|
|
240
235
|
if (elem.elements)
|
|
241
236
|
forEachGeneric( elem, 'elements', rewriteAssociation );
|
|
242
237
|
if (elem.targetAspect?.elements)
|
|
@@ -456,15 +451,6 @@ function tweakAssocs( model ) {
|
|
|
456
451
|
};
|
|
457
452
|
setArtifactLink( elem.type, assocType._artifact );
|
|
458
453
|
|
|
459
|
-
if (!isV5preview) { // TODO(v5): Remove, only use $enclosed
|
|
460
|
-
elem.$filtered = {
|
|
461
|
-
val: true,
|
|
462
|
-
literal: 'boolean',
|
|
463
|
-
location,
|
|
464
|
-
$inferred: '$generated',
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
|
|
468
454
|
const isComp = (getUnderlyingBuiltinType( assoc )?.name?.id === 'cds.Composition');
|
|
469
455
|
if (isComp) {
|
|
470
456
|
elem.$enclosed = {
|
package/lib/compiler/utils.js
CHANGED
|
@@ -125,7 +125,8 @@ function proxyCopyMembers( art, dictProp, originDict, location, kind, tmpDepreca
|
|
|
125
125
|
// TODO throughout the compiler: do not set art.‹prop›.$inferred if art.$inferred
|
|
126
126
|
if (kind)
|
|
127
127
|
member.kind = kind;
|
|
128
|
-
else if (origin.key && !tmpDeprecated)
|
|
128
|
+
else if (origin.key && !tmpDeprecated)
|
|
129
|
+
// TODO(v6): remove tmpDeprecated once `noKeyPropagationWithExpansions` is removed
|
|
129
130
|
member.key = Object.assign( { $inferred: 'expanded' }, origin.key );
|
|
130
131
|
if (kind && origin.masked) // TODO: remove!
|
|
131
132
|
member.masked = Object.assign( { $inferred: 'nav' }, origin.masked );
|