@sap/cds-compiler 3.0.0 → 3.1.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 +104 -9
- package/bin/.eslintrc.json +2 -1
- package/bin/cdsc.js +28 -16
- package/doc/API.md +11 -0
- package/doc/CHANGELOG_ARCHIVE.md +1 -1
- package/doc/CHANGELOG_BETA.md +24 -2
- package/doc/CHANGELOG_DEPRECATED.md +21 -1
- package/lib/api/main.js +92 -40
- package/lib/api/options.js +2 -3
- package/lib/base/keywords.js +64 -1
- package/lib/base/message-registry.js +33 -5
- package/lib/base/messages.js +54 -65
- package/lib/base/model.js +2 -0
- package/lib/base/optionProcessorHelper.js +53 -21
- package/lib/checks/actionsFunctions.js +8 -7
- package/lib/checks/selectItems.js +96 -14
- package/lib/checks/types.js +5 -8
- package/lib/checks/validator.js +1 -2
- package/lib/compiler/assert-consistency.js +65 -13
- package/lib/compiler/base.js +6 -4
- package/lib/compiler/builtins.js +93 -4
- package/lib/compiler/checks.js +1 -1
- package/lib/compiler/define.js +28 -23
- package/lib/compiler/extend.js +20 -11
- package/lib/compiler/finalize-parse-cdl.js +5 -9
- package/lib/compiler/index.js +2 -0
- package/lib/compiler/populate.js +37 -32
- package/lib/compiler/propagator.js +11 -6
- package/lib/compiler/resolve.js +15 -19
- package/lib/compiler/shared.js +54 -18
- package/lib/compiler/tweak-assocs.js +5 -11
- package/lib/compiler/utils.js +15 -6
- package/lib/edm/annotations/genericTranslation.js +12 -2
- package/lib/edm/annotations/preprocessAnnotations.js +18 -15
- package/lib/edm/csn2edm.js +18 -17
- package/lib/edm/edm.js +22 -13
- package/lib/edm/edmAnnoPreprocessor.js +349 -0
- package/lib/edm/edmInboundChecks.js +85 -0
- package/lib/edm/edmPreprocessor.js +336 -665
- package/lib/edm/edmUtils.js +86 -45
- package/lib/gen/Dictionary.json +29 -9
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -2
- package/lib/gen/languageLexer.js +3 -0
- package/lib/gen/languageParser.js +4332 -4496
- package/lib/inspect/.eslintrc.json +4 -0
- package/lib/inspect/index.js +14 -0
- package/lib/inspect/inspectModelStatistics.js +81 -0
- package/lib/inspect/inspectPropagation.js +189 -0
- package/lib/inspect/inspectUtils.js +44 -0
- package/lib/json/from-csn.js +19 -20
- package/lib/json/to-csn.js +11 -8
- package/lib/language/genericAntlrParser.js +150 -92
- package/lib/language/language.g4 +47 -74
- package/lib/main.d.ts +1 -0
- package/lib/model/api.js +1 -1
- package/lib/model/csnRefs.js +56 -29
- package/lib/model/csnUtils.js +29 -14
- package/lib/model/revealInternalProperties.js +6 -4
- package/lib/modelCompare/compare.js +3 -0
- package/lib/optionProcessor.js +81 -38
- package/lib/render/toCdl.js +57 -32
- package/lib/render/toHdbcds.js +1 -1
- package/lib/render/toSql.js +31 -11
- package/lib/render/utils/common.js +3 -4
- package/lib/transform/db/associations.js +43 -35
- package/lib/transform/db/cdsPersistence.js +0 -1
- package/lib/transform/db/flattening.js +3 -4
- package/lib/transform/db/transformExists.js +7 -5
- package/lib/transform/draft/db.js +1 -1
- package/lib/transform/forHanaNew.js +11 -2
- package/lib/transform/forOdataNew.js +4 -4
- package/lib/transform/localized.js +15 -11
- package/lib/transform/odata/typesExposure.js +14 -5
- package/lib/utils/file.js +28 -18
- package/lib/utils/moduleResolve.js +0 -1
- package/package.json +3 -4
- package/share/messages/syntax-expected-integer.md +9 -8
- package/lib/checks/unknownMagic.js +0 -41
package/lib/edm/edmUtils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const { setProp } = require('../base/model');
|
|
3
|
-
const { isBuiltinType, isEdmPropertyRendered } = require('../model/csnUtils');
|
|
3
|
+
const { isBuiltinType, isEdmPropertyRendered, applyTransformations } = require('../model/csnUtils');
|
|
4
4
|
const { escapeString, hasControlCharacters, hasUnpairedUnicodeSurrogate } = require("../render/utils/stringEscapes");
|
|
5
5
|
|
|
6
6
|
/* eslint max-statements-per-line:off */
|
|
@@ -27,8 +27,8 @@ function validateOptions(_options)
|
|
|
27
27
|
if(options.v.filter(v=>v).length !== 1)
|
|
28
28
|
throw Error(`Please debug me: EDM V2:${v2}, V4:${v4}`);
|
|
29
29
|
|
|
30
|
-
options.isV2 =
|
|
31
|
-
options.isV4 =
|
|
30
|
+
options.isV2 = () => v2;
|
|
31
|
+
options.isV4 = () => v4;
|
|
32
32
|
|
|
33
33
|
options.pathDelimiter = options.isStructFormat ? '/' : '_';
|
|
34
34
|
|
|
@@ -56,22 +56,11 @@ 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) {
|
|
67
|
-
// if
|
|
68
|
-
return (artifact
|
|
69
|
-
}
|
|
70
|
-
|
|
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;
|
|
62
|
+
// if $containerNames is present, it is guaranteed that it has at least one entry
|
|
63
|
+
return (artifact.$containerNames && (artifact.$containerNames.length > 1 || artifact.$containerNames[0] != artifact.name));
|
|
75
64
|
}
|
|
76
65
|
|
|
77
66
|
function isComposition(artifact) {
|
|
@@ -79,16 +68,6 @@ function isComposition(artifact) {
|
|
|
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)) {
|
|
@@ -783,24 +753,94 @@ function resolveOriginAssoc(csn, env, path) {
|
|
|
783
753
|
return env;
|
|
784
754
|
}
|
|
785
755
|
|
|
756
|
+
function mergeIntoNavPropEntry(annoPrefix, navPropEntry, prefix, props) {
|
|
757
|
+
let newEntry = false;
|
|
758
|
+
|
|
759
|
+
// Filter properties with prefix and reduce them into a new dictionary
|
|
760
|
+
const o = props.filter(p => p[0].startsWith(annoPrefix+'.')).reduce((a,c) => {
|
|
761
|
+
a[c[0].replace(annoPrefix+'.', '')] = c[1];
|
|
762
|
+
return a;
|
|
763
|
+
}, { });
|
|
764
|
+
|
|
765
|
+
// BEFORE merging found capabilities, prefix the paths
|
|
766
|
+
applyTransformations({ definitions: { o }}, {
|
|
767
|
+
"=": (parent, prop, value) => {
|
|
768
|
+
parent[prop] = prefix.concat(value).join('.');
|
|
769
|
+
}
|
|
770
|
+
});
|
|
771
|
+
// don't overwrite existing restrictions
|
|
772
|
+
const prop = annoPrefix.split('.')[1];
|
|
773
|
+
if(!navPropEntry[prop]) {
|
|
774
|
+
// if dictionary has entries, add them to navPropEnty
|
|
775
|
+
if(Object.keys(o).length) {
|
|
776
|
+
// ReadRestrictions may have sub type ReadByKeyRestrictions { Description, LongDescription }
|
|
777
|
+
// chop annotations into dictionaries
|
|
778
|
+
if(annoPrefix === '@Capabilities.ReadRestrictions' &&
|
|
779
|
+
Object.keys(o).some(k => k.startsWith('ReadByKeyRestrictions.'))) {
|
|
780
|
+
const no = {};
|
|
781
|
+
Object.entries(o).forEach(([k,v]) => {
|
|
782
|
+
const [head, ...tail] = k.split('.');
|
|
783
|
+
if(head === 'ReadByKeyRestrictions' && tail.length) {
|
|
784
|
+
if(!no['ReadByKeyRestrictions'])
|
|
785
|
+
no['ReadByKeyRestrictions'] = {};
|
|
786
|
+
// Don't try to add entry into non object
|
|
787
|
+
if(typeof no['ReadByKeyRestrictions'] === 'object')
|
|
788
|
+
no['ReadByKeyRestrictions'][tail.join('.')] = v;
|
|
789
|
+
}
|
|
790
|
+
else {
|
|
791
|
+
no[k] = v;
|
|
792
|
+
}
|
|
793
|
+
});
|
|
794
|
+
navPropEntry[prop] = no;
|
|
795
|
+
}
|
|
796
|
+
else {
|
|
797
|
+
navPropEntry[prop] = o;
|
|
798
|
+
}
|
|
799
|
+
newEntry = true;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
else {
|
|
803
|
+
// merge but don't overwrite into existing navprop
|
|
804
|
+
Object.entries(o).forEach(([k,v]) => {
|
|
805
|
+
if(!navPropEntry[prop][k])
|
|
806
|
+
navPropEntry[prop][k] = v;
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
return newEntry;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// Assign but not overwrite annotation
|
|
813
|
+
function assignAnnotation(node, name, value) {
|
|
814
|
+
if(value !== undefined &&
|
|
815
|
+
name !== undefined && name[0] === '@' &&
|
|
816
|
+
(node[name] === undefined || node[name] === null)) {
|
|
817
|
+
node[name] = value;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// Set non enumerable property if it doesn't exist yet
|
|
822
|
+
function assignProp(obj, prop, value) {
|
|
823
|
+
if(obj[prop] === undefined) {
|
|
824
|
+
setProp(obj, prop, value);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
|
|
786
830
|
module.exports = {
|
|
831
|
+
assignAnnotation,
|
|
832
|
+
assignProp,
|
|
787
833
|
validateOptions,
|
|
788
834
|
intersect,
|
|
789
835
|
foreach,
|
|
790
|
-
forAll,
|
|
791
836
|
isContainee,
|
|
792
|
-
isAssociation,
|
|
793
|
-
isManagedAssociation,
|
|
794
837
|
isComposition,
|
|
795
|
-
isAssociationOrComposition,
|
|
796
838
|
isToMany,
|
|
797
839
|
isSingleton,
|
|
798
|
-
isEntity,
|
|
799
840
|
isStructuredType,
|
|
800
841
|
isStructuredArtifact,
|
|
801
842
|
isParameterizedEntity,
|
|
802
843
|
isDerivedType,
|
|
803
|
-
isActionOrFunction,
|
|
804
844
|
resolveOnConditionAndPrepareConstraints,
|
|
805
845
|
finalizeReferentialConstraints,
|
|
806
846
|
determineMultiplicity,
|
|
@@ -810,5 +850,6 @@ module.exports = {
|
|
|
810
850
|
escapeStringForAttributeValue,
|
|
811
851
|
escapeStringForText,
|
|
812
852
|
getSchemaPrefix,
|
|
813
|
-
getBaseName
|
|
853
|
+
getBaseName,
|
|
854
|
+
mergeIntoNavPropEntry
|
|
814
855
|
}
|
package/lib/gen/Dictionary.json
CHANGED
|
@@ -989,8 +989,7 @@
|
|
|
989
989
|
"NavigationProperty",
|
|
990
990
|
"Action",
|
|
991
991
|
"Function"
|
|
992
|
-
]
|
|
993
|
-
"$experimental": true
|
|
992
|
+
]
|
|
994
993
|
},
|
|
995
994
|
"Common.DerivedDefaultValue": {
|
|
996
995
|
"Type": "Edm.String",
|
|
@@ -1424,6 +1423,13 @@
|
|
|
1424
1423
|
"Type": "Graph.DetailsType",
|
|
1425
1424
|
"$experimental": true
|
|
1426
1425
|
},
|
|
1426
|
+
"Graph.CompositionRoot": {
|
|
1427
|
+
"Type": "Core.Tag",
|
|
1428
|
+
"AppliesTo": [
|
|
1429
|
+
"EntityType"
|
|
1430
|
+
],
|
|
1431
|
+
"$experimental": true
|
|
1432
|
+
},
|
|
1427
1433
|
"Hierarchy.RecursiveHierarchy": {
|
|
1428
1434
|
"Type": "Hierarchy.RecursiveHierarchyType",
|
|
1429
1435
|
"AppliesTo": [
|
|
@@ -2413,7 +2419,8 @@
|
|
|
2413
2419
|
"CustomHeaders": "Collection(Capabilities.CustomParameter)",
|
|
2414
2420
|
"CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
|
|
2415
2421
|
"Description": "Edm.String",
|
|
2416
|
-
"LongDescription": "Edm.String"
|
|
2422
|
+
"LongDescription": "Edm.String",
|
|
2423
|
+
"ErrorResponses": "Collection(Capabilities.HttpResponse)"
|
|
2417
2424
|
}
|
|
2418
2425
|
},
|
|
2419
2426
|
"Capabilities.PermissionType": {
|
|
@@ -2455,7 +2462,8 @@
|
|
|
2455
2462
|
"CustomHeaders": "Collection(Capabilities.CustomParameter)",
|
|
2456
2463
|
"CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
|
|
2457
2464
|
"Description": "Edm.String",
|
|
2458
|
-
"LongDescription": "Edm.String"
|
|
2465
|
+
"LongDescription": "Edm.String",
|
|
2466
|
+
"ErrorResponses": "Collection(Capabilities.HttpResponse)"
|
|
2459
2467
|
}
|
|
2460
2468
|
},
|
|
2461
2469
|
"Capabilities.DeepUpdateSupportType": {
|
|
@@ -2477,7 +2485,8 @@
|
|
|
2477
2485
|
"CustomHeaders": "Collection(Capabilities.CustomParameter)",
|
|
2478
2486
|
"CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
|
|
2479
2487
|
"Description": "Edm.String",
|
|
2480
|
-
"LongDescription": "Edm.String"
|
|
2488
|
+
"LongDescription": "Edm.String",
|
|
2489
|
+
"ErrorResponses": "Collection(Capabilities.HttpResponse)"
|
|
2481
2490
|
}
|
|
2482
2491
|
},
|
|
2483
2492
|
"Capabilities.CollectionPropertyRestrictionsType": {
|
|
@@ -2502,7 +2511,8 @@
|
|
|
2502
2511
|
"FilterSegmentSupported": "Edm.Boolean",
|
|
2503
2512
|
"Permissions": "Collection(Capabilities.PermissionType)",
|
|
2504
2513
|
"CustomHeaders": "Collection(Capabilities.CustomParameter)",
|
|
2505
|
-
"CustomQueryOptions": "Collection(Capabilities.CustomParameter)"
|
|
2514
|
+
"CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
|
|
2515
|
+
"ErrorResponses": "Collection(Capabilities.HttpResponse)"
|
|
2506
2516
|
}
|
|
2507
2517
|
},
|
|
2508
2518
|
"Capabilities.ModificationQueryOptionsType": {
|
|
@@ -2525,7 +2535,8 @@
|
|
|
2525
2535
|
"CustomHeaders": "Collection(Capabilities.CustomParameter)",
|
|
2526
2536
|
"CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
|
|
2527
2537
|
"Description": "Edm.String",
|
|
2528
|
-
"LongDescription": "Edm.String"
|
|
2538
|
+
"LongDescription": "Edm.String",
|
|
2539
|
+
"ErrorResponses": "Collection(Capabilities.HttpResponse)"
|
|
2529
2540
|
}
|
|
2530
2541
|
},
|
|
2531
2542
|
"Capabilities.ReadByKeyRestrictionsType": {
|
|
@@ -2537,7 +2548,8 @@
|
|
|
2537
2548
|
"CustomHeaders": "Collection(Capabilities.CustomParameter)",
|
|
2538
2549
|
"CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
|
|
2539
2550
|
"Description": "Edm.String",
|
|
2540
|
-
"LongDescription": "Edm.String"
|
|
2551
|
+
"LongDescription": "Edm.String",
|
|
2552
|
+
"ErrorResponses": "Collection(Capabilities.HttpResponse)"
|
|
2541
2553
|
}
|
|
2542
2554
|
},
|
|
2543
2555
|
"Capabilities.ReadRestrictionsType": {
|
|
@@ -2550,7 +2562,8 @@
|
|
|
2550
2562
|
"CustomHeaders": "Collection(Capabilities.CustomParameter)",
|
|
2551
2563
|
"CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
|
|
2552
2564
|
"Description": "Edm.String",
|
|
2553
|
-
"LongDescription": "Edm.String"
|
|
2565
|
+
"LongDescription": "Edm.String",
|
|
2566
|
+
"ErrorResponses": "Collection(Capabilities.HttpResponse)"
|
|
2554
2567
|
}
|
|
2555
2568
|
},
|
|
2556
2569
|
"Capabilities.CustomParameter": {
|
|
@@ -2563,6 +2576,13 @@
|
|
|
2563
2576
|
"ExampleValues": "Collection(Core.PrimitiveExampleValue)"
|
|
2564
2577
|
}
|
|
2565
2578
|
},
|
|
2579
|
+
"Capabilities.HttpResponse": {
|
|
2580
|
+
"$kind": "ComplexType",
|
|
2581
|
+
"Properties": {
|
|
2582
|
+
"StatusCode": "Edm.String",
|
|
2583
|
+
"Description": "Edm.String"
|
|
2584
|
+
}
|
|
2585
|
+
},
|
|
2566
2586
|
"Capabilities.FilterExpressionType": {
|
|
2567
2587
|
"$kind": "TypeDefinition",
|
|
2568
2588
|
"UnderlyingType": "Edm.String"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
2067e213918678e2d85713a46e69d9cc
|