@sap/cds-compiler 2.12.0 → 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 (118) hide show
  1. package/CHANGELOG.md +110 -15
  2. package/bin/cdsc.js +13 -13
  3. package/bin/cdsse.js +2 -2
  4. package/doc/CHANGELOG_BETA.md +13 -6
  5. package/doc/CHANGELOG_DEPRECATED.md +22 -6
  6. package/doc/NameResolution.md +21 -16
  7. package/lib/api/main.js +28 -63
  8. package/lib/api/options.js +3 -3
  9. package/lib/api/validate.js +0 -5
  10. package/lib/backends.js +15 -23
  11. package/lib/base/dictionaries.js +0 -8
  12. package/lib/base/error.js +26 -0
  13. package/lib/base/keywords.js +7 -17
  14. package/lib/base/location.js +9 -4
  15. package/lib/base/message-registry.js +25 -4
  16. package/lib/base/messages.js +16 -26
  17. package/lib/base/model.js +2 -63
  18. package/lib/base/optionProcessorHelper.js +158 -123
  19. package/lib/checks/annotationsOData.js +1 -1
  20. package/lib/checks/cdsPersistence.js +2 -1
  21. package/lib/checks/enricher.js +17 -1
  22. package/lib/checks/invalidTarget.js +3 -1
  23. package/lib/checks/managedWithoutKeys.js +3 -1
  24. package/lib/checks/selectItems.js +4 -4
  25. package/lib/checks/sql-snippets.js +27 -26
  26. package/lib/checks/types.js +1 -1
  27. package/lib/checks/validator.js +4 -7
  28. package/lib/compiler/assert-consistency.js +5 -3
  29. package/lib/compiler/builtins.js +8 -6
  30. package/lib/compiler/checks.js +14 -3
  31. package/lib/compiler/cycle-detector.js +1 -1
  32. package/lib/compiler/define.js +1103 -0
  33. package/lib/compiler/extend.js +983 -0
  34. package/lib/compiler/finalize-parse-cdl.js +231 -0
  35. package/lib/compiler/index.js +32 -13
  36. package/lib/compiler/kick-start.js +190 -0
  37. package/lib/compiler/moduleLayers.js +4 -4
  38. package/lib/compiler/populate.js +1226 -0
  39. package/lib/compiler/propagator.js +111 -46
  40. package/lib/compiler/resolve.js +1433 -0
  41. package/lib/compiler/shared.js +64 -37
  42. package/lib/compiler/tweak-assocs.js +529 -0
  43. package/lib/compiler/utils.js +197 -33
  44. package/lib/edm/.eslintrc.json +5 -0
  45. package/lib/edm/annotations/genericTranslation.js +5 -9
  46. package/lib/edm/annotations/preprocessAnnotations.js +2 -2
  47. package/lib/edm/csn2edm.js +9 -8
  48. package/lib/edm/edm.js +11 -12
  49. package/lib/edm/edmPreprocessor.js +137 -73
  50. package/lib/edm/edmUtils.js +116 -22
  51. package/lib/gen/Dictionary.json +10 -3
  52. package/lib/gen/language.checksum +1 -1
  53. package/lib/gen/language.interp +9 -1
  54. package/lib/gen/language.tokens +86 -83
  55. package/lib/gen/languageLexer.interp +10 -1
  56. package/lib/gen/languageLexer.js +860 -833
  57. package/lib/gen/languageLexer.tokens +78 -75
  58. package/lib/gen/languageParser.js +5282 -4265
  59. package/lib/json/from-csn.js +12 -1
  60. package/lib/json/to-csn.js +126 -66
  61. package/lib/language/docCommentParser.js +2 -2
  62. package/lib/language/genericAntlrParser.js +76 -3
  63. package/lib/language/language.g4 +297 -130
  64. package/lib/language/multiLineStringParser.js +5 -5
  65. package/lib/main.d.ts +468 -59
  66. package/lib/main.js +35 -9
  67. package/lib/model/api.js +3 -1
  68. package/lib/model/csnRefs.js +225 -156
  69. package/lib/model/csnUtils.js +192 -223
  70. package/lib/model/enrichCsn.js +70 -29
  71. package/lib/model/revealInternalProperties.js +27 -6
  72. package/lib/model/sortViews.js +2 -1
  73. package/lib/modelCompare/compare.js +17 -12
  74. package/lib/optionProcessor.js +5 -4
  75. package/lib/render/manageConstraints.js +35 -32
  76. package/lib/render/toCdl.js +73 -288
  77. package/lib/render/toHdbcds.js +25 -23
  78. package/lib/render/toSql.js +98 -41
  79. package/lib/render/utils/common.js +5 -10
  80. package/lib/render/utils/sql.js +4 -3
  81. package/lib/render/utils/stringEscapes.js +111 -0
  82. package/lib/sql-identifier.js +1 -1
  83. package/lib/transform/.eslintrc.json +5 -0
  84. package/lib/transform/db/.eslintrc.json +2 -0
  85. package/lib/transform/db/applyTransformations.js +35 -12
  86. package/lib/transform/db/assertUnique.js +1 -1
  87. package/lib/transform/db/associations.js +103 -305
  88. package/lib/transform/db/cdsPersistence.js +2 -2
  89. package/lib/transform/db/constraints.js +55 -52
  90. package/lib/transform/db/expansion.js +46 -24
  91. package/lib/transform/db/flattening.js +553 -102
  92. package/lib/transform/db/groupByOrderBy.js +3 -1
  93. package/lib/transform/db/transformExists.js +59 -6
  94. package/lib/transform/db/views.js +5 -4
  95. package/lib/transform/draft/.eslintrc.json +38 -0
  96. package/lib/transform/{db/draft.js → draft/db.js} +6 -5
  97. package/lib/transform/draft/odata.js +227 -0
  98. package/lib/transform/forHanaNew.js +67 -183
  99. package/lib/transform/forOdataNew.js +17 -171
  100. package/lib/transform/localized.js +34 -19
  101. package/lib/transform/odata/generateForeignKeyElements.js +1 -1
  102. package/lib/transform/odata/referenceFlattener.js +95 -89
  103. package/lib/transform/odata/structureFlattener.js +1 -1
  104. package/lib/transform/odata/toFinalBaseType.js +86 -12
  105. package/lib/transform/odata/typesExposure.js +5 -5
  106. package/lib/transform/odata/utils.js +2 -2
  107. package/lib/transform/transformUtilsNew.js +36 -22
  108. package/lib/transform/translateAssocsToJoins.js +2 -19
  109. package/lib/transform/universalCsn/.eslintrc.json +36 -0
  110. package/lib/transform/universalCsn/coreComputed.js +170 -0
  111. package/lib/transform/universalCsn/universalCsnEnricher.js +715 -0
  112. package/lib/transform/universalCsn/utils.js +63 -0
  113. package/lib/utils/objectUtils.js +30 -0
  114. package/package.json +1 -1
  115. package/share/messages/README.md +26 -0
  116. package/lib/compiler/definer.js +0 -2361
  117. package/lib/compiler/resolver.js +0 -3079
  118. package/lib/transform/universalCsnEnricher.js +0 -237
@@ -5,9 +5,13 @@
5
5
 
6
6
  const { searchName } = require('../base/messages');
7
7
  const { dictAddArray } = require('../base/dictionaries');
8
- const { setProp } = require('../base/model');
9
8
 
10
- const { setLink, dependsOn, pathName } = require('./utils');
9
+ const {
10
+ setLink,
11
+ setArtifactLink,
12
+ dependsOn,
13
+ pathName,
14
+ } = require('./utils');
11
15
 
12
16
  function artifactsEnv( art ) {
13
17
  return art._subArtifacts || Object.create(null);
@@ -161,7 +165,7 @@ function fns( model ) {
161
165
  return;
162
166
 
163
167
  function checkConstRef( art ) {
164
- return ![ 'builtin', 'param' ].includes( art.kind );
168
+ return art.kind !== 'builtin' && art.kind !== 'param';
165
169
  }
166
170
 
167
171
  function checkIncludesRef( art ) {
@@ -265,9 +269,9 @@ function fns( model ) {
265
269
  return ref._artifact;
266
270
  if (!ref.path || ref.path.broken || !ref.path.length) {
267
271
  // incomplete type AST or empty env (already reported)
268
- return setLink( ref, undefined );
272
+ return setArtifactLink( ref, undefined );
269
273
  }
270
- setLink( ref, 0 ); // avoid cycles for type T: association to T.m;
274
+ setArtifactLink( ref, 0 ); // avoid cycles for type T: association to T.m;
271
275
 
272
276
  let spec = specExpected[expected];
273
277
  const { path } = ref;
@@ -280,7 +284,7 @@ function fns( model ) {
280
284
  if (!spec.escape) {
281
285
  error( 'ref-unexpected-scope', [ ref.location, user ], {},
282
286
  'Unexpected parameter reference' );
283
- return setLink( ref, null );
287
+ return setArtifactLink( ref, null );
284
288
  }
285
289
  spec = specExpected[spec.escape];
286
290
  // In queries and query entities, the first lexical search environment
@@ -298,7 +302,7 @@ function fns( model ) {
298
302
  const query = (spec.lexical === 'main') ? user._main : userQuery( user );
299
303
  // in path filter, just $magic (and $parameters)
300
304
  env = (spec.lexical === 'from') ? query._parent : query || user._main || user;
301
- // queries: first tabaliases, then $magic - value refs: first $self, then $magic
305
+ // queries: first table aliases, then $magic - value refs: first $self, then $magic
302
306
  if (!extDict && !spec.noExt) {
303
307
  // TODO: change to name restriction for $joins, not own environments
304
308
  extDict = query && spec.rootEnv !== 'elements' &&
@@ -314,18 +318,34 @@ function fns( model ) {
314
318
  ? getPathRoot( path, spec, user, {}, model[spec.global || 'definitions'] )
315
319
  : getPathRoot( path, spec, user, env, extDict, msgArt || 0 );
316
320
  if (!art) {
317
- return setLink( ref, art );
321
+ return setArtifactLink( ref, art );
318
322
  }
319
323
  else if (!spec.envFn && user._pathHead) {
320
324
  // eslint-disable-next-line no-empty
321
325
  }
322
326
  else if (art.kind === 'using') {
323
- art = model.definitions[art.name.absolute];
324
- if (!art)
325
- return setLink( ref, art );
326
- else if (art.$duplicates) // redefined art referenced by using proxy
327
- return setLink( ref, false );
328
- setLink( head, art ); // we do not want to see the using
327
+ const def = model.definitions[art.name.absolute];
328
+ if (!def) {
329
+ // It could be that the artifact was removed and that the using-proxy needs to be reported.
330
+ // The check for $inferred is required to avoid consequential errors for cases such as:
331
+ // using unknown.abc;
332
+ // entity P as projection on abc; // <-- no consequential error here
333
+ if (art.$inferred === 'path-prefix') {
334
+ // head._artifact referred to the `using`. Remove the reference,
335
+ // so that getPathItem() below emits an error.
336
+ setArtifactLink( head, false );
337
+ setArtifactLink( ref, false );
338
+ }
339
+ else {
340
+ return setArtifactLink( ref, false );
341
+ }
342
+ }
343
+ else if (def.$duplicates) { // redefined art referenced by using proxy
344
+ return setArtifactLink( ref, false );
345
+ }
346
+ else {
347
+ setArtifactLink( head, def ); // we do not want to see the using
348
+ }
329
349
  }
330
350
  else if (art.kind === 'mixin') {
331
351
  if (spec.noAliasOrMixin) {
@@ -333,14 +353,14 @@ function fns( model ) {
333
353
  signalNotFound( 'ref-rejected-on', [ head.location, user ], extDict && [ extDict ],
334
354
  { '#': 'mixin', id: head.id } );
335
355
  // also set link on head?
336
- return setLink( ref, false );
356
+ return setArtifactLink( ref, false );
337
357
  }
338
358
  // console.log(message( null, art.location, art, {}, 'Info','MIX').toString())
339
- setLink( head, art, '_navigation' );
359
+ setLink( head, '_navigation', art );
340
360
  }
341
361
  else if (art.kind === '$navElement') {
342
- setLink( head, art, '_navigation' );
343
- setLink( head, art._origin );
362
+ setLink( head, '_navigation', art );
363
+ setArtifactLink( head, art._origin );
344
364
  // TODO: set art?
345
365
  }
346
366
  else if (art.kind === '$tableAlias' || art.kind === '$self') {
@@ -349,13 +369,17 @@ function fns( model ) {
349
369
  signalNotFound( 'ref-rejected-on', [ head.location, user ], extDict && [ extDict ],
350
370
  { '#': 'alias', id: head.id } );
351
371
  // also set link on head?
352
- return setLink( ref, false );
372
+ return setArtifactLink( ref, false );
353
373
  }
354
- setLink( head, art, '_navigation' );
355
- setLink( head, art._origin ); // query source or leading query in FROM
374
+ setLink( head, '_navigation', art );
375
+ setArtifactLink( head, art._origin ); // query source or leading query in FROM
356
376
  // require('../model/revealInternalProperties').log(model, 'foo.bar.S.V1a')
357
377
  if (!art._origin)
358
- return setLink( ref, art._origin );
378
+ return setArtifactLink( ref, art._origin );
379
+ // if just table alias (with expand), mark `user` with `$noOrigin` to indicate
380
+ // that the corresponding entity should not be put as $origin into the CSN
381
+ if (path.length === 1 && user && art.kind === '$tableAlias')
382
+ user.$noOrigin = true;
359
383
  }
360
384
 
361
385
  // how many path items are for artifacts (rest: elements)
@@ -365,20 +389,20 @@ function fns( model ) {
365
389
  // console.log(expected, ref.path.map(a=>a.id),artItemsCount)
366
390
  art = getPathItem( path, spec, user, artItemsCount, !spec.envFn && user._pathHead && art);
367
391
  if (!art)
368
- return setLink( ref, art );
392
+ return setArtifactLink( ref, art );
369
393
 
370
394
  if (art.$autoElement) {
371
395
  const { location } = path[path.length - 1];
372
396
  const step = { id: art.$autoElement, $inferred: '$autoElement', location };
373
397
  art = art.elements[step.id];
374
- setLink( step, art );
398
+ setArtifactLink( step, art );
375
399
  path.push( step );
376
400
  }
377
401
  if (spec.check) {
378
402
  const fail = spec.check( art, path );
379
403
  if (fail === true) {
380
404
  signalNotFound( spec.expectedMsgId, [ ref.location, user ], null );
381
- return setLink( ref, false );
405
+ return setArtifactLink( ref, false );
382
406
  }
383
407
  else if (fail) {
384
408
  signalNotFound( spec.sloppyMsgId, [ ref.location, user ], null );
@@ -410,7 +434,7 @@ function fns( model ) {
410
434
  !(env.$frontend && env.$frontend !== 'cdl'))
411
435
  deprecateSmart( ref, art, user );
412
436
  // TODO: follow FROM here, see csnRef - fromRef
413
- return setLink( ref, art );
437
+ return setArtifactLink( ref, art );
414
438
  }
415
439
 
416
440
  // Issue errors for "smart" element-in-artifact references
@@ -475,6 +499,8 @@ function fns( model ) {
475
499
  // TODO: not necessarily for explicit ON condition in expand
476
500
  VolatileFns.environment( user._pathHead ); // make sure _origin is set
477
501
  return user._pathHead._origin;
502
+ // const { _origin } = user._pathHead;
503
+ // return (_origin && _origin.kind === '$tableAlias') ? _origin._origin : _origin;
478
504
  }
479
505
  const head = path[0];
480
506
  if (!head || !head.id || !env)
@@ -501,7 +527,7 @@ function fns( model ) {
501
527
  const r = e[head.id];
502
528
  if (r) {
503
529
  if (Array.isArray(r)) { // redefinitions
504
- setLink( head, r );
530
+ setArtifactLink( head, r );
505
531
  return false;
506
532
  }
507
533
  // if (head.$delimited && r.kind !== '$tableAlias' && r.kind !== 'mixin')
@@ -512,18 +538,18 @@ function fns( model ) {
512
538
  { code: `$parameters.${ path[1].id }`, newcode: `:${ path[1].id }` },
513
539
  'Obsolete $(CODE) - replace by $(NEWCODE)' );
514
540
  // TODO: replace it in to-csn correspondingly
515
- return setLink( head, r );
541
+ return setArtifactLink( head, r );
516
542
  }
517
543
  }
518
544
  else if (r.kind === '$self') {
519
545
  // TODO: handle $delimited differently
520
546
  // TODO: $projection only if not delimited _and_ length > 1
521
- return setLink( head, r );
547
+ return setArtifactLink( head, r );
522
548
  }
523
549
  else if (r.kind !== '$tableAlias' || path.length > 1 || user.expand || user.inline) {
524
550
  // except "real" table aliases (not $self) with path len 1
525
551
  // TODO: $projection only if not delimited _and_ length > 1
526
- return setLink( head, r );
552
+ return setArtifactLink( head, r );
527
553
  }
528
554
  }
529
555
  }
@@ -540,11 +566,11 @@ function fns( model ) {
540
566
  'Ambiguous $(ID), replace by $(NAMES)' );
541
567
  }
542
568
  }
543
- setLink( head, r );
569
+ setArtifactLink( head, r );
544
570
  return false;
545
571
  }
546
572
  else if (r) {
547
- return setLink( head, r );
573
+ return setArtifactLink( head, r );
548
574
  }
549
575
  }
550
576
  if (spec.noMessage || msgArt === true && extDict === model.definitions)
@@ -598,7 +624,7 @@ function fns( model ) {
598
624
  signalNotFound( spec.undefinedArt || 'ref-undefined-art', [ head.location, user ],
599
625
  valid, { name: head.id } );
600
626
  }
601
- return setLink( head, null );
627
+ return setArtifactLink( head, null );
602
628
  }
603
629
 
604
630
  // Return artifact or element referred by path (array of ids) `tail`. The
@@ -606,6 +632,7 @@ function fns( model ) {
606
632
  // missing artifacts (as opposed to elements), provide the `head` (first
607
633
  // element item in the path)
608
634
  function getPathItem( path, spec, user, artItemsCount, headArt ) {
635
+ // let art = (headArt && headArt.kind === '$tableAlias') ? headArt._origin : headArt;
609
636
  let art = headArt;
610
637
  let nav = spec.assoc !== '$keys' && null; // false for '$keys'
611
638
  const last = path[path.length - 1];
@@ -622,7 +649,7 @@ function fns( model ) {
622
649
 
623
650
  const fn = (spec.envFn && artItemsCount >= 0) ? spec.envFn : VolatileFns.environment;
624
651
  const env = fn( art, item.location, user, spec.assoc );
625
- const sub = setLink( item, env && env[item.id] );
652
+ const sub = setArtifactLink( item, env && env[item.id] );
626
653
 
627
654
  if (!sub) {
628
655
  // element was not found in environment
@@ -684,7 +711,7 @@ function fns( model ) {
684
711
  if (node._artifact) {
685
712
  // set the original(!) foreign key for the assoc - the "right" ones
686
713
  // after rewriteKeys() is the one with the same name.id
687
- setLink( item, node._artifact, '_navigation' );
714
+ setLink( item, '_navigation', node._artifact );
688
715
  if (item === last)
689
716
  return;
690
717
  }
@@ -817,7 +844,7 @@ function fns( model ) {
817
844
  if (!(Array.isArray(annos)))
818
845
  annos = [ annos ];
819
846
  for (const a of annos) {
820
- setProp( a, '_block', block );
847
+ setLink( a, '_block', block );
821
848
  a.$priority = priority;
822
849
  if (construct !== art)
823
850
  addAnnotation( art, annoProp, a );
@@ -867,7 +894,7 @@ function fns( model ) {
867
894
  value.name && value.name.location ||
868
895
  value.path && value.path.location,
869
896
  };
870
- setProp( anno, '_block', block );
897
+ setLink( anno, '_block', block );
871
898
  // TODO: _parent, _main is set later (if we have ElementRef), or do we
872
899
  // set _artifact?
873
900
  anno.$priority = priority;