@sap/cds-compiler 4.4.4 → 4.5.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 (59) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/bin/cdsc.js +5 -0
  3. package/bin/cdsv2m.js +7 -5
  4. package/doc/CHANGELOG_BETA.md +16 -0
  5. package/lib/api/main.js +68 -47
  6. package/lib/api/options.js +10 -6
  7. package/lib/api/validate.js +1 -1
  8. package/lib/base/message-registry.js +28 -6
  9. package/lib/base/messages.js +18 -13
  10. package/lib/base/model.js +3 -0
  11. package/lib/checks/annotationsOData.js +49 -0
  12. package/lib/checks/validator.js +6 -4
  13. package/lib/compiler/assert-consistency.js +38 -16
  14. package/lib/compiler/builtins.js +10 -49
  15. package/lib/compiler/checks.js +16 -8
  16. package/lib/compiler/cycle-detector.js +1 -4
  17. package/lib/compiler/define.js +4 -1
  18. package/lib/compiler/extend.js +21 -7
  19. package/lib/compiler/generate.js +3 -0
  20. package/lib/compiler/populate.js +5 -1
  21. package/lib/compiler/propagator.js +46 -9
  22. package/lib/compiler/resolve.js +68 -14
  23. package/lib/compiler/shared.js +44 -27
  24. package/lib/compiler/tweak-assocs.js +158 -37
  25. package/lib/compiler/utils.js +9 -0
  26. package/lib/edm/annotations/edmJson.js +35 -61
  27. package/lib/edm/annotations/genericTranslation.js +13 -5
  28. package/lib/edm/annotations/preprocessAnnotations.js +2 -3
  29. package/lib/edm/csn2edm.js +4 -1
  30. package/lib/edm/edmInboundChecks.js +59 -15
  31. package/lib/edm/edmPreprocessor.js +1 -7
  32. package/lib/gen/Dictionary.json +8 -0
  33. package/lib/gen/language.checksum +1 -1
  34. package/lib/gen/language.interp +12 -2
  35. package/lib/gen/languageParser.js +6095 -5195
  36. package/lib/json/from-csn.js +4 -5
  37. package/lib/json/to-csn.js +22 -3
  38. package/lib/language/errorStrategy.js +7 -3
  39. package/lib/language/genericAntlrParser.js +120 -24
  40. package/lib/language/textUtils.js +16 -0
  41. package/lib/model/csnUtils.js +9 -8
  42. package/lib/model/revealInternalProperties.js +5 -2
  43. package/lib/optionProcessor.js +2 -3
  44. package/lib/render/toCdl.js +31 -13
  45. package/lib/render/toHdbcds.js +20 -30
  46. package/lib/render/toSql.js +33 -54
  47. package/lib/render/utils/common.js +24 -6
  48. package/lib/transform/db/applyTransformations.js +59 -2
  49. package/lib/transform/db/backlinks.js +13 -1
  50. package/lib/transform/db/expansion.js +24 -3
  51. package/lib/transform/db/flattening.js +2 -2
  52. package/lib/transform/db/killAnnotations.js +37 -0
  53. package/lib/transform/db/rewriteCalculatedElements.js +46 -6
  54. package/lib/transform/forOdata.js +13 -46
  55. package/lib/transform/forRelationalDB.js +2 -1
  56. package/lib/transform/translateAssocsToJoins.js +13 -4
  57. package/lib/transform/universalCsn/coreComputed.js +1 -1
  58. package/lib/transform/universalCsn/universalCsnEnricher.js +4 -4
  59. package/package.json +7 -6
@@ -477,7 +477,10 @@ function csn2edmAll( _csn, _options, serviceNames = undefined ) {
477
477
  const type = `${schema.name}.${EntityTypeName}`;
478
478
  if (properties.length === 0)
479
479
  warning(null, location, { type }, 'EDM EntityType $(TYPE) has no properties');
480
- else if (entityCsn.$edmKeyPaths.length === 0 && !isSingleton)
480
+ // only if this entity has an entity set, it is required to have a key
481
+ // this especially covers: 'items: composition of one { data : String; }'
482
+ // "keyless" composition targets in structured containment mode
483
+ else if (entityCsn.$hasEntitySet && entityCsn.$edmKeyPaths.length === 0 && !isSingleton)
481
484
  message('odata-spec-violation-no-key', location);
482
485
 
483
486
  if (!edmUtils.isODataSimpleIdentifier(EntityTypeName))
@@ -2,8 +2,9 @@
2
2
 
3
3
  const { setProp, isBetaEnabled } = require('../base/model');
4
4
  const {
5
- forEachDefinition, forEachMemberRecursively,
5
+ forEachDefinition, forEachMemberRecursively, isBuiltinType, getUtils,
6
6
  } = require('../model/csnUtils');
7
+ const { assignAnnotation } = require('./edmUtils.js');
7
8
 
8
9
  // eslint-disable-next-line no-unused-vars
9
10
  function resolveForeignKeyRefs( csn, csnUtils ) {
@@ -22,9 +23,11 @@ function resolveForeignKeyRefs( csn, csnUtils ) {
22
23
 
23
24
  function inboundQualificationChecks( csn, options, messageFunctions,
24
25
  serviceRootNames, requestedServiceNames, isMyServiceRequested, whatsMyServiceRootName, csnUtils ) {
25
- const { message, throwWithError } = messageFunctions;
26
+ const { message, warning, throwWithError } = messageFunctions;
26
27
 
27
- forEachDefinition(csn, [ attach$path, checkProperArrayUsage ]);
28
+ const { getFinalTypeInfo } = getUtils(csn);
29
+
30
+ forEachDefinition(csn, [ attach$path, onServiceMember ]);
28
31
  checkNestedContextsAndServices();
29
32
  throwWithError();
30
33
 
@@ -37,27 +40,68 @@ function inboundQualificationChecks( csn, options, messageFunctions,
37
40
  }, [ 'definitions', defName ]);
38
41
  }
39
42
 
40
- function checkProperArrayUsage( def, defName ) {
43
+ // code that should be run only on service members
44
+ function onServiceMember( def, defName ) {
41
45
  if (!isMyServiceRequested(defName))
42
46
  return;
43
- const currPath = [ 'definitions', defName ];
44
- checkIfItemsOfItems(def, undefined, undefined, currPath);
45
- forEachMemberRecursively(def, checkIfItemsOfItems, currPath);
46
-
47
- function checkIfItemsOfItems( construct, _constructName, _prop, path ) {
48
- const constructType = csnUtils.effectiveType(construct);
49
- if (constructType.items) {
50
- if (constructType.items.target) {
51
- const isComp = constructType.items.type === 'cds.Composition';
47
+
48
+ const location = [ 'definitions', defName ];
49
+ // check items.items
50
+ checkIfItemsOfItems(def, undefined, undefined, location);
51
+ forEachMemberRecursively(def, checkIfItemsOfItems, location);
52
+
53
+ // decorate UUID keys with @Core.ComputedDefaultValue and complain
54
+ // on named type UUID elements that have no such annotation
55
+ const anno = '@Core.ComputedDefaultValue';
56
+ if (def.kind === 'entity' && def.elements) {
57
+ Object.entries(def.elements).forEach(([ eltName, elt ]) => {
58
+ if (elt.key)
59
+ addCoreComputedDefaultValueOnUUIDKeys(elt, [ eltName ], location);
60
+ });
61
+ }
62
+
63
+ function addCoreComputedDefaultValueOnUUIDKeys( elt, eltPath, path ) {
64
+ let type = elt.items?.type || elt.type;
65
+ if (type && !isBuiltinType(type)) {
66
+ type = getFinalTypeInfo(type);
67
+ if (!isBuiltinType(type.type))
68
+ path = [ 'definitions', type.type ];
69
+ }
70
+ else {
71
+ type = elt;
72
+ }
73
+
74
+ if (type.type === 'cds.UUID') {
75
+ if (path[1] === defName)
76
+ assignAnnotation(elt, anno, true);
77
+
78
+ else if (elt[anno] == null)
79
+ warning('odata-key-uuid-default-anno', path, { type: type.type, anno, id: `${defName}:${eltPath.join('.')}` });
80
+ }
81
+ else {
82
+ const elements = type.items?.elements || type.elements;
83
+ if (elements) {
84
+ Object.entries(elements).forEach(([ eltName, subelt ]) => {
85
+ addCoreComputedDefaultValueOnUUIDKeys(subelt, [ ...eltPath, eltName ], [ ...path, 'elements', eltName ]);
86
+ });
87
+ }
88
+ }
89
+ }
90
+
91
+ function checkIfItemsOfItems( member, _memberName, _prop, path ) {
92
+ const memberType = csnUtils.effectiveType(member);
93
+ if (memberType.items) {
94
+ if (memberType.items.target) {
95
+ const isComp = memberType.items.type === 'cds.Composition';
52
96
  message('type-invalid-items', path, { '#': isComp ? 'comp' : 'assoc', prop: 'items' });
53
97
  return;
54
98
  }
55
- if (constructType.items.items) {
99
+ if (memberType.items.items) {
56
100
  message('chained-array-of', path);
57
101
  return;
58
102
  }
59
103
 
60
- const itemsType = csnUtils.effectiveType(constructType.items);
104
+ const itemsType = csnUtils.effectiveType(memberType.items);
61
105
  if (itemsType.items)
62
106
  message('chained-array-of', path);
63
107
  }
@@ -168,7 +168,6 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
168
168
  initEdmNavPropBindingTargets,
169
169
  pullupCapabilitiesAnnotations,
170
170
  annotateOptionalActFuncParams,
171
- openService,
172
171
  ]);
173
172
  }
174
173
 
@@ -2125,7 +2124,7 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
2125
2124
  optPns.forEach((op) => {
2126
2125
  const type = op.items?.type || op.type;
2127
2126
  if (type !== special$self)
2128
- warning('odata-parameter-order', location.concat(op.name));
2127
+ error('odata-parameter-order', location.concat(op.name));
2129
2128
  });
2130
2129
  optPns = [];
2131
2130
  }
@@ -2134,11 +2133,6 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
2134
2133
  }
2135
2134
  }
2136
2135
 
2137
- function openService( def ) {
2138
- if (options.odataOpenType && !def.$isParamEntity && !def.$proxy)
2139
- edmUtils.assignAnnotation(def, '@open', true);
2140
- }
2141
-
2142
2136
  // ////////////////////////////////////////////////////////////////////
2143
2137
  //
2144
2138
  // Helper section starts here
@@ -801,6 +801,13 @@
801
801
  "Parameter"
802
802
  ]
803
803
  },
804
+ "Common.ValueListShowValuesImmediately": {
805
+ "Type": "Core.Tag",
806
+ "AppliesTo": [
807
+ "Annotation"
808
+ ],
809
+ "$experimental": true
810
+ },
804
811
  "Common.ValueListForValidation": {
805
812
  "Type": "Edm.String",
806
813
  "AppliesTo": [
@@ -2956,6 +2963,7 @@
2956
2963
  "Common.IntervalType": {
2957
2964
  "$kind": "ComplexType",
2958
2965
  "Properties": {
2966
+ "Label": "Edm.String",
2959
2967
  "LowerBoundary": "Edm.PropertyPath",
2960
2968
  "LowerBoundaryIncluded": "Edm.Boolean",
2961
2969
  "UpperBoundary": "Edm.PropertyPath",
@@ -1 +1 @@
1
- 582fa96ad61075beb0b9f9f8c46f11f3
1
+ 942cce045e6fb6ecaf7cbf3039001aa9