@sap/cds-compiler 2.7.0 → 2.11.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 (87) hide show
  1. package/CHANGELOG.md +167 -0
  2. package/bin/cdsc.js +42 -25
  3. package/bin/cdsse.js +1 -0
  4. package/doc/CHANGELOG_BETA.md +10 -0
  5. package/lib/api/.eslintrc.json +2 -0
  6. package/lib/api/main.js +17 -33
  7. package/lib/api/options.js +25 -13
  8. package/lib/api/validate.js +33 -9
  9. package/lib/backends.js +9 -8
  10. package/lib/base/dictionaries.js +2 -1
  11. package/lib/base/keywords.js +32 -2
  12. package/lib/base/message-registry.js +26 -2
  13. package/lib/base/messages.js +25 -9
  14. package/lib/base/model.js +5 -3
  15. package/lib/base/optionProcessorHelper.js +56 -22
  16. package/lib/checks/onConditions.js +5 -0
  17. package/lib/checks/selectItems.js +4 -0
  18. package/lib/checks/types.js +26 -2
  19. package/lib/checks/unknownMagic.js +41 -0
  20. package/lib/checks/validator.js +7 -2
  21. package/lib/compiler/assert-consistency.js +18 -5
  22. package/lib/compiler/base.js +65 -0
  23. package/lib/compiler/builtins.js +30 -1
  24. package/lib/compiler/checks.js +5 -2
  25. package/lib/compiler/definer.js +145 -120
  26. package/lib/compiler/index.js +16 -4
  27. package/lib/compiler/propagator.js +5 -2
  28. package/lib/compiler/resolver.js +207 -47
  29. package/lib/compiler/shared.js +47 -200
  30. package/lib/compiler/utils.js +173 -0
  31. package/lib/edm/annotations/genericTranslation.js +183 -187
  32. package/lib/edm/csn2edm.js +94 -98
  33. package/lib/edm/edm.js +16 -20
  34. package/lib/edm/edmPreprocessor.js +302 -115
  35. package/lib/edm/edmUtils.js +31 -12
  36. package/lib/gen/language.checksum +1 -1
  37. package/lib/gen/language.interp +28 -1
  38. package/lib/gen/language.tokens +79 -69
  39. package/lib/gen/languageLexer.interp +28 -1
  40. package/lib/gen/languageLexer.js +879 -805
  41. package/lib/gen/languageLexer.tokens +71 -62
  42. package/lib/gen/languageParser.js +5308 -4308
  43. package/lib/json/from-csn.js +59 -30
  44. package/lib/json/to-csn.js +354 -105
  45. package/lib/language/antlrParser.js +11 -0
  46. package/lib/language/errorStrategy.js +1 -0
  47. package/lib/language/genericAntlrParser.js +81 -14
  48. package/lib/language/language.g4 +163 -31
  49. package/lib/main.d.ts +136 -17
  50. package/lib/main.js +7 -1
  51. package/lib/model/api.js +78 -0
  52. package/lib/model/csnRefs.js +115 -32
  53. package/lib/model/csnUtils.js +71 -33
  54. package/lib/model/enrichCsn.js +36 -9
  55. package/lib/model/revealInternalProperties.js +20 -4
  56. package/lib/modelCompare/compare.js +2 -1
  57. package/lib/optionProcessor.js +33 -16
  58. package/lib/render/.eslintrc.json +3 -1
  59. package/lib/render/DuplicateChecker.js +1 -1
  60. package/lib/render/toCdl.js +60 -17
  61. package/lib/render/toHdbcds.js +122 -74
  62. package/lib/render/toSql.js +57 -32
  63. package/lib/render/utils/common.js +6 -10
  64. package/lib/sql-identifier.js +6 -1
  65. package/lib/transform/db/constraints.js +273 -119
  66. package/lib/transform/db/draft.js +9 -6
  67. package/lib/transform/db/expansion.js +19 -7
  68. package/lib/transform/db/flattening.js +31 -7
  69. package/lib/transform/db/transformExists.js +344 -66
  70. package/lib/transform/db/views.js +438 -0
  71. package/lib/transform/forHanaNew.js +65 -436
  72. package/lib/transform/forOdataNew.js +21 -10
  73. package/lib/transform/localized.js +2 -0
  74. package/lib/transform/odata/attachPath.js +19 -4
  75. package/lib/transform/odata/generateForeignKeyElements.js +11 -10
  76. package/lib/transform/odata/referenceFlattener.js +44 -38
  77. package/lib/transform/odata/sortByAssociationDependency.js +2 -2
  78. package/lib/transform/odata/structuralPath.js +72 -0
  79. package/lib/transform/odata/structureFlattener.js +13 -10
  80. package/lib/transform/odata/typesExposure.js +22 -12
  81. package/lib/transform/transformUtilsNew.js +55 -9
  82. package/lib/transform/translateAssocsToJoins.js +11 -17
  83. package/lib/transform/universalCsnEnricher.js +67 -0
  84. package/lib/utils/file.js +5 -3
  85. package/lib/utils/term.js +65 -42
  86. package/lib/utils/timetrace.js +48 -26
  87. package/package.json +1 -1
@@ -2,6 +2,7 @@
2
2
 
3
3
  const { setProp } = require('../base/model');
4
4
  const { csnRefs } = require('../model/csnRefs');
5
+ const { isBuiltinType } = require('../compiler/builtins.js')
5
6
  const { sortCsn, cloneCsnDictionary: _cloneCsnDictionary } = require('../json/to-csn');
6
7
  const version = require('../../package.json').version;
7
8
 
@@ -11,8 +12,8 @@ const version = require('../../package.json').version;
11
12
  * Generic Callback
12
13
  *
13
14
  * @callback genericCallback
14
- * @param {CSN.Artifact} art
15
- * @param {CSN.FQN} name Artifact Name
15
+ * @param {any} art
16
+ * @param {string} name Artifact Name
16
17
  * @param {string} prop Dictionary Property
17
18
  * @param {CSN.Path} path Location
18
19
  * @param {CSN.Artifact} [dictionary]
@@ -36,7 +37,7 @@ const version = require('../../package.json').version;
36
37
  * @param {CSN.Model} model (Compact) CSN model
37
38
  */
38
39
  function getUtils(model) {
39
- const { artifactRef, inspectRef, effectiveType } = csnRefs(model);
40
+ const { artifactRef, inspectRef, effectiveType, getOrigin } = csnRefs(model);
40
41
 
41
42
  return {
42
43
  getCsnDef,
@@ -59,6 +60,7 @@ function getUtils(model) {
59
60
  artifactRef,
60
61
  effectiveType,
61
62
  get$combined,
63
+ getOrigin,
62
64
  };
63
65
 
64
66
  /**
@@ -456,8 +458,8 @@ function getUtils(model) {
456
458
  return resultNode;
457
459
  }
458
460
  }
459
-
460
-
461
+
462
+
461
463
  /**
462
464
  * Resolve to the final type of a type, that means follow type chains, references to other types or
463
465
  * elements a.s.o
@@ -496,12 +498,12 @@ function getUtils(model) {
496
498
  * Composed types (structures, entities, views, ...) are returned as type objects, if not drilled down into
497
499
  * the elements. Path steps that have no corresponding element lead to 'undefined'. Refs to something that has
498
500
  * no type (e.g. expr in a view without explicit type) returns 'null'
499
- *
501
+ *
500
502
  * @param {string|object} type Type - either string or ref
501
- * @param {CSN.Path} path
503
+ * @param {CSN.Path} path
502
504
  * @param {WeakMap} [resolved=new WeakMap()] WeakMap containing already resolved refs - if a ref is not cached, it will be resolved JIT
503
- * @param {object} [cycleCheck] Dictionary to remember already resolved types - to be cycle-safe
504
- * @returns
505
+ * @param {object} [cycleCheck] Dictionary to remember already resolved types - to be cycle-safe
506
+ * @returns
505
507
  */
506
508
  function getFinalBaseType(type, path = [], resolved = new WeakMap(), cycleCheck = undefined) {
507
509
  if (!type)
@@ -551,16 +553,6 @@ function getUtils(model) {
551
553
  }
552
554
  }
553
555
 
554
- // Tell if a type is (directly) a builtin type
555
- // Note that in CSN builtins are not in the definition of the model, so we can only check against their absolute names.
556
- // Builtin types are "cds.<something>", i.e. they are directly in 'cds', but not for example
557
- // in 'cds.foundation'. Also note, that a type might be a ref object, that refers to something else,
558
- // so if you consider type chains don't forget first to resolve to the final type before
559
- function isBuiltinType(type) {
560
- return typeof(type) === 'string' && type.startsWith('cds.') && !type.startsWith('cds.foundation.')
561
- }
562
-
563
-
564
556
  /**
565
557
  * Deeply clone the given CSN model and return it.
566
558
  * In testMode (or with testSortCsn), definitions are sorted.
@@ -630,12 +622,12 @@ function forEachMember( construct, callback, path=[], ignoreIgnore=true, iterate
630
622
  // Backends rely on the fact that `forEachElement` also goes through all
631
623
  // `elements` of the return type (if structured).
632
624
  // TODO: `returns` should be handled like a parameter just like XSN (maybe with different prop name)
633
- if (construct.returns) {
625
+ if (construct.returns && !iterateOptions.elementsOnly) {
634
626
  forEachMember( construct.returns, callback, [...path, 'returns'], ignoreIgnore, iterateOptions );
635
627
  }
636
628
 
637
629
  path = [...path]; // Copy
638
- const propsWithMembers = ['elements', 'enum', 'foreignKeys', 'actions', 'params'];
630
+ const propsWithMembers = (iterateOptions.elementsOnly ? ['elements'] : ['elements', 'enum', 'foreignKeys', 'actions', 'params']);
639
631
  propsWithMembers.forEach((prop) => forEachGeneric( construct, prop, callback, path, iterateOptions ));
640
632
  }
641
633
 
@@ -816,11 +808,25 @@ function forAllQueries(query, callback, path = []){
816
808
  }
817
809
  }
818
810
 
819
- function forAllElements(artifact, artifactName, cb){
811
+ function forAllElements(artifact, artifactName, cb, includeActions = false){
820
812
  if(artifact.elements) {
821
813
  cb(artifact, artifact.elements, ['definitions', artifactName, 'elements']);
822
814
  }
823
815
 
816
+ if(includeActions && artifact.actions) {
817
+ Object.entries(artifact.actions).forEach( ([actionName, action]) => {
818
+ const path = ['definitions', artifactName, 'actions', actionName];
819
+ if(action.params) {
820
+ Object.entries(action.params).forEach( ([paramName, param]) => {
821
+ if(param.elements)
822
+ cb(param, param.elements, path.concat(['params', paramName, 'elements']));
823
+ });
824
+ }
825
+ if(action.returns && action.returns.elements)
826
+ cb(action.returns, action.returns.elements,path.concat(['returns', 'elements']));
827
+ });
828
+ }
829
+
824
830
  if(artifact.query) {
825
831
  forAllQueries(artifact.query, (q, p) => {
826
832
  const s = q.SELECT;
@@ -870,7 +876,7 @@ function hasAnnotationValue(artifact, annotationName, expected = true) {
870
876
  * function accepts EDM internal and external options
871
877
  *
872
878
  * @param {CSN.Element} elementCsn
873
- * @param {CSN.Options & CSN.ODataOptions} options EDM specific options
879
+ * @param {ODataOptions} options EDM specific options
874
880
  */
875
881
  function isEdmPropertyRendered(elementCsn, options) {
876
882
  if(options.toOdata)
@@ -920,10 +926,10 @@ function getArtifactDatabaseNameOf(artifactName, namingConvention, csn) {
920
926
  throw new Error('Unknown naming convention: ' + namingConvention);
921
927
  }
922
928
  else {
923
- const namespace = csn;
924
929
  console.error(`This invocation of "getArtifactCdsPersistenceName" is deprecated, as it doesn't produce correct output with definition names containing dots - please provide a CSN as the third parameter.`);
925
930
  if (namingConvention === 'hdbcds') {
926
- if (namespace) {
931
+ if (csn) {
932
+ const namespace = String(csn);
927
933
  return `${namespace}::${artifactName.substring(namespace.length + 1)}`;
928
934
  }
929
935
  return artifactName;
@@ -1097,7 +1103,7 @@ function applyTransformations( csn, customTransformers={}, artifactTransformers=
1097
1103
  for (let name of Object.getOwnPropertyNames( node )) {
1098
1104
  const trans = transformers[name] || standard;
1099
1105
  if(customTransformers[name])
1100
- customTransformers[name](node, name, node[name], csnPath);
1106
+ customTransformers[name](node, name, node[name], csnPath, parent, prop);
1101
1107
 
1102
1108
  trans( node, name, node[name], csnPath );
1103
1109
  }
@@ -1106,6 +1112,9 @@ function applyTransformations( csn, customTransformers={}, artifactTransformers=
1106
1112
  }
1107
1113
 
1108
1114
  function dictionary( node, prop, dict ) {
1115
+ // Allow skipping dicts like actions in forHanaNew
1116
+ if(options.skipDict && options.skipDict[prop])
1117
+ return;
1109
1118
  csnPath.push( prop );
1110
1119
  for (let name of Object.getOwnPropertyNames( dict )) {
1111
1120
  standard( dict, name, dict[name] );
@@ -1528,7 +1537,7 @@ function sortCsnDefinitionsForTests(csn, options) {
1528
1537
  if (!options.testMode)
1529
1538
  return;
1530
1539
  const sorted = Object.create(null);
1531
- Object.keys(csn.definitions).sort().forEach((name) => {
1540
+ Object.keys(csn.definitions || {}).sort().forEach((name) => {
1532
1541
  sorted[name] = csn.definitions[name];
1533
1542
  });
1534
1543
  csn.definitions = sorted;
@@ -1538,7 +1547,7 @@ function sortCsnDefinitionsForTests(csn, options) {
1538
1547
  * Return an array of non-abstract service names contained in CSN
1539
1548
  *
1540
1549
  * @param {CSN.Model} csn
1541
- * @returns {CSN.Service[]}
1550
+ * @returns {string[]}
1542
1551
  */
1543
1552
  function getServiceNames(csn) {
1544
1553
  let result = [];
@@ -1552,8 +1561,8 @@ function getServiceNames(csn) {
1552
1561
 
1553
1562
  /**
1554
1563
  * Check wether the artifact is @cds.persistence.skip
1555
- *
1556
- * @param {CSN.Artifact} artifact
1564
+ *
1565
+ * @param {CSN.Artifact} artifact
1557
1566
  * @returns {Boolean}
1558
1567
  */
1559
1568
  function isSkipped(artifact) {
@@ -1562,9 +1571,9 @@ function isSkipped(artifact) {
1562
1571
 
1563
1572
  /**
1564
1573
  * Walk path in the CSN and return the result.
1565
- *
1566
- * @param {CSN.Model} csn
1567
- * @param {CSN.Path} path
1574
+ *
1575
+ * @param {CSN.Model} csn
1576
+ * @param {CSN.Path} path
1568
1577
  * @returns {object} Whatever is at the end of path
1569
1578
  */
1570
1579
  function walkCsnPath(csn, path) {
@@ -1577,6 +1586,34 @@ function walkCsnPath(csn, path) {
1577
1586
  return obj;
1578
1587
  }
1579
1588
 
1589
+ /**
1590
+ * If provided, get the replacement string for the given magic variable ref.
1591
+ * No validation is done that the ref is actually magic!
1592
+ *
1593
+ * @param {array} ref
1594
+ * @param {CSN.Options} options
1595
+ * @returns {string|null}
1596
+ */
1597
+ function getVariableReplacement(ref, options) {
1598
+ if(options && options.variableReplacements) {
1599
+ let replacement = options.variableReplacements;
1600
+ for(let i = 0; i < ref.length; i++) {
1601
+ replacement = replacement[ref[i]];
1602
+ if(replacement === undefined)
1603
+ return null;
1604
+ }
1605
+
1606
+ if(replacement === undefined)
1607
+ return null; // no valid replacement found
1608
+ else if(typeof replacement === 'string')
1609
+ return replacement; // valid replacement
1610
+ else
1611
+ return null; // $user.foo, but we only have configured $user.foo.bar -> error
1612
+ } else {
1613
+ return null;
1614
+ }
1615
+ }
1616
+
1580
1617
  module.exports = {
1581
1618
  getUtils,
1582
1619
  cloneCsn,
@@ -1617,4 +1654,5 @@ module.exports = {
1617
1654
  getServiceNames,
1618
1655
  isSkipped,
1619
1656
  walkCsnPath,
1657
+ getVariableReplacement
1620
1658
  };
@@ -39,6 +39,8 @@ function enrichCsn( csn, options = {} ) {
39
39
  params: dictionary,
40
40
  enum: dictionary,
41
41
  mixin: dictionary,
42
+ returns: definition,
43
+ items: definition,
42
44
  ref: pathRef,
43
45
  type: simpleRef,
44
46
  targetAspect: simpleRef,
@@ -81,10 +83,19 @@ function enrichCsn( csn, options = {} ) {
81
83
  csnPath.pop();
82
84
  }
83
85
 
86
+ function definition( parent, prop, obj ) {
87
+ const origin = getOrigin( obj ); // before standard for implicit protos inside
88
+ standard( parent, prop, obj );
89
+ if (obj.$origin === undefined && origin != null)
90
+ obj._origin = refLocation( origin );
91
+ }
92
+
84
93
  function dictionary( parent, prop, dict ) {
94
+ if (!dict) // value null for inheritance interruption
95
+ return;
85
96
  csnPath.push( prop );
86
97
  for (let name of Object.getOwnPropertyNames( dict )) {
87
- standard( dict, name, dict[name] );
98
+ definition( dict, name, dict[name] );
88
99
  }
89
100
  if (!Object.prototype.propertyIsEnumerable.call( parent, prop ))
90
101
  parent['$'+prop] = dict;
@@ -123,13 +134,17 @@ function enrichCsn( csn, options = {} ) {
123
134
 
124
135
  function $origin( parent, prop, ref ) {
125
136
  if (options.testMode) {
126
- if (Array.isArray( ref )) // $origin: […], not $origin: {…}
127
- parent._origin = refLocation( getOrigin( parent ) );
137
+ if (Array.isArray( ref ) || typeof ref === 'string') // $origin: […], not $origin: {…}
138
+ parent._origin = refLocation( getOrigin( parent, true ) );
139
+ else if ( ref )
140
+ standard( parent, prop, ref )
128
141
  }
129
142
  else {
130
143
  try {
131
- if (Array.isArray( ref )) // $origin: […], not $origin: {…}
132
- parent._origin = refLocation( getOrigin( parent ) );
144
+ if (Array.isArray( ref ) || typeof ref === 'string') // $origin: […], not $origin: {…}
145
+ parent._origin = refLocation( getOrigin( parent, true ) );
146
+ else if ( ref )
147
+ standard( parent, prop, ref )
133
148
  } catch (e) {
134
149
  parent._origin = e.toString();
135
150
  }
@@ -171,10 +186,10 @@ function enrichCsn( csn, options = {} ) {
171
186
  csnPath.pop();
172
187
  }
173
188
 
174
- function _cache_debug( obj ) {
189
+ function _cache_debug( obj, subCache ) {
175
190
  if (options.enrichCsn !== 'DEBUG')
176
191
  return;
177
- const cache = __getCache_forEnrichCsnDebugging( obj );
192
+ const cache = subCache || __getCache_forEnrichCsnDebugging( obj );
178
193
  if (!cache)
179
194
  return;
180
195
  if (cache.$$objectNumber > 0) {
@@ -197,8 +212,20 @@ function enrichCsn( csn, options = {} ) {
197
212
  }
198
213
  else if (name[0] !== '$' || !Object.getPrototypeOf( val )) {
199
214
  // ‹name›: dictionary of CSN nodes,
200
- // ‹$name›: dictionary of cache values if no prototype,
201
- obj.$$cacheObject[name] = Object.keys( val ); // TODO: or dict?
215
+ // ‹$name›: dictionary of cache values if no prototype
216
+ if (name !== '$aliases') {
217
+ obj.$$cacheObject[name] = Object.keys( val ); // TODO: or dict?
218
+ }
219
+ else {
220
+ const sub = Object.create(null);
221
+ for (const n in val) {
222
+ const alias = val[n];
223
+ const c = {};
224
+ _cache_debug( c, alias );
225
+ sub[n] = c.$$cacheObject;
226
+ }
227
+ obj.$$cacheObject[name] = sub;
228
+ }
202
229
  }
203
230
  else if (Array.isArray( val )) {
204
231
  obj.$$cacheObject[name] = val.map( item => {
@@ -13,6 +13,8 @@
13
13
 
14
14
  const msg = require('../base/messages');
15
15
 
16
+ const $inferred = Symbol.for('cds.$inferred');
17
+
16
18
  class NOT_A_DICTIONARY {} // used for consol.log display
17
19
 
18
20
  function locationString( loc ) {
@@ -32,15 +34,22 @@ const kindsRepresentedAsLinks = {
32
34
  // represent SELECTs in query / SET-args property as link:
33
35
  select: (art, parent) => art._main && parent !== art._main.$queries,
34
36
  // represent table alias in from / join-args property as link:
35
- $tableAlias: (art, parent) => art._parent && parent !== art._parent.$tableAliases,
36
- // represent table alias in JOIN node as link:
37
+ $tableAlias: tableAliasAsLink,
38
+ // represent "navigation elemens" in _combined as links:
37
39
  $navElement: (art, parent) => art._parent && parent !== art._parent.elements,
38
40
  // represent mixin in $tableAliases as link:
39
- mixin: (art, parent) => art._parent && parent !== art._parent.mixin,
41
+ mixin: tableAliasAsLink,
40
42
  // represent $projection as link, as it is just another search name for $self:
41
43
  $self: (_a, _p, name) => name !== '$self',
42
44
  }
43
45
 
46
+ function tableAliasAsLink( art, parent, name ) {
47
+ return art._parent && art._parent.$tableAliases && // initXYZ() is run
48
+ parent !== art._parent.$tableAliases && // not in $tableAliases
49
+ !(art.$duplicates === true && name && // and its $duplicates
50
+ parent === art._parent.$tableAliases[name].$duplicates);
51
+ }
52
+
44
53
  function revealInternalProperties( model, name ) {
45
54
  const transformers = {
46
55
  messages: m => m,
@@ -65,6 +74,7 @@ function revealInternalProperties( model, name ) {
65
74
  mixin: dictionary,
66
75
  args: dictionary,
67
76
  $tableAliases: dictionary,
77
+ $duplicates: duplicates,
68
78
  $keysNavigation: dictionary,
69
79
  $layerNumber: n => n,
70
80
  $extra: e => e,
@@ -203,6 +213,8 @@ function revealInternalProperties( model, name ) {
203
213
  for (let prop of Object.getOwnPropertyNames( node )) { // also non-enumerable
204
214
  r[prop] = reveal( node[prop], node, prop );
205
215
  }
216
+ if (node[$inferred] && !node['[$inferred]'])
217
+ r['[$inferred]'] = node[$inferred];
206
218
  return r;
207
219
  }
208
220
 
@@ -228,7 +240,7 @@ function revealInternalProperties( model, name ) {
228
240
  if (node == null || typeof node !== 'object' )
229
241
  return node
230
242
  if (Array.isArray(node))
231
- return node.map( n => reveal( n, node ) );
243
+ return node.map( n => reveal( n, node, name ) );
232
244
 
233
245
  const asLinkTest = kindsRepresentedAsLinks[ node.kind ];
234
246
  if (asLinkTest && asLinkTest( node, parent, name ))
@@ -246,6 +258,10 @@ function revealInternalProperties( model, name ) {
246
258
  }
247
259
  return r;
248
260
  }
261
+
262
+ function duplicates( node, parent ) {
263
+ return reveal( node, parent, parent.name && parent.name.id );
264
+ }
249
265
  }
250
266
 
251
267
  function artifactIdentifier( node, parent ) {
@@ -12,11 +12,12 @@ const {
12
12
  *
13
13
  * @param beforeModel the before-model
14
14
  * @param afterModel the after-model
15
- * @param {hdiOptions|false} options
15
+ * @param {import('../api/main.js').hdiOptions|false} options
16
16
  * @returns {object} the sets of deletions, extensions, and migrations of entities necessary to transform the before-model
17
17
  * to the after-model, together with all the definitions of the after-model
18
18
  */
19
19
  function compareModels(beforeModel, afterModel, options) {
20
+ // @ts-ignore
20
21
  if(!(options && options.testMode)) // no $version with testMode
21
22
  validateCsnVersions(beforeModel, afterModel, options);
22
23
 
@@ -27,8 +27,10 @@ optionProcessor
27
27
  .option(' --internal-msg')
28
28
  .option(' --beta-mode')
29
29
  .option(' --beta <list>')
30
- .option(' --constraints-not-validated')
31
- .option(' --constraints-not-enforced')
30
+ .option(' --integrity-not-validated')
31
+ .option(' --integrity-not-enforced')
32
+ .option(' --assert-integrity <mode>', [ 'true', 'false', 'individual' ])
33
+ .option(' --assert-integrity-type <type>', [ 'RT', 'DB' ])
32
34
  .option(' --deprecated <list>')
33
35
  .option(' --hana-flavor')
34
36
  .option(' --direct-backend')
@@ -37,8 +39,11 @@ optionProcessor
37
39
  .option(' --test-mode')
38
40
  .option(' --test-sort-csn')
39
41
  .option(' --doc-comment')
42
+ .option(' --add-texts-language-assoc')
40
43
  .option(' --localized-without-coalesce')
41
- .option(' --defaultStringLength <length>')
44
+ .option(' --default-binary-length <length>')
45
+ .option(' --default-string-length <length>')
46
+ .option(' --no-recompile')
42
47
  .positionalArgument('<files...>')
43
48
  .help(`
44
49
  Usage: cdsc <command> [options] <files...>
@@ -73,7 +78,8 @@ optionProcessor
73
78
  -- Indicate the end of options (helpful if source names start with "-")
74
79
 
75
80
  Type options
76
- --defaultStringLength <length> Default 'length' for 'cds.String'
81
+ --default-binary-length <length> Default 'length' for 'cds.Binary'
82
+ --default-string-length <length> Default 'length' for 'cds.String'
77
83
 
78
84
  Diagnostic options
79
85
  --trace-parser Trace parser
@@ -88,15 +94,23 @@ optionProcessor
88
94
  --beta-mode Enable all unsupported, incomplete (beta) features
89
95
  --beta <list> Comma separated list of unsupported, incomplete (beta) features to use.
90
96
  Valid values are:
91
- foreignKeyConstraints
92
97
  addTextsLanguageAssoc
93
98
  hanaAssocRealCardinality
94
99
  mapAssocToJoinCardinality
95
100
  ignoreAssocPublishingInUnion
96
- --constraints-not-enforced If this option is supplied, referential constraints are NOT ENFORCED
97
- This option is also applied to result of "cdsc manageConstraints"
98
- --constraints-not-validated If this option is supplied, referential constraints are NOT VALIDATED
99
- This option is also applied to result of "cdsc manageConstraints"
101
+ --integrity-not-enforced If this option is supplied, referential constraints are NOT ENFORCED.
102
+ This option is also applied to result of "cdsc manageConstraints"
103
+ --integrity-not-validated If this option is supplied, referential constraints are NOT VALIDATED.
104
+ This option is also applied to result of "cdsc manageConstraints"
105
+ --assert-integrity <mode> Turn DB constraints on/off:
106
+ true : Constraints will be generated for all associations if
107
+ the assert-integrity-type is set to DB
108
+ false : No constraints will be generated
109
+ individual : Constraints will be generated for selected associations
110
+ --assert-integrity-type <type> Specifies how the referential integrity checks should be performed:
111
+ RT : (default) No database constraint for an association
112
+ if not explicitly demanded via annotation
113
+ DB : Create database constraints for associations
100
114
  --deprecated <list> Comma separated list of deprecated options.
101
115
  Valid values are:
102
116
  noElementsExpansion
@@ -123,7 +137,10 @@ optionProcessor
123
137
  OData CSN, CDL order and more. When --test-mode is enabled, this
124
138
  option is implicitly enabled as well.
125
139
  --doc-comment Preserve /** */ comments at annotation positions as doc property in CSN
140
+ --add-texts-language-assoc In generated texts entities, add association "language"
141
+ to "sap.common.Languages" if it exists
126
142
  --localized-without-coalesce Omit coalesce in localized convenience views
143
+ --no-recompile Don't recompile in case of internal errors
127
144
 
128
145
  Commands
129
146
  H, toHana [options] <files...> Generate HANA CDS source files
@@ -134,7 +151,7 @@ optionProcessor
134
151
  parseCdl [options] <file> Generate a CSN that is close to the CDL source.
135
152
  explain <message-id> Explain a compiler message.
136
153
  toRename [options] <files...> (internal) Generate SQL DDL rename statements
137
- manageConstraints [options] <files...> (internal) Generate ALTER TABLE statements to
154
+ manageConstraints [options] <files...> (internal) Generate ALTER TABLE statements to
138
155
  add / modify referential constraints.
139
156
  `);
140
157
 
@@ -144,7 +161,6 @@ optionProcessor.command('H, toHana')
144
161
  .option('-n, --names <style>', ['plain', 'quoted', 'hdbcds'])
145
162
  .option(' --render-virtual')
146
163
  .option(' --joinfk')
147
- .option(' --skip-db-constraints')
148
164
  .option('-u, --user <user>')
149
165
  .option('-s, --src')
150
166
  .option('-c, --csn')
@@ -168,7 +184,6 @@ optionProcessor.command('H, toHana')
168
184
  using element names with dots).
169
185
  --render-virtual Render virtual elements in views and draft tables
170
186
  --joinfk Create JOINs for foreign key accesses
171
- --skip-db-constraints Do not render referential constraints for associations
172
187
  -u, --user <user> Value for the "$user" variable
173
188
  -s, --src (default) Generate HANA CDS source files "<artifact>.hdbcds"
174
189
  -c, --csn Generate "hana_csn.json" with HANA-preprocessed model
@@ -235,7 +250,6 @@ optionProcessor.command('Q, toSql')
235
250
  .option('-n, --names <style>', ['plain', 'quoted', 'hdbcds'])
236
251
  .option(' --render-virtual')
237
252
  .option(' --joinfk')
238
- .option(' --skip-db-constraints')
239
253
  .option('-d, --dialect <dialect>', ['hana', 'sqlite', 'plain'])
240
254
  .option('-u, --user <user>')
241
255
  .option('-l, --locale <locale>')
@@ -261,7 +275,6 @@ optionProcessor.command('Q, toSql')
261
275
  combination with "hana" dialect.
262
276
  --render-virtual Render virtual elements in views and draft tables
263
277
  --joinfk Create JOINs for foreign key accesses
264
- --skip-db-constraints Do not render referential constraints for associations
265
278
  -d, --dialect <dialect> SQL dialect to be generated:
266
279
  plain : (default) Common SQL - no assumptions about DB restrictions
267
280
  hana : SQL with HANA specific language features
@@ -309,7 +322,7 @@ optionProcessor.command('manageConstraints')
309
322
 
310
323
  (internal, subject to change): Generate SQL DDL ALTER TABLE statements to add / modify
311
324
  referential constraints on an existing model.
312
- Combine with options "--constraints-not-enforced" and "--constraint-not-validated"
325
+ Combine with options "--integrity-not-enforced" and "--integrity-not-validated"
313
326
  to switch off foreign key constraint enforcement / validation.
314
327
 
315
328
  Options
@@ -357,6 +370,7 @@ optionProcessor.command('toCsn')
357
370
 
358
371
  optionProcessor.command('parseCdl')
359
372
  .option('-h, --help')
373
+ .positionalArgument('<file>')
360
374
  .help(`
361
375
  Usage: cdsc parseCdl [options] <file>
362
376
 
@@ -369,14 +383,17 @@ optionProcessor.command('parseCdl')
369
383
 
370
384
  optionProcessor.command('explain')
371
385
  .option('-h, --help')
386
+ .positionalArgument('<message-id>')
372
387
  .help(`
373
388
  Usage: cdsc explain [options] <message-id>
374
389
 
375
390
  Explain the compiler message that has the given message-id.
376
391
  The explanation contains a faulty example and a solution.
377
392
 
393
+ Use \`explain list\` to list all available messages.
394
+
378
395
  Options
379
- -h, --help Show this help text
396
+ -h, --help Show this help text
380
397
  `);
381
398
 
382
399
  module.exports = {
@@ -7,9 +7,11 @@
7
7
  "prefer-template": "error",
8
8
  "no-trailing-spaces": "error",
9
9
  "sonarjs/cognitive-complexity": "off",
10
+ "sonarjs/no-duplicate-string": ["off"],
10
11
  "sonarjs/no-nested-template-literals": "off",
11
12
  "template-curly-spacing":["error", "never"],
12
- "complexity": ["warn", 30],
13
+ // Who cares - just very whiny and in the way
14
+ "complexity": "off",
13
15
  "max-len": "off",
14
16
  // We should enable this
15
17
  "no-shadow": "off"
@@ -44,7 +44,7 @@ class DuplicateChecker {
44
44
  * Add an artifact to the "seen"-list
45
45
  *
46
46
  * @param {string} name Persistence name of the artifact
47
- * @param {CSN.Location} location CSN location of the artifact
47
+ * @param {CSN.Location|CSN.Path} location CSN location of the artifact
48
48
  * @param {string} modelName CSN artifact name
49
49
  */
50
50
  addArtifact( name, location, modelName ) {