@sap/cds-compiler 2.11.2 → 2.13.6

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 (140) hide show
  1. package/CHANGELOG.md +175 -2
  2. package/bin/.eslintrc.json +1 -2
  3. package/bin/cds_update_identifiers.js +10 -8
  4. package/bin/cdsc.js +23 -17
  5. package/bin/cdsse.js +2 -2
  6. package/bin/cdsv2m.js +3 -2
  7. package/doc/CHANGELOG_ARCHIVE.md +1 -1
  8. package/doc/CHANGELOG_BETA.md +25 -6
  9. package/doc/CHANGELOG_DEPRECATED.md +22 -6
  10. package/doc/NameResolution.md +21 -16
  11. package/lib/api/main.js +32 -79
  12. package/lib/api/options.js +3 -2
  13. package/lib/api/validate.js +2 -1
  14. package/lib/backends.js +16 -26
  15. package/lib/base/dictionaries.js +0 -8
  16. package/lib/base/error.js +26 -0
  17. package/lib/base/keywords.js +10 -19
  18. package/lib/base/location.js +9 -4
  19. package/lib/base/message-registry.js +75 -9
  20. package/lib/base/messages.js +31 -35
  21. package/lib/base/model.js +2 -62
  22. package/lib/base/optionProcessorHelper.js +246 -183
  23. package/lib/checks/.eslintrc.json +2 -0
  24. package/lib/checks/actionsFunctions.js +2 -1
  25. package/lib/checks/annotationsOData.js +1 -1
  26. package/lib/checks/cdsPersistence.js +2 -1
  27. package/lib/checks/emptyOrOnlyVirtual.js +2 -2
  28. package/lib/checks/enricher.js +17 -1
  29. package/lib/checks/foreignKeys.js +4 -4
  30. package/lib/checks/invalidTarget.js +3 -1
  31. package/lib/checks/managedInType.js +4 -4
  32. package/lib/checks/managedWithoutKeys.js +3 -1
  33. package/lib/checks/queryNoDbArtifacts.js +1 -3
  34. package/lib/checks/selectItems.js +4 -4
  35. package/lib/checks/sql-snippets.js +94 -0
  36. package/lib/checks/types.js +1 -1
  37. package/lib/checks/unknownMagic.js +1 -1
  38. package/lib/checks/validator.js +12 -7
  39. package/lib/compiler/assert-consistency.js +12 -8
  40. package/lib/compiler/base.js +0 -1
  41. package/lib/compiler/builtins.js +42 -21
  42. package/lib/compiler/checks.js +46 -12
  43. package/lib/compiler/cycle-detector.js +1 -1
  44. package/lib/compiler/define.js +1103 -0
  45. package/lib/compiler/extend.js +983 -0
  46. package/lib/compiler/finalize-parse-cdl.js +231 -0
  47. package/lib/compiler/index.js +46 -39
  48. package/lib/compiler/kick-start.js +190 -0
  49. package/lib/compiler/moduleLayers.js +4 -4
  50. package/lib/compiler/populate.js +1226 -0
  51. package/lib/compiler/propagator.js +113 -47
  52. package/lib/compiler/resolve.js +1433 -0
  53. package/lib/compiler/shared.js +100 -65
  54. package/lib/compiler/tweak-assocs.js +529 -0
  55. package/lib/compiler/utils.js +215 -33
  56. package/lib/edm/.eslintrc.json +5 -0
  57. package/lib/edm/annotations/genericTranslation.js +38 -25
  58. package/lib/edm/annotations/preprocessAnnotations.js +3 -3
  59. package/lib/edm/csn2edm.js +10 -9
  60. package/lib/edm/edm.js +19 -20
  61. package/lib/edm/edmPreprocessor.js +166 -95
  62. package/lib/edm/edmUtils.js +127 -34
  63. package/lib/gen/Dictionary.json +92 -43
  64. package/lib/gen/language.checksum +1 -1
  65. package/lib/gen/language.interp +11 -1
  66. package/lib/gen/language.tokens +86 -82
  67. package/lib/gen/languageLexer.interp +18 -1
  68. package/lib/gen/languageLexer.js +925 -847
  69. package/lib/gen/languageLexer.tokens +78 -74
  70. package/lib/gen/languageParser.js +5434 -4298
  71. package/lib/json/from-csn.js +59 -17
  72. package/lib/json/to-csn.js +189 -71
  73. package/lib/language/antlrParser.js +3 -3
  74. package/lib/language/docCommentParser.js +3 -3
  75. package/lib/language/errorStrategy.js +26 -8
  76. package/lib/language/genericAntlrParser.js +144 -53
  77. package/lib/language/language.g4 +424 -200
  78. package/lib/language/multiLineStringParser.js +536 -0
  79. package/lib/main.d.ts +550 -61
  80. package/lib/main.js +38 -11
  81. package/lib/model/api.js +3 -1
  82. package/lib/model/csnRefs.js +322 -198
  83. package/lib/model/csnUtils.js +226 -370
  84. package/lib/model/enrichCsn.js +124 -69
  85. package/lib/model/revealInternalProperties.js +29 -7
  86. package/lib/model/sortViews.js +10 -2
  87. package/lib/modelCompare/compare.js +17 -12
  88. package/lib/optionProcessor.js +8 -3
  89. package/lib/render/.eslintrc.json +1 -2
  90. package/lib/render/DuplicateChecker.js +1 -1
  91. package/lib/render/manageConstraints.js +36 -33
  92. package/lib/render/toCdl.js +174 -275
  93. package/lib/render/toHdbcds.js +203 -122
  94. package/lib/render/toRename.js +7 -10
  95. package/lib/render/toSql.js +161 -82
  96. package/lib/render/utils/common.js +22 -8
  97. package/lib/render/utils/sql.js +10 -7
  98. package/lib/render/utils/stringEscapes.js +111 -0
  99. package/lib/sql-identifier.js +1 -1
  100. package/lib/transform/.eslintrc.json +5 -0
  101. package/lib/transform/braceExpression.js +4 -2
  102. package/lib/transform/db/.eslintrc.json +2 -0
  103. package/lib/transform/db/applyTransformations.js +212 -0
  104. package/lib/transform/db/assertUnique.js +1 -1
  105. package/lib/transform/db/associations.js +187 -0
  106. package/lib/transform/db/cdsPersistence.js +150 -0
  107. package/lib/transform/db/constraints.js +61 -56
  108. package/lib/transform/db/expansion.js +50 -29
  109. package/lib/transform/db/flattening.js +556 -106
  110. package/lib/transform/db/groupByOrderBy.js +3 -1
  111. package/lib/transform/db/temporal.js +236 -0
  112. package/lib/transform/db/transformExists.js +103 -28
  113. package/lib/transform/db/views.js +92 -44
  114. package/lib/transform/draft/.eslintrc.json +38 -0
  115. package/lib/transform/{db/draft.js → draft/db.js} +9 -7
  116. package/lib/transform/draft/odata.js +227 -0
  117. package/lib/transform/forHanaNew.js +98 -783
  118. package/lib/transform/forOdataNew.js +22 -175
  119. package/lib/transform/localized.js +36 -32
  120. package/lib/transform/odata/generateForeignKeyElements.js +3 -3
  121. package/lib/transform/odata/referenceFlattener.js +95 -89
  122. package/lib/transform/odata/structureFlattener.js +1 -1
  123. package/lib/transform/odata/toFinalBaseType.js +86 -12
  124. package/lib/transform/odata/typesExposure.js +5 -5
  125. package/lib/transform/odata/utils.js +2 -2
  126. package/lib/transform/transformUtilsNew.js +47 -33
  127. package/lib/transform/translateAssocsToJoins.js +13 -30
  128. package/lib/transform/universalCsn/.eslintrc.json +36 -0
  129. package/lib/transform/universalCsn/coreComputed.js +170 -0
  130. package/lib/transform/universalCsn/universalCsnEnricher.js +715 -0
  131. package/lib/transform/universalCsn/utils.js +63 -0
  132. package/lib/utils/file.js +8 -3
  133. package/lib/utils/objectUtils.js +30 -0
  134. package/lib/utils/timetrace.js +8 -2
  135. package/package.json +1 -1
  136. package/share/messages/README.md +26 -0
  137. package/lib/compiler/definer.js +0 -2349
  138. package/lib/compiler/resolver.js +0 -2922
  139. package/lib/transform/db/helpers.js +0 -58
  140. package/lib/transform/universalCsnEnricher.js +0 -67
@@ -89,6 +89,8 @@
89
89
 
90
90
  const { dictAdd } = require('../base/dictionaries');
91
91
 
92
+ const $location = Symbol.for('cds.$location');
93
+
92
94
  let inExtensions = null;
93
95
 
94
96
  let vocabInDefinitions = null; // must be reset!
@@ -661,6 +663,9 @@ const schema = compileSchema( {
661
663
  ignore: true, type: ignore,
662
664
  },
663
665
  // TODO: should we keep $parens ?
666
+ $generated: {
667
+ type: string,
668
+ },
664
669
  $: { type: ignore, ignore: true }, // including $origin
665
670
  _: { type: ignore, ignore: true },
666
671
  } );
@@ -705,7 +710,7 @@ let csnFilename = '';
705
710
  let virtualLine = 1;
706
711
  /** @type {CSN.Location[]} */
707
712
  let dollarLocations = [];
708
- let arrayLvlCnt = 0;
713
+ let arrayLevelCount = 0;
709
714
 
710
715
  /**
711
716
  * @param {Object.<string, SchemaSpec>} specs
@@ -931,8 +936,10 @@ function definition( def, spec, xsn, csn, name ) {
931
936
  popLocation( def );
932
937
  if (kind !== 'annotation' || prop === 'vocabularies')
933
938
  return r;
934
- if (!vocabInDefinitions)
939
+ if (!vocabInDefinitions) {
935
940
  vocabInDefinitions = Object.create(null);
941
+ vocabInDefinitions[$location] = location();
942
+ }
936
943
  vocabInDefinitions[name] = r; // deprecated: anno def in 'definitions'
937
944
  return undefined;
938
945
 
@@ -957,6 +964,7 @@ function dictionaryOf( elementFct ) {
957
964
  return ignore( dict );
958
965
  }
959
966
  const r = Object.create(null);
967
+ r[$location] = location();
960
968
  const allNames = Object.keys( dict );
961
969
  if (!allNames.length)
962
970
  return r; // {} in one JSON line
@@ -980,6 +988,7 @@ function keys( array, spec, xsn ) {
980
988
  if (!isArray( array, spec ))
981
989
  return;
982
990
  const r = Object.create(null);
991
+ r[$location] = location();
983
992
  ++virtualLine;
984
993
  for (const def of array) {
985
994
  const id = def.as || implicitName( def.ref );
@@ -1164,6 +1173,12 @@ function symbol( id, spec, xsn ) { // for CSN property '#'
1164
1173
  xsn.sym = { id, location: location() };
1165
1174
  }
1166
1175
 
1176
+ // returns: false = no "...", true = "..." without UP TO, 'upTo' = "..." with UP TO
1177
+ function isEllipsis( val ) {
1178
+ return val && typeof val === 'object' && '...' in val && Object.keys(val).length === 1 &&
1179
+ (val['...'] === true || 'upTo');
1180
+ }
1181
+
1167
1182
  function annoValue( val, spec ) {
1168
1183
  if (val == null) // TODO: reject undefined
1169
1184
  return { val, literal: 'null', location: location() };
@@ -1171,22 +1186,40 @@ function annoValue( val, spec ) {
1171
1186
  if (lit !== 'object')
1172
1187
  return { val, literal: lit, location: location() };
1173
1188
  if (Array.isArray( val )) {
1174
- const ec = val.reduce((c, v) => ((v && v['...'] && Object.keys(v).length === 1) ? ++c : c), 0);
1175
- if (arrayLvlCnt === 0 && ec > 1) {
1176
- error( 'syntax-csn-duplicate-ellipsis', location(true), { code: '...' },
1177
- 'Expected no more than one $(CODE)' );
1189
+ /** @type {string|boolean} */
1190
+ let seenEllipsis = false;
1191
+ if (arrayLevelCount > 0) { // TODO: also inside structure (possible in CSN!)
1192
+ if (val.some( isEllipsis )) {
1193
+ error( 'syntax-csn-unexpected-ellipsis', location(true), { code: '...' },
1194
+ 'Unexpected $(CODE) in nested array' );
1195
+ }
1178
1196
  }
1179
- if (arrayLvlCnt > 0 && ec > 0) {
1180
- error( 'syntax-csn-unexpected-ellipsis', location(true), { code: '...' },
1181
- 'Unexpected $(CODE) in nested array' );
1197
+ else {
1198
+ for (const item of val) {
1199
+ if (seenEllipsis !== true) {
1200
+ seenEllipsis = isEllipsis( item ) || seenEllipsis;
1201
+ }
1202
+ else if (isEllipsis( item )) { // with or without UP TO
1203
+ // error position at the beginning of the array, but that is fine
1204
+ error( 'syntax-csn-duplicate-ellipsis', location(true), { code: '...' },
1205
+ 'Expected no more than one $(CODE)' );
1206
+ break;
1207
+ }
1208
+ }
1182
1209
  }
1183
- arrayLvlCnt++;
1210
+ arrayLevelCount++;
1184
1211
  const retval = {
1185
1212
  location: location(),
1186
1213
  val: arrayOf( annoValue )( val, spec ),
1187
1214
  literal: 'array',
1188
1215
  };
1189
- arrayLvlCnt--;
1216
+ arrayLevelCount--;
1217
+ if (seenEllipsis === 'upTo') {
1218
+ error( 'syntax-csn-expecting-ellipsis', location(true), // at closing bracket
1219
+ { code: '... up to', newcode: '...' },
1220
+ // TODO: should we be more CSN specific in the message?
1221
+ 'Expecting an array item $(NEWCODE) after an item with $(CODE)' );
1222
+ }
1190
1223
  return retval;
1191
1224
  }
1192
1225
  if (typeof val['#'] === 'string') {
@@ -1205,12 +1238,19 @@ function annoValue( val, spec ) {
1205
1238
  return refSplit( val['='], '=' );
1206
1239
  }
1207
1240
  }
1208
- else if (val['...'] && Object.keys(val).length === 1) {
1209
- return {
1241
+ else if (val['...'] && Object.keys( val ).length === 1) {
1242
+ // TODO: only if not nested - see error above
1243
+ ++virtualLine;
1244
+ const ell = val['...'];
1245
+ const r = {
1210
1246
  val: '...',
1211
1247
  literal: 'token',
1212
1248
  location: location(),
1213
1249
  };
1250
+ if (ell !== true)
1251
+ r.upTo = annoValue( ell, schema['@'] );
1252
+ ++virtualLine;
1253
+ return r;
1214
1254
  }
1215
1255
  const struct = Object.create(null);
1216
1256
  ++virtualLine;
@@ -1354,12 +1394,11 @@ function exprArgs( cond, spec, xsn, csn ) {
1354
1394
 
1355
1395
  function condition( cond, spec ) {
1356
1396
  const loc = location();
1357
- const x = {
1397
+ return {
1358
1398
  op: { val: 'xpr', location: loc },
1359
1399
  args: exprArgs( cond, spec ),
1360
1400
  location: loc,
1361
1401
  };
1362
- return x;
1363
1402
  }
1364
1403
 
1365
1404
  function vZeroValue( obj, spec, xsn ) {
@@ -1406,6 +1445,7 @@ function excluding( array, spec, xsn ) {
1406
1445
  if (!isArray( array, spec ))
1407
1446
  return;
1408
1447
  const r = Object.create(null);
1448
+ r[$location] = location();
1409
1449
  ++virtualLine;
1410
1450
  for (const ex of array) {
1411
1451
  const id = string( ex, spec ) || '';
@@ -1666,8 +1706,8 @@ function pushLocation( obj ) {
1666
1706
  error( 'syntax-csn-expected-object', location(true), { prop: '$location' } );
1667
1707
  }
1668
1708
  // hidden feature: string $location
1669
- const m = /:(\d+)(?::(\d+)(?:-[0-9-]+)?)?$/.exec( loc ); // extra - at end for .refloc
1670
- if (!m) {
1709
+ const m = /:(\d+)(?::(\d+))?$/.exec( loc ); // extra '^'s at end deliberately left out
1710
+ if (!m) { // without location or with '^'s: do not use
1671
1711
  dollarLocations.push( null );
1672
1712
  }
1673
1713
  else {
@@ -1710,8 +1750,10 @@ function toXsn( csn, filename, options, messageFunctions ) {
1710
1750
  csnFilename = filename;
1711
1751
  virtualLine = 1;
1712
1752
  dollarLocations = [];
1753
+ arrayLevelCount = 0;
1713
1754
  inExtensions = null;
1714
1755
  vocabInDefinitions = null;
1756
+
1715
1757
  const xsn = { $frontend: 'json' };
1716
1758
 
1717
1759
  // eslint-disable-next-line object-curly-newline