@sap/cds-compiler 2.13.8 → 3.0.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 +155 -1594
- package/bin/cdsc.js +144 -66
- package/doc/CHANGELOG_ARCHIVE.md +1592 -0
- package/doc/CHANGELOG_BETA.md +3 -4
- package/doc/CHANGELOG_DEPRECATED.md +35 -1
- package/doc/{DeprecatedOptions.md → DeprecatedOptions_v2.md} +3 -1
- package/doc/Versioning.md +20 -1
- package/lib/api/.eslintrc.json +2 -2
- package/lib/api/main.js +237 -122
- package/lib/api/options.js +17 -88
- package/lib/api/validate.js +12 -16
- package/lib/base/keywords.js +216 -109
- package/lib/base/message-registry.js +152 -37
- package/lib/base/messages.js +145 -83
- package/lib/base/model.js +44 -2
- package/lib/base/optionProcessorHelper.js +19 -0
- package/lib/checks/actionsFunctions.js +7 -5
- package/lib/checks/annotationsOData.js +11 -32
- package/lib/checks/arrayOfs.js +1 -34
- package/lib/checks/cdsPersistence.js +1 -0
- package/lib/checks/elements.js +6 -6
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/nonexpandableStructured.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +2 -1
- package/lib/checks/selectItems.js +5 -1
- package/lib/checks/types.js +4 -2
- package/lib/checks/utils.js +2 -2
- package/lib/checks/validator.js +4 -5
- package/lib/compiler/assert-consistency.js +16 -10
- package/lib/compiler/base.js +1 -0
- package/lib/compiler/builtins.js +98 -9
- package/lib/compiler/checks.js +22 -70
- package/lib/compiler/define.js +61 -13
- package/lib/compiler/extend.js +79 -14
- package/lib/compiler/finalize-parse-cdl.js +46 -29
- package/lib/compiler/index.js +100 -37
- package/lib/compiler/moduleLayers.js +7 -0
- package/lib/compiler/populate.js +19 -18
- package/lib/compiler/propagator.js +7 -4
- package/lib/compiler/resolve.js +297 -234
- package/lib/compiler/shared.js +107 -102
- package/lib/compiler/tweak-assocs.js +16 -11
- package/lib/compiler/utils.js +5 -0
- package/lib/edm/annotations/genericTranslation.js +93 -21
- package/lib/edm/csn2edm.js +230 -115
- package/lib/edm/edm.js +305 -226
- package/lib/edm/edmPreprocessor.js +509 -438
- package/lib/edm/edmUtils.js +31 -45
- package/lib/gen/Dictionary.json +98 -22
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +10 -30
- package/lib/gen/language.tokens +105 -114
- package/lib/gen/languageLexer.interp +1 -34
- package/lib/gen/languageLexer.js +889 -1007
- package/lib/gen/languageLexer.tokens +95 -106
- package/lib/gen/languageParser.js +20786 -22199
- package/lib/json/csnVersion.js +10 -11
- package/lib/json/from-csn.js +59 -51
- package/lib/json/to-csn.js +10 -10
- package/lib/language/antlrParser.js +2 -2
- package/lib/language/docCommentParser.js +62 -39
- package/lib/language/errorStrategy.js +52 -40
- package/lib/language/genericAntlrParser.js +348 -229
- package/lib/language/language.g4 +629 -653
- package/lib/language/multiLineStringParser.js +14 -42
- package/lib/language/textUtils.js +44 -0
- package/lib/main.d.ts +46 -43
- package/lib/main.js +108 -79
- package/lib/model/csnRefs.js +34 -7
- package/lib/model/csnUtils.js +337 -332
- package/lib/model/enrichCsn.js +1 -0
- package/lib/model/revealInternalProperties.js +30 -10
- package/lib/model/sortViews.js +32 -31
- package/lib/modelCompare/compare.js +6 -6
- package/lib/optionProcessor.js +73 -46
- package/lib/render/.eslintrc.json +1 -1
- package/lib/render/DuplicateChecker.js +4 -7
- package/lib/render/manageConstraints.js +70 -2
- package/lib/render/toCdl.js +1042 -882
- package/lib/render/toHdbcds.js +195 -245
- package/lib/render/toRename.js +44 -22
- package/lib/render/toSql.js +225 -241
- package/lib/render/utils/common.js +145 -15
- package/lib/render/utils/sql.js +20 -19
- package/lib/sql-identifier.js +6 -0
- package/lib/transform/db/.eslintrc.json +4 -3
- package/lib/transform/db/associations.js +2 -2
- package/lib/transform/db/cdsPersistence.js +5 -15
- package/lib/transform/db/constraints.js +4 -2
- package/lib/transform/db/expansion.js +22 -16
- package/lib/transform/db/flattening.js +109 -80
- package/lib/transform/db/transformExists.js +7 -7
- package/lib/transform/db/views.js +9 -6
- package/lib/transform/draft/.eslintrc.json +2 -2
- package/lib/transform/draft/db.js +6 -6
- package/lib/transform/draft/odata.js +6 -7
- package/lib/transform/forHanaNew.js +62 -48
- package/lib/transform/forOdataNew.js +49 -50
- package/lib/transform/localized.js +31 -20
- package/lib/transform/odata/toFinalBaseType.js +16 -14
- package/lib/transform/odata/typesExposure.js +146 -198
- package/lib/transform/odata/utils.js +1 -38
- package/lib/transform/transformUtilsNew.js +67 -84
- package/lib/transform/translateAssocsToJoins.js +7 -3
- package/lib/transform/universalCsn/.eslintrc.json +2 -2
- package/lib/transform/universalCsn/coreComputed.js +16 -9
- package/lib/transform/universalCsn/universalCsnEnricher.js +60 -10
- package/lib/utils/file.js +3 -3
- package/lib/utils/moduleResolve.js +13 -6
- package/lib/utils/timetrace.js +20 -21
- package/package.json +35 -4
- package/share/messages/message-explanations.json +2 -1
- package/share/messages/syntax-expected-integer.md +37 -0
- package/doc/ApiMigration.md +0 -237
- package/doc/CommandLineMigration.md +0 -58
- package/doc/ErrorMessages.md +0 -175
- package/doc/FioriAnnotations.md +0 -94
- package/doc/ODataTransformation.md +0 -273
- package/lib/backends.js +0 -529
- package/lib/fix_antlr4-8_warning.js +0 -56
- 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 -296
- 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/compiler/index.js
CHANGED
|
@@ -33,6 +33,7 @@ const check = require('./checks');
|
|
|
33
33
|
|
|
34
34
|
const { emptyWeakLocation } = require('../base/location');
|
|
35
35
|
const { createMessageFunctions, deduplicateMessages } = require('../base/messages');
|
|
36
|
+
const { checkRemovedDeprecatedFlags } = require('../base/model');
|
|
36
37
|
const { promiseAllDoNotRejectImmediately } = require('../base/node-helpers');
|
|
37
38
|
const { cdsFs } = require('../utils/file');
|
|
38
39
|
|
|
@@ -128,30 +129,35 @@ function compileX( filenames, dir = '', options = {}, fileCache = Object.create(
|
|
|
128
129
|
// if (Object.getPrototypeOf( fileCache ))
|
|
129
130
|
// fileCache = Object.assign( Object.create(null), fileCache );
|
|
130
131
|
dir = path.resolve(dir);
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
const model = { sources: a.sources, options };
|
|
132
|
+
const model = { sources: null, options };
|
|
134
133
|
model.$messageFunctions = createMessageFunctions( options, 'compile', model );
|
|
135
|
-
let
|
|
136
|
-
|
|
137
|
-
all =
|
|
134
|
+
let input = null;
|
|
135
|
+
|
|
136
|
+
let all = processFilenames( filenames, dir )
|
|
137
|
+
.then((processedInput) => {
|
|
138
|
+
input = processedInput;
|
|
139
|
+
model.sources = input.sources;
|
|
140
|
+
})
|
|
141
|
+
.then(() => promiseAllDoNotRejectImmediately( input.files.map(readAndParse) ))
|
|
138
142
|
.then( testInvocation, (reason) => {
|
|
139
143
|
// do not reject with PromiseAllError, use InvocationError:
|
|
140
144
|
const errs = reason.valuesOrErrors.filter( e => e instanceof Error );
|
|
141
145
|
// internal error if no file IO error (has property `path`)
|
|
142
146
|
return Promise.reject( errs.find( e => !e.path ) ||
|
|
143
|
-
new InvocationError( [ ...
|
|
147
|
+
new InvocationError( [ ...input.repeated, ...errs ]) );
|
|
144
148
|
});
|
|
149
|
+
|
|
145
150
|
if (!options.parseOnly && !options.parseCdl)
|
|
146
151
|
all = all.then( readDependencies );
|
|
152
|
+
|
|
147
153
|
return all.then( () => {
|
|
148
|
-
moduleLayers.setLayers(
|
|
154
|
+
moduleLayers.setLayers( input.sources );
|
|
149
155
|
return compileDoX( model );
|
|
150
156
|
});
|
|
151
157
|
|
|
152
158
|
// Read file `filename` and parse its content, return messages
|
|
153
159
|
async function readAndParse( filename ) {
|
|
154
|
-
const { sources } =
|
|
160
|
+
const { sources } = input;
|
|
155
161
|
if ( filename === false ) // module which has not been found
|
|
156
162
|
return [];
|
|
157
163
|
const rel = sources[filename] || path.relative( dir, filename );
|
|
@@ -173,9 +179,9 @@ function compileX( filenames, dir = '', options = {}, fileCache = Object.create(
|
|
|
173
179
|
|
|
174
180
|
// Combine the parse results (if there are not file IO errors)
|
|
175
181
|
function testInvocation( values ) {
|
|
176
|
-
if (
|
|
182
|
+
if (input.repeated.length)
|
|
177
183
|
// repeated file names in invocation => just report these
|
|
178
|
-
return Promise.reject( new InvocationError(
|
|
184
|
+
return Promise.reject( new InvocationError(input.repeated) );
|
|
179
185
|
return values;
|
|
180
186
|
}
|
|
181
187
|
|
|
@@ -219,18 +225,19 @@ function compileX( filenames, dir = '', options = {}, fileCache = Object.create(
|
|
|
219
225
|
* @param {string} [dir=""] Base directory. All files are resolved relatively
|
|
220
226
|
* to this directory
|
|
221
227
|
* @param {object} [options={}] Compilation options.
|
|
228
|
+
* @param {object} [fileCache]
|
|
222
229
|
* @returns {XSN.Model} Augmented CSN
|
|
223
230
|
*/
|
|
224
231
|
function compileSyncX( filenames, dir = '', options = {}, fileCache = Object.create(null) ) {
|
|
225
232
|
// A non-proper dictionary (i.e. with prototype) is safe if the keys are
|
|
226
233
|
// absolute file names - they start with `/` or `\` or similar
|
|
227
234
|
dir = path.resolve(dir);
|
|
228
|
-
const a =
|
|
235
|
+
const a = processFilenamesSync( filenames, dir );
|
|
229
236
|
|
|
230
237
|
const model = { sources: a.sources, options };
|
|
231
238
|
model.$messageFunctions = createMessageFunctions( options, 'compile', model );
|
|
232
239
|
|
|
233
|
-
|
|
240
|
+
const asts = [];
|
|
234
241
|
const errors = [];
|
|
235
242
|
a.files.forEach( val => readAndParseSync( val, (err, ast) => {
|
|
236
243
|
if (err)
|
|
@@ -248,17 +255,16 @@ function compileSyncX( filenames, dir = '', options = {}, fileCache = Object.cre
|
|
|
248
255
|
if (!options.parseOnly && !options.parseCdl) {
|
|
249
256
|
while (asts.length) {
|
|
250
257
|
const fileNames = readDependenciesSync( asts );
|
|
251
|
-
asts =
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
fileNames.forEach( (fileName) => {
|
|
258
|
+
asts.length = 0;
|
|
259
|
+
// Push dependencies to `ast`. Only works because readAndParseSync() is synchronous.
|
|
260
|
+
for (const fileName of fileNames) {
|
|
255
261
|
readAndParseSync(fileName, ( err, ast ) => {
|
|
256
262
|
if (err)
|
|
257
263
|
throw err;
|
|
258
264
|
if (ast)
|
|
259
265
|
asts.push( ast );
|
|
260
266
|
});
|
|
261
|
-
}
|
|
267
|
+
}
|
|
262
268
|
}
|
|
263
269
|
}
|
|
264
270
|
|
|
@@ -373,6 +379,15 @@ function compileSourcesX( sourcesDict, options = {} ) {
|
|
|
373
379
|
ast.location = { file: filename };
|
|
374
380
|
assertConsistency( ast, options );
|
|
375
381
|
}
|
|
382
|
+
|
|
383
|
+
for (const dep of sources[filename].dependencies || []) {
|
|
384
|
+
if (!dep.realname) {
|
|
385
|
+
// `realname` is used by setLayers(). For compileSources(), we don't resolve
|
|
386
|
+
// the USING paths and use the literal instead, which may be part of the
|
|
387
|
+
// source dictionary.
|
|
388
|
+
dep.realname = dep.val;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
376
391
|
}
|
|
377
392
|
moduleLayers.setLayers( sources );
|
|
378
393
|
|
|
@@ -386,14 +401,15 @@ function compileSourcesX( sourcesDict, options = {} ) {
|
|
|
386
401
|
* @param {object} options Options
|
|
387
402
|
* @returns {object} XSN
|
|
388
403
|
*
|
|
389
|
-
* TODO:
|
|
404
|
+
* TODO: probably issue message api-recompiled-csn there.
|
|
390
405
|
*/
|
|
391
406
|
function recompileX( csn, options ) {
|
|
392
|
-
options = { ...options, parseCdl: false, $recompile: true };
|
|
393
|
-
// TODO: $recompile: true should be enough
|
|
394
407
|
// Explicitly set parseCdl to false because backends cannot handle it
|
|
395
|
-
|
|
408
|
+
options = { ...options, parseCdl: false, $recompile: true };
|
|
409
|
+
// Reset csnFlavor: Use client style (default)
|
|
410
|
+
delete options.csnFlavor;
|
|
396
411
|
delete options.toCsn;
|
|
412
|
+
// TODO: $recompile: true should be enough
|
|
397
413
|
|
|
398
414
|
const file = csn.$location && csn.$location.file &&
|
|
399
415
|
csn.$location.file.replace(/[.]cds$/, '.cds.csn') || '<recompile>.csn';
|
|
@@ -423,6 +439,9 @@ function compileDoX( model ) {
|
|
|
423
439
|
const { throwWithError } = model.$messageFunctions;
|
|
424
440
|
if (!options.testMode)
|
|
425
441
|
model.meta = {}; // provide initial central meta object
|
|
442
|
+
|
|
443
|
+
checkRemovedDeprecatedFlags( options, model.$messageFunctions );
|
|
444
|
+
|
|
426
445
|
if (options.parseOnly) {
|
|
427
446
|
throwWithError();
|
|
428
447
|
return model;
|
|
@@ -453,32 +472,76 @@ function compileDoX( model ) {
|
|
|
453
472
|
return propagator.propagate( model );
|
|
454
473
|
}
|
|
455
474
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
const
|
|
475
|
+
/**
|
|
476
|
+
* Process an array of `filenames`. Returns an object with properties:
|
|
477
|
+
* - `sources`: dictionary which has a filename as key (value is irrelevant)
|
|
478
|
+
* - `files`: the argument array without repeating the same name
|
|
479
|
+
* - `repeated`: array of filenames which have been repeatedly listed
|
|
480
|
+
* (listed only once here even if listed thrice)
|
|
481
|
+
*
|
|
482
|
+
* Note: there is nothing file-specific about the filenames, the filenames are
|
|
483
|
+
* not normalized - any strings work
|
|
484
|
+
*/
|
|
485
|
+
async function processFilenames( filenames, dir ) {
|
|
486
|
+
const filenameMap = Object.create(null);
|
|
468
487
|
|
|
488
|
+
const promises = [];
|
|
469
489
|
for (const originalName of filenames) {
|
|
470
|
-
|
|
490
|
+
const setName = (name) => {
|
|
491
|
+
filenameMap[originalName] = name;
|
|
492
|
+
};
|
|
493
|
+
// Resolve possible symbolic link; if the file does not exist
|
|
494
|
+
// we just continue using the original name because readFile()
|
|
495
|
+
// already handles non-existent files.
|
|
496
|
+
const promise = fs.promises.realpath(path.resolve(dir, originalName))
|
|
497
|
+
.then(setName, () => setName(originalName));
|
|
498
|
+
promises.push(promise);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
await Promise.all(promises);
|
|
502
|
+
return createSourcesDict( filenames, filenameMap, dir );
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Synchronous version of processFilenames().
|
|
507
|
+
*/
|
|
508
|
+
function processFilenamesSync( filenames, dir ) {
|
|
509
|
+
const filenameMap = Object.create(null);
|
|
471
510
|
|
|
511
|
+
for (const originalName of filenames) {
|
|
512
|
+
let name = path.resolve(dir, originalName);
|
|
472
513
|
try {
|
|
473
514
|
// Resolve possible symbolic link; if the file does not exist
|
|
474
515
|
// we just continue using the original name because readFile()
|
|
475
516
|
// already handles non-existent files.
|
|
476
|
-
name = fs.realpathSync(name);
|
|
517
|
+
name = fs.realpathSync.native(name);
|
|
477
518
|
}
|
|
478
519
|
catch (e) {
|
|
479
520
|
// Ignore the not-found (ENOENT) error
|
|
480
521
|
}
|
|
522
|
+
filenameMap[originalName] = name;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
return createSourcesDict( filenames, filenameMap, dir );
|
|
526
|
+
}
|
|
481
527
|
|
|
528
|
+
/**
|
|
529
|
+
* Creates the sources dictionary as well as a list of absolute filenames.
|
|
530
|
+
* If files are repeated, `repeated` will contain ArgumentErrors for it.
|
|
531
|
+
*
|
|
532
|
+
* @param {string[]} filenames List of (possibly relative) filenames. Defines the file order.
|
|
533
|
+
* @param {Record<string, string>} filenameMap Map from original name to actual filename
|
|
534
|
+
* (e.g. from symlink to underlying path)
|
|
535
|
+
* @param {string} dir "Current working directory"
|
|
536
|
+
* @return {{sources: object, files: string[], repeated: ArgumentError[]}}
|
|
537
|
+
*/
|
|
538
|
+
function createSourcesDict( filenames, filenameMap, dir ) {
|
|
539
|
+
const sources = Object.create(null);
|
|
540
|
+
const files = [];
|
|
541
|
+
const repeated = [];
|
|
542
|
+
|
|
543
|
+
for (const originalName of filenames) {
|
|
544
|
+
const name = filenameMap[originalName];
|
|
482
545
|
if (!sources[name]) {
|
|
483
546
|
sources[name] = path.relative( dir, name );
|
|
484
547
|
files.push(name);
|
|
@@ -488,10 +551,10 @@ function processFilenames( filenames, dir ) {
|
|
|
488
551
|
repeated.push( new ArgumentError( name, msg ) );
|
|
489
552
|
}
|
|
490
553
|
}
|
|
554
|
+
|
|
491
555
|
return { sources, files, repeated };
|
|
492
556
|
}
|
|
493
557
|
|
|
494
|
-
|
|
495
558
|
module.exports = {
|
|
496
559
|
parseX,
|
|
497
560
|
compileX,
|
|
@@ -53,6 +53,12 @@ function layer( art ) {
|
|
|
53
53
|
return art && art._layerRepresentative;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
function realname( art ) {
|
|
57
|
+
while (art && art.kind !== 'source')
|
|
58
|
+
art = art._block;
|
|
59
|
+
return art && art.realname || '';
|
|
60
|
+
}
|
|
61
|
+
|
|
56
62
|
function compareLayer( a, b ) {
|
|
57
63
|
while (a && a.kind !== 'source')
|
|
58
64
|
a = a._block;
|
|
@@ -64,5 +70,6 @@ function compareLayer( a, b ) {
|
|
|
64
70
|
module.exports = {
|
|
65
71
|
setLayers,
|
|
66
72
|
layer,
|
|
73
|
+
realname,
|
|
67
74
|
compareLayer,
|
|
68
75
|
};
|
package/lib/compiler/populate.js
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
// used when resolving element references: when starting a references at a
|
|
6
6
|
// certain definition or element, which names are allowed next?
|
|
7
7
|
//
|
|
8
|
-
// To calculate that info, the compiler might
|
|
9
|
-
// definitions.
|
|
10
|
-
// algorithm where appropriate).
|
|
8
|
+
// To calculate that info, the compiler might need the same info for other
|
|
9
|
+
// definitions. In other words: it calls itself recursively (using an iterative
|
|
10
|
+
// algorithm where appropriate). To be able to calculate that info on demand,
|
|
11
11
|
// the definitions need to have enough information, which must have been set in
|
|
12
12
|
// an earlier compiler phase. It is essential to do things in the right order.
|
|
13
13
|
|
|
@@ -74,21 +74,21 @@ function populate( model ) {
|
|
|
74
74
|
let newAutoExposed = [];
|
|
75
75
|
|
|
76
76
|
// behavior depending on option `deprecated`:
|
|
77
|
-
const enableExpandElements = !isDeprecatedEnabled( options, '
|
|
77
|
+
const enableExpandElements = !isDeprecatedEnabled( options, '_noElementsExpansion' );
|
|
78
78
|
// TODO: we should get rid of noElementsExpansion soon; both
|
|
79
79
|
// beta.nestedProjections and beta.universalCsn do not work with it.
|
|
80
80
|
const scopedRedirections
|
|
81
81
|
= enableExpandElements &&
|
|
82
|
-
!isDeprecatedEnabled( options, '
|
|
83
|
-
!isDeprecatedEnabled( options, '
|
|
84
|
-
!isDeprecatedEnabled( options, '
|
|
85
|
-
!isDeprecatedEnabled( options, '
|
|
86
|
-
!isDeprecatedEnabled( options, '
|
|
82
|
+
!isDeprecatedEnabled( options, '_generatedEntityNameWithUnderscore' ) &&
|
|
83
|
+
!isDeprecatedEnabled( options, '_shortAutoexposed' ) &&
|
|
84
|
+
!isDeprecatedEnabled( options, '_longAutoexposed' ) &&
|
|
85
|
+
!isDeprecatedEnabled( options, '_noInheritedAutoexposeViaComposition' ) &&
|
|
86
|
+
!isDeprecatedEnabled( options, '_noScopedRedirections' );
|
|
87
87
|
const autoexposeViaComposition
|
|
88
|
-
= (isDeprecatedEnabled( options, '
|
|
88
|
+
= (isDeprecatedEnabled( options, '_noInheritedAutoexposeViaComposition' ))
|
|
89
89
|
? 'Composition'
|
|
90
90
|
: true;
|
|
91
|
-
const redirectInSubQueries = isDeprecatedEnabled( options, '
|
|
91
|
+
const redirectInSubQueries = isDeprecatedEnabled( options, '_redirectInSubQueries' );
|
|
92
92
|
|
|
93
93
|
forEachDefinition( model, traverseElementEnvironments );
|
|
94
94
|
while (newAutoExposed.length) {
|
|
@@ -166,7 +166,7 @@ function populate( model ) {
|
|
|
166
166
|
const chain = [];
|
|
167
167
|
while (art && !('_effectiveType' in art) &&
|
|
168
168
|
(art.type || art._origin || art.value && art.value.path) &&
|
|
169
|
-
// TODO: really stop at art.enum?
|
|
169
|
+
// TODO: really stop at art.enum? See #8942
|
|
170
170
|
!art.target && !art.enum && !art.elements && !art.items) {
|
|
171
171
|
chain.push( art );
|
|
172
172
|
setLink( art, '_effectiveType', 0 ); // initial setting in case of cycles
|
|
@@ -564,7 +564,8 @@ function populate( model ) {
|
|
|
564
564
|
error( null, [ col.location, query ], { prop: (col.expand ? 'expand' : 'inline') },
|
|
565
565
|
'Unsupported nested $(PROP)' );
|
|
566
566
|
}
|
|
567
|
-
|
|
567
|
+
// If neither expression (value), expand nor new association.
|
|
568
|
+
if (!col.value && !col.expand && !(col.target && col.type))
|
|
568
569
|
continue; // error should have been reported by parser
|
|
569
570
|
if (col.inline) {
|
|
570
571
|
col.kind = '$inline';
|
|
@@ -1093,7 +1094,7 @@ function populate( model ) {
|
|
|
1093
1094
|
return false;
|
|
1094
1095
|
}
|
|
1095
1096
|
// no @cds.autoexpose or @cds.autoexpose:null
|
|
1096
|
-
// TODO: introduce deprecated.
|
|
1097
|
+
// TODO: introduce deprecated._noInheritedAutoexposeViaComposition
|
|
1097
1098
|
art.$autoexpose = model.$compositionTargets[art.name.absolute]
|
|
1098
1099
|
? autoexposeViaComposition
|
|
1099
1100
|
: null;
|
|
@@ -1102,15 +1103,15 @@ function populate( model ) {
|
|
|
1102
1103
|
|
|
1103
1104
|
function autoExposedName( target, service, elemScope ) {
|
|
1104
1105
|
const { absolute } = target.name;
|
|
1105
|
-
if (isDeprecatedEnabled( options, '
|
|
1106
|
+
if (isDeprecatedEnabled( options, '_shortAutoexposed' )) {
|
|
1106
1107
|
const parent = definitionScope( target )._parent;
|
|
1107
1108
|
const name = (parent) ? absolute.substring( parent.name.absolute.length + 1 ) : absolute;
|
|
1108
|
-
// no need for dedot here (as opposed to deprecated.
|
|
1109
|
+
// no need for dedot here (as opposed to deprecated._longAutoexposed), as
|
|
1109
1110
|
// the name for dependent entities have already been created using `_` then
|
|
1110
1111
|
return `${ service.name.absolute }.${ name }`;
|
|
1111
1112
|
}
|
|
1112
|
-
if (isDeprecatedEnabled( options, '
|
|
1113
|
-
const dedot = isDeprecatedEnabled( options, '
|
|
1113
|
+
if (isDeprecatedEnabled( options, '_longAutoexposed' )) {
|
|
1114
|
+
const dedot = isDeprecatedEnabled( options, '_generatedEntityNameWithUnderscore' );
|
|
1114
1115
|
return `${ service.name.absolute }.${ dedot ? absolute.replace( /\./g, '_' ) : absolute }`;
|
|
1115
1116
|
}
|
|
1116
1117
|
const base = definitionScope( target );
|
|
@@ -56,9 +56,9 @@ function propagate( model ) {
|
|
|
56
56
|
returns,
|
|
57
57
|
};
|
|
58
58
|
const { options } = model;
|
|
59
|
-
const enableExpandElements = !isDeprecatedEnabled( options, '
|
|
59
|
+
const enableExpandElements = !isDeprecatedEnabled( options, '_noElementsExpansion' );
|
|
60
60
|
// eslint-disable-next-line max-len
|
|
61
|
-
const oldVirtualNotNullPropagation = isDeprecatedEnabled( options, '
|
|
61
|
+
const oldVirtualNotNullPropagation = isDeprecatedEnabled( options, '_oldVirtualNotNullPropagation' );
|
|
62
62
|
|
|
63
63
|
forEachDefinition( model, run );
|
|
64
64
|
|
|
@@ -117,6 +117,9 @@ function propagate( model ) {
|
|
|
117
117
|
function runMembers( art ) {
|
|
118
118
|
// console.log('MEMBERS:',refString(art), art.elements ? Object.keys(art.elements) : 0)
|
|
119
119
|
forEachMember( art, run ); // after propagation in parent!
|
|
120
|
+
// propagate to sub query elements even if not requested:
|
|
121
|
+
if (art.$queries)
|
|
122
|
+
art.$queries.forEach( run );
|
|
120
123
|
let obj = art;
|
|
121
124
|
if (art.returns) {
|
|
122
125
|
obj = art.returns;
|
|
@@ -186,7 +189,7 @@ function propagate( model ) {
|
|
|
186
189
|
if (!type || type._main)
|
|
187
190
|
return false;
|
|
188
191
|
// We do not consider the $expand status, as elements are already expanded
|
|
189
|
-
// by the resolve(), and if not due to deprecated.
|
|
192
|
+
// by the resolve(), and if not due to deprecated._noElementsExpansion
|
|
190
193
|
run( type );
|
|
191
194
|
return type[prop];
|
|
192
195
|
}
|
|
@@ -230,7 +233,7 @@ function propagate( model ) {
|
|
|
230
233
|
}
|
|
231
234
|
|
|
232
235
|
function notWithExpand( prop, target, source ) {
|
|
233
|
-
if (!target.expand)
|
|
236
|
+
if (!target.expand || prop === 'type' && source.elements)
|
|
234
237
|
always( prop, target, source );
|
|
235
238
|
}
|
|
236
239
|
|