@sap/cds-compiler 3.4.4 → 3.5.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.
Files changed (129) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +1 -0
  3. package/bin/cds_update_identifiers.js +5 -5
  4. package/bin/cdsc.js +12 -12
  5. package/doc/CHANGELOG_ARCHIVE.md +1 -1
  6. package/doc/CHANGELOG_BETA.md +9 -1
  7. package/doc/CHANGELOG_DEPRECATED.md +2 -0
  8. package/lib/api/main.js +58 -59
  9. package/lib/api/options.js +4 -2
  10. package/lib/api/validate.js +2 -2
  11. package/lib/base/cleanSymbols.js +2 -3
  12. package/lib/base/dictionaries.js +6 -6
  13. package/lib/base/error.js +2 -2
  14. package/lib/base/keywords.js +6 -6
  15. package/lib/base/location.js +11 -12
  16. package/lib/base/message-registry.js +124 -28
  17. package/lib/base/messages.js +247 -179
  18. package/lib/base/model.js +14 -11
  19. package/lib/base/node-helpers.js +9 -10
  20. package/lib/base/optionProcessorHelper.js +138 -129
  21. package/lib/checks/actionsFunctions.js +5 -5
  22. package/lib/checks/annotationsOData.js +4 -4
  23. package/lib/checks/arrayOfs.js +1 -1
  24. package/lib/checks/cdsPersistence.js +1 -1
  25. package/lib/checks/checkForTypes.js +3 -3
  26. package/lib/checks/defaultValues.js +3 -3
  27. package/lib/checks/elements.js +7 -7
  28. package/lib/checks/emptyOrOnlyVirtual.js +2 -2
  29. package/lib/checks/foreignKeys.js +1 -1
  30. package/lib/checks/invalidTarget.js +4 -4
  31. package/lib/checks/managedInType.js +1 -1
  32. package/lib/checks/managedWithoutKeys.js +1 -1
  33. package/lib/checks/nonexpandableStructured.js +5 -3
  34. package/lib/checks/nullableKeys.js +1 -1
  35. package/lib/checks/onConditions.js +5 -6
  36. package/lib/checks/parameters.js +1 -1
  37. package/lib/checks/queryNoDbArtifacts.js +2 -2
  38. package/lib/checks/selectItems.js +4 -4
  39. package/lib/checks/sql-snippets.js +4 -4
  40. package/lib/checks/types.js +7 -7
  41. package/lib/checks/utils.js +4 -4
  42. package/lib/checks/validator.js +16 -13
  43. package/lib/compiler/.eslintrc.json +1 -1
  44. package/lib/compiler/assert-consistency.js +0 -1
  45. package/lib/compiler/builtins.js +1 -1
  46. package/lib/compiler/checks.js +73 -15
  47. package/lib/compiler/define.js +3 -7
  48. package/lib/compiler/extend.js +212 -32
  49. package/lib/compiler/finalize-parse-cdl.js +7 -2
  50. package/lib/compiler/index.js +17 -14
  51. package/lib/compiler/populate.js +2 -5
  52. package/lib/compiler/propagator.js +2 -0
  53. package/lib/compiler/shared.js +23 -12
  54. package/lib/compiler/tweak-assocs.js +5 -6
  55. package/lib/compiler/utils.js +6 -0
  56. package/lib/edm/annotations/genericTranslation.js +553 -319
  57. package/lib/edm/annotations/preprocessAnnotations.js +39 -35
  58. package/lib/edm/csn2edm.js +88 -75
  59. package/lib/edm/edm.js +17 -3
  60. package/lib/edm/edmAnnoPreprocessor.js +5 -5
  61. package/lib/edm/edmPreprocessor.js +106 -76
  62. package/lib/edm/edmUtils.js +41 -2
  63. package/lib/gen/Dictionary.json +34 -0
  64. package/lib/gen/language.checksum +1 -1
  65. package/lib/gen/language.interp +66 -63
  66. package/lib/gen/language.tokens +81 -81
  67. package/lib/gen/languageLexer.interp +4 -10
  68. package/lib/gen/languageLexer.js +854 -869
  69. package/lib/gen/languageLexer.tokens +79 -81
  70. package/lib/gen/languageParser.js +14360 -14146
  71. package/lib/inspect/inspectModelStatistics.js +2 -2
  72. package/lib/inspect/inspectPropagation.js +6 -6
  73. package/lib/inspect/inspectUtils.js +2 -2
  74. package/lib/json/from-csn.js +82 -40
  75. package/lib/json/to-csn.js +82 -157
  76. package/lib/language/.eslintrc.json +1 -4
  77. package/lib/language/genericAntlrParser.js +59 -38
  78. package/lib/language/language.g4 +1508 -1490
  79. package/lib/language/multiLineStringParser.js +1 -1
  80. package/lib/main.js +3 -3
  81. package/lib/model/csnUtils.js +130 -122
  82. package/lib/model/revealInternalProperties.js +1 -1
  83. package/lib/model/sortViews.js +4 -6
  84. package/lib/modelCompare/utils/filter.js +4 -3
  85. package/lib/optionProcessor.js +5 -0
  86. package/lib/render/DuplicateChecker.js +1 -1
  87. package/lib/render/manageConstraints.js +12 -12
  88. package/lib/render/toCdl.js +225 -159
  89. package/lib/render/toHdbcds.js +63 -63
  90. package/lib/render/toRename.js +5 -5
  91. package/lib/render/toSql.js +55 -65
  92. package/lib/render/utils/common.js +20 -37
  93. package/lib/render/utils/delta.js +3 -3
  94. package/lib/render/utils/sql.js +22 -6
  95. package/lib/render/utils/stringEscapes.js +3 -3
  96. package/lib/transform/db/applyTransformations.js +3 -3
  97. package/lib/transform/db/assertUnique.js +13 -12
  98. package/lib/transform/db/associations.js +5 -5
  99. package/lib/transform/db/cdsPersistence.js +10 -8
  100. package/lib/transform/db/constraints.js +14 -14
  101. package/lib/transform/db/expansion.js +20 -22
  102. package/lib/transform/db/flattening.js +24 -42
  103. package/lib/transform/db/groupByOrderBy.js +3 -3
  104. package/lib/transform/db/temporal.js +6 -6
  105. package/lib/transform/db/transformExists.js +23 -23
  106. package/lib/transform/db/views.js +16 -16
  107. package/lib/transform/draft/db.js +10 -10
  108. package/lib/transform/draft/odata.js +2 -2
  109. package/lib/transform/forOdataNew.js +12 -40
  110. package/lib/transform/forRelationalDB.js +17 -7
  111. package/lib/transform/localized.js +2 -2
  112. package/lib/transform/odata/toFinalBaseType.js +41 -27
  113. package/lib/transform/odata/typesExposure.js +106 -62
  114. package/lib/transform/parseExpr.js +209 -106
  115. package/lib/transform/transformUtilsNew.js +2 -2
  116. package/lib/transform/translateAssocsToJoins.js +24 -19
  117. package/lib/transform/universalCsn/coreComputed.js +10 -10
  118. package/lib/transform/universalCsn/universalCsnEnricher.js +26 -26
  119. package/lib/transform/universalCsn/utils.js +3 -3
  120. package/lib/utils/file.js +5 -5
  121. package/lib/utils/moduleResolve.js +13 -13
  122. package/lib/utils/objectUtils.js +6 -6
  123. package/lib/utils/term.js +5 -2
  124. package/lib/utils/timetrace.js +51 -24
  125. package/package.json +5 -7
  126. package/share/messages/check-proper-type-of.md +1 -1
  127. package/share/messages/message-explanations.json +1 -1
  128. package/share/messages/redirected-to-complex.md +4 -4
  129. package/share/messages/{syntax-expecting-integer.md → syntax-expecting-unsigned-int.md} +7 -4
@@ -572,10 +572,12 @@ function fns( model ) {
572
572
  artifact.$typeArgs = undefined;
573
573
  }
574
574
 
575
- // Return artifact or element referred by name `head`. The first environment
576
- // we search in is `env`. If `unchecked` is equal to `true`, do not report an error
577
- // if the artifact does not exist. Return a "fresh" artifact for
578
- // non-existing external using references if `unchecked` is truthy.
575
+ /**
576
+ * Return artifact or element referred by name `head`. The first environment
577
+ * we search in is `env`. If `unchecked` is equal to `true`, do not report an error
578
+ * if the artifact does not exist. Return a "fresh" artifact for
579
+ * non-existing external using references if `unchecked` is truthy.
580
+ */
579
581
  function getPathRoot( path, spec, user, env, extDict, msgArt ) {
580
582
  const head = path[0];
581
583
  if (!head || !head.id || !env)
@@ -689,14 +691,13 @@ function fns( model ) {
689
691
  // navigation elements (for which you should use a table alias)
690
692
  if (extDict !== model.definitions) {
691
693
  for (const name in extDict) {
692
- const def = extDict[name];
693
- if (!(Array.isArray(def) && def[0].kind === '$navElement'))
694
- e[name] = def;
694
+ if (!spec.dollar || name[0] !== '$')
695
+ e[name] = extDict[name];
695
696
  }
696
697
  }
697
698
  else {
698
699
  for (const name in extDict) {
699
- if (!name.includes('.') && (spec.nodollar || name[0] !== '$'))
700
+ if (!name.includes('.') && (!spec.dollar || name[0] !== '$'))
700
701
  e[name] = extDict[name];
701
702
  }
702
703
  }
@@ -712,8 +713,18 @@ function fns( model ) {
712
713
  signalNotFound( 'ref-undefined-element', [ head.location, user ], valid,
713
714
  { art: searchName( msgArt, head.id, 'element' ) } );
714
715
  }
716
+ else if (head.id[0] === '$') {
717
+ const tableAlias = extDict[head.id]?._parent;
718
+ const alias = tableAlias?.kind === '$tableAlias' ? tableAlias.name?.alias : null;
719
+ signalNotFound( 'ref-undefined-var', [ head.location, user ], valid, {
720
+ '#': alias ? 'alias' : 'std',
721
+ alias,
722
+ id: head.id,
723
+ } );
724
+ }
715
725
  else {
716
- signalNotFound( 'ref-undefined-var', [ head.location, user ], valid, { id: head.id } );
726
+ signalNotFound( 'ref-undefined-element', [ head.location, user ], valid,
727
+ { art: head.id, '#': 'std' } );
717
728
  }
718
729
  }
719
730
  else if (env.$frontend && env.$frontend !== 'cdl' || spec.global) {
@@ -764,7 +775,7 @@ function fns( model ) {
764
775
  return 0;
765
776
  if (art.$uncheckedElements) { // magic variable / replacement variable
766
777
  signalNotFound( 'ref-unknown-var', [ item.location, user ], [ env ],
767
- { id: path.map(n => n.id).join('.') } );
778
+ { id: pathName( path ) } );
768
779
  }
769
780
  else {
770
781
  errorNotFound( item, env );
@@ -922,7 +933,7 @@ function fns( model ) {
922
933
  msg.validNames[name] = valid[name];
923
934
  }
924
935
 
925
- if (options.testMode) {
936
+ if (options.testMode && !options.$recompile) {
926
937
  // no semantic location => either first of [loc, semantic loc] pair or just location.
927
938
  const loc = msg.location[0] || msg.location;
928
939
  const names = Object.keys(msg.validNames);
@@ -959,7 +970,7 @@ function fns( model ) {
959
970
  // for non-actions. We can't only check for !art.returns, because `action A();` is valid.
960
971
  // `art._block` ensures that `art` is a defined def.
961
972
  warning('anno-unexpected-returns', [ construct.name.location, construct ],
962
- { keyword: 'returns', kind: art.kind }, 'Unexpected $(KEYWORD) for $(KIND)');
973
+ { keyword: 'returns', meta: art.kind }, 'Unexpected $(KEYWORD) for $(META)');
963
974
  }
964
975
  }
965
976
 
@@ -21,7 +21,7 @@ const {
21
21
  } = require('./utils');
22
22
 
23
23
  const $location = Symbol.for('cds.$location');
24
-
24
+ const $inferred = Symbol.for('cds.$inferred');
25
25
 
26
26
  // Export function of this file.
27
27
  function tweakAssocs( model ) {
@@ -242,10 +242,7 @@ function tweakAssocs( model ) {
242
242
  }
243
243
 
244
244
  function inferredForeignKeys( foreignKeys, ignore ) {
245
- // TODO: better use a symbol $inferred for dictionaries later
246
- for (const name in foreignKeys)
247
- return foreignKeys[name].$inferred && foreignKeys[name].$inferred !== ignore;
248
- return false;
245
+ return foreignKeys[$inferred] && foreignKeys[$inferred] !== ignore;
249
246
  }
250
247
 
251
248
  function rewriteKeys( elem, assoc ) {
@@ -255,7 +252,7 @@ function tweakAssocs( model ) {
255
252
  // 'Info','FK').toString())
256
253
  forEachInOrder( assoc, 'foreignKeys', ( orig, name ) => {
257
254
  const fk = linkToOrigin( orig, name, elem, 'foreignKeys', elem.location );
258
- fk.$inferred = 'rewrite'; // TODO: other $inferred value?
255
+ fk.$inferred = 'rewrite'; // Override existing value; TODO: other $inferred value?
259
256
  // TODO: re-check for case that foreign key is managed association
260
257
  if ('_effectiveType' in orig)
261
258
  setLink( fk, '_effectiveType', orig._effectiveType);
@@ -268,6 +265,8 @@ function tweakAssocs( model ) {
268
265
  }
269
266
  fk.targetElement = te;
270
267
  });
268
+ if (elem.foreignKeys) // Possibly no fk was set
269
+ elem.foreignKeys[$inferred] = 'rewrite';
271
270
  }
272
271
 
273
272
  // TODO: there is no need to rewrite the on condition of non-leading queries,
@@ -413,6 +413,11 @@ function setExpandStatusAnnotate( elem, status ) {
413
413
  }
414
414
  }
415
415
 
416
+ function isDirectComposition( art ) {
417
+ const type = art.type && art.type.path;
418
+ return type && type[0] && type[0].id === 'cds.Composition';
419
+ }
420
+
416
421
  module.exports = {
417
422
  pushLink,
418
423
  annotationVal,
@@ -438,4 +443,5 @@ module.exports = {
438
443
  traverseQueryExtra,
439
444
  setExpandStatus,
440
445
  setExpandStatusAnnotate,
446
+ isDirectComposition,
441
447
  };