@sap/cds-compiler 3.0.0 → 3.1.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 (79) hide show
  1. package/CHANGELOG.md +104 -9
  2. package/bin/.eslintrc.json +2 -1
  3. package/bin/cdsc.js +28 -16
  4. package/doc/API.md +11 -0
  5. package/doc/CHANGELOG_ARCHIVE.md +1 -1
  6. package/doc/CHANGELOG_BETA.md +24 -2
  7. package/doc/CHANGELOG_DEPRECATED.md +21 -1
  8. package/lib/api/main.js +92 -40
  9. package/lib/api/options.js +2 -3
  10. package/lib/base/keywords.js +64 -1
  11. package/lib/base/message-registry.js +33 -5
  12. package/lib/base/messages.js +54 -65
  13. package/lib/base/model.js +2 -0
  14. package/lib/base/optionProcessorHelper.js +53 -21
  15. package/lib/checks/actionsFunctions.js +8 -7
  16. package/lib/checks/selectItems.js +96 -14
  17. package/lib/checks/types.js +5 -8
  18. package/lib/checks/validator.js +1 -2
  19. package/lib/compiler/assert-consistency.js +65 -13
  20. package/lib/compiler/base.js +6 -4
  21. package/lib/compiler/builtins.js +93 -4
  22. package/lib/compiler/checks.js +1 -1
  23. package/lib/compiler/define.js +28 -23
  24. package/lib/compiler/extend.js +20 -11
  25. package/lib/compiler/finalize-parse-cdl.js +5 -9
  26. package/lib/compiler/index.js +2 -0
  27. package/lib/compiler/populate.js +37 -32
  28. package/lib/compiler/propagator.js +11 -6
  29. package/lib/compiler/resolve.js +15 -19
  30. package/lib/compiler/shared.js +54 -18
  31. package/lib/compiler/tweak-assocs.js +5 -11
  32. package/lib/compiler/utils.js +15 -6
  33. package/lib/edm/annotations/genericTranslation.js +12 -2
  34. package/lib/edm/annotations/preprocessAnnotations.js +18 -15
  35. package/lib/edm/csn2edm.js +18 -17
  36. package/lib/edm/edm.js +22 -13
  37. package/lib/edm/edmAnnoPreprocessor.js +349 -0
  38. package/lib/edm/edmInboundChecks.js +85 -0
  39. package/lib/edm/edmPreprocessor.js +336 -665
  40. package/lib/edm/edmUtils.js +86 -45
  41. package/lib/gen/Dictionary.json +29 -9
  42. package/lib/gen/language.checksum +1 -1
  43. package/lib/gen/language.interp +1 -2
  44. package/lib/gen/languageLexer.js +3 -0
  45. package/lib/gen/languageParser.js +4332 -4496
  46. package/lib/inspect/.eslintrc.json +4 -0
  47. package/lib/inspect/index.js +14 -0
  48. package/lib/inspect/inspectModelStatistics.js +81 -0
  49. package/lib/inspect/inspectPropagation.js +189 -0
  50. package/lib/inspect/inspectUtils.js +44 -0
  51. package/lib/json/from-csn.js +19 -20
  52. package/lib/json/to-csn.js +11 -8
  53. package/lib/language/genericAntlrParser.js +150 -92
  54. package/lib/language/language.g4 +47 -74
  55. package/lib/main.d.ts +1 -0
  56. package/lib/model/api.js +1 -1
  57. package/lib/model/csnRefs.js +56 -29
  58. package/lib/model/csnUtils.js +29 -14
  59. package/lib/model/revealInternalProperties.js +6 -4
  60. package/lib/modelCompare/compare.js +3 -0
  61. package/lib/optionProcessor.js +81 -38
  62. package/lib/render/toCdl.js +57 -32
  63. package/lib/render/toHdbcds.js +1 -1
  64. package/lib/render/toSql.js +31 -11
  65. package/lib/render/utils/common.js +3 -4
  66. package/lib/transform/db/associations.js +43 -35
  67. package/lib/transform/db/cdsPersistence.js +0 -1
  68. package/lib/transform/db/flattening.js +3 -4
  69. package/lib/transform/db/transformExists.js +7 -5
  70. package/lib/transform/draft/db.js +1 -1
  71. package/lib/transform/forHanaNew.js +11 -2
  72. package/lib/transform/forOdataNew.js +4 -4
  73. package/lib/transform/localized.js +15 -11
  74. package/lib/transform/odata/typesExposure.js +14 -5
  75. package/lib/utils/file.js +28 -18
  76. package/lib/utils/moduleResolve.js +0 -1
  77. package/package.json +3 -4
  78. package/share/messages/syntax-expected-integer.md +9 -8
  79. package/lib/checks/unknownMagic.js +0 -41
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  const { setProp } = require('../base/model');
3
- const { isBuiltinType, isEdmPropertyRendered } = require('../model/csnUtils');
3
+ const { isBuiltinType, isEdmPropertyRendered, applyTransformations } = require('../model/csnUtils');
4
4
  const { escapeString, hasControlCharacters, hasUnpairedUnicodeSurrogate } = require("../render/utils/stringEscapes");
5
5
 
6
6
  /* eslint max-statements-per-line:off */
@@ -27,8 +27,8 @@ function validateOptions(_options)
27
27
  if(options.v.filter(v=>v).length !== 1)
28
28
  throw Error(`Please debug me: EDM V2:${v2}, V4:${v4}`);
29
29
 
30
- options.isV2 = function() { return this.v[0]; }
31
- options.isV4 = function() { return this.v[1]; }
30
+ options.isV2 = () => v2;
31
+ options.isV4 = () => v4;
32
32
 
33
33
  options.pathDelimiter = options.isStructFormat ? '/' : '_';
34
34
 
@@ -56,22 +56,11 @@ function foreach(dictionary, filter, func) {
56
56
  });
57
57
  }
58
58
 
59
- // Call func(art, name) for each artifact 'art' with name 'name' in 'dictionary'
60
- function forAll(dictionary, func) {
61
- foreach(dictionary, ()=>true, func);
62
- }
63
-
64
59
  // true if _containerEntity is unequal to artifact name (non-recursive containment association)
65
60
  // or if artifact belongs to an artificial parameter entity
66
61
  function isContainee(artifact) {
67
- // if _containerEntity is present, it is guaranteed that it has at least one entry
68
- return (artifact._containerEntity && (artifact._containerEntity.length > 1 || artifact._containerEntity[0] != artifact.name));
69
- }
70
-
71
- // Return true if 'artifact' has an association type
72
- function isAssociation(artifact) {
73
- return (artifact.type === 'cds.Association' || artifact.type === 'Association') && artifact.target != undefined;
74
- //return artifact.target != undefined;
62
+ // if $containerNames is present, it is guaranteed that it has at least one entry
63
+ return (artifact.$containerNames && (artifact.$containerNames.length > 1 || artifact.$containerNames[0] != artifact.name));
75
64
  }
76
65
 
77
66
  function isComposition(artifact) {
@@ -79,16 +68,6 @@ function isComposition(artifact) {
79
68
  artifact.target != undefined;
80
69
  }
81
70
 
82
- function isAssociationOrComposition(artifact)
83
- {
84
- return isAssociation(artifact) || isComposition(artifact);
85
- }
86
-
87
- function isManagedAssociation(artifact)
88
- {
89
- return isAssociation(artifact) && artifact.on == undefined;
90
- }
91
-
92
71
  // Return true if the association 'assoc' has cardinality 'to-many'
93
72
  function isToMany(assoc) {
94
73
  if (!assoc.cardinality) {
@@ -108,13 +87,8 @@ function isSingleton(entityCsn) {
108
87
  return singleton || ((singleton === undefined || singleton === null) && hasNullable);
109
88
  }
110
89
 
111
- function isEntity(artifact)
112
- {
113
- return artifact.kind === 'entity';
114
- }
115
-
116
90
  function isParameterizedEntity(artifact) {
117
- return isEntity(artifact) && artifact.params;
91
+ return artifact.kind === 'entity' && artifact.params;
118
92
  }
119
93
 
120
94
  // Return true if 'artifact' is structured (i.e. has elements, like a structured type or an entity)
@@ -132,10 +106,6 @@ function isDerivedType(artifact) {
132
106
  return artifact.kind === 'type' && !isStructuredArtifact(artifact);
133
107
  }
134
108
 
135
- function isActionOrFunction(artifact) {
136
- return artifact.kind === 'action' || artifact.kind === 'function';
137
- }
138
-
139
109
  function resolveOnConditionAndPrepareConstraints(csn, assocCsn, messageFunctions) {
140
110
  if(!assocCsn._constraints)
141
111
  throw Error('Please debug me: need _constraints');
@@ -175,7 +145,7 @@ function resolveOnConditionAndPrepareConstraints(csn, assocCsn, messageFunctions
175
145
  info(null, ['definitions', parentName, 'elements', assocCsn.name],
176
146
  `"${originParentName}:${partnerPath.join('.')}" with target "${originAssocCsn._target.name}" is compared with $self which represents "${parentName}"`);
177
147
  }
178
- if(isAssociationOrComposition(originAssocCsn)) {
148
+ if(originAssocCsn.target) {
179
149
  // Mark this association as backlink if $self appears exactly once
180
150
  // to surpress edm:Association generation in V2 mode
181
151
  if(isBacklink) {
@@ -345,7 +315,7 @@ function finalizeReferentialConstraints(csn, assocCsn, options, info)
345
315
  // in structured mode only resolve top level element (path rewriting is done elsewhere)
346
316
  const depEltName = ( options.isFlatFormat ? c[0].join('_') : c[0][0] );
347
317
  const principalEltName = ( options.isFlatFormat ? c[1].join('_') : c[1][0] );
348
- const fk = (isEntity(dependentEntity) && dependentEntity.elements[ depEltName ]) ||
318
+ const fk = (dependentEntity.kind === 'entity' && dependentEntity.elements[ depEltName ]) ||
349
319
  (localDepEntity && localDepEntity.elements && localDepEntity.elements[ depEltName ]);
350
320
  const pk = principalEntity.$keys && principalEntity.$keys[ principalEltName ];
351
321
  if(isConstraintCandidate(fk) && isConstraintCandidate(pk)) {
@@ -783,24 +753,94 @@ function resolveOriginAssoc(csn, env, path) {
783
753
  return env;
784
754
  }
785
755
 
756
+ function mergeIntoNavPropEntry(annoPrefix, navPropEntry, prefix, props) {
757
+ let newEntry = false;
758
+
759
+ // Filter properties with prefix and reduce them into a new dictionary
760
+ const o = props.filter(p => p[0].startsWith(annoPrefix+'.')).reduce((a,c) => {
761
+ a[c[0].replace(annoPrefix+'.', '')] = c[1];
762
+ return a;
763
+ }, { });
764
+
765
+ // BEFORE merging found capabilities, prefix the paths
766
+ applyTransformations({ definitions: { o }}, {
767
+ "=": (parent, prop, value) => {
768
+ parent[prop] = prefix.concat(value).join('.');
769
+ }
770
+ });
771
+ // don't overwrite existing restrictions
772
+ const prop = annoPrefix.split('.')[1];
773
+ if(!navPropEntry[prop]) {
774
+ // if dictionary has entries, add them to navPropEnty
775
+ if(Object.keys(o).length) {
776
+ // ReadRestrictions may have sub type ReadByKeyRestrictions { Description, LongDescription }
777
+ // chop annotations into dictionaries
778
+ if(annoPrefix === '@Capabilities.ReadRestrictions' &&
779
+ Object.keys(o).some(k => k.startsWith('ReadByKeyRestrictions.'))) {
780
+ const no = {};
781
+ Object.entries(o).forEach(([k,v]) => {
782
+ const [head, ...tail] = k.split('.');
783
+ if(head === 'ReadByKeyRestrictions' && tail.length) {
784
+ if(!no['ReadByKeyRestrictions'])
785
+ no['ReadByKeyRestrictions'] = {};
786
+ // Don't try to add entry into non object
787
+ if(typeof no['ReadByKeyRestrictions'] === 'object')
788
+ no['ReadByKeyRestrictions'][tail.join('.')] = v;
789
+ }
790
+ else {
791
+ no[k] = v;
792
+ }
793
+ });
794
+ navPropEntry[prop] = no;
795
+ }
796
+ else {
797
+ navPropEntry[prop] = o;
798
+ }
799
+ newEntry = true;
800
+ }
801
+ }
802
+ else {
803
+ // merge but don't overwrite into existing navprop
804
+ Object.entries(o).forEach(([k,v]) => {
805
+ if(!navPropEntry[prop][k])
806
+ navPropEntry[prop][k] = v;
807
+ });
808
+ }
809
+ return newEntry;
810
+ }
811
+
812
+ // Assign but not overwrite annotation
813
+ function assignAnnotation(node, name, value) {
814
+ if(value !== undefined &&
815
+ name !== undefined && name[0] === '@' &&
816
+ (node[name] === undefined || node[name] === null)) {
817
+ node[name] = value;
818
+ }
819
+ }
820
+
821
+ // Set non enumerable property if it doesn't exist yet
822
+ function assignProp(obj, prop, value) {
823
+ if(obj[prop] === undefined) {
824
+ setProp(obj, prop, value);
825
+ }
826
+ }
827
+
828
+
829
+
786
830
  module.exports = {
831
+ assignAnnotation,
832
+ assignProp,
787
833
  validateOptions,
788
834
  intersect,
789
835
  foreach,
790
- forAll,
791
836
  isContainee,
792
- isAssociation,
793
- isManagedAssociation,
794
837
  isComposition,
795
- isAssociationOrComposition,
796
838
  isToMany,
797
839
  isSingleton,
798
- isEntity,
799
840
  isStructuredType,
800
841
  isStructuredArtifact,
801
842
  isParameterizedEntity,
802
843
  isDerivedType,
803
- isActionOrFunction,
804
844
  resolveOnConditionAndPrepareConstraints,
805
845
  finalizeReferentialConstraints,
806
846
  determineMultiplicity,
@@ -810,5 +850,6 @@ module.exports = {
810
850
  escapeStringForAttributeValue,
811
851
  escapeStringForText,
812
852
  getSchemaPrefix,
813
- getBaseName
853
+ getBaseName,
854
+ mergeIntoNavPropEntry
814
855
  }
@@ -989,8 +989,7 @@
989
989
  "NavigationProperty",
990
990
  "Action",
991
991
  "Function"
992
- ],
993
- "$experimental": true
992
+ ]
994
993
  },
995
994
  "Common.DerivedDefaultValue": {
996
995
  "Type": "Edm.String",
@@ -1424,6 +1423,13 @@
1424
1423
  "Type": "Graph.DetailsType",
1425
1424
  "$experimental": true
1426
1425
  },
1426
+ "Graph.CompositionRoot": {
1427
+ "Type": "Core.Tag",
1428
+ "AppliesTo": [
1429
+ "EntityType"
1430
+ ],
1431
+ "$experimental": true
1432
+ },
1427
1433
  "Hierarchy.RecursiveHierarchy": {
1428
1434
  "Type": "Hierarchy.RecursiveHierarchyType",
1429
1435
  "AppliesTo": [
@@ -2413,7 +2419,8 @@
2413
2419
  "CustomHeaders": "Collection(Capabilities.CustomParameter)",
2414
2420
  "CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
2415
2421
  "Description": "Edm.String",
2416
- "LongDescription": "Edm.String"
2422
+ "LongDescription": "Edm.String",
2423
+ "ErrorResponses": "Collection(Capabilities.HttpResponse)"
2417
2424
  }
2418
2425
  },
2419
2426
  "Capabilities.PermissionType": {
@@ -2455,7 +2462,8 @@
2455
2462
  "CustomHeaders": "Collection(Capabilities.CustomParameter)",
2456
2463
  "CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
2457
2464
  "Description": "Edm.String",
2458
- "LongDescription": "Edm.String"
2465
+ "LongDescription": "Edm.String",
2466
+ "ErrorResponses": "Collection(Capabilities.HttpResponse)"
2459
2467
  }
2460
2468
  },
2461
2469
  "Capabilities.DeepUpdateSupportType": {
@@ -2477,7 +2485,8 @@
2477
2485
  "CustomHeaders": "Collection(Capabilities.CustomParameter)",
2478
2486
  "CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
2479
2487
  "Description": "Edm.String",
2480
- "LongDescription": "Edm.String"
2488
+ "LongDescription": "Edm.String",
2489
+ "ErrorResponses": "Collection(Capabilities.HttpResponse)"
2481
2490
  }
2482
2491
  },
2483
2492
  "Capabilities.CollectionPropertyRestrictionsType": {
@@ -2502,7 +2511,8 @@
2502
2511
  "FilterSegmentSupported": "Edm.Boolean",
2503
2512
  "Permissions": "Collection(Capabilities.PermissionType)",
2504
2513
  "CustomHeaders": "Collection(Capabilities.CustomParameter)",
2505
- "CustomQueryOptions": "Collection(Capabilities.CustomParameter)"
2514
+ "CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
2515
+ "ErrorResponses": "Collection(Capabilities.HttpResponse)"
2506
2516
  }
2507
2517
  },
2508
2518
  "Capabilities.ModificationQueryOptionsType": {
@@ -2525,7 +2535,8 @@
2525
2535
  "CustomHeaders": "Collection(Capabilities.CustomParameter)",
2526
2536
  "CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
2527
2537
  "Description": "Edm.String",
2528
- "LongDescription": "Edm.String"
2538
+ "LongDescription": "Edm.String",
2539
+ "ErrorResponses": "Collection(Capabilities.HttpResponse)"
2529
2540
  }
2530
2541
  },
2531
2542
  "Capabilities.ReadByKeyRestrictionsType": {
@@ -2537,7 +2548,8 @@
2537
2548
  "CustomHeaders": "Collection(Capabilities.CustomParameter)",
2538
2549
  "CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
2539
2550
  "Description": "Edm.String",
2540
- "LongDescription": "Edm.String"
2551
+ "LongDescription": "Edm.String",
2552
+ "ErrorResponses": "Collection(Capabilities.HttpResponse)"
2541
2553
  }
2542
2554
  },
2543
2555
  "Capabilities.ReadRestrictionsType": {
@@ -2550,7 +2562,8 @@
2550
2562
  "CustomHeaders": "Collection(Capabilities.CustomParameter)",
2551
2563
  "CustomQueryOptions": "Collection(Capabilities.CustomParameter)",
2552
2564
  "Description": "Edm.String",
2553
- "LongDescription": "Edm.String"
2565
+ "LongDescription": "Edm.String",
2566
+ "ErrorResponses": "Collection(Capabilities.HttpResponse)"
2554
2567
  }
2555
2568
  },
2556
2569
  "Capabilities.CustomParameter": {
@@ -2563,6 +2576,13 @@
2563
2576
  "ExampleValues": "Collection(Core.PrimitiveExampleValue)"
2564
2577
  }
2565
2578
  },
2579
+ "Capabilities.HttpResponse": {
2580
+ "$kind": "ComplexType",
2581
+ "Properties": {
2582
+ "StatusCode": "Edm.String",
2583
+ "Description": "Edm.String"
2584
+ }
2585
+ },
2566
2586
  "Capabilities.FilterExpressionType": {
2567
2587
  "$kind": "TypeDefinition",
2568
2588
  "UnderlyingType": "Edm.String"
@@ -1 +1 @@
1
- dd18d05cabbe93eabf1bd17b83add5ee
1
+ 2067e213918678e2d85713a46e69d9cc