@sap/cds-compiler 2.12.0 → 2.15.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 +221 -15
- package/bin/cdsc.js +125 -50
- package/bin/cdsse.js +2 -2
- package/doc/CHANGELOG_BETA.md +13 -6
- package/doc/CHANGELOG_DEPRECATED.md +22 -6
- package/doc/NameResolution.md +21 -16
- package/lib/api/main.js +47 -84
- package/lib/api/options.js +5 -6
- package/lib/api/validate.js +6 -11
- package/lib/backends.js +15 -23
- package/lib/base/dictionaries.js +0 -8
- package/lib/base/error.js +26 -0
- package/lib/base/keywords.js +7 -17
- package/lib/base/location.js +9 -4
- package/lib/base/message-registry.js +114 -18
- package/lib/base/messages.js +101 -90
- package/lib/base/model.js +2 -63
- package/lib/base/optionProcessorHelper.js +177 -123
- package/lib/checks/annotationsOData.js +12 -33
- package/lib/checks/arrayOfs.js +1 -34
- package/lib/checks/cdsPersistence.js +2 -1
- package/lib/checks/enricher.js +17 -1
- package/lib/checks/invalidTarget.js +3 -1
- package/lib/checks/managedWithoutKeys.js +3 -1
- package/lib/checks/selectItems.js +4 -4
- package/lib/checks/sql-snippets.js +27 -26
- package/lib/checks/types.js +1 -1
- package/lib/checks/validator.js +6 -11
- package/lib/compiler/assert-consistency.js +6 -3
- package/lib/compiler/base.js +1 -0
- package/lib/compiler/builtins.js +19 -6
- package/lib/compiler/checks.js +23 -60
- package/lib/compiler/cycle-detector.js +1 -1
- package/lib/compiler/define.js +1151 -0
- package/lib/compiler/extend.js +1000 -0
- package/lib/compiler/finalize-parse-cdl.js +237 -0
- package/lib/compiler/index.js +107 -39
- package/lib/compiler/kick-start.js +190 -0
- package/lib/compiler/moduleLayers.js +4 -4
- package/lib/compiler/populate.js +1227 -0
- package/lib/compiler/propagator.js +114 -46
- package/lib/compiler/resolve.js +1521 -0
- package/lib/compiler/shared.js +126 -65
- package/lib/compiler/tweak-assocs.js +535 -0
- package/lib/compiler/utils.js +197 -33
- package/lib/edm/.eslintrc.json +5 -0
- package/lib/edm/annotations/genericTranslation.js +38 -24
- package/lib/edm/annotations/preprocessAnnotations.js +2 -2
- package/lib/edm/csn2edm.js +219 -100
- package/lib/edm/edm.js +302 -230
- package/lib/edm/edmPreprocessor.js +554 -419
- package/lib/edm/edmUtils.js +138 -44
- package/lib/gen/Dictionary.json +100 -19
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +11 -1
- package/lib/gen/language.tokens +86 -83
- package/lib/gen/languageLexer.interp +10 -1
- package/lib/gen/languageLexer.js +860 -833
- package/lib/gen/languageLexer.tokens +78 -75
- package/lib/gen/languageParser.js +5765 -4480
- package/lib/json/csnVersion.js +10 -11
- package/lib/json/from-csn.js +15 -3
- package/lib/json/to-csn.js +126 -68
- package/lib/language/docCommentParser.js +4 -4
- package/lib/language/genericAntlrParser.js +123 -5
- package/lib/language/language.g4 +355 -156
- package/lib/language/multiLineStringParser.js +5 -5
- package/lib/main.d.ts +486 -59
- package/lib/main.js +41 -9
- package/lib/model/api.js +3 -1
- package/lib/model/csnRefs.js +252 -156
- package/lib/model/csnUtils.js +384 -297
- package/lib/model/enrichCsn.js +71 -29
- package/lib/model/revealInternalProperties.js +29 -8
- package/lib/model/sortViews.js +2 -1
- package/lib/modelCompare/compare.js +23 -18
- package/lib/optionProcessor.js +63 -26
- package/lib/render/manageConstraints.js +35 -32
- package/lib/render/toCdl.js +897 -947
- package/lib/render/toHdbcds.js +205 -257
- package/lib/render/toSql.js +264 -225
- package/lib/render/utils/common.js +136 -25
- package/lib/render/utils/sql.js +4 -3
- package/lib/render/utils/stringEscapes.js +111 -0
- package/lib/sql-identifier.js +1 -1
- package/lib/transform/.eslintrc.json +5 -0
- package/lib/transform/db/.eslintrc.json +3 -1
- package/lib/transform/db/applyTransformations.js +35 -12
- package/lib/transform/db/assertUnique.js +1 -1
- package/lib/transform/db/associations.js +104 -306
- package/lib/transform/db/cdsPersistence.js +2 -2
- package/lib/transform/db/constraints.js +58 -53
- package/lib/transform/db/expansion.js +60 -33
- package/lib/transform/db/flattening.js +582 -104
- package/lib/transform/db/groupByOrderBy.js +3 -1
- package/lib/transform/db/transformExists.js +66 -13
- package/lib/transform/db/views.js +11 -7
- package/lib/transform/draft/.eslintrc.json +38 -0
- package/lib/transform/{db/draft.js → draft/db.js} +6 -5
- package/lib/transform/draft/odata.js +227 -0
- package/lib/transform/forHanaNew.js +109 -208
- package/lib/transform/forOdataNew.js +59 -212
- package/lib/transform/localized.js +46 -26
- package/lib/transform/odata/toFinalBaseType.js +85 -11
- package/lib/transform/odata/typesExposure.js +147 -199
- package/lib/transform/odata/utils.js +2 -2
- package/lib/transform/transformUtilsNew.js +44 -33
- package/lib/transform/translateAssocsToJoins.js +3 -20
- package/lib/transform/universalCsn/.eslintrc.json +36 -0
- package/lib/transform/universalCsn/coreComputed.js +172 -0
- package/lib/transform/universalCsn/universalCsnEnricher.js +737 -0
- package/lib/transform/universalCsn/utils.js +63 -0
- package/lib/utils/moduleResolve.js +13 -6
- package/lib/utils/objectUtils.js +30 -0
- package/package.json +1 -1
- package/share/messages/README.md +26 -0
- package/share/messages/message-explanations.json +2 -1
- package/share/messages/syntax-expected-integer.md +37 -0
- package/lib/compiler/definer.js +0 -2361
- package/lib/compiler/resolver.js +0 -3079
- 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 -290
- 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/transform/universalCsnEnricher.js +0 -237
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
// Kick-start: prepare to resolve all references
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const { isBetaEnabled, forEachGeneric } = require('../base/model');
|
|
6
|
+
const { setLink, annotationVal, annotationIsFalse } = require('./utils');
|
|
7
|
+
|
|
8
|
+
function kickStart( model ) {
|
|
9
|
+
const { options } = model;
|
|
10
|
+
const { message } = model.$messageFunctions;
|
|
11
|
+
|
|
12
|
+
const { resolveUncheckedPath, resolvePath } = model.$functions;
|
|
13
|
+
Object.assign( model.$functions, { projectionAncestor } );
|
|
14
|
+
|
|
15
|
+
// Set _service link (sorted to set it on parent first). Could be set
|
|
16
|
+
// directly, but beware a namespace becoming a service later.
|
|
17
|
+
Object.keys( model.definitions ).sort().forEach( setAncestorsAndService );
|
|
18
|
+
forEachGeneric( model, 'definitions', postProcessArtifact );
|
|
19
|
+
|
|
20
|
+
forEachGeneric( model, 'sources', resolveUsings );
|
|
21
|
+
return;
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Set projection ancestors, and _service link for artifact with absolute name 'name':
|
|
26
|
+
* - not set: internal artifact
|
|
27
|
+
* - null: not within service
|
|
28
|
+
* - service: the artifact of the embedding service
|
|
29
|
+
* This function must be called ordered: parent first
|
|
30
|
+
*
|
|
31
|
+
* @param {string} name Artifact name
|
|
32
|
+
*/
|
|
33
|
+
function setAncestorsAndService( name ) {
|
|
34
|
+
const art = model.definitions[name];
|
|
35
|
+
if (!('_parent' in art))
|
|
36
|
+
return; // nothing to do for builtins and redefinitions
|
|
37
|
+
if (art._from && !('_ancestors' in art))
|
|
38
|
+
setProjectionAncestors( art );
|
|
39
|
+
|
|
40
|
+
let parent = art._parent;
|
|
41
|
+
if (parent === model.definitions.localized)
|
|
42
|
+
parent = model.definitions[name.substring( 'localized.'.length )];
|
|
43
|
+
const service = parent && (parent._service || parent.kind === 'service' && parent);
|
|
44
|
+
setLink( art, '_service', service );
|
|
45
|
+
if (!parent || !service)
|
|
46
|
+
return;
|
|
47
|
+
// To be removed when nested services are allowed
|
|
48
|
+
if (!isBetaEnabled(options, 'nestedServices') && art.kind === 'service') {
|
|
49
|
+
while (parent.kind !== 'service')
|
|
50
|
+
parent = parent._parent;
|
|
51
|
+
message( 'service-nested-service', [ art.name.location, art ], { art: parent },
|
|
52
|
+
'A service can\'t be nested within a service $(ART)' );
|
|
53
|
+
}
|
|
54
|
+
else if (art.kind === 'context') {
|
|
55
|
+
while (parent.kind !== 'service')
|
|
56
|
+
parent = parent._parent;
|
|
57
|
+
// TODO: remove this error
|
|
58
|
+
message( 'service-nested-context', [ art.name.location, art ], { art: parent },
|
|
59
|
+
'A context can\'t be nested within a service $(ART)' );
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function setProjectionAncestors( art ) {
|
|
64
|
+
// Must be run after processLocalizedData() as we could have a projection
|
|
65
|
+
// on a generated entity.
|
|
66
|
+
|
|
67
|
+
// TODO: do not do implicit redirection across services, i.e. Service2.E is
|
|
68
|
+
// no redirection target for E if Service2.E = projection on Service1.E and
|
|
69
|
+
// Service1.E = projection on E
|
|
70
|
+
const chain = [];
|
|
71
|
+
const autoexposed = art.$generated || annotationVal( art['@cds.autoexposed'] );
|
|
72
|
+
const preferredRedirectionTarget = annotationVal( art['@cds.redirection.target'] );
|
|
73
|
+
// no need to set preferredRedirectionTarget in the while loop as we would
|
|
74
|
+
// use the projection having @cds.redirection.target anyhow instead of
|
|
75
|
+
// `art` anyway (if we do the no-x-service-implicit-redirection TODO above)
|
|
76
|
+
while (art && !('_ancestors' in art) &&
|
|
77
|
+
art._from && art._from.length === 1 &&
|
|
78
|
+
(preferredRedirectionTarget || !annotationIsFalse( art['@cds.redirection.target'] ) ) &&
|
|
79
|
+
art.query.op && art.query.op.val === 'SELECT') {
|
|
80
|
+
chain.push( art );
|
|
81
|
+
setLink( art, '_ancestors', null ); // avoid infloop with cyclic from
|
|
82
|
+
const name = resolveUncheckedPath( art._from[0], 'include', art ); // TODO: 'include'?
|
|
83
|
+
art = name && projectionAncestor( model.definitions[name], art.params );
|
|
84
|
+
if (autoexposed)
|
|
85
|
+
break; // only direct projection for auto-exposed
|
|
86
|
+
}
|
|
87
|
+
let ancestors = art && (!autoexposed && art._ancestors || []);
|
|
88
|
+
chain.reverse();
|
|
89
|
+
for (const a of chain) {
|
|
90
|
+
ancestors = (ancestors ? [ ...ancestors, art ] : []);
|
|
91
|
+
setLink( a, '_ancestors', ancestors );
|
|
92
|
+
art = a;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Return argument `source` if entity `source` has parameters like `params`
|
|
97
|
+
// - same parameters, although `params` can contain a new optional one (with DEFAULT)
|
|
98
|
+
// - a parameter in `params` can be optional which is not in `source.params`, but not vice versa
|
|
99
|
+
// - exactly the same types (type argument do not matter)
|
|
100
|
+
function projectionAncestor( source, params ) {
|
|
101
|
+
if (!source)
|
|
102
|
+
return source;
|
|
103
|
+
if (!params) // proj has no params => ok if source has no params
|
|
104
|
+
return !source.params && source;
|
|
105
|
+
const sourceParams = source.params || Object.create(null);
|
|
106
|
+
for (const n in sourceParams) {
|
|
107
|
+
if (!(n in params)) // source param is not projection param
|
|
108
|
+
return null; // -> can't be used as implicit redirection target
|
|
109
|
+
}
|
|
110
|
+
for (const n in params) {
|
|
111
|
+
const pp = params[n];
|
|
112
|
+
const sp = sourceParams[n];
|
|
113
|
+
if (sp) {
|
|
114
|
+
if (sp.default && !pp.default) // param DEFAULT clause not supported yet
|
|
115
|
+
return null; // param is not optional anymore
|
|
116
|
+
const pt = pp.type && resolveUncheckedPath( pp.type, 'type', pp );
|
|
117
|
+
const st = sp.type && resolveUncheckedPath( sp.type, 'type', sp );
|
|
118
|
+
if ((pt || null) !== (st || null))
|
|
119
|
+
return null; // params have different type
|
|
120
|
+
}
|
|
121
|
+
else if (!pp.default) {
|
|
122
|
+
return null;
|
|
123
|
+
} // non-optional param in projection, but not source
|
|
124
|
+
}
|
|
125
|
+
return source;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function postProcessArtifact( art ) {
|
|
129
|
+
tagCompositionTargets( art );
|
|
130
|
+
if (art.$queries) {
|
|
131
|
+
for (const query of art.$queries) {
|
|
132
|
+
if (query.mixin)
|
|
133
|
+
forEachGeneric( query, 'mixin', tagCompositionTargets );
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (!art._ancestors || art.kind !== 'entity')
|
|
137
|
+
return; // redirections only to entities
|
|
138
|
+
const service = art._service;
|
|
139
|
+
if (!service)
|
|
140
|
+
return;
|
|
141
|
+
const sname = service.name.absolute;
|
|
142
|
+
art._ancestors.forEach( expose );
|
|
143
|
+
return;
|
|
144
|
+
|
|
145
|
+
function expose( ancestor ) {
|
|
146
|
+
if (ancestor._service === service)
|
|
147
|
+
return;
|
|
148
|
+
const desc = ancestor._descendants ||
|
|
149
|
+
setLink( ancestor, '_descendants', Object.create(null) );
|
|
150
|
+
if (!desc[sname])
|
|
151
|
+
desc[sname] = [ art ];
|
|
152
|
+
else
|
|
153
|
+
desc[sname].push( art );
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function tagCompositionTargets( elem ) {
|
|
158
|
+
const type = elem.type && elem.type.path;
|
|
159
|
+
if (elem.target && type && type[0] && type[0].id === 'cds.Composition') {
|
|
160
|
+
// A target aspect would have already moved to property `targetAspect` in
|
|
161
|
+
// define.js (hm... more something for kick-start.js...)
|
|
162
|
+
const target = resolvePath( elem.target, 'target', elem );
|
|
163
|
+
if (target)
|
|
164
|
+
model.$compositionTargets[target.name.absolute] = true;
|
|
165
|
+
}
|
|
166
|
+
forEachGeneric( elem, 'elements', tagCompositionTargets );
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Resolve the using declarations in `using`. Issue
|
|
170
|
+
// error message if the referenced artifact does not exist.
|
|
171
|
+
function resolveUsings( src, topLevel ) {
|
|
172
|
+
if (!src.usings)
|
|
173
|
+
return;
|
|
174
|
+
for (const def of src.usings) {
|
|
175
|
+
if (def.usings) // using {...}
|
|
176
|
+
resolveUsings( def );
|
|
177
|
+
if (!def.name || !def.name.absolute)
|
|
178
|
+
continue; // using {...}, parse error
|
|
179
|
+
const art = model.definitions[def.name.absolute];
|
|
180
|
+
if (art && art.$duplicates)
|
|
181
|
+
continue;
|
|
182
|
+
const ref = def.extern;
|
|
183
|
+
const from = (topLevel ? def : src).fileDep;
|
|
184
|
+
if (art || !from || from.realname) // no error for non-existing ref with non-existing module
|
|
185
|
+
resolvePath( ref, 'global', def ); // TODO: consider FROM for validNames
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
module.exports = kickStart;
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
5
|
const detectCycles = require('./cycle-detector');
|
|
6
|
-
const {
|
|
6
|
+
const { setLink } = require('./utils');
|
|
7
7
|
|
|
8
8
|
function setLayers( sources ) {
|
|
9
9
|
// set dependencies
|
|
10
10
|
for (const name in sources) {
|
|
11
11
|
const ast = sources[name];
|
|
12
12
|
ast.realname = name;
|
|
13
|
-
|
|
13
|
+
setLink( ast, '_deps', [] );
|
|
14
14
|
for (const d of ast.dependencies || []) {
|
|
15
15
|
const art = sources[d.realname];
|
|
16
16
|
if (art)
|
|
@@ -24,7 +24,7 @@ function setLayers( sources ) {
|
|
|
24
24
|
// It is ensured that the representative is called last in SCC and that
|
|
25
25
|
// dependent SCCs are called first
|
|
26
26
|
function setExtends( node, representative, sccDeps = Object.create(null) ) {
|
|
27
|
-
|
|
27
|
+
setLink( node, '_layerRepresentative', representative );
|
|
28
28
|
if (layerRepresentative !== representative) {
|
|
29
29
|
layerRepresentative = representative;
|
|
30
30
|
++layerNumber;
|
|
@@ -40,7 +40,7 @@ function setLayers( sources ) {
|
|
|
40
40
|
if (node === representative) {
|
|
41
41
|
const exts = Object.keys( sccDeps ).map( name => sccDeps[name]._layerExtends );
|
|
42
42
|
Object.assign( sccDeps, ...exts );
|
|
43
|
-
|
|
43
|
+
setLink( representative, '_layerExtends', sccDeps );
|
|
44
44
|
// console.log ('SCC:', node.realname)
|
|
45
45
|
}
|
|
46
46
|
return sccDeps;
|