@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,6 +11,7 @@ const {
11
11
  setArtifactLink,
12
12
  dependsOn,
13
13
  pathName,
14
+ annotationHasEllipsis,
14
15
  } = require('./utils');
15
16
 
16
17
  function artifactsEnv( art ) {
@@ -512,7 +513,7 @@ function fns( model ) {
512
513
  if (args.length > 0) {
513
514
  const loc = [ args[args.length - 1].location, user ];
514
515
  if (typeArtifact.builtin)
515
- warning( 'type-ignoring-argument', loc, { art: typeArtifact } );
516
+ message( 'type-ignoring-argument', loc, { art: typeArtifact } );
516
517
  else
517
518
  error( 'type-unexpected-argument', loc, { '#': 'std', art: typeArtifact });
518
519
  }
@@ -673,6 +674,9 @@ function fns( model ) {
673
674
  art = item._artifact;
674
675
  if (Array.isArray(art))
675
676
  return false;
677
+ if (art.$requireElementAccess && path.length === 1)
678
+ // Path with only one item, but we expect an element, e.g. `$at.from`.
679
+ signalMissingElementAccess(art, [ item.location, user ]);
676
680
  continue;
677
681
  }
678
682
 
@@ -808,11 +812,30 @@ function fns( model ) {
808
812
  attachAndEmitValidNames(err, ...valid.reverse());
809
813
  }
810
814
 
815
+ /**
816
+ * Emit a 'ref-expected-element' error for magic variable references
817
+ * that require element accesses but don't do.
818
+ * For example: `$at`, but `$at.from` or `$at.to` is required.
819
+ *
820
+ * @param {object} art
821
+ * @param {any} location
822
+ */
823
+ function signalMissingElementAccess(art, location) {
824
+ const err = message( 'ref-expected-element', location,
825
+ { '#': 'magicVar', id: art.name.id } );
826
+ // Mapping for better valid names: from -> $at.from
827
+ const valid = Object.keys(art.elements || {}).reduce((prev, curr) => {
828
+ prev[`${ art.name.id }.${ curr }`] = true;
829
+ return prev;
830
+ }, Object.create(null));
831
+ attachAndEmitValidNames(err, valid);
832
+ }
833
+
811
834
  /**
812
835
  * Attaches a dictionary of valid names to the given compiler message.
813
836
  * In test mode, an info message is emitted with a list of valid names.
814
837
  *
815
- * @param {CSN.Message} msg CDS Compiler message
838
+ * @param {CompileMessage} msg CDS Compiler message
816
839
  * @param {...object} validDicts One ore more artifact dictionaries such as in `_block`.
817
840
  */
818
841
  function attachAndEmitValidNames(msg, ...validDicts) {
@@ -838,14 +861,10 @@ function fns( model ) {
838
861
  }
839
862
  }
840
863
 
841
- // Resolve all annotation assignments for the node `art`. Set `art.@` to all
842
- // flattened assignments. This function might issue error message for
843
- // duplicate assignments.
844
- // TODOs:
845
- // * do something for extensions by CSN or Properties parsers
846
- // * make sure that we do not issue repeated warnings due to flattening if an
847
- // annotation definition is missing
848
- function defineAnnotations( construct, art, block, priority = 'define' ) {
864
+ // Set _block links for annotations (necessary for layering).
865
+ // Issue messages for annotations on namespaces and builtins (TODO: really here?)
866
+ // Also copy annotations from `construct` to `art` (TODO: separate that functionality).
867
+ function defineAnnotations( construct, art, block, priority = false ) {
849
868
  if (!options.parseCdl && construct.kind === 'annotate') {
850
869
  // Namespaces cannot be annotated in CSN but because they exist as XSN artifacts
851
870
  // they can still be applied. Namespace annotations are extracted in to-csn.js
@@ -862,77 +881,38 @@ function fns( model ) {
862
881
  info( 'anno-builtin', [ construct.name.location, construct ], {},
863
882
  'Builtin types should not be annotated. Use custom type instead' );
864
883
  }
865
- }
866
- // TODO: block should be construct._block
867
- if (construct.$annotations && construct.$annotations.doc )
868
- art.doc = construct.$annotations.doc; // e.g. through `annotate` statement in CDL
869
- else if (construct.doc)
870
- art.doc = construct.doc; // e.g. through `extensions` array in CSN
871
- if (!construct.$annotations) {
872
- if (!block || block.$frontend !== 'json')
873
- return; // namespace, or in CDL source without @annos:
874
- // CSN input: set _block and $priority, shallow-copy from extension
875
- for (const annoProp in construct) {
876
- if (annoProp.charAt(0) === '@') {
877
- let annos = construct[annoProp];
878
- if (!(Array.isArray(annos)))
879
- annos = [ annos ];
880
- for (const a of annos) {
881
- setLink( a, '_block', block );
882
- a.$priority = priority;
883
- if (construct !== art)
884
- addAnnotation( art, annoProp, a );
885
- }
886
- }
884
+ else if (construct.$syntax === 'returns' && art._block && art.kind !== 'action' &&
885
+ art.kind !== 'function' ) {
886
+ // `annotate ABC with returns {}` is handled just like `elements`. Warn if it is used
887
+ // for non-actions. We can't only check for !art.returns, because `action A();` is valid.
888
+ // `art._block` ensures that `art` is a defined def.
889
+ warning('anno-unexpected-returns', [ construct.name.location, construct ],
890
+ { keyword: 'returns', kind: art.kind }, 'Unexpected $(KEYWORD) for $(KIND)');
887
891
  }
888
- return;
889
892
  }
890
- for (const anno of construct.$annotations) {
891
- const ref = anno.name;
892
- const name = resolveUncheckedPath( ref, 'annotation', { _block: block } );
893
- const annoProp = (anno.name.variant)
894
- ? `@${ name }#${ anno.name.variant.id }`
895
- : `@${ name }`;
896
- flatten( ref.path, annoProp, anno.value || {}, anno.name.variant, anno.name.location );
897
- }
898
- return;
899
-
900
- function flatten( path, annoProp, value, iHaveVariant, location ) {
901
- // Be robust if struct value has duplicate element names
902
- if (Array.isArray(value)) // TODO: do that differently in CDL parser
903
- return; // discard duplicates in flattened form
904
-
905
- if (value.literal === 'struct') {
906
- for (const item of value._struct || []) {
907
- let prop = pathName(item.name.path);
908
- if (item.name.variant) {
909
- if (iHaveVariant) {
910
- error( 'anno-duplicate-variant', [ item.name.variant.location, construct ],
911
- {}, // TODO: params
912
- 'Annotation variant has been already provided' );
913
- }
914
- prop = `${ prop }#${ item.name.variant.id }`; // TODO: check for double variants
893
+ if (construct.doc)
894
+ art.doc = construct.doc; // e.g. through `extensions` array in CSN
895
+
896
+ // set _block (for layering) and $priority, shallow-copy from extension
897
+ // TODO: think of removing $priority, then
898
+ // no _block: define, _block: annotate/extend/edmx
899
+ // would fit with extending defs with props like length
900
+ for (const annoProp in construct) {
901
+ if (annoProp.charAt(0) === '@') {
902
+ let annos = construct[annoProp];
903
+ if (!(Array.isArray(annos)))
904
+ annos = [ annos ];
905
+ for (const a of annos) {
906
+ setLink( a, '_block', block );
907
+ a.$priority = priority; // is now: undefined (auto-set) | false | 'annotate' | 'extend'
908
+ if (construct !== art)
909
+ addAnnotation( art, annoProp, a );
910
+ if (!priority && annotationHasEllipsis( a )) {
911
+ error( 'anno-unexpected-ellipsis',
912
+ [ a.name.location, art ], { code: '...' } );
915
913
  }
916
- flatten( [ ...path, ...item.name.path ], `${ annoProp }.${ prop }`, item, iHaveVariant || item.name.variant);
917
- }
918
- for (const prop in value.struct) {
919
- const item = value.struct[prop];
920
- flatten( [ ...path, item.name ], `${ annoProp }.${ prop }`, item, iHaveVariant );
921
914
  }
922
- return;
923
915
  }
924
- const anno = Object.assign( {}, value ); // shallow copy
925
- anno.name = {
926
- path,
927
- location: location ||
928
- value.name && value.name.location ||
929
- value.path && value.path.location,
930
- };
931
- setLink( anno, '_block', block );
932
- // TODO: _parent, _main is set later (if we have ElementRef), or do we
933
- // set _artifact?
934
- anno.$priority = priority;
935
- addAnnotation( art, annoProp, anno );
936
916
  }
937
917
  }
938
918
  }
@@ -39,7 +39,7 @@ function tweakAssocs( model ) {
39
39
  const { environment } = model.$volatileFunctions;
40
40
 
41
41
  // behavior depending on option `deprecated`:
42
- const enableExpandElements = !isDeprecatedEnabled( options, 'noElementsExpansion' );
42
+ const enableExpandElements = !isDeprecatedEnabled( options, '_noElementsExpansion' );
43
43
  // TODO: we should get rid of noElementsExpansion soon; both
44
44
  // beta.nestedProjections and beta.universalCsn do not work with it.
45
45
 
@@ -95,15 +95,14 @@ function tweakAssocs( model ) {
95
95
  if (!target || target._service) // assoc to other service is OK
96
96
  return;
97
97
  if (!elem.$inferred) { // && !elem.target.$inferred
98
- // TODO: spec meeting 2021-01-22: no warning
99
- warning( 'assoc-target-not-in-service', [ elem.target.location, elem ],
100
- { target, '#': (elem._main.query ? 'select' : 'define') }, {
101
- std: 'Target $(TARGET) of association is outside any service', // not used
102
- // eslint-disable-next-line max-len
103
- define: 'Target $(TARGET) of explicitly defined association is outside any service',
104
- // eslint-disable-next-line max-len
105
- select: 'Target $(TARGET) of explicitly selected association is outside any service',
106
- } );
98
+ info( 'assoc-target-not-in-service', [ elem.target.location, elem ],
99
+ { target, '#': (elem._main.query ? 'select' : 'define') }, {
100
+ std: 'Target $(TARGET) of association is outside any service', // not used
101
+ // eslint-disable-next-line max-len
102
+ define: 'Target $(TARGET) of explicitly defined association is outside any service',
103
+ // eslint-disable-next-line max-len
104
+ select: 'Target $(TARGET) of explicitly selected association is outside any service',
105
+ } );
107
106
  }
108
107
  else {
109
108
  info( 'assoc-outside-service', [ elem.target.location, elem ],
@@ -31,6 +31,10 @@ function annotationVal( anno ) {
31
31
  function annotationIsFalse( anno ) { // falsy, but not null (unset)
32
32
  return anno && (anno.val === false || anno.val === 0 || anno.val === '');
33
33
  }
34
+ function annotationHasEllipsis( anno ) {
35
+ const { val } = anno || {};
36
+ return Array.isArray( val ) && val.some( v => v.literal === 'token' && v.val === '...' );
37
+ }
34
38
 
35
39
  /**
36
40
  * Set compiler-calculated annotation value.
@@ -184,8 +188,8 @@ function withAssociation( ref, test = testFunctionPlaceholder, alsoTestLast = fa
184
188
  *
185
189
  * @param {XSN.Path} path
186
190
  */
187
- function pathName(path) {
188
- return (path.broken) ? '' : path.map( id => id.id ).join('.');
191
+ function pathName( path ) {
192
+ return (path && !path.broken) ? path.map( id => id.id ).join('.') : '';
189
193
  }
190
194
 
191
195
  /**
@@ -381,6 +385,7 @@ module.exports = {
381
385
  pushLink,
382
386
  annotationVal,
383
387
  annotationIsFalse,
388
+ annotationHasEllipsis,
384
389
  annotateWith,
385
390
  setLink,
386
391
  setArtifactLink,
@@ -333,7 +333,7 @@ function csn2annotationEdm(csn, serviceName, Edm = undefined, options=undefined,
333
333
  function handleNestedElements(objname, baseElemName, elementsObj) {
334
334
  if(!elementsObj) return;
335
335
  Object.entries(elementsObj).forEach(([elemName, element]) => {
336
- if (Object.keys(element).filter( x => x.substr(0,1) === '@' ).filter(filterKnownVocabularies).length > 0) {
336
+ if (Object.keys(element).filter( x => x[0] === '@' ).filter(filterKnownVocabularies).length > 0) {
337
337
  message(warning, null, `annotations at nested elements are not yet supported, object ${objname}, element ${baseElemName}.${elemName}`);
338
338
  }
339
339
 
@@ -437,11 +437,17 @@ function csn2annotationEdm(csn, serviceName, Edm = undefined, options=undefined,
437
437
 
438
438
  // Filter unknown toplevel annotations
439
439
  // Final filtering of all annotations is done in handleTerm
440
- const annoNames = Object.keys(carrier).filter( x => x.substr(0,1) === '@' );
440
+
441
+ let annoNames = Object.keys(carrier).filter( x => x[0] === '@' );
441
442
  const nullWhitelist = [ '@Core.OperationAvailable' ];
442
- const knownAnnos = annoNames.filter(filterKnownVocabularies).filter(x => carrier[x] !== null || nullWhitelist.includes(x));
443
+ let knownAnnos = annoNames.filter(filterKnownVocabularies).filter(x => carrier[x] !== null || nullWhitelist.includes(x));
443
444
  if (knownAnnos.length === 0) return;
444
445
 
446
+ if(rewriteInnerAnnotations()) {
447
+ annoNames = Object.keys(carrier).filter( x => x[0] === '@' );
448
+ knownAnnos = annoNames.filter(filterKnownVocabularies).filter(x => carrier[x] !== null || nullWhitelist.includes(x));
449
+ if (knownAnnos.length === 0) return;
450
+ }
445
451
  const prefixTree = createPrefixTree();
446
452
 
447
453
  // usually, for a given carrier there is one target
@@ -610,6 +616,51 @@ function csn2annotationEdm(csn, serviceName, Edm = undefined, options=undefined,
610
616
  */
611
617
  }
612
618
 
619
+ function rewriteInnerAnnotations() {
620
+ let rc = false;
621
+ for (let a of knownAnnos) {
622
+ const [ prefix, innerAnnotation ] = a.split('.@');
623
+ /*
624
+ New inner annotation (de-)structuring of the core compiler to make
625
+ $value arrays extendable via ellipsis
626
+ @anno: { $value: [ ... ], @innerAnno: ... } is now cracked up by
627
+ the core compiler into:
628
+ @anno: [ ...]
629
+ @anno.@innerAnno: ...
630
+
631
+ Conflict handling if $value is present:
632
+ @anno
633
+ @anno.$value
634
+ @anno.@innerAnno
635
+
636
+ @anno has precedence (as it was before this change) but now
637
+ @anno.$value is overwritten with @anno and the inner annotations
638
+ are applied.
639
+
640
+ Trigger is always the inner annotation, if no inner annotation
641
+ is available, @anno has precedence.
642
+
643
+ Insert $value into $edmJson with inner annotation as well.
644
+ */
645
+ if(innerAnnotation) {
646
+ if(carrier[prefix]) {
647
+ const valPrefix = prefix + '.$value';
648
+ carrier[valPrefix] = carrier[prefix];
649
+ delete carrier[prefix];
650
+ rc = true;
651
+ }
652
+ const edmJsonPrefix = prefix + '.$edmJson';
653
+ if(carrier[edmJsonPrefix]) {
654
+ const valPrefix = prefix + '.$value.$edmJson';
655
+ carrier[valPrefix] = carrier[edmJsonPrefix];
656
+ delete carrier[edmJsonPrefix];
657
+ rc = true;
658
+ }
659
+ }
660
+ }
661
+ return rc;
662
+ }
663
+
613
664
  function createPrefixTree() {
614
665
  // in csn, all annotations are flattened
615
666
  // => values can be - primitive values (string, number)
@@ -619,6 +670,7 @@ function csn2annotationEdm(csn, serviceName, Edm = undefined, options=undefined,
619
670
  // by building a "prefix tree" for the annotations attached to the carrier
620
671
  // see example at definition of function mergePathStepsIntoPrefixTree
621
672
  const prefixTree = {};
673
+
622
674
  for (let a of knownAnnos) {
623
675
  // remove leading @ and split at "."
624
676
  // stop splitting at ".@" (used for nested annotations)
@@ -845,7 +897,7 @@ function csn2annotationEdm(csn, serviceName, Edm = undefined, options=undefined,
845
897
  // "pseudo-structure" used for embedding a piece of JSON that represents "OData CSDL, JSON Representation"
846
898
  oTarget.append(handleEdmJson(cAnnoValue['$edmJson'], context));
847
899
  }
848
- else if ( Object.keys(cAnnoValue).filter( x => x.substr(0,1) !== '@' ).length === 0) {
900
+ else if ( Object.keys(cAnnoValue).filter( x => x[0] !== '@' ).length === 0) {
849
901
  // object consists only of properties starting with "@"
850
902
  message(warning, context, 'nested annotations without corresponding base annotation');
851
903
  }
@@ -952,6 +1004,8 @@ function csn2annotationEdm(csn, serviceName, Edm = undefined, options=undefined,
952
1004
  // Edm.Decimal -> Decimal
953
1005
  // integer tpye -> Int
954
1006
  function handleSimpleValue(val, dTypeName, context) {
1007
+ // these types must be represented as "String" values in XML:
1008
+ const castToXmlString = [ 'Edm.PrimitiveType', 'Edm.Stream', 'Edm.Untyped' ];
955
1009
  // caller already made sure that val is neither object nor array
956
1010
  dTypeName = resolveType(dTypeName);
957
1011
 
@@ -989,12 +1043,12 @@ function csn2annotationEdm(csn, serviceName, Edm = undefined, options=undefined,
989
1043
  message(warning, context, `found String, but expected enum type ${ dTypeName }`);
990
1044
  typeName = 'EnumMember';
991
1045
  }
992
- else if (dTypeName && dTypeName.startsWith('Edm.') && dTypeName !== 'Edm.PrimitiveType') {
1046
+ else if (dTypeName && dTypeName.startsWith('Edm.') && !castToXmlString.includes(dTypeName)) {
993
1047
  // this covers also all paths
994
1048
  typeName = dTypeName.substring(4);
995
1049
  }
996
1050
  else {
997
- if(dTypeName == undefined || dTypeName === 'Edm.PrimitiveType')
1051
+ if(dTypeName == undefined || castToXmlString.some(t => t === dTypeName))
998
1052
  dTypeName = 'Edm.String';
999
1053
  // TODO
1000
1054
  //message(warning, context, "type is not yet handled: found String, expected type: " + dTypeName);
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const edmUtils = require('../edmUtils.js');
4
3
  const { makeMessageFunction } = require('../../base/messages.js');
4
+ const { forEachDefinition } = require('../../model/csnUtils.js');
5
5
 
6
6
 
7
7
  /**************************************************************************************************
@@ -37,15 +37,14 @@ function preprocessAnnotations(csn, serviceName, options) {
37
37
  let targetName = (typeof assoc.target === 'object') ? assoc.target.name : assoc.target;
38
38
  let target = (typeof assoc.target === 'object') ? assoc.target : csn.definitions[assoc.target];
39
39
 
40
- let keyNames = Object.keys(target.elements).filter(x => target.elements[x].key);
40
+ let keyNames = Object.keys(target.elements).filter(x => target.elements[x].key && !target.elements[x].target);
41
41
  if (keyNames.length === 0) {
42
42
  keyNames.push('MISSING');
43
43
  warning(null, null, `in annotation preprocessing: target ${targetName} has no key`);
44
44
  }
45
45
  else if (keyNames.length > 1)
46
46
  warning(null, null, `in annotation preprocessing: target ${targetName} has multiple key elements`);
47
-
48
- // TODO: what happens if key of target is itself a managed association?
47
+
49
48
  return keyNames[0];
50
49
  }
51
50
 
@@ -58,15 +57,15 @@ function preprocessAnnotations(csn, serviceName, options) {
58
57
  function resolveShortcuts() {
59
58
  let art = null;
60
59
 
61
- edmUtils.forAll(csn.definitions, (artifact, artifactName) => {
60
+ forEachDefinition(csn, (artifact, artifactName) => {
62
61
  if(artifactName == serviceName || artifactName.startsWith(serviceName + '.')) {
63
62
  art = artifactName;
64
63
  handleAnnotations(artifactName, artifact);
65
- edmUtils.forAll(artifact.elements, (element, elementName) => {
64
+ artifact.elements && Object.entries(artifact.elements).forEach(([elementName, element]) => {
66
65
  handleAnnotations(elementName, element);
67
66
  });
68
- edmUtils.forAll(artifact.actions, (action) => {
69
- edmUtils.forAll(action.params, (param, paramName) => {
67
+ artifact.actions && Object.values(artifact.actions).forEach(action => {
68
+ action.params && Object.entries(action.params).forEach(([paramName, param]) => {
70
69
  handleAnnotations(paramName, param);
71
70
  });
72
71
  });
@@ -155,7 +154,7 @@ function preprocessAnnotations(csn, serviceName, options) {
155
154
  return false;
156
155
  }
157
156
  let assoc = csn.definitions[art].elements[assocName];
158
- if (!assoc || !(assoc.type === 'cds.Association' || assoc.type === 'cds.Composition')) {
157
+ if (!assoc || !assoc.target) {
159
158
  warning(null, null, `in annotation preprocessing/${aNameWithoutQualifier}: there is no association "${assocName}", ${ctx}`);
160
159
  return false;
161
160
  }
@@ -196,7 +195,7 @@ function preprocessAnnotations(csn, serviceName, options) {
196
195
  // name of the element carrying the value help annotation
197
196
  // if this is a managed assoc, use fk field instead (if there is a single one)
198
197
  let localDataProp = carrierName.split('/').pop();
199
- if (edmUtils.isManagedAssociation(carrier)) {
198
+ if (carrier.target && carrier.on === undefined) {
200
199
  localDataProp = localDataProp + fkSeparator + getKeyOfTargetOfManagedAssoc(carrier);
201
200
  }
202
201
 
@@ -212,7 +211,7 @@ function preprocessAnnotations(csn, serviceName, options) {
212
211
  // valueListProp: the (single) key field of the value list entity
213
212
  // if no key or multiple keys -> warning
214
213
  let valueListProp = null;
215
- let keys = Object.keys(vlEntity.elements).filter( x => vlEntity.elements[x].key );
214
+ let keys = Object.keys(vlEntity.elements).filter( x => vlEntity.elements[x].key && !vlEntity.elements[x].target );
216
215
  if (keys.length === 0) {
217
216
  warning(null, null, `in annotation preprocessing/value help shortcut: entity "${enameFull}" has no key, ${ctx}`);
218
217
  return false;