@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.
Files changed (127) hide show
  1. package/CHANGELOG.md +155 -1594
  2. package/bin/cdsc.js +144 -66
  3. package/doc/CHANGELOG_ARCHIVE.md +1592 -0
  4. package/doc/CHANGELOG_BETA.md +3 -4
  5. package/doc/CHANGELOG_DEPRECATED.md +35 -1
  6. package/doc/{DeprecatedOptions.md → DeprecatedOptions_v2.md} +3 -1
  7. package/doc/Versioning.md +20 -1
  8. package/lib/api/.eslintrc.json +2 -2
  9. package/lib/api/main.js +237 -122
  10. package/lib/api/options.js +17 -88
  11. package/lib/api/validate.js +12 -16
  12. package/lib/base/keywords.js +216 -109
  13. package/lib/base/message-registry.js +152 -37
  14. package/lib/base/messages.js +145 -83
  15. package/lib/base/model.js +44 -2
  16. package/lib/base/optionProcessorHelper.js +19 -0
  17. package/lib/checks/actionsFunctions.js +7 -5
  18. package/lib/checks/annotationsOData.js +11 -32
  19. package/lib/checks/arrayOfs.js +1 -34
  20. package/lib/checks/cdsPersistence.js +1 -0
  21. package/lib/checks/elements.js +6 -6
  22. package/lib/checks/invalidTarget.js +1 -1
  23. package/lib/checks/nonexpandableStructured.js +1 -1
  24. package/lib/checks/queryNoDbArtifacts.js +2 -1
  25. package/lib/checks/selectItems.js +5 -1
  26. package/lib/checks/types.js +4 -2
  27. package/lib/checks/utils.js +2 -2
  28. package/lib/checks/validator.js +4 -5
  29. package/lib/compiler/assert-consistency.js +16 -10
  30. package/lib/compiler/base.js +1 -0
  31. package/lib/compiler/builtins.js +98 -9
  32. package/lib/compiler/checks.js +22 -70
  33. package/lib/compiler/define.js +61 -13
  34. package/lib/compiler/extend.js +79 -14
  35. package/lib/compiler/finalize-parse-cdl.js +46 -29
  36. package/lib/compiler/index.js +100 -37
  37. package/lib/compiler/moduleLayers.js +7 -0
  38. package/lib/compiler/populate.js +19 -18
  39. package/lib/compiler/propagator.js +7 -4
  40. package/lib/compiler/resolve.js +297 -234
  41. package/lib/compiler/shared.js +107 -102
  42. package/lib/compiler/tweak-assocs.js +16 -11
  43. package/lib/compiler/utils.js +5 -0
  44. package/lib/edm/annotations/genericTranslation.js +93 -21
  45. package/lib/edm/csn2edm.js +230 -115
  46. package/lib/edm/edm.js +305 -226
  47. package/lib/edm/edmPreprocessor.js +509 -438
  48. package/lib/edm/edmUtils.js +31 -45
  49. package/lib/gen/Dictionary.json +98 -22
  50. package/lib/gen/language.checksum +1 -1
  51. package/lib/gen/language.interp +10 -30
  52. package/lib/gen/language.tokens +105 -114
  53. package/lib/gen/languageLexer.interp +1 -34
  54. package/lib/gen/languageLexer.js +889 -1007
  55. package/lib/gen/languageLexer.tokens +95 -106
  56. package/lib/gen/languageParser.js +20786 -22199
  57. package/lib/json/csnVersion.js +10 -11
  58. package/lib/json/from-csn.js +59 -51
  59. package/lib/json/to-csn.js +10 -10
  60. package/lib/language/antlrParser.js +2 -2
  61. package/lib/language/docCommentParser.js +62 -39
  62. package/lib/language/errorStrategy.js +52 -40
  63. package/lib/language/genericAntlrParser.js +348 -229
  64. package/lib/language/language.g4 +629 -653
  65. package/lib/language/multiLineStringParser.js +14 -42
  66. package/lib/language/textUtils.js +44 -0
  67. package/lib/main.d.ts +46 -43
  68. package/lib/main.js +108 -79
  69. package/lib/model/csnRefs.js +34 -7
  70. package/lib/model/csnUtils.js +337 -332
  71. package/lib/model/enrichCsn.js +1 -0
  72. package/lib/model/revealInternalProperties.js +30 -10
  73. package/lib/model/sortViews.js +32 -31
  74. package/lib/modelCompare/compare.js +6 -6
  75. package/lib/optionProcessor.js +73 -46
  76. package/lib/render/.eslintrc.json +1 -1
  77. package/lib/render/DuplicateChecker.js +4 -7
  78. package/lib/render/manageConstraints.js +70 -2
  79. package/lib/render/toCdl.js +1042 -882
  80. package/lib/render/toHdbcds.js +195 -245
  81. package/lib/render/toRename.js +44 -22
  82. package/lib/render/toSql.js +225 -241
  83. package/lib/render/utils/common.js +145 -15
  84. package/lib/render/utils/sql.js +20 -19
  85. package/lib/sql-identifier.js +6 -0
  86. package/lib/transform/db/.eslintrc.json +4 -3
  87. package/lib/transform/db/associations.js +2 -2
  88. package/lib/transform/db/cdsPersistence.js +5 -15
  89. package/lib/transform/db/constraints.js +4 -2
  90. package/lib/transform/db/expansion.js +22 -16
  91. package/lib/transform/db/flattening.js +109 -80
  92. package/lib/transform/db/transformExists.js +7 -7
  93. package/lib/transform/db/views.js +9 -6
  94. package/lib/transform/draft/.eslintrc.json +2 -2
  95. package/lib/transform/draft/db.js +6 -6
  96. package/lib/transform/draft/odata.js +6 -7
  97. package/lib/transform/forHanaNew.js +62 -48
  98. package/lib/transform/forOdataNew.js +49 -50
  99. package/lib/transform/localized.js +31 -20
  100. package/lib/transform/odata/toFinalBaseType.js +16 -14
  101. package/lib/transform/odata/typesExposure.js +146 -198
  102. package/lib/transform/odata/utils.js +1 -38
  103. package/lib/transform/transformUtilsNew.js +67 -84
  104. package/lib/transform/translateAssocsToJoins.js +7 -3
  105. package/lib/transform/universalCsn/.eslintrc.json +2 -2
  106. package/lib/transform/universalCsn/coreComputed.js +16 -9
  107. package/lib/transform/universalCsn/universalCsnEnricher.js +60 -10
  108. package/lib/utils/file.js +3 -3
  109. package/lib/utils/moduleResolve.js +13 -6
  110. package/lib/utils/timetrace.js +20 -21
  111. package/package.json +35 -4
  112. package/share/messages/message-explanations.json +2 -1
  113. package/share/messages/syntax-expected-integer.md +37 -0
  114. package/doc/ApiMigration.md +0 -237
  115. package/doc/CommandLineMigration.md +0 -58
  116. package/doc/ErrorMessages.md +0 -175
  117. package/doc/FioriAnnotations.md +0 -94
  118. package/doc/ODataTransformation.md +0 -273
  119. package/lib/backends.js +0 -529
  120. package/lib/fix_antlr4-8_warning.js +0 -56
  121. package/lib/transform/odata/attachPath.js +0 -96
  122. package/lib/transform/odata/expandStructKeysInAssociations.js +0 -59
  123. package/lib/transform/odata/generateForeignKeyElements.js +0 -261
  124. package/lib/transform/odata/referenceFlattener.js +0 -296
  125. package/lib/transform/odata/sortByAssociationDependency.js +0 -105
  126. package/lib/transform/odata/structuralPath.js +0 -72
  127. package/lib/transform/odata/structureFlattener.js +0 -171
@@ -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 a = processFilenames( filenames, dir );
132
-
133
- const model = { sources: a.sources, options };
132
+ const model = { sources: null, options };
134
133
  model.$messageFunctions = createMessageFunctions( options, 'compile', model );
135
- let all = promiseAllDoNotRejectImmediately( a.files.map(readAndParse) );
136
-
137
- all = 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( [ ...a.repeated, ...errs ]) );
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( a.sources );
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 } = a;
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 (a.repeated.length)
182
+ if (input.repeated.length)
177
183
  // repeated file names in invocation => just report these
178
- return Promise.reject( new InvocationError(a.repeated) );
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 = processFilenames( filenames, dir );
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
- let asts = [];
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
- // TODO: check the following eslint error
253
- // eslint-disable-next-line no-loop-func
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: probaby issue message api-recompiled-csn there.
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
- // Explicitly delete all toCsn options:
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
- // Process an array of `filenames`. Returns an object with properties:
457
- // - `sources`: dictionary which has a filename as key (value is irrelevant)
458
- // - `files`: the argument array without repeating the same name
459
- // - `repeated`: array of filenames which have been repeatedly listed
460
- // (listed only once here even if listed thrice)
461
- //
462
- // Note: there is nothing file-specific about the filenames, the filenames are
463
- // not normalized - any strings work
464
- function processFilenames( filenames, dir ) {
465
- const sources = Object.create(null); // not {} = no [[Prototype]]
466
- const files = [];
467
- const repeated = [];
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
- let name = path.resolve(dir, originalName);
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
  };
@@ -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 needs the same info for other
9
- // definitions. In other words: it calls itself recursively (using an iterative
10
- // algorithm where appropriate). The be able to calculate that info on demand,
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, 'noElementsExpansion' );
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, 'generatedEntityNameWithUnderscore' ) &&
83
- !isDeprecatedEnabled( options, 'shortAutoexposed' ) &&
84
- !isDeprecatedEnabled( options, 'longAutoexposed' ) &&
85
- !isDeprecatedEnabled( options, 'noInheritedAutoexposeViaComposition' ) &&
86
- !isDeprecatedEnabled( options, 'noScopedRedirections' );
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, 'noInheritedAutoexposeViaComposition' ))
88
+ = (isDeprecatedEnabled( options, '_noInheritedAutoexposeViaComposition' ))
89
89
  ? 'Composition'
90
90
  : true;
91
- const redirectInSubQueries = isDeprecatedEnabled( options, 'redirectInSubQueries' );
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
- if (!col.value && !col.expand)
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.noInheritedAutoexposeViaComposition
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, 'shortAutoexposed' )) {
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.longAutoexposed), as
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, 'longAutoexposed' )) {
1113
- const dedot = isDeprecatedEnabled( options, 'generatedEntityNameWithUnderscore' );
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, 'noElementsExpansion' );
59
+ const enableExpandElements = !isDeprecatedEnabled( options, '_noElementsExpansion' );
60
60
  // eslint-disable-next-line max-len
61
- const oldVirtualNotNullPropagation = isDeprecatedEnabled( options, 'oldVirtualNotNullPropagation' );
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.noElementsExpansion
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