@sap/cds-compiler 2.4.4 → 2.10.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 (106) hide show
  1. package/CHANGELOG.md +241 -1
  2. package/bin/.eslintrc.json +17 -0
  3. package/bin/cds_update_identifiers.js +8 -7
  4. package/bin/cdsc.js +180 -132
  5. package/bin/cdshi.js +18 -11
  6. package/bin/cdsse.js +38 -32
  7. package/bin/cdsv2m.js +8 -7
  8. package/doc/CHANGELOG_BETA.md +36 -1
  9. package/lib/api/main.js +81 -100
  10. package/lib/api/options.js +17 -11
  11. package/lib/api/validate.js +12 -8
  12. package/lib/backends.js +0 -81
  13. package/lib/base/keywords.js +32 -2
  14. package/lib/base/location.js +2 -2
  15. package/lib/base/message-registry.js +66 -4
  16. package/lib/base/messages.js +84 -27
  17. package/lib/base/model.js +2 -61
  18. package/lib/checks/arrayOfs.js +0 -1
  19. package/lib/checks/defaultValues.js +27 -2
  20. package/lib/checks/elements.js +1 -6
  21. package/lib/checks/enricher.js +8 -2
  22. package/lib/checks/foreignKeys.js +0 -6
  23. package/lib/checks/managedWithoutKeys.js +17 -0
  24. package/lib/checks/nonexpandableStructured.js +38 -0
  25. package/lib/checks/onConditions.js +9 -45
  26. package/lib/checks/queryNoDbArtifacts.js +27 -9
  27. package/lib/checks/selectItems.js +25 -2
  28. package/lib/checks/types.js +26 -2
  29. package/lib/checks/unknownMagic.js +38 -0
  30. package/lib/checks/utils.js +61 -0
  31. package/lib/checks/validator.js +66 -13
  32. package/lib/compiler/assert-consistency.js +24 -12
  33. package/lib/compiler/builtins.js +2 -0
  34. package/lib/compiler/checks.js +6 -4
  35. package/lib/compiler/definer.js +101 -39
  36. package/lib/compiler/index.js +88 -59
  37. package/lib/compiler/resolver.js +455 -209
  38. package/lib/compiler/shared.js +57 -33
  39. package/lib/edm/annotations/genericTranslation.js +183 -187
  40. package/lib/edm/csn2edm.js +128 -99
  41. package/lib/edm/edm.js +18 -21
  42. package/lib/edm/edmPreprocessor.js +361 -127
  43. package/lib/edm/edmUtils.js +103 -33
  44. package/lib/gen/Dictionary.json +74 -28
  45. package/lib/gen/language.checksum +1 -1
  46. package/lib/gen/language.interp +18 -4
  47. package/lib/gen/language.tokens +124 -118
  48. package/lib/gen/languageLexer.interp +13 -1
  49. package/lib/gen/languageLexer.js +870 -839
  50. package/lib/gen/languageLexer.tokens +116 -111
  51. package/lib/gen/languageParser.js +5894 -5614
  52. package/lib/json/from-csn.js +152 -67
  53. package/lib/json/to-csn.js +334 -135
  54. package/lib/language/antlrParser.js +4 -3
  55. package/lib/language/errorStrategy.js +1 -0
  56. package/lib/language/genericAntlrParser.js +24 -14
  57. package/lib/language/language.g4 +188 -128
  58. package/lib/main.d.ts +435 -0
  59. package/lib/main.js +31 -7
  60. package/lib/model/api.js +78 -0
  61. package/lib/model/csnRefs.js +463 -187
  62. package/lib/model/csnUtils.js +280 -136
  63. package/lib/model/enrichCsn.js +75 -4
  64. package/lib/model/revealInternalProperties.js +2 -1
  65. package/lib/modelCompare/compare.js +70 -25
  66. package/lib/optionProcessor.js +13 -10
  67. package/lib/render/.eslintrc.json +4 -1
  68. package/lib/render/DuplicateChecker.js +8 -5
  69. package/lib/render/toCdl.js +123 -40
  70. package/lib/render/toHdbcds.js +156 -65
  71. package/lib/render/toSql.js +87 -11
  72. package/lib/render/utils/common.js +55 -9
  73. package/lib/render/utils/sql.js +3 -3
  74. package/lib/sql-identifier.js +6 -1
  75. package/lib/transform/{sql → db}/.eslintrc.json +0 -0
  76. package/lib/transform/{sql → db}/assertUnique.js +7 -8
  77. package/lib/transform/{sql → db}/constraints.js +35 -20
  78. package/lib/transform/db/draft.js +353 -0
  79. package/lib/transform/db/expansion.js +582 -0
  80. package/lib/transform/db/flattening.js +325 -0
  81. package/lib/transform/{sql → db}/groupByOrderBy.js +8 -16
  82. package/lib/transform/{sql → db}/helpers.js +0 -0
  83. package/lib/transform/{sql → db}/transformExists.js +256 -60
  84. package/lib/transform/forHanaNew.js +216 -765
  85. package/lib/transform/forOdataNew.js +60 -56
  86. package/lib/transform/localized.js +48 -26
  87. package/lib/transform/odata/attachPath.js +19 -4
  88. package/lib/transform/odata/expandStructKeysInAssociations.js +2 -2
  89. package/lib/transform/odata/generateForeignKeyElements.js +13 -12
  90. package/lib/transform/odata/referenceFlattener.js +60 -36
  91. package/lib/transform/odata/sortByAssociationDependency.js +4 -4
  92. package/lib/transform/odata/structuralPath.js +76 -0
  93. package/lib/transform/odata/structureFlattener.js +21 -22
  94. package/lib/transform/odata/toFinalBaseType.js +5 -5
  95. package/lib/transform/odata/typesExposure.js +27 -17
  96. package/lib/transform/odata/utils.js +2 -2
  97. package/lib/transform/transformUtilsNew.js +141 -77
  98. package/lib/transform/translateAssocsToJoins.js +17 -14
  99. package/lib/transform/universalCsnEnricher.js +67 -0
  100. package/lib/utils/file.js +0 -11
  101. package/lib/utils/moduleResolve.js +6 -8
  102. package/lib/utils/timetrace.js +6 -1
  103. package/package.json +2 -1
  104. package/lib/base/deepCopy.js +0 -66
  105. package/lib/json/walker.js +0 -26
  106. package/lib/utils/string.js +0 -17
@@ -3,7 +3,7 @@
3
3
 
4
4
  'use strict';
5
5
 
6
- const { searchName, makeMessageFunction } = require('../base/messages');
6
+ const { searchName } = require('../base/messages');
7
7
  const { dictAdd, dictAddArray, pushToDict } = require('../base/dictionaries');
8
8
  const { setProp } = require('../base/model');
9
9
 
@@ -60,7 +60,7 @@ const kindProperties = {
60
60
 
61
61
  function propExists( prop, parent ) {
62
62
  const obj = parent.returns || parent;
63
- return (obj.items || obj)[prop];
63
+ return (obj.items || obj.targetAspect || obj)[prop];
64
64
  }
65
65
 
66
66
  function artifactsEnv( art ) {
@@ -83,7 +83,7 @@ function fns( model, environment = artifactsEnv ) {
83
83
  const options = model.options || {};
84
84
  const {
85
85
  info, warning, error, message,
86
- } = makeMessageFunction( model, model.options, 'compile' );
86
+ } = model.$messageFunctions;
87
87
  // TODO: combine envFn and assoc ?
88
88
  const specExpected = {
89
89
  global: { // for using declaration
@@ -284,6 +284,16 @@ function fns( model, environment = artifactsEnv ) {
284
284
  return art.name.absolute;
285
285
  }
286
286
 
287
+ function userQuery( user ) {
288
+ // TODO: we need _query links set by the definer
289
+ while (user._main) {
290
+ if (user.kind === 'select' || user.kind === '$join')
291
+ return user;
292
+ user = user._parent;
293
+ }
294
+ return null;
295
+ }
296
+
287
297
  // Return artifact or element referred by the path in `ref`. The first
288
298
  // environment we search in is `env`. If no such artifact or element exist,
289
299
  // complain with message and return `undefined`. Record a dependency from
@@ -325,12 +335,8 @@ function fns( model, environment = artifactsEnv ) {
325
335
  }
326
336
  else if (spec.next) { // TODO: combine spec.next / spec.lexical to spec.lexical
327
337
  // TODO: SIMPLIFY this function
328
- // eslint-disable-next-line no-nested-ternary
329
- const query = (spec.lexical === 'main')
330
- ? user._main // in path filter, just $magic (and $parameters)
331
- : (user.kind === 'select' || user.kind === '$join')
332
- ? user
333
- : user._parent && user._parent.kind === 'select' && user._parent;
338
+ const query = (spec.lexical === 'main') ? user._main : userQuery( user );
339
+ // in path filter, just $magic (and $parameters)
334
340
  env = (spec.lexical === 'from') ? query._parent : query || user._main || user;
335
341
  // queries: first tabaliases, then $magic - value refs: first $self, then $magic
336
342
  if (!extDict && !spec.noExt) {
@@ -350,7 +356,7 @@ function fns( model, environment = artifactsEnv ) {
350
356
  if (!art) {
351
357
  return setLink( ref, art );
352
358
  }
353
- else if (user._pathHead) {
359
+ else if (!spec.envFn && user._pathHead) {
354
360
  // eslint-disable-next-line no-empty
355
361
  }
356
362
  else if (art.kind === 'using') {
@@ -397,7 +403,7 @@ function fns( model, environment = artifactsEnv ) {
397
403
  ? ref.scope || Number.MAX_SAFE_INTEGER
398
404
  : spec.artItemsCount || 1;
399
405
  // console.log(expected, ref.path.map(a=>a.id),artItemsCount)
400
- art = getPathItem( path, spec, user, artItemsCount, user._pathHead && art);
406
+ art = getPathItem( path, spec, user, artItemsCount, !spec.envFn && user._pathHead && art);
401
407
  if (!art)
402
408
  return setLink( ref, art );
403
409
 
@@ -505,7 +511,8 @@ function fns( model, environment = artifactsEnv ) {
505
511
  // if the artifact does not exist. Return a "fresh" artifact for
506
512
  // non-existing external using references if `unchecked` is truthy.
507
513
  function getPathRoot( path, spec, user, env, extDict, msgArt ) {
508
- if (user._pathHead) { // TODO: not necessarily for explicit ON condition in expand
514
+ if (!spec.envFn && user._pathHead) {
515
+ // TODO: not necessarily for explicit ON condition in expand
509
516
  environment( user._pathHead ); // make sure _origin is set
510
517
  return user._pathHead._origin;
511
518
  }
@@ -650,13 +657,28 @@ function fns( model, environment = artifactsEnv ) {
650
657
  return false;
651
658
  continue;
652
659
  }
653
- if (art && art.$uncheckedElements) {
654
- // do not check any elements of the path, e.g. $session
655
- return art;
656
- }
660
+
657
661
  const fn = (spec.envFn && artItemsCount >= 0) ? spec.envFn : environment;
658
662
  const env = fn( art, item.location, user, spec.assoc );
663
+
664
+ // do not check any elements of the path, e.g. $session - but still don't return path-head
665
+ if (art && art.$uncheckedElements) {
666
+ if (env && env[item.id]) // something like $user.id/$user.locale
667
+ return env[item.id];
668
+
669
+ // $user.foo - build our own valid path step obj
670
+ // Important: Don't directly modify item!
671
+ const obj = {
672
+ location: item.location,
673
+ kind: 'builtin',
674
+ name: { id: item.id, element: path.map(p => p.id).join('.') },
675
+ };
676
+ setLink(obj, art, '_parent');
677
+ return obj;
678
+ }
679
+
659
680
  const sub = setLink( item, env && env[item.id] );
681
+
660
682
  if (!sub)
661
683
  return (sub === 0) ? 0 : errorNotFound( item, env );
662
684
  else if (Array.isArray(sub)) // redefinitions
@@ -805,7 +827,7 @@ function fns( model, environment = artifactsEnv ) {
805
827
  // * do something for extensions by CSN or Properties parsers
806
828
  // * make sure that we do not issue repeated warnings due to flattening if an
807
829
  // annotation definition is missing
808
- function defineAnnotations( construct, art, block, priority ) {
830
+ function defineAnnotations( construct, art, block, priority = 'define' ) {
809
831
  if (!options.parseCdl && construct.kind === 'annotate') {
810
832
  // Namespaces cannot be annotated in CSN but because they exist as XSN artifacts
811
833
  // they can still be applied. Namespace annotations are extracted in to-csn.js
@@ -826,11 +848,10 @@ function fns( model, environment = artifactsEnv ) {
826
848
  // TODO: block should be construct._block
827
849
  if (construct.$annotations && construct.$annotations.doc )
828
850
  art.doc = construct.$annotations.doc;
829
- if (!construct.$annotations || !construct.$annotations.length) {
830
- if (construct === art)
831
- return;
832
- // $annotations is set if parsed from CDL but may not be set if
833
- // the input is CSN so we extract them.
851
+ if (!construct.$annotations) {
852
+ if (!block || block.$frontend !== 'json')
853
+ return; // namespace, or in CDL source without @annos:
854
+ // CSN input: set _block and $priority, shallow-copy from extension
834
855
  for (const annoProp in construct) {
835
856
  if (annoProp.charAt(0) === '@') {
836
857
  let annos = construct[annoProp];
@@ -838,7 +859,9 @@ function fns( model, environment = artifactsEnv ) {
838
859
  annos = [ annos ];
839
860
  for (const a of annos) {
840
861
  setProp( a, '_block', block );
841
- setAnnotation(art, annoProp, a, priority);
862
+ a.$priority = priority;
863
+ if (construct !== art)
864
+ dictAddArray( art, annoProp, a );
842
865
  }
843
866
  }
844
867
  }
@@ -888,14 +911,10 @@ function fns( model, environment = artifactsEnv ) {
888
911
  setProp( anno, '_block', block );
889
912
  // TODO: _parent, _main is set later (if we have ElementRef), or do we
890
913
  // set _artifact?
891
- setAnnotation( art, annoProp, anno, priority );
914
+ anno.$priority = priority;
915
+ dictAddArray( art, annoProp, anno );
892
916
  }
893
917
  }
894
-
895
- function setAnnotation( art, annoProp, anno, priority = 'define') {
896
- anno.$priority = priority;
897
- dictAddArray( art, annoProp, anno );
898
- }
899
918
  }
900
919
 
901
920
  // Return string 'A.B.C' for parsed source `A.B.C` (is vector of ids with
@@ -937,10 +956,11 @@ function linkToOrigin( origin, name, parent, prop, location, silentDep ) {
937
956
 
938
957
  function setMemberParent( elem, name, parent, prop ) {
939
958
  if (prop) { // extension or structure include
940
- // TODO: consider ARRAY OF and RETURNS, COMPOSITION OF type
941
- if (!(prop in parent))
942
- parent[prop] = Object.create(null);
943
- dictAdd( parent[prop], name, elem );
959
+ // TODO: consider nested ARRAY OF and RETURNS, COMPOSITION OF type
960
+ const p = parent.items || parent.targetAspect || parent;
961
+ if (!(prop in p))
962
+ p[prop] = Object.create(null);
963
+ dictAdd( p[prop], name, elem );
944
964
  }
945
965
  if (parent._outer)
946
966
  parent = parent._outer;
@@ -996,6 +1016,10 @@ function storeExtension( elem, name, prop, parent, block ) {
996
1016
  const kind = `_${ elem.kind }`; // _extend or _annotate
997
1017
  if (!parent[kind])
998
1018
  setProp( parent, kind, {} );
1019
+ // if (name === '' && prop === 'params') {
1020
+ // pushToDict( parent[kind], 'returns', elem ); // not really a dict
1021
+ // return;
1022
+ // }
999
1023
  if (!parent[kind][prop])
1000
1024
  parent[kind][prop] = Object.create(null);
1001
1025
  pushToDict( parent[kind][prop], name, elem );