@sap/cds-compiler 3.6.2 → 3.8.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 +109 -1
- package/README.md +3 -0
- package/bin/cdsc.js +12 -5
- package/doc/CHANGELOG_ARCHIVE.md +6 -6
- package/doc/CHANGELOG_BETA.md +35 -2
- package/doc/CHANGELOG_DEPRECATED.md +2 -2
- package/doc/DeprecatedOptions_v2.md +1 -1
- package/doc/NameResolution.md +1 -1
- package/lib/api/main.js +63 -23
- package/lib/api/options.js +1 -0
- package/lib/api/validate.js +5 -0
- package/lib/base/dictionaries.js +15 -3
- package/lib/base/keywords.js +2 -0
- package/lib/base/message-registry.js +120 -34
- package/lib/base/messages.js +51 -27
- package/lib/base/model.js +4 -2
- package/lib/base/shuffle.js +2 -1
- package/lib/checks/arrayOfs.js +1 -1
- package/lib/checks/defaultValues.js +1 -1
- package/lib/checks/elements.js +29 -1
- package/lib/checks/{emptyOrOnlyVirtual.js → hasPersistedElements.js} +10 -6
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/nonexpandableStructured.js +1 -1
- package/lib/checks/onConditions.js +15 -9
- package/lib/checks/sql-snippets.js +2 -2
- package/lib/checks/types.js +5 -1
- package/lib/checks/validator.js +7 -3
- package/lib/compiler/assert-consistency.js +42 -26
- package/lib/compiler/base.js +50 -4
- package/lib/compiler/builtins.js +17 -8
- package/lib/compiler/checks.js +241 -246
- package/lib/compiler/define.js +113 -146
- package/lib/compiler/extend.js +889 -383
- package/lib/compiler/finalize-parse-cdl.js +5 -58
- package/lib/compiler/index.js +1 -1
- package/lib/compiler/kick-start.js +7 -8
- package/lib/compiler/populate.js +297 -293
- package/lib/compiler/propagator.js +27 -18
- package/lib/compiler/resolve.js +146 -463
- package/lib/compiler/shared.js +36 -79
- package/lib/compiler/tweak-assocs.js +30 -28
- package/lib/compiler/utils.js +31 -5
- package/lib/edm/annotations/genericTranslation.js +131 -59
- package/lib/edm/annotations/preprocessAnnotations.js +3 -0
- package/lib/edm/csn2edm.js +22 -5
- package/lib/edm/edm.js +6 -4
- package/lib/edm/edmAnnoPreprocessor.js +1 -0
- package/lib/edm/edmPreprocessor.js +42 -26
- package/lib/gen/Dictionary.json +38 -2
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +3 -1
- package/lib/gen/languageLexer.js +1 -1
- package/lib/gen/languageParser.js +4828 -4472
- package/lib/inspect/inspectPropagation.js +20 -34
- package/lib/json/from-csn.js +140 -44
- package/lib/json/to-csn.js +114 -122
- package/lib/language/errorStrategy.js +2 -0
- package/lib/language/genericAntlrParser.js +156 -36
- package/lib/language/language.g4 +100 -58
- package/lib/language/textUtils.js +13 -0
- package/lib/main.d.ts +43 -3
- package/lib/main.js +4 -2
- package/lib/model/csnRefs.js +15 -3
- package/lib/model/csnUtils.js +12 -74
- package/lib/model/revealInternalProperties.js +4 -2
- package/lib/modelCompare/compare.js +2 -1
- package/lib/optionProcessor.js +3 -0
- package/lib/render/manageConstraints.js +5 -2
- package/lib/render/toCdl.js +216 -104
- package/lib/render/toHdbcds.js +2 -9
- package/lib/render/toRename.js +14 -51
- package/lib/render/toSql.js +4 -3
- package/lib/render/utils/common.js +9 -5
- package/lib/transform/braceExpression.js +6 -0
- package/lib/transform/db/assertUnique.js +2 -1
- package/lib/transform/db/expansion.js +2 -0
- package/lib/transform/db/flattening.js +37 -36
- package/lib/transform/db/rewriteCalculatedElements.js +600 -0
- package/lib/transform/db/transformExists.js +4 -0
- package/lib/transform/db/views.js +40 -37
- package/lib/transform/forOdataNew.js +20 -15
- package/lib/transform/forRelationalDB.js +58 -41
- package/lib/transform/odata/typesExposure.js +50 -15
- package/lib/transform/parseExpr.js +16 -8
- package/lib/transform/transformUtilsNew.js +42 -14
- package/lib/transform/translateAssocsToJoins.js +60 -37
- package/lib/transform/universalCsn/coreComputed.js +15 -7
- package/lib/transform/universalCsn/universalCsnEnricher.js +4 -4
- package/package.json +2 -1
|
@@ -13,8 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
'use strict';
|
|
15
15
|
|
|
16
|
-
const {
|
|
17
|
-
const { forEachGeneric, forEachMember } = require('../base/model');
|
|
16
|
+
const { forEachGeneric } = require('../base/model');
|
|
18
17
|
const { setLink, setArtifactLink } = require('./utils');
|
|
19
18
|
|
|
20
19
|
|
|
@@ -30,19 +29,19 @@ function finalizeParseCdl( model ) {
|
|
|
30
29
|
resolveUncheckedPath,
|
|
31
30
|
resolveTypeArgumentsUnchecked,
|
|
32
31
|
initMembers,
|
|
33
|
-
extensionsDict,
|
|
34
32
|
} = model.$functions;
|
|
35
33
|
|
|
36
34
|
resolveTypesAndExtensionsForParseCdl();
|
|
37
35
|
return;
|
|
38
36
|
|
|
39
37
|
function resolveTypesAndExtensionsForParseCdl() {
|
|
38
|
+
const late = model.$lateExtensions;
|
|
40
39
|
const extensions = [];
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
// TODO: why not just use the extensions as they are from the first source?
|
|
42
|
+
for (const name in late) {
|
|
43
|
+
for (const ext of late[name]._extensions) {
|
|
44
44
|
ext.name.absolute = resolveUncheckedPath( ext.name, 'extend', ext );
|
|
45
|
-
mergeAnnotatesForSameArtifact( ext ); // TODO: should not be necessary anymore
|
|
46
45
|
// Initialize members and define annotations in sub-elements.
|
|
47
46
|
initMembers( ext, ext, ext._block, true );
|
|
48
47
|
extensions.push( ext );
|
|
@@ -96,8 +95,6 @@ function finalizeParseCdl( model ) {
|
|
|
96
95
|
|
|
97
96
|
if (artifact.from) {
|
|
98
97
|
const { from } = artifact;
|
|
99
|
-
// Note: `_from` only contains sources necessary for calculating elements,
|
|
100
|
-
// not e.g. those from the `where exists` clause.
|
|
101
98
|
resolveUncheckedPath(from, 'from', main);
|
|
102
99
|
resolveTypesForParseCdl(from, main);
|
|
103
100
|
}
|
|
@@ -108,11 +105,6 @@ function finalizeParseCdl( model ) {
|
|
|
108
105
|
if (parseCdlSpeciallyHandledXsnProps.includes(prop) || parseCdlIgnoredXsnProps.includes(prop))
|
|
109
106
|
continue;
|
|
110
107
|
|
|
111
|
-
// define.js (and initMembers()) initializes annotations. If there is a duplicate, the
|
|
112
|
-
// annotation is an array in XSN.
|
|
113
|
-
if (prop[0] === '@' && Array.isArray(artifact[prop]))
|
|
114
|
-
chooseAndReportDuplicateAnnotation(artifact, prop);
|
|
115
|
-
|
|
116
108
|
if (artifact[prop] && Object.getPrototypeOf(artifact[prop]) === null)
|
|
117
109
|
// Dictionary in XSN
|
|
118
110
|
forEachGeneric(artifact, prop, art => resolveTypesForParseCdl(art, art));
|
|
@@ -172,12 +164,10 @@ function finalizeParseCdl( model ) {
|
|
|
172
164
|
const name = resolveUncheckedPath( artWithType.type, 'type', user );
|
|
173
165
|
const type = name && model.definitions[name] || { name: { absolute: name } };
|
|
174
166
|
resolveTypeArgumentsUnchecked( artWithType, type, user );
|
|
175
|
-
return;
|
|
176
167
|
}
|
|
177
168
|
else if (!user._main) {
|
|
178
169
|
error( 'ref-undefined-typeof', [ artWithType.type.location, user ], {},
|
|
179
170
|
'Current artifact has no element to refer to as type' );
|
|
180
|
-
return;
|
|
181
171
|
}
|
|
182
172
|
else if (root.id === '$self' || root.id === '$projection') {
|
|
183
173
|
setArtifactLink( root, user._main );
|
|
@@ -206,49 +196,6 @@ function finalizeParseCdl( model ) {
|
|
|
206
196
|
setArtifactLink( root, fake );
|
|
207
197
|
}
|
|
208
198
|
}
|
|
209
|
-
|
|
210
|
-
function chooseAndReportDuplicateAnnotation( artifact, annoName ) {
|
|
211
|
-
for (const anno of artifact[annoName])
|
|
212
|
-
message( 'anno-duplicate', [ anno.name.location, artifact ], { anno: annoName } );
|
|
213
|
-
|
|
214
|
-
// Choose any annotation, doesn't matter because of the error above.
|
|
215
|
-
artifact[annoName] = artifact[annoName][0];
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* For duplicate entries in `annotate {}` blocks, we de-duplicate the entries and merge them.
|
|
220
|
-
* Since it is allowed in "normal" compilations to have e.g.
|
|
221
|
-
* `annotate E with { @anno1 id, @anno2 id }`.
|
|
222
|
-
*
|
|
223
|
-
* @param {object} ext
|
|
224
|
-
*/
|
|
225
|
-
function mergeAnnotatesForSameArtifact( ext ) {
|
|
226
|
-
if (!ext || typeof ext !== 'object')
|
|
227
|
-
return;
|
|
228
|
-
|
|
229
|
-
forEachMember(ext, sub => mergeAnnotatesForSameArtifact(sub));
|
|
230
|
-
|
|
231
|
-
// do not do a complex merge:
|
|
232
|
-
if (isComplexExtension( ext ) ||
|
|
233
|
-
!Array.isArray( ext.$duplicates ) || ext.$duplicates.some( isComplexExtension ))
|
|
234
|
-
return;
|
|
235
|
-
for (const dup of ext.$duplicates) {
|
|
236
|
-
for (const prop in dup) {
|
|
237
|
-
if (prop.charAt(0) === '@')
|
|
238
|
-
dictAddArray( ext, prop, dup[prop] );
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
delete ext.$duplicates;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* We only de-duplicate an extend/annotate `ext` in function
|
|
247
|
-
* mergeAnnotatesForSameArtifact() if the extend/annotate is simple, i.e. has
|
|
248
|
-
* no members like elements.
|
|
249
|
-
*/
|
|
250
|
-
function isComplexExtension( ext ) {
|
|
251
|
-
return ext.kind !== 'annotate' || ext.elements || ext.parameters || ext.actions;
|
|
252
199
|
}
|
|
253
200
|
|
|
254
201
|
module.exports = finalizeParseCdl;
|
package/lib/compiler/index.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
'use strict';
|
|
16
16
|
|
|
17
17
|
const { resolveModule, resolveModuleSync } = require('../utils/moduleResolve');
|
|
18
|
-
const parseLanguage = require('../language/antlrParser');
|
|
18
|
+
const parseLanguage = require('../language/antlrParser'); // TODO: should we do some lazyload here?
|
|
19
19
|
const parseCsn = require('../json/from-csn');
|
|
20
20
|
|
|
21
21
|
const assertConsistency = require('./assert-consistency');
|
|
@@ -31,9 +31,9 @@ function kickStart( model ) {
|
|
|
31
31
|
*/
|
|
32
32
|
function setAncestorsAndService( name ) {
|
|
33
33
|
const art = model.definitions[name];
|
|
34
|
-
if (
|
|
34
|
+
if (art._parent === undefined)
|
|
35
35
|
return; // nothing to do for builtins and redefinitions
|
|
36
|
-
if (art.
|
|
36
|
+
if (art.query && art._ancestors === undefined)
|
|
37
37
|
setProjectionAncestors( art );
|
|
38
38
|
|
|
39
39
|
let parent = art._parent;
|
|
@@ -72,13 +72,12 @@ function kickStart( model ) {
|
|
|
72
72
|
// no need to set preferredRedirectionTarget in the while loop as we would
|
|
73
73
|
// use the projection having @cds.redirection.target anyhow instead of
|
|
74
74
|
// `art` anyway (if we do the no-x-service-implicit-redirection TODO above)
|
|
75
|
-
while (art &&
|
|
76
|
-
art.
|
|
77
|
-
(preferredRedirectionTarget || !annotationIsFalse( art['@cds.redirection.target'] ) )
|
|
78
|
-
art.query.op && art.query.op.val === 'SELECT') {
|
|
75
|
+
while (art?.query?.from?.path && // direct select with one source
|
|
76
|
+
art._ancestors !== 0 && // prevent inf-loop
|
|
77
|
+
(preferredRedirectionTarget || !annotationIsFalse( art['@cds.redirection.target'] ) )) {
|
|
79
78
|
chain.push( art );
|
|
80
|
-
setLink( art, '_ancestors',
|
|
81
|
-
const name = resolveUncheckedPath( art.
|
|
79
|
+
setLink( art, '_ancestors', 0 ); // avoid infloop with cyclic from
|
|
80
|
+
const name = resolveUncheckedPath( art.query.from, 'include', art ); // TODO: 'include'?
|
|
82
81
|
art = name && model.definitions[name];
|
|
83
82
|
if (autoexposed)
|
|
84
83
|
break; // only direct projection for auto-exposed
|