@sap/cds-compiler 3.0.2 → 3.1.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 (72) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/bin/.eslintrc.json +2 -1
  3. package/bin/cdsc.js +19 -0
  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 +7 -7
  9. package/lib/api/options.js +2 -3
  10. package/lib/base/message-registry.js +17 -5
  11. package/lib/base/messages.js +18 -39
  12. package/lib/base/model.js +2 -0
  13. package/lib/checks/actionsFunctions.js +8 -7
  14. package/lib/checks/selectItems.js +96 -14
  15. package/lib/checks/types.js +5 -8
  16. package/lib/checks/validator.js +1 -2
  17. package/lib/compiler/assert-consistency.js +64 -12
  18. package/lib/compiler/base.js +6 -4
  19. package/lib/compiler/builtins.js +58 -8
  20. package/lib/compiler/checks.js +1 -1
  21. package/lib/compiler/define.js +25 -22
  22. package/lib/compiler/extend.js +16 -10
  23. package/lib/compiler/finalize-parse-cdl.js +5 -9
  24. package/lib/compiler/index.js +2 -0
  25. package/lib/compiler/populate.js +34 -31
  26. package/lib/compiler/propagator.js +11 -6
  27. package/lib/compiler/resolve.js +14 -15
  28. package/lib/compiler/shared.js +53 -26
  29. package/lib/compiler/tweak-assocs.js +5 -11
  30. package/lib/compiler/utils.js +13 -4
  31. package/lib/edm/annotations/preprocessAnnotations.js +8 -4
  32. package/lib/edm/csn2edm.js +3 -3
  33. package/lib/edm/edm.js +9 -1
  34. package/lib/edm/edmAnnoPreprocessor.js +349 -0
  35. package/lib/edm/edmInboundChecks.js +85 -0
  36. package/lib/edm/edmPreprocessor.js +295 -638
  37. package/lib/edm/edmUtils.js +85 -5
  38. package/lib/gen/Dictionary.json +29 -9
  39. package/lib/gen/language.checksum +1 -1
  40. package/lib/gen/language.interp +1 -2
  41. package/lib/gen/languageLexer.js +3 -0
  42. package/lib/gen/languageParser.js +4344 -4530
  43. package/lib/inspect/.eslintrc.json +4 -0
  44. package/lib/inspect/index.js +14 -0
  45. package/lib/inspect/inspectModelStatistics.js +81 -0
  46. package/lib/inspect/inspectPropagation.js +189 -0
  47. package/lib/inspect/inspectUtils.js +44 -0
  48. package/lib/json/from-csn.js +3 -2
  49. package/lib/json/to-csn.js +8 -6
  50. package/lib/language/genericAntlrParser.js +121 -63
  51. package/lib/language/language.g4 +19 -57
  52. package/lib/main.d.ts +1 -0
  53. package/lib/model/api.js +1 -1
  54. package/lib/model/csnRefs.js +55 -29
  55. package/lib/model/csnUtils.js +11 -7
  56. package/lib/model/revealInternalProperties.js +2 -3
  57. package/lib/modelCompare/compare.js +3 -0
  58. package/lib/optionProcessor.js +27 -0
  59. package/lib/render/toCdl.js +57 -32
  60. package/lib/render/toSql.js +24 -8
  61. package/lib/render/utils/common.js +3 -4
  62. package/lib/transform/db/associations.js +43 -35
  63. package/lib/transform/db/cdsPersistence.js +0 -1
  64. package/lib/transform/db/flattening.js +3 -4
  65. package/lib/transform/db/transformExists.js +7 -5
  66. package/lib/transform/draft/db.js +1 -1
  67. package/lib/transform/forHanaNew.js +11 -2
  68. package/lib/transform/forOdataNew.js +1 -1
  69. package/lib/transform/odata/typesExposure.js +14 -5
  70. package/lib/utils/moduleResolve.js +0 -1
  71. package/package.json +2 -2
  72. package/lib/checks/unknownMagic.js +0 -41
@@ -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
 
@@ -59,8 +59,8 @@ function foreach(dictionary, filter, func) {
59
59
  // true if _containerEntity is unequal to artifact name (non-recursive containment association)
60
60
  // or if artifact belongs to an artificial parameter entity
61
61
  function isContainee(artifact) {
62
- // if _containerEntity is present, it is guaranteed that it has at least one entry
63
- return (artifact._containerEntity && (artifact._containerEntity.length > 1 || artifact._containerEntity[0] != artifact.name));
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));
64
64
  }
65
65
 
66
66
  function isComposition(artifact) {
@@ -753,7 +753,86 @@ function resolveOriginAssoc(csn, env, path) {
753
753
  return env;
754
754
  }
755
755
 
756
+ function mergeIntoNavPropRestrictions(annoPrefix, assocPath, props, navPropRestrictions) {
757
+ let navPropEntry;
758
+ let hasEntry = false;
759
+ let newEntry = false;
760
+ hasEntry = !!(navPropEntry = navPropRestrictions.find(p =>
761
+ p.NavigationProperty && p.NavigationProperty['='] === assocPath));
762
+
763
+ if(!hasEntry) {
764
+ navPropEntry = { NavigationProperty: { '=': assocPath } };
765
+ }
766
+
767
+ const prop = annoPrefix.split('.')[1];
768
+ // Filter properties with prefix and reduce them into a new dictionary
769
+ const o = props.filter(p => p[0].startsWith(annoPrefix+'.')).reduce((a,c) => {
770
+ a[c[0].replace(annoPrefix+'.', '')] = c[1];
771
+ return a;
772
+ }, { });
773
+ // don't overwrite existing restrictions
774
+ if(!navPropEntry[prop]) {
775
+ // if dictionary has entries, add them to navPropEnty
776
+ if(Object.keys(o).length) {
777
+ // ReadRestrictions may have sub type ReadByKeyRestrictions { Description, LongDescription }
778
+ // chop annotations into dictionaries
779
+ if(annoPrefix === '@Capabilities.ReadRestrictions' &&
780
+ Object.keys(o).some(k => k.startsWith('ReadByKeyRestrictions.'))) {
781
+ const no = {};
782
+ Object.entries(o).forEach(([k,v]) => {
783
+ const [head, ...tail] = k.split('.');
784
+ if(head === 'ReadByKeyRestrictions' && tail.length) {
785
+ if(!no['ReadByKeyRestrictions'])
786
+ no['ReadByKeyRestrictions'] = {};
787
+ // Don't try to add entry into non object
788
+ if(typeof no['ReadByKeyRestrictions'] === 'object')
789
+ no['ReadByKeyRestrictions'][tail.join('.')] = v;
790
+ }
791
+ else {
792
+ no[k] = v;
793
+ }
794
+ });
795
+ navPropEntry[prop] = no;
796
+ }
797
+ else {
798
+ navPropEntry[prop] = o;
799
+ }
800
+ newEntry = true;
801
+ }
802
+ }
803
+ else {
804
+ // merge but don't overwrite into existing navprop
805
+ Object.entries(o).forEach(([k,v]) => {
806
+ if(!navPropEntry[prop][k])
807
+ navPropEntry[prop][k] = v;
808
+ });
809
+ }
810
+ if(newEntry && !hasEntry) {
811
+ navPropRestrictions.push(navPropEntry);
812
+ }
813
+ }
814
+
815
+ // Assign but not overwrite annotation
816
+ function assignAnnotation(node, name, value) {
817
+ if(value !== undefined &&
818
+ name !== undefined && name[0] === '@' &&
819
+ (node[name] === undefined || node[name] === null)) {
820
+ node[name] = value;
821
+ }
822
+ }
823
+
824
+ // Set non enumerable property if it doesn't exist yet
825
+ function assignProp(obj, prop, value) {
826
+ if(obj[prop] === undefined) {
827
+ setProp(obj, prop, value);
828
+ }
829
+ }
830
+
831
+
832
+
756
833
  module.exports = {
834
+ assignAnnotation,
835
+ assignProp,
757
836
  validateOptions,
758
837
  intersect,
759
838
  foreach,
@@ -774,5 +853,6 @@ module.exports = {
774
853
  escapeStringForAttributeValue,
775
854
  escapeStringForText,
776
855
  getSchemaPrefix,
777
- getBaseName
856
+ getBaseName,
857
+ mergeIntoNavPropRestrictions
778
858
  }
@@ -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
- ca4caa65192cebc39f35cd598958dbb0
1
+ 2067e213918678e2d85713a46e69d9cc