@sap/cds-compiler 2.15.2 → 3.0.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 (111) hide show
  1. package/CHANGELOG.md +66 -1590
  2. package/bin/cdsc.js +42 -46
  3. package/doc/CHANGELOG_ARCHIVE.md +1592 -0
  4. package/doc/CHANGELOG_BETA.md +3 -4
  5. package/doc/CHANGELOG_DEPRECATED.md +35 -1
  6. package/doc/{DeprecatedOptions.md → DeprecatedOptions_v2.md} +3 -1
  7. package/doc/Versioning.md +20 -1
  8. package/lib/api/.eslintrc.json +2 -2
  9. package/lib/api/main.js +312 -143
  10. package/lib/api/options.js +15 -85
  11. package/lib/api/validate.js +6 -10
  12. package/lib/base/keywords.js +280 -110
  13. package/lib/base/message-registry.js +80 -24
  14. package/lib/base/messages.js +103 -52
  15. package/lib/base/model.js +44 -2
  16. package/lib/base/optionProcessorHelper.js +53 -21
  17. package/lib/checks/actionsFunctions.js +7 -5
  18. package/lib/checks/annotationsOData.js +1 -1
  19. package/lib/checks/cdsPersistence.js +1 -0
  20. package/lib/checks/elements.js +6 -6
  21. package/lib/checks/invalidTarget.js +1 -1
  22. package/lib/checks/nonexpandableStructured.js +1 -1
  23. package/lib/checks/queryNoDbArtifacts.js +2 -1
  24. package/lib/checks/selectItems.js +5 -1
  25. package/lib/checks/types.js +4 -2
  26. package/lib/checks/utils.js +2 -2
  27. package/lib/checks/validator.js +2 -1
  28. package/lib/compiler/assert-consistency.js +15 -10
  29. package/lib/compiler/builtins.js +127 -10
  30. package/lib/compiler/define.js +6 -4
  31. package/lib/compiler/extend.js +63 -12
  32. package/lib/compiler/finalize-parse-cdl.js +20 -9
  33. package/lib/compiler/index.js +25 -11
  34. package/lib/compiler/moduleLayers.js +7 -0
  35. package/lib/compiler/populate.js +16 -14
  36. package/lib/compiler/propagator.js +3 -3
  37. package/lib/compiler/resolve.js +194 -222
  38. package/lib/compiler/shared.js +56 -76
  39. package/lib/compiler/tweak-assocs.js +9 -10
  40. package/lib/compiler/utils.js +7 -2
  41. package/lib/edm/annotations/genericTranslation.js +60 -6
  42. package/lib/edm/annotations/preprocessAnnotations.js +10 -11
  43. package/lib/edm/csn2edm.js +39 -41
  44. package/lib/edm/edm.js +22 -15
  45. package/lib/edm/edmPreprocessor.js +66 -69
  46. package/lib/edm/edmUtils.js +12 -62
  47. package/lib/gen/Dictionary.json +8 -6
  48. package/lib/gen/language.checksum +1 -1
  49. package/lib/gen/language.interp +8 -30
  50. package/lib/gen/language.tokens +105 -114
  51. package/lib/gen/languageLexer.interp +1 -34
  52. package/lib/gen/languageLexer.js +889 -1007
  53. package/lib/gen/languageLexer.tokens +95 -106
  54. package/lib/gen/languageParser.js +20717 -22376
  55. package/lib/json/from-csn.js +73 -68
  56. package/lib/json/to-csn.js +13 -10
  57. package/lib/language/antlrParser.js +2 -2
  58. package/lib/language/docCommentParser.js +61 -38
  59. package/lib/language/errorStrategy.js +52 -40
  60. package/lib/language/genericAntlrParser.js +333 -259
  61. package/lib/language/language.g4 +600 -645
  62. package/lib/language/multiLineStringParser.js +14 -42
  63. package/lib/language/textUtils.js +44 -0
  64. package/lib/main.d.ts +27 -42
  65. package/lib/main.js +104 -81
  66. package/lib/model/csnRefs.js +2 -1
  67. package/lib/model/csnUtils.js +183 -285
  68. package/lib/model/revealInternalProperties.js +32 -9
  69. package/lib/model/sortViews.js +32 -31
  70. package/lib/optionProcessor.js +64 -57
  71. package/lib/render/.eslintrc.json +1 -1
  72. package/lib/render/DuplicateChecker.js +4 -7
  73. package/lib/render/manageConstraints.js +70 -2
  74. package/lib/render/toCdl.js +334 -339
  75. package/lib/render/toHdbcds.js +20 -16
  76. package/lib/render/toRename.js +44 -22
  77. package/lib/render/toSql.js +60 -54
  78. package/lib/render/utils/common.js +15 -1
  79. package/lib/render/utils/sql.js +20 -19
  80. package/lib/sql-identifier.js +6 -0
  81. package/lib/transform/db/.eslintrc.json +3 -2
  82. package/lib/transform/db/cdsPersistence.js +5 -15
  83. package/lib/transform/db/constraints.js +1 -1
  84. package/lib/transform/db/expansion.js +7 -6
  85. package/lib/transform/db/flattening.js +18 -19
  86. package/lib/transform/db/views.js +3 -3
  87. package/lib/transform/draft/.eslintrc.json +2 -2
  88. package/lib/transform/draft/db.js +6 -6
  89. package/lib/transform/draft/odata.js +6 -7
  90. package/lib/transform/forHanaNew.js +19 -22
  91. package/lib/transform/forOdataNew.js +13 -15
  92. package/lib/transform/localized.js +35 -25
  93. package/lib/transform/odata/toFinalBaseType.js +11 -9
  94. package/lib/transform/odata/typesExposure.js +3 -3
  95. package/lib/transform/odata/utils.js +1 -38
  96. package/lib/transform/transformUtilsNew.js +63 -77
  97. package/lib/transform/translateAssocsToJoins.js +6 -2
  98. package/lib/transform/universalCsn/.eslintrc.json +2 -2
  99. package/lib/transform/universalCsn/coreComputed.js +11 -6
  100. package/lib/transform/universalCsn/universalCsnEnricher.js +33 -5
  101. package/lib/utils/file.js +31 -21
  102. package/lib/utils/timetrace.js +20 -21
  103. package/package.json +34 -4
  104. package/share/messages/syntax-expected-integer.md +9 -8
  105. package/doc/ApiMigration.md +0 -237
  106. package/doc/CommandLineMigration.md +0 -58
  107. package/doc/ErrorMessages.md +0 -175
  108. package/doc/FioriAnnotations.md +0 -94
  109. package/doc/ODataTransformation.md +0 -273
  110. package/lib/backends.js +0 -529
  111. package/lib/fix_antlr4-8_warning.js +0 -56
@@ -11,14 +11,11 @@ const {
11
11
  intersect,
12
12
  validateOptions,
13
13
  foreach,
14
- forAll,
15
- isAssociationOrComposition,
16
14
  isComposition,
17
15
  isStructuredArtifact,
18
16
  isParameterizedEntity,
19
17
  resolveOnConditionAndPrepareConstraints,
20
18
  finalizeReferentialConstraints,
21
- isEntity,
22
19
  getSchemaPrefix,
23
20
  } = require('./edmUtils.js');
24
21
 
@@ -54,6 +51,10 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
54
51
  fallBackSchemaName,
55
52
  whatsMyServiceRootName ] = getAnOverviewOnTheServices(csn);
56
53
 
54
+ if(serviceRootNames.length === 0) {
55
+ return [serviceRoots, Object.create(null), reqDefs, whatsMyServiceRootName, fallBackSchemaName, options];
56
+ }
57
+
57
58
  if(requestedServiceNames === undefined)
58
59
  requestedServiceNames = options.serviceNames;
59
60
  if(requestedServiceNames === undefined) {
@@ -64,10 +65,6 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
64
65
  return requestedServiceNames.includes(whatsMyServiceRootName(n));
65
66
  }
66
67
 
67
- if(serviceRootNames.length === 0) {
68
- return [serviceRoots, Object.create(null), reqDefs, whatsMyServiceRootName, fallBackSchemaName, options];
69
- }
70
-
71
68
  // Structural CSN inbound QA checks
72
69
  inboundQualificationChecks();
73
70
  // not needed at the moment
@@ -85,7 +82,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
85
82
 
86
83
  /*
87
84
  Final base type expansion is required here when:
88
- 1) The input CSN was already transformed for V4 but shall be rendered in V2 and the
85
+ 1) The input CSN was already transformed for V4 but shall be rendered in V2 and the
89
86
  edmx generator is called directly (bypassing OData transformation)
90
87
  2) The input CSN was already transformed for V4 and persisted (all non-enumerables are
91
88
  stripped of)
@@ -119,17 +116,12 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
119
116
  }
120
117
 
121
118
  if(schemaNames.length) {
122
- // First attach names to all definitions (and actions/params) in the model
123
- // elements are done in initializeStruct
124
- // Set myServiceName for later reference and indication of a service member
125
- // First attach names to all definitions in the model and fill reqDefs
126
- // Link association targets and spray @odata.contained over untagged compositions
127
119
  forEachDefinition(csn, [
128
120
  attachNameProperty,
129
121
  (def, defName) => {
130
122
  const mySchemaName = whatsMySchemaName(defName);
131
123
  mySchemaName && setProp(def, '$mySchemaName', mySchemaName);
132
- if(isMyServiceRequested(defName))
124
+ if(isMyServiceRequested(defName) && def.kind !== 'aspect')
133
125
  reqDefs.definitions[defName] = def;
134
126
  },
135
127
  linkAssociationTarget ]);
@@ -307,7 +299,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
307
299
  const myServiceRoot = whatsMyServiceRootName(defName);
308
300
  const mySchemaPrefix = getSchemaPrefix(defName);
309
301
  if(myServiceRoot && options.isV4() &&
310
- /*(options.toOdata.odataProxies || options.toOdata.odataXServiceRefs) && options.isStructFormat && */
302
+ /*(options.odataProxies || options.odataXServiceRefs) && options.isStructFormat && */
311
303
  defName !== myServiceRoot && myServiceRoot !== mySchemaPrefix) {
312
304
  const service = { kind: 'service', name: mySchemaPrefix };
313
305
  serviceRoots[mySchemaPrefix] = service;
@@ -341,23 +333,21 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
341
333
  // link association target to association and add @odata.contained to compositions in V4
342
334
  function linkAssociationTarget(struct) {
343
335
  forEachMemberRecursively(struct, (element, name, prop, subpath) => {
344
- if(isAssociationOrComposition(element) && !element._ignore) {
345
- if(!element._target) {
346
- let target = csn.definitions[element.target];
347
- if(target) {
348
- setProp(element, '_target', target);
336
+ if(element.target && !element._target) {
337
+ let target = csn.definitions[element.target];
338
+ if(target) {
339
+ setProp(element, '_target', target);
349
340
  // If target has parameters, xref assoc at target for redirection
350
- if(isParameterizedEntity(target)) {
351
- if(!target.$sources) {
352
- setProp(target, '$sources', Object.create(null));
353
- }
354
- target.$sources[struct.name + '.' + name] = element;
341
+ if(isParameterizedEntity(target)) {
342
+ if(!target.$sources) {
343
+ setProp(target, '$sources', Object.create(null));
355
344
  }
356
- }
357
- else {
358
- error(null, subpath, { target: element.target }, "Target $(TARGET) can't be found in the model");
345
+ target.$sources[struct.name + '.' + name] = element;
359
346
  }
360
347
  }
348
+ else {
349
+ error(null, subpath, { target: element.target }, "Target $(TARGET) can't be found in the model");
350
+ }
361
351
  }
362
352
  // in V4 tag all compositions to be containments
363
353
  if(options.odataContainment &&
@@ -389,7 +379,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
389
379
  }
390
380
 
391
381
  function initContainments(elt, eltName) {
392
- if(isAssociationOrComposition(elt) && elt['@odata.contained'] && !elt._ignore) {
382
+ if(elt.target && elt['@odata.contained'] && !elt._ignore) {
393
383
  // Let the containee know its container
394
384
  // (array because the contanee may contained more then once)
395
385
  let containee = elt._target;
@@ -660,17 +650,19 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
660
650
  }
661
651
  //forward annotations from managed association element to its foreign keys
662
652
  const elements = construct.items && construct.items.elements || construct.elements;
663
- forAll(elements[element['@odata.foreignKey4']], (attr, attrName) => {
653
+ const fk = elements[element['@odata.foreignKey4']];
654
+ for(const attrName in fk) {
655
+ const attr = fk[attrName];
664
656
  if(attrName[0] === '@') {
665
657
  element[attrName] = attr;
666
658
  }
667
- });
659
+ }
668
660
  // and eventually remove some afterwards:)
669
661
  if(options.isV2())
670
662
  setSAPSpecificV2AnnotationsToAssociation(element);
671
663
 
672
664
  // initialize an association
673
- if(isAssociationOrComposition(element)) {
665
+ if(element.target) {
674
666
  // in case this is a forward assoc, store the backlink partners here, _selfReferences.length > 1 => error
675
667
  assignProp(element, '_selfReferences', []);
676
668
  assignProp(element._target, '$proxies', []);
@@ -685,7 +677,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
685
677
  applyAppSpecificLateCsnTransformationOnElement(options, element, def, error);
686
678
  }, [], true, { elementsOnly: true });
687
679
 
688
- if(!isDeprecatedEnabled(options, 'v1KeysForTemporal')) {
680
+ if(!isDeprecatedEnabled(options, '_v1KeysForTemporal')) {
689
681
  // if artifact has a cds.valid.key mention it as @Core.AlternateKey
690
682
  if(validKey.length) {
691
683
  let altKeys = [{ Key: [] }];
@@ -699,7 +691,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
699
691
  // @Core.AlternateKeys: [{ Key: [ { Name: 'slID', Alias: 'slID' }, { Name: 'validFrom', Alias: 'validFrom'} ] }]
700
692
  if(validKey.length) {
701
693
  let altKeys = [{ Key: [] }];
702
- forAll(keys, (k, kn) => {
694
+ Object.entries(([kn, k]) => {
703
695
  altKeys[0].Key.push( { Name: kn, Alias: kn } );
704
696
  delete k.key;
705
697
  });
@@ -722,7 +714,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
722
714
  }
723
715
 
724
716
  // prepare the structure itself
725
- if(isEntity(def)) {
717
+ if(def.kind === 'entity') {
726
718
  assignProp(def, '_SetAttributes', Object.create(null));
727
719
  assignProp(def, '$keys', keys);
728
720
  applyAppSpecificLateCsnTransformationOnStructure(options, def, error);
@@ -738,7 +730,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
738
730
  forEachMemberRecursively(def.items || def, initConstraintsOnAssoc, [], true, { elementsOnly: true });
739
731
  }
740
732
  function initConstraintsOnAssoc(element) {
741
- if (isAssociationOrComposition(element) && !element._ignore && !element._constraints) {
733
+ if (element.target && !element._constraints) {
742
734
  // setup the constraints object
743
735
  setProp(element, '_constraints', { constraints: Object.create(null), selfs: [], _origins: [], termCount: 0 });
744
736
  // and crack the ON condition
@@ -790,7 +782,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
790
782
  delete struct.$keys[element.name];
791
783
  }
792
784
  }
793
- // deprecated unmanagedUpInComponent:
785
+ // deprecated._unmanagedUpInComponent:
794
786
  // Only in containment:
795
787
  // Ignore this (foreign key) elment if renderForeignKeys is false
796
788
  if(options.odataContainment && element['@odata.containment.ignore']) {
@@ -822,7 +814,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
822
814
  forEachMemberRecursively(def.items || def, finalizeConstraintsOnAssoc, [], true, { elementsOnly: true });
823
815
  }
824
816
  function finalizeConstraintsOnAssoc(element) {
825
- if (isAssociationOrComposition(element) && !element._ignore && element._constraints) {
817
+ if (element.target && !element._ignore && element._constraints) {
826
818
  finalizeReferentialConstraints(csn, element, options, info);
827
819
 
828
820
  if(element._constraints._partnerCsn && element.cardinality && element.cardinality.max) {
@@ -855,7 +847,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
855
847
  sub artifacts exposed by the initial type exposure
856
848
  */
857
849
  function convertExposedTypesOfOtherServicesIntoCrossReferences() {
858
- if(options.toOdata.odataXServiceRefs && options.isV4()) {
850
+ if(options.odataXServiceRefs && options.isV4()) {
859
851
  serviceRootNames.forEach(srn => {
860
852
  schemaNames.forEach(fqSchemaName => {
861
853
  if(fqSchemaName.startsWith(srn + '.')) {
@@ -912,7 +904,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
912
904
  // if this artifact is a service member check its associations
913
905
  if(globalSchemaPrefix) {
914
906
  forEachGeneric(struct.items || struct, 'elements', element => {
915
- if(!isAssociationOrComposition(element) || element._ignore || element['@odata.navigable'] === false)
907
+ if(!element.target || element['@odata.navigable'] === false)
916
908
  return;
917
909
  /*
918
910
  * Consider everything @cds.autoexpose: falsy to be a proxy candidate for now
@@ -949,18 +941,18 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
949
941
  const targetSchemaName = element._target.$mySchemaName;
950
942
  if(isProxyRequired(element)) {
951
943
  if(options.isV4() &&
952
- (options.toOdata.odataProxies || options.toOdata.odataXServiceRefs) &&
944
+ (options.odataProxies || options.odataXServiceRefs) &&
953
945
  // must be a managed association with keys OR an unambiguous backlink
954
- element.keys ||
946
+ element.keys ||
955
947
  (element.on && element._constraints.selfs.length === 1 && element._constraints.termCount === 1)
956
948
  ) {
957
949
  // reuse proxy if available
958
950
  let proxy = getProxyForTargetOf(element);
959
951
  if(!proxy) {
960
- if(targetSchemaName && options.toOdata.odataXServiceRefs) {
952
+ if(targetSchemaName && options.odataXServiceRefs) {
961
953
  proxy = createSchemaRefFor(targetSchemaName);
962
954
  }
963
- else if(options.toOdata.odataProxies) {
955
+ else if(options.odataProxies) {
964
956
  proxy = createProxyFor(element, targetSchemaName);
965
957
  }
966
958
  proxy = registerProxy(proxy, element);
@@ -1024,7 +1016,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
1024
1016
  // proxyDefinitionName: strip the serviceName and replace '.' with '_'
1025
1017
  let defName =
1026
1018
  `${assoc._target.name.replace(proxySchemaName + '.', '').replace(/\./g, '_')}`;
1027
-
1019
+
1028
1020
  // fullName: Prepend serviceName and if in same service add '_proxy'
1029
1021
  const proxy = isParamProxy
1030
1022
  ? createParameterEntity(assoc._target, proxySchemaName + '.' + defName, true)
@@ -1068,13 +1060,13 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
1068
1060
  // copy over the primary keys of the target and trigger the type exposure
1069
1061
  // if the element already exists we assume it was fully exposed
1070
1062
  function populateProxyElements(assoc, proxy, elements) {
1071
- forAll(elements, e => {
1063
+ Object.values(elements).forEach(e => {
1072
1064
  if (isEdmPropertyRendered(e, options)) {
1073
1065
  let newElt = proxy.elements[e.name];
1074
1066
  if(!newElt) {
1075
1067
  if(csnUtils.isAssocOrComposition(e.type)) {
1076
1068
  if(!e.on && e.keys) {
1077
- if(options.toOdata.odataNoTransitiveProxies)
1069
+ if(options.odataNoTransitiveProxies)
1078
1070
  newElt = convertManagedAssocIntoStruct(e);
1079
1071
  else
1080
1072
  newElt = createProxyOrSchemaRefForManagedAssoc(e);
@@ -1275,10 +1267,10 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
1275
1267
  proxy = getProxyForTargetOf(e);
1276
1268
  if(!proxy) {
1277
1269
  // option odataXServiceRefs has precedence over odataProxies
1278
- if(e._target.$mySchemaName && options.toOdata.odataXServiceRefs) {
1270
+ if(e._target.$mySchemaName && options.odataXServiceRefs) {
1279
1271
  proxy = createSchemaRefFor(e._target.$mySchemaName);
1280
1272
  }
1281
- else if(options.toOdata.odataProxies) {
1273
+ else if(options.odataProxies) {
1282
1274
  proxy = createProxyFor(e, e._target.$mySchemaName);
1283
1275
  if(!e._target.$isParamEntity)
1284
1276
  populateProxyElements(e, proxy, getForeignKeyDefinitions(e));
@@ -1451,16 +1443,13 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
1451
1443
  if(def.$keys) {
1452
1444
  setProp(def, '$edmKeyPaths', []);
1453
1445
  // for all key elements that shouldn't be ignored produce the paths
1454
- foreach(def.$keys, k => !k._ignore && !(k._isToContainer && k._selfReferences.length), (k, kn) => {
1446
+ foreach(def.$keys, k => !(k._isToContainer && k._selfReferences.length), (k, kn) => {
1455
1447
  if(isEdmPropertyRendered(k, options) &&
1456
1448
  !(options.isV2() && k['@Core.MediaType'])) {
1457
1449
  if(options.isV4() && options.isStructFormat) {
1458
- // This is structured OData ONLY
1459
- // if the foreign keys are explicitly requested, ignore associations and use the flat foreign keys instead
1460
- if(options.renderForeignKeys && !k.target)
1461
- def.$edmKeyPaths.push([kn]);
1462
- // else produce paths (isEdmPropertyRendered() has filtered @odata.foreignKey4 already)
1463
- else if(!options.renderForeignKeys)
1450
+ // This is structured OData ONLY
1451
+ // if the foreign keys are explicitly requested, ignore associations and use the flat foreign keys instead
1452
+ if(!options.renderForeignKeys || (options.renderForeignKeys && !k.target))
1464
1453
  def.$edmKeyPaths.push(...produceKeyRefPaths(k, kn));
1465
1454
  }
1466
1455
  // In v2/v4 flat, associations are never rendered
@@ -1543,13 +1532,13 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
1543
1532
  // Nullability
1544
1533
  if((!elt.key && (elt.notNull === undefined || elt.notNull === false)) ||
1545
1534
  elt.key && (elt.notNull !== undefined && elt.notNull === false)) {
1546
- error('odata-spec-violation-key-null', location,
1535
+ message('odata-spec-violation-key-null', location,
1547
1536
  {name: pathSegment, '#': pathSegment ? 'std' : 'scalar'});
1548
1537
  }
1549
1538
  // many
1550
1539
  let type = elt.items || elt.type && !isBuiltinType(elt.type) && csnUtils.getFinalTypeDef(elt.type).items;
1551
1540
  if(type) {
1552
- error('odata-spec-violation-key-array', location,
1541
+ message('odata-spec-violation-key-array', location,
1553
1542
  {name: pathSegment, '#': pathSegment ? 'std' : 'scalar'});
1554
1543
  }
1555
1544
  // type
@@ -1559,7 +1548,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
1559
1548
 
1560
1549
  // check for legal scalar types, proxy exposed structured types are not resolvable in CSN
1561
1550
  // V2 allows any Edm.PrimitiveType (even Double and Binary), V4 is more specific:
1562
- if(options.isV4() && type && !isAssociationOrComposition(type) && isBuiltinType(type.type)) {
1551
+ if(options.isV4() && type && !type.target && isBuiltinType(type.type)) {
1563
1552
  const edmType = edmUtils.mapCdsToEdmType(type);
1564
1553
  const legalEdmTypes = {
1565
1554
  'Edm.Boolean':1, 'Edm.Byte':1, 'Edm.Date':1, 'Edm.DateTimeOffset':1, 'Edm.Decimal':1, 'Edm.Duration':1,
@@ -1612,10 +1601,17 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
1612
1601
  if(isEdmPropertyRendered(elt, options)) {
1613
1602
  // Assoc can never be a derived TypeDefinition, no need to
1614
1603
  // unroll derived type chains for assocs
1615
- if(isAssociationOrComposition(elt) && !elt.$touched) {
1604
+ if(elt.target && !elt.$touched) {
1616
1605
  if(!elt._target.$edmTgtPaths)
1617
1606
  setProp(elt._target, '$edmTgtPaths', []);
1618
- if(!elt._target.$hasEntitySet && !elt._isToContainer && curDef !== elt._target) {
1607
+ // drill into target only if
1608
+ // 1) target has no entity set and this assoc is not going to the container
1609
+ // 2) current definition and target are the same (cycle)
1610
+ // 3) it's no external reference
1611
+ if(!elt.$externalRef &&
1612
+ !elt._target.$hasEntitySet &&
1613
+ !elt._isToContainer &&
1614
+ curDef !== elt._target) {
1619
1615
  // follow elements in the target but avoid cycles
1620
1616
  setProp(elt, '$touched', true);
1621
1617
  elt._target.$edmTgtPaths.push(newPrefix);
@@ -1650,10 +1646,11 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
1650
1646
  if(isEdmPropertyRendered(elt, options)) {
1651
1647
  // Assoc can never be a derived TypeDefinition, no need to
1652
1648
  // unroll derived type chains for assocs
1653
- if(isAssociationOrComposition(elt) && !elt.$touched) {
1649
+ if(elt.target && !elt.$touched) {
1654
1650
  // drill into target only if
1655
1651
  // 1) target has no entity set and this assoc is not going to the container
1656
1652
  // 2) current definition and target are the same (cycle)
1653
+ // 3) it's no external reference
1657
1654
  if(!elt.$externalRef &&
1658
1655
  !elt._target.$hasEntitySet &&
1659
1656
  !elt._isToContainer &&
@@ -1713,7 +1710,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
1713
1710
  // 1) must not be a proxy and not a containee in V4
1714
1711
  // No annos are rendered for non-existing EntitySet targets.
1715
1712
  if(def.$hasEntitySet === undefined) {
1716
- const hasEntitySet = isEntity(def) && !(options.isV4() && edmUtils.isContainee(def)) && !def.$proxy;
1713
+ const hasEntitySet = def.kind === 'entity' && !(options.isV4() && edmUtils.isContainee(def)) && !def.$proxy;
1717
1714
  setProp(def, '$hasEntitySet', hasEntitySet);
1718
1715
  }
1719
1716
  }
@@ -1917,7 +1914,7 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
1917
1914
  if(Object.keys(o).length) {
1918
1915
  // ReadRestrictions may have sub type ReadByKeyRestrictions { Description, LongDescription }
1919
1916
  // chop annotations into dictionaries
1920
- if(prefix === '@Capabilities.ReadRestrictions' &&
1917
+ if(prefix === '@Capabilities.ReadRestrictions' &&
1921
1918
  Object.keys(o).some(k => k.startsWith('ReadByKeyRestrictions.'))) {
1922
1919
  const no = {};
1923
1920
  Object.entries(o).forEach(([k,v]) => {
@@ -1958,16 +1955,16 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
1958
1955
  }
1959
1956
 
1960
1957
  function mapCdsToEdmProp(obj) {
1961
- if (obj.type && isBuiltinType(obj.type) && !isAssociationOrComposition(obj) && !obj.targetAspect) {
1962
- let edmType = edmUtils.mapCdsToEdmType(obj, messageFunctions, _options.toOdata.version === 'v2', obj['@Core.MediaType']);
1958
+ if (obj.type && isBuiltinType(obj.type) && !obj.target && !obj.targetAspect) {
1959
+ let edmType = edmUtils.mapCdsToEdmType(obj, messageFunctions, _options.odataVersion === 'v2', obj['@Core.MediaType']);
1963
1960
  assignProp(obj, '_edmType', edmType);
1964
1961
  } else if (obj._isCollection && (obj.items && isBuiltinType(csnUtils.getFinalTypeDef(obj.items.type)))) {
1965
- let edmType = edmUtils.mapCdsToEdmType(obj.items, messageFunctions, _options.toOdata.version === 'v2', obj['@Core.MediaType'], obj.$path);
1962
+ let edmType = edmUtils.mapCdsToEdmType(obj.items, messageFunctions, _options.odataVersion === 'v2', obj['@Core.MediaType'], obj.$path);
1966
1963
  assignProp(obj, '_edmType', edmType);
1967
1964
  }
1968
1965
  // This is the special case when we have array of array, but will not be supported in the future
1969
1966
  else if (obj._isCollection && obj.items && obj.items.type && obj.items.items && isBuiltinType(csnUtils.getFinalTypeDef(obj.items.items.type))) {
1970
- let edmType = edmUtils.mapCdsToEdmType(obj.items.items, messageFunctions, _options.toOdata.version === 'v2', obj['@Core.MediaType']);
1967
+ let edmType = edmUtils.mapCdsToEdmType(obj.items.items, messageFunctions, _options.odataVersion === 'v2', obj['@Core.MediaType']);
1971
1968
  assignProp(obj, '_edmType', edmType);
1972
1969
  }
1973
1970
  }
@@ -2321,7 +2318,7 @@ function setSAPSpecificV2AnnotationsToAssociation(carrier) {
2321
2318
  });
2322
2319
 
2323
2320
  function addToAssociationSet(carrier, propName, propValue, removeFromType=true) {
2324
- if(isAssociationOrComposition(carrier)) {
2321
+ if(carrier.target) {
2325
2322
  assignProp(carrier, '_SetAttributes', Object.create(null));
2326
2323
  assignAnnotation(carrier._SetAttributes, propName, propValue);
2327
2324
  if(removeFromType) {
@@ -8,31 +8,17 @@ function validateOptions(_options)
8
8
  {
9
9
  if(!_options.isV2 && !_options.isV4)
10
10
  {
11
- // csn2edm expects "version" to be a top-level property of options
11
+ // csn2edm expects "odataVersion" to be a top-level property of options
12
12
  // set to 'v4' as default, override with value from incoming options
13
- // (here version comes inside "toOdata")
14
- const options = Object.assign({ version: 'v4'}, _options);
15
- if (options.toOdata) {
16
- if(options.toOdata.version)
17
- options.version = options.toOdata.version;
18
- if(options.toOdata.odataFormat)
19
- options.odataFormat = options.toOdata.odataFormat;
20
- if(options.toOdata.odataContainment)
21
- options.odataContainment = options.toOdata.odataContainment;
22
- if(options.toOdata.odataForeignKeys)
23
- options.odataForeignKeys = options.toOdata.odataForeignKeys;
24
- if(options.toOdata.odataV2PartialConstr)
25
- options.odataV2PartialConstr = options.toOdata.odataV2PartialConstr;
26
- // global flag that indicates whether or not FKs shall be rendered in general
27
- // V2/V4 flat: yes
28
- // V4/struct: depending on odataForeignKeys
29
- options.renderForeignKeys =
30
- options.version === 'v4' ? options.odataFormat === 'structured' && !!options.odataForeignKeys : true;
13
+ const options = Object.assign({ odataVersion: 'v4'}, _options);
14
+ // global flag that indicates whether or not FKs shall be rendered in general
15
+ // V2/V4 flat: yes
16
+ // V4/struct: depending on odataForeignKeys
17
+ options.renderForeignKeys =
18
+ options.odataVersion === 'v4' ? options.odataFormat === 'structured' && !!options.odataForeignKeys : true;
31
19
 
32
- }
33
-
34
- const v2 = options.version.match(/v2/i) !== null;
35
- const v4 = options.version.match(/v4/i) !== null;
20
+ const v2 = options.odataVersion.match(/v2/i) !== null;
21
+ const v4 = options.odataVersion.match(/v4/i) !== null;
36
22
 
37
23
  options.v = [v2, v4];
38
24
  options.isStructFormat = options.odataFormat && options.odataFormat === 'structured';
@@ -70,11 +56,6 @@ function foreach(dictionary, filter, func) {
70
56
  });
71
57
  }
72
58
 
73
- // Call func(art, name) for each artifact 'art' with name 'name' in 'dictionary'
74
- function forAll(dictionary, func) {
75
- foreach(dictionary, ()=>true, func);
76
- }
77
-
78
59
  // true if _containerEntity is unequal to artifact name (non-recursive containment association)
79
60
  // or if artifact belongs to an artificial parameter entity
80
61
  function isContainee(artifact) {
@@ -82,27 +63,11 @@ function isContainee(artifact) {
82
63
  return (artifact._containerEntity && (artifact._containerEntity.length > 1 || artifact._containerEntity[0] != artifact.name));
83
64
  }
84
65
 
85
- // Return true if 'artifact' has an association type
86
- function isAssociation(artifact) {
87
- return (artifact.type === 'cds.Association' || artifact.type === 'Association') && artifact.target != undefined;
88
- //return artifact.target != undefined;
89
- }
90
-
91
66
  function isComposition(artifact) {
92
67
  return (artifact.type === 'cds.Composition' || artifact.type === 'Composition') &&
93
68
  artifact.target != undefined;
94
69
  }
95
70
 
96
- function isAssociationOrComposition(artifact)
97
- {
98
- return isAssociation(artifact) || isComposition(artifact);
99
- }
100
-
101
- function isManagedAssociation(artifact)
102
- {
103
- return isAssociation(artifact) && artifact.on == undefined;
104
- }
105
-
106
71
  // Return true if the association 'assoc' has cardinality 'to-many'
107
72
  function isToMany(assoc) {
108
73
  if (!assoc.cardinality) {
@@ -122,13 +87,8 @@ function isSingleton(entityCsn) {
122
87
  return singleton || ((singleton === undefined || singleton === null) && hasNullable);
123
88
  }
124
89
 
125
- function isEntity(artifact)
126
- {
127
- return artifact.kind === 'entity';
128
- }
129
-
130
90
  function isParameterizedEntity(artifact) {
131
- return isEntity(artifact) && artifact.params;
91
+ return artifact.kind === 'entity' && artifact.params;
132
92
  }
133
93
 
134
94
  // Return true if 'artifact' is structured (i.e. has elements, like a structured type or an entity)
@@ -146,10 +106,6 @@ function isDerivedType(artifact) {
146
106
  return artifact.kind === 'type' && !isStructuredArtifact(artifact);
147
107
  }
148
108
 
149
- function isActionOrFunction(artifact) {
150
- return artifact.kind === 'action' || artifact.kind === 'function';
151
- }
152
-
153
109
  function resolveOnConditionAndPrepareConstraints(csn, assocCsn, messageFunctions) {
154
110
  if(!assocCsn._constraints)
155
111
  throw Error('Please debug me: need _constraints');
@@ -189,7 +145,7 @@ function resolveOnConditionAndPrepareConstraints(csn, assocCsn, messageFunctions
189
145
  info(null, ['definitions', parentName, 'elements', assocCsn.name],
190
146
  `"${originParentName}:${partnerPath.join('.')}" with target "${originAssocCsn._target.name}" is compared with $self which represents "${parentName}"`);
191
147
  }
192
- if(isAssociationOrComposition(originAssocCsn)) {
148
+ if(originAssocCsn.target) {
193
149
  // Mark this association as backlink if $self appears exactly once
194
150
  // to surpress edm:Association generation in V2 mode
195
151
  if(isBacklink) {
@@ -359,7 +315,7 @@ function finalizeReferentialConstraints(csn, assocCsn, options, info)
359
315
  // in structured mode only resolve top level element (path rewriting is done elsewhere)
360
316
  const depEltName = ( options.isFlatFormat ? c[0].join('_') : c[0][0] );
361
317
  const principalEltName = ( options.isFlatFormat ? c[1].join('_') : c[1][0] );
362
- const fk = (isEntity(dependentEntity) && dependentEntity.elements[ depEltName ]) ||
318
+ const fk = (dependentEntity.kind === 'entity' && dependentEntity.elements[ depEltName ]) ||
363
319
  (localDepEntity && localDepEntity.elements && localDepEntity.elements[ depEltName ]);
364
320
  const pk = principalEntity.$keys && principalEntity.$keys[ principalEltName ];
365
321
  if(isConstraintCandidate(fk) && isConstraintCandidate(pk)) {
@@ -801,20 +757,14 @@ module.exports = {
801
757
  validateOptions,
802
758
  intersect,
803
759
  foreach,
804
- forAll,
805
760
  isContainee,
806
- isAssociation,
807
- isManagedAssociation,
808
761
  isComposition,
809
- isAssociationOrComposition,
810
762
  isToMany,
811
763
  isSingleton,
812
- isEntity,
813
764
  isStructuredType,
814
765
  isStructuredArtifact,
815
766
  isParameterizedEntity,
816
767
  isDerivedType,
817
- isActionOrFunction,
818
768
  resolveOnConditionAndPrepareConstraints,
819
769
  finalizeReferentialConstraints,
820
770
  determineMultiplicity,
@@ -658,6 +658,7 @@
658
658
  "Type": "Common.FieldControlType",
659
659
  "AppliesTo": [
660
660
  "Property",
661
+ "Parameter",
661
662
  "Record",
662
663
  "EntityType"
663
664
  ]
@@ -3246,6 +3247,7 @@
3246
3247
  "TypeNamePlural": "Edm.String",
3247
3248
  "Title": "UI.DataFieldAbstract",
3248
3249
  "Description": "UI.DataFieldAbstract",
3250
+ "Image": "Edm.Stream",
3249
3251
  "ImageUrl": "Edm.String",
3250
3252
  "TypeImageUrl": "Edm.String",
3251
3253
  "Initials": "Edm.String"
@@ -3693,7 +3695,7 @@
3693
3695
  "$kind": "ComplexType",
3694
3696
  "BaseType": "UI.DataFieldAbstract",
3695
3697
  "Properties": {
3696
- "Value": "Edm.PrimitiveType",
3698
+ "Value": "Edm.Untyped",
3697
3699
  "Label": "Edm.String",
3698
3700
  "Criticality": "UI.CriticalityType",
3699
3701
  "CriticalityRepresentation": "UI.CriticalityRepresentationType",
@@ -3704,8 +3706,8 @@
3704
3706
  "$kind": "ComplexType",
3705
3707
  "BaseType": "UI.DataField",
3706
3708
  "Properties": {
3707
- "Action": "Common.QualifiedName",
3708
3709
  "Value": "Edm.PrimitiveType",
3710
+ "Action": "Common.QualifiedName",
3709
3711
  "Label": "Edm.String",
3710
3712
  "Criticality": "UI.CriticalityType",
3711
3713
  "CriticalityRepresentation": "UI.CriticalityRepresentationType",
@@ -3716,10 +3718,10 @@
3716
3718
  "$kind": "ComplexType",
3717
3719
  "BaseType": "UI.DataField",
3718
3720
  "Properties": {
3721
+ "Value": "Edm.PrimitiveType",
3719
3722
  "SemanticObject": "Edm.String",
3720
3723
  "Action": "Edm.String",
3721
3724
  "Mapping": "Collection(Common.SemanticObjectMappingType)",
3722
- "Value": "Edm.PrimitiveType",
3723
3725
  "Label": "Edm.String",
3724
3726
  "Criticality": "UI.CriticalityType",
3725
3727
  "CriticalityRepresentation": "UI.CriticalityRepresentationType",
@@ -3730,8 +3732,8 @@
3730
3732
  "$kind": "ComplexType",
3731
3733
  "BaseType": "UI.DataField",
3732
3734
  "Properties": {
3733
- "Target": "Edm.NavigationPropertyPath",
3734
3735
  "Value": "Edm.PrimitiveType",
3736
+ "Target": "Edm.NavigationPropertyPath",
3735
3737
  "Label": "Edm.String",
3736
3738
  "Criticality": "UI.CriticalityType",
3737
3739
  "CriticalityRepresentation": "UI.CriticalityRepresentationType",
@@ -3742,9 +3744,9 @@
3742
3744
  "$kind": "ComplexType",
3743
3745
  "BaseType": "UI.DataField",
3744
3746
  "Properties": {
3747
+ "Value": "Edm.PrimitiveType",
3745
3748
  "Url": "Edm.String",
3746
3749
  "UrlContentType": "Edm.String",
3747
- "Value": "Edm.PrimitiveType",
3748
3750
  "Label": "Edm.String",
3749
3751
  "Criticality": "UI.CriticalityType",
3750
3752
  "CriticalityRepresentation": "UI.CriticalityRepresentationType",
@@ -3755,8 +3757,8 @@
3755
3757
  "$kind": "ComplexType",
3756
3758
  "BaseType": "UI.DataField",
3757
3759
  "Properties": {
3758
- "Actions": "Collection(UI.DataField)",
3759
3760
  "Value": "Edm.PrimitiveType",
3761
+ "Actions": "Collection(UI.DataField)",
3760
3762
  "Label": "Edm.String",
3761
3763
  "Criticality": "UI.CriticalityType",
3762
3764
  "CriticalityRepresentation": "UI.CriticalityRepresentationType",
@@ -1 +1 @@
1
- 351a6ed427f91f2eef4d8e9a2e11dd17
1
+ ca4caa65192cebc39f35cd598958dbb0