@sap/cds-compiler 3.0.0 → 3.0.2
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 +29 -9
- package/bin/cdsc.js +9 -16
- package/lib/api/main.js +92 -40
- package/lib/base/keywords.js +64 -1
- package/lib/base/message-registry.js +17 -1
- package/lib/base/messages.js +38 -28
- package/lib/base/optionProcessorHelper.js +53 -21
- package/lib/compiler/assert-consistency.js +1 -1
- package/lib/compiler/builtins.js +40 -1
- package/lib/compiler/define.js +4 -2
- package/lib/compiler/extend.js +4 -1
- package/lib/compiler/populate.js +3 -1
- package/lib/compiler/resolve.js +1 -4
- package/lib/compiler/shared.js +9 -0
- package/lib/compiler/utils.js +2 -2
- package/lib/edm/annotations/preprocessAnnotations.js +10 -11
- package/lib/edm/csn2edm.js +15 -14
- package/lib/edm/edm.js +13 -12
- package/lib/edm/edmPreprocessor.js +30 -33
- package/lib/edm/edmUtils.js +3 -39
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +3311 -3289
- package/lib/json/from-csn.js +17 -19
- package/lib/json/to-csn.js +3 -2
- package/lib/language/genericAntlrParser.js +42 -42
- package/lib/language/language.g4 +28 -17
- package/lib/model/csnRefs.js +1 -0
- package/lib/model/csnUtils.js +19 -8
- package/lib/model/revealInternalProperties.js +4 -1
- package/lib/optionProcessor.js +54 -38
- package/lib/render/toHdbcds.js +1 -1
- package/lib/render/toSql.js +7 -3
- package/lib/transform/forOdataNew.js +3 -3
- package/lib/transform/localized.js +15 -11
- package/lib/utils/file.js +28 -18
- package/package.json +2 -3
- package/share/messages/syntax-expected-integer.md +9 -8
|
@@ -11,14 +11,11 @@ const {
|
|
|
11
11
|
intersect,
|
|
12
12
|
validateOptions,
|
|
13
13
|
foreach,
|
|
14
|
-
forAll,
|
|
15
|
-
isAssociationOrComposition,
|
|
16
14
|
isComposition,
|
|
17
15
|
isStructuredArtifact,
|
|
18
16
|
isParameterizedEntity,
|
|
19
17
|
resolveOnConditionAndPrepareConstraints,
|
|
20
18
|
finalizeReferentialConstraints,
|
|
21
|
-
isEntity,
|
|
22
19
|
getSchemaPrefix,
|
|
23
20
|
} = require('./edmUtils.js');
|
|
24
21
|
|
|
@@ -124,7 +121,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
124
121
|
(def, defName) => {
|
|
125
122
|
const mySchemaName = whatsMySchemaName(defName);
|
|
126
123
|
mySchemaName && setProp(def, '$mySchemaName', mySchemaName);
|
|
127
|
-
if(isMyServiceRequested(defName))
|
|
124
|
+
if(isMyServiceRequested(defName) && def.kind !== 'aspect')
|
|
128
125
|
reqDefs.definitions[defName] = def;
|
|
129
126
|
},
|
|
130
127
|
linkAssociationTarget ]);
|
|
@@ -336,23 +333,21 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
336
333
|
// link association target to association and add @odata.contained to compositions in V4
|
|
337
334
|
function linkAssociationTarget(struct) {
|
|
338
335
|
forEachMemberRecursively(struct, (element, name, prop, subpath) => {
|
|
339
|
-
if(
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
setProp(element, '_target', target);
|
|
336
|
+
if(element.target && !element._target) {
|
|
337
|
+
let target = csn.definitions[element.target];
|
|
338
|
+
if(target) {
|
|
339
|
+
setProp(element, '_target', target);
|
|
344
340
|
// If target has parameters, xref assoc at target for redirection
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
}
|
|
349
|
-
target.$sources[struct.name + '.' + name] = element;
|
|
341
|
+
if(isParameterizedEntity(target)) {
|
|
342
|
+
if(!target.$sources) {
|
|
343
|
+
setProp(target, '$sources', Object.create(null));
|
|
350
344
|
}
|
|
351
|
-
|
|
352
|
-
else {
|
|
353
|
-
error(null, subpath, { target: element.target }, "Target $(TARGET) can't be found in the model");
|
|
345
|
+
target.$sources[struct.name + '.' + name] = element;
|
|
354
346
|
}
|
|
355
347
|
}
|
|
348
|
+
else {
|
|
349
|
+
error(null, subpath, { target: element.target }, "Target $(TARGET) can't be found in the model");
|
|
350
|
+
}
|
|
356
351
|
}
|
|
357
352
|
// in V4 tag all compositions to be containments
|
|
358
353
|
if(options.odataContainment &&
|
|
@@ -384,7 +379,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
384
379
|
}
|
|
385
380
|
|
|
386
381
|
function initContainments(elt, eltName) {
|
|
387
|
-
if(
|
|
382
|
+
if(elt.target && elt['@odata.contained'] && !elt._ignore) {
|
|
388
383
|
// Let the containee know its container
|
|
389
384
|
// (array because the contanee may contained more then once)
|
|
390
385
|
let containee = elt._target;
|
|
@@ -655,17 +650,19 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
655
650
|
}
|
|
656
651
|
//forward annotations from managed association element to its foreign keys
|
|
657
652
|
const elements = construct.items && construct.items.elements || construct.elements;
|
|
658
|
-
|
|
653
|
+
const fk = elements[element['@odata.foreignKey4']];
|
|
654
|
+
for(const attrName in fk) {
|
|
655
|
+
const attr = fk[attrName];
|
|
659
656
|
if(attrName[0] === '@') {
|
|
660
657
|
element[attrName] = attr;
|
|
661
658
|
}
|
|
662
|
-
}
|
|
659
|
+
}
|
|
663
660
|
// and eventually remove some afterwards:)
|
|
664
661
|
if(options.isV2())
|
|
665
662
|
setSAPSpecificV2AnnotationsToAssociation(element);
|
|
666
663
|
|
|
667
664
|
// initialize an association
|
|
668
|
-
if(
|
|
665
|
+
if(element.target) {
|
|
669
666
|
// in case this is a forward assoc, store the backlink partners here, _selfReferences.length > 1 => error
|
|
670
667
|
assignProp(element, '_selfReferences', []);
|
|
671
668
|
assignProp(element._target, '$proxies', []);
|
|
@@ -694,7 +691,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
694
691
|
// @Core.AlternateKeys: [{ Key: [ { Name: 'slID', Alias: 'slID' }, { Name: 'validFrom', Alias: 'validFrom'} ] }]
|
|
695
692
|
if(validKey.length) {
|
|
696
693
|
let altKeys = [{ Key: [] }];
|
|
697
|
-
|
|
694
|
+
Object.entries(([kn, k]) => {
|
|
698
695
|
altKeys[0].Key.push( { Name: kn, Alias: kn } );
|
|
699
696
|
delete k.key;
|
|
700
697
|
});
|
|
@@ -717,7 +714,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
717
714
|
}
|
|
718
715
|
|
|
719
716
|
// prepare the structure itself
|
|
720
|
-
if(
|
|
717
|
+
if(def.kind === 'entity') {
|
|
721
718
|
assignProp(def, '_SetAttributes', Object.create(null));
|
|
722
719
|
assignProp(def, '$keys', keys);
|
|
723
720
|
applyAppSpecificLateCsnTransformationOnStructure(options, def, error);
|
|
@@ -733,7 +730,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
733
730
|
forEachMemberRecursively(def.items || def, initConstraintsOnAssoc, [], true, { elementsOnly: true });
|
|
734
731
|
}
|
|
735
732
|
function initConstraintsOnAssoc(element) {
|
|
736
|
-
if (
|
|
733
|
+
if (element.target && !element._constraints) {
|
|
737
734
|
// setup the constraints object
|
|
738
735
|
setProp(element, '_constraints', { constraints: Object.create(null), selfs: [], _origins: [], termCount: 0 });
|
|
739
736
|
// and crack the ON condition
|
|
@@ -817,7 +814,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
817
814
|
forEachMemberRecursively(def.items || def, finalizeConstraintsOnAssoc, [], true, { elementsOnly: true });
|
|
818
815
|
}
|
|
819
816
|
function finalizeConstraintsOnAssoc(element) {
|
|
820
|
-
if (
|
|
817
|
+
if (element.target && !element._ignore && element._constraints) {
|
|
821
818
|
finalizeReferentialConstraints(csn, element, options, info);
|
|
822
819
|
|
|
823
820
|
if(element._constraints._partnerCsn && element.cardinality && element.cardinality.max) {
|
|
@@ -907,7 +904,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
907
904
|
// if this artifact is a service member check its associations
|
|
908
905
|
if(globalSchemaPrefix) {
|
|
909
906
|
forEachGeneric(struct.items || struct, 'elements', element => {
|
|
910
|
-
if(!
|
|
907
|
+
if(!element.target || element['@odata.navigable'] === false)
|
|
911
908
|
return;
|
|
912
909
|
/*
|
|
913
910
|
* Consider everything @cds.autoexpose: falsy to be a proxy candidate for now
|
|
@@ -1063,7 +1060,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
1063
1060
|
// copy over the primary keys of the target and trigger the type exposure
|
|
1064
1061
|
// if the element already exists we assume it was fully exposed
|
|
1065
1062
|
function populateProxyElements(assoc, proxy, elements) {
|
|
1066
|
-
|
|
1063
|
+
Object.values(elements).forEach(e => {
|
|
1067
1064
|
if (isEdmPropertyRendered(e, options)) {
|
|
1068
1065
|
let newElt = proxy.elements[e.name];
|
|
1069
1066
|
if(!newElt) {
|
|
@@ -1551,7 +1548,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
1551
1548
|
|
|
1552
1549
|
// check for legal scalar types, proxy exposed structured types are not resolvable in CSN
|
|
1553
1550
|
// V2 allows any Edm.PrimitiveType (even Double and Binary), V4 is more specific:
|
|
1554
|
-
if(options.isV4() && type && !
|
|
1551
|
+
if(options.isV4() && type && !type.target && isBuiltinType(type.type)) {
|
|
1555
1552
|
const edmType = edmUtils.mapCdsToEdmType(type);
|
|
1556
1553
|
const legalEdmTypes = {
|
|
1557
1554
|
'Edm.Boolean':1, 'Edm.Byte':1, 'Edm.Date':1, 'Edm.DateTimeOffset':1, 'Edm.Decimal':1, 'Edm.Duration':1,
|
|
@@ -1604,7 +1601,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
1604
1601
|
if(isEdmPropertyRendered(elt, options)) {
|
|
1605
1602
|
// Assoc can never be a derived TypeDefinition, no need to
|
|
1606
1603
|
// unroll derived type chains for assocs
|
|
1607
|
-
if(
|
|
1604
|
+
if(elt.target && !elt.$touched) {
|
|
1608
1605
|
if(!elt._target.$edmTgtPaths)
|
|
1609
1606
|
setProp(elt._target, '$edmTgtPaths', []);
|
|
1610
1607
|
// drill into target only if
|
|
@@ -1649,7 +1646,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
1649
1646
|
if(isEdmPropertyRendered(elt, options)) {
|
|
1650
1647
|
// Assoc can never be a derived TypeDefinition, no need to
|
|
1651
1648
|
// unroll derived type chains for assocs
|
|
1652
|
-
if(
|
|
1649
|
+
if(elt.target && !elt.$touched) {
|
|
1653
1650
|
// drill into target only if
|
|
1654
1651
|
// 1) target has no entity set and this assoc is not going to the container
|
|
1655
1652
|
// 2) current definition and target are the same (cycle)
|
|
@@ -1713,7 +1710,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
1713
1710
|
// 1) must not be a proxy and not a containee in V4
|
|
1714
1711
|
// No annos are rendered for non-existing EntitySet targets.
|
|
1715
1712
|
if(def.$hasEntitySet === undefined) {
|
|
1716
|
-
const hasEntitySet =
|
|
1713
|
+
const hasEntitySet = def.kind === 'entity' && !(options.isV4() && edmUtils.isContainee(def)) && !def.$proxy;
|
|
1717
1714
|
setProp(def, '$hasEntitySet', hasEntitySet);
|
|
1718
1715
|
}
|
|
1719
1716
|
}
|
|
@@ -1958,7 +1955,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
|
|
|
1958
1955
|
}
|
|
1959
1956
|
|
|
1960
1957
|
function mapCdsToEdmProp(obj) {
|
|
1961
|
-
if (obj.type && isBuiltinType(obj.type) && !
|
|
1958
|
+
if (obj.type && isBuiltinType(obj.type) && !obj.target && !obj.targetAspect) {
|
|
1962
1959
|
let edmType = edmUtils.mapCdsToEdmType(obj, messageFunctions, _options.odataVersion === 'v2', obj['@Core.MediaType']);
|
|
1963
1960
|
assignProp(obj, '_edmType', edmType);
|
|
1964
1961
|
} else if (obj._isCollection && (obj.items && isBuiltinType(csnUtils.getFinalTypeDef(obj.items.type)))) {
|
|
@@ -2321,7 +2318,7 @@ function setSAPSpecificV2AnnotationsToAssociation(carrier) {
|
|
|
2321
2318
|
});
|
|
2322
2319
|
|
|
2323
2320
|
function addToAssociationSet(carrier, propName, propValue, removeFromType=true) {
|
|
2324
|
-
if(
|
|
2321
|
+
if(carrier.target) {
|
|
2325
2322
|
assignProp(carrier, '_SetAttributes', Object.create(null));
|
|
2326
2323
|
assignAnnotation(carrier._SetAttributes, propName, propValue);
|
|
2327
2324
|
if(removeFromType) {
|
package/lib/edm/edmUtils.js
CHANGED
|
@@ -56,11 +56,6 @@ function foreach(dictionary, filter, func) {
|
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
// Call func(art, name) for each artifact 'art' with name 'name' in 'dictionary'
|
|
60
|
-
function forAll(dictionary, func) {
|
|
61
|
-
foreach(dictionary, ()=>true, func);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
59
|
// true if _containerEntity is unequal to artifact name (non-recursive containment association)
|
|
65
60
|
// or if artifact belongs to an artificial parameter entity
|
|
66
61
|
function isContainee(artifact) {
|
|
@@ -68,27 +63,11 @@ function isContainee(artifact) {
|
|
|
68
63
|
return (artifact._containerEntity && (artifact._containerEntity.length > 1 || artifact._containerEntity[0] != artifact.name));
|
|
69
64
|
}
|
|
70
65
|
|
|
71
|
-
// Return true if 'artifact' has an association type
|
|
72
|
-
function isAssociation(artifact) {
|
|
73
|
-
return (artifact.type === 'cds.Association' || artifact.type === 'Association') && artifact.target != undefined;
|
|
74
|
-
//return artifact.target != undefined;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
66
|
function isComposition(artifact) {
|
|
78
67
|
return (artifact.type === 'cds.Composition' || artifact.type === 'Composition') &&
|
|
79
68
|
artifact.target != undefined;
|
|
80
69
|
}
|
|
81
70
|
|
|
82
|
-
function isAssociationOrComposition(artifact)
|
|
83
|
-
{
|
|
84
|
-
return isAssociation(artifact) || isComposition(artifact);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function isManagedAssociation(artifact)
|
|
88
|
-
{
|
|
89
|
-
return isAssociation(artifact) && artifact.on == undefined;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
71
|
// Return true if the association 'assoc' has cardinality 'to-many'
|
|
93
72
|
function isToMany(assoc) {
|
|
94
73
|
if (!assoc.cardinality) {
|
|
@@ -108,13 +87,8 @@ function isSingleton(entityCsn) {
|
|
|
108
87
|
return singleton || ((singleton === undefined || singleton === null) && hasNullable);
|
|
109
88
|
}
|
|
110
89
|
|
|
111
|
-
function isEntity(artifact)
|
|
112
|
-
{
|
|
113
|
-
return artifact.kind === 'entity';
|
|
114
|
-
}
|
|
115
|
-
|
|
116
90
|
function isParameterizedEntity(artifact) {
|
|
117
|
-
return
|
|
91
|
+
return artifact.kind === 'entity' && artifact.params;
|
|
118
92
|
}
|
|
119
93
|
|
|
120
94
|
// Return true if 'artifact' is structured (i.e. has elements, like a structured type or an entity)
|
|
@@ -132,10 +106,6 @@ function isDerivedType(artifact) {
|
|
|
132
106
|
return artifact.kind === 'type' && !isStructuredArtifact(artifact);
|
|
133
107
|
}
|
|
134
108
|
|
|
135
|
-
function isActionOrFunction(artifact) {
|
|
136
|
-
return artifact.kind === 'action' || artifact.kind === 'function';
|
|
137
|
-
}
|
|
138
|
-
|
|
139
109
|
function resolveOnConditionAndPrepareConstraints(csn, assocCsn, messageFunctions) {
|
|
140
110
|
if(!assocCsn._constraints)
|
|
141
111
|
throw Error('Please debug me: need _constraints');
|
|
@@ -175,7 +145,7 @@ function resolveOnConditionAndPrepareConstraints(csn, assocCsn, messageFunctions
|
|
|
175
145
|
info(null, ['definitions', parentName, 'elements', assocCsn.name],
|
|
176
146
|
`"${originParentName}:${partnerPath.join('.')}" with target "${originAssocCsn._target.name}" is compared with $self which represents "${parentName}"`);
|
|
177
147
|
}
|
|
178
|
-
if(
|
|
148
|
+
if(originAssocCsn.target) {
|
|
179
149
|
// Mark this association as backlink if $self appears exactly once
|
|
180
150
|
// to surpress edm:Association generation in V2 mode
|
|
181
151
|
if(isBacklink) {
|
|
@@ -345,7 +315,7 @@ function finalizeReferentialConstraints(csn, assocCsn, options, info)
|
|
|
345
315
|
// in structured mode only resolve top level element (path rewriting is done elsewhere)
|
|
346
316
|
const depEltName = ( options.isFlatFormat ? c[0].join('_') : c[0][0] );
|
|
347
317
|
const principalEltName = ( options.isFlatFormat ? c[1].join('_') : c[1][0] );
|
|
348
|
-
const fk = (
|
|
318
|
+
const fk = (dependentEntity.kind === 'entity' && dependentEntity.elements[ depEltName ]) ||
|
|
349
319
|
(localDepEntity && localDepEntity.elements && localDepEntity.elements[ depEltName ]);
|
|
350
320
|
const pk = principalEntity.$keys && principalEntity.$keys[ principalEltName ];
|
|
351
321
|
if(isConstraintCandidate(fk) && isConstraintCandidate(pk)) {
|
|
@@ -787,20 +757,14 @@ module.exports = {
|
|
|
787
757
|
validateOptions,
|
|
788
758
|
intersect,
|
|
789
759
|
foreach,
|
|
790
|
-
forAll,
|
|
791
760
|
isContainee,
|
|
792
|
-
isAssociation,
|
|
793
|
-
isManagedAssociation,
|
|
794
761
|
isComposition,
|
|
795
|
-
isAssociationOrComposition,
|
|
796
762
|
isToMany,
|
|
797
763
|
isSingleton,
|
|
798
|
-
isEntity,
|
|
799
764
|
isStructuredType,
|
|
800
765
|
isStructuredArtifact,
|
|
801
766
|
isParameterizedEntity,
|
|
802
767
|
isDerivedType,
|
|
803
|
-
isActionOrFunction,
|
|
804
768
|
resolveOnConditionAndPrepareConstraints,
|
|
805
769
|
finalizeReferentialConstraints,
|
|
806
770
|
determineMultiplicity,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
ca4caa65192cebc39f35cd598958dbb0
|