@sap/cds-compiler 3.1.2 → 3.3.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 (100) hide show
  1. package/CHANGELOG.md +80 -3
  2. package/bin/cdsc.js +1 -1
  3. package/doc/CHANGELOG_BETA.md +18 -0
  4. package/lib/api/main.js +8 -13
  5. package/lib/base/error.js +2 -2
  6. package/lib/base/keywords.js +2 -24
  7. package/lib/base/message-registry.js +43 -14
  8. package/lib/base/messages.js +20 -10
  9. package/lib/base/model.js +1 -1
  10. package/lib/checks/actionsFunctions.js +1 -1
  11. package/lib/checks/annotationsOData.js +2 -2
  12. package/lib/checks/arrayOfs.js +15 -7
  13. package/lib/checks/cdsPersistence.js +1 -1
  14. package/lib/checks/checkForTypes.js +48 -0
  15. package/lib/checks/defaultValues.js +2 -2
  16. package/lib/checks/elements.js +81 -6
  17. package/lib/checks/foreignKeys.js +12 -13
  18. package/lib/checks/invalidTarget.js +10 -11
  19. package/lib/checks/managedInType.js +21 -15
  20. package/lib/checks/nullableKeys.js +1 -1
  21. package/lib/checks/onConditions.js +9 -9
  22. package/lib/checks/parameters.js +21 -0
  23. package/lib/checks/selectItems.js +1 -1
  24. package/lib/checks/types.js +2 -2
  25. package/lib/checks/utils.js +17 -7
  26. package/lib/checks/validator.js +26 -14
  27. package/lib/compiler/assert-consistency.js +13 -6
  28. package/lib/compiler/builtins.js +8 -0
  29. package/lib/compiler/checks.js +40 -33
  30. package/lib/compiler/define.js +50 -44
  31. package/lib/compiler/extend.js +303 -37
  32. package/lib/compiler/kick-start.js +2 -35
  33. package/lib/compiler/populate.js +83 -62
  34. package/lib/compiler/propagator.js +1 -1
  35. package/lib/compiler/resolve.js +61 -104
  36. package/lib/compiler/shared.js +16 -6
  37. package/lib/compiler/tweak-assocs.js +25 -12
  38. package/lib/compiler/utils.js +2 -2
  39. package/lib/edm/annotations/genericTranslation.js +3 -3
  40. package/lib/edm/csn2edm.js +10 -10
  41. package/lib/edm/edm.js +17 -9
  42. package/lib/edm/edmPreprocessor.js +53 -30
  43. package/lib/edm/edmUtils.js +7 -2
  44. package/lib/gen/Dictionary.json +14 -0
  45. package/lib/gen/language.checksum +1 -1
  46. package/lib/gen/language.interp +3 -2
  47. package/lib/gen/languageParser.js +4205 -4100
  48. package/lib/inspect/inspectModelStatistics.js +1 -1
  49. package/lib/inspect/inspectPropagation.js +23 -9
  50. package/lib/json/csnVersion.js +1 -1
  51. package/lib/json/from-csn.js +26 -19
  52. package/lib/json/to-csn.js +47 -5
  53. package/lib/language/antlrParser.js +1 -1
  54. package/lib/language/genericAntlrParser.js +29 -13
  55. package/lib/language/language.g4 +28 -8
  56. package/lib/main.d.ts +3 -6
  57. package/lib/model/.eslintrc.json +13 -0
  58. package/lib/model/api.js +4 -2
  59. package/lib/model/csnRefs.js +74 -47
  60. package/lib/model/csnUtils.js +236 -218
  61. package/lib/model/enrichCsn.js +41 -31
  62. package/lib/model/revealInternalProperties.js +61 -57
  63. package/lib/model/sortViews.js +31 -31
  64. package/lib/modelCompare/compare.js +6 -6
  65. package/lib/optionProcessor.js +5 -0
  66. package/lib/render/manageConstraints.js +2 -2
  67. package/lib/render/toCdl.js +31 -44
  68. package/lib/render/toHdbcds.js +7 -5
  69. package/lib/render/toRename.js +4 -4
  70. package/lib/render/toSql.js +11 -5
  71. package/lib/render/utils/common.js +20 -9
  72. package/lib/render/utils/sql.js +5 -5
  73. package/lib/transform/db/applyTransformations.js +32 -3
  74. package/lib/transform/db/expansion.js +81 -37
  75. package/lib/transform/db/flattening.js +1 -1
  76. package/lib/transform/db/temporal.js +1 -1
  77. package/lib/transform/db/transformExists.js +1 -1
  78. package/lib/transform/forOdataNew.js +10 -7
  79. package/lib/transform/{forHanaNew.js → forRelationalDB.js} +7 -7
  80. package/lib/transform/localized.js +28 -19
  81. package/lib/transform/odata/toFinalBaseType.js +8 -11
  82. package/lib/transform/odata/typesExposure.js +1 -1
  83. package/lib/transform/transformUtilsNew.js +101 -39
  84. package/lib/transform/translateAssocsToJoins.js +5 -4
  85. package/lib/utils/moduleResolve.js +5 -5
  86. package/lib/utils/objectUtils.js +3 -3
  87. package/package.json +2 -2
  88. package/share/messages/anno-duplicate-unrelated-layer.md +6 -6
  89. package/share/messages/check-proper-type-of.md +4 -4
  90. package/share/messages/check-proper-type.md +2 -2
  91. package/share/messages/duplicate-autoexposed.md +4 -4
  92. package/share/messages/extend-repeated-intralayer.md +4 -5
  93. package/share/messages/extend-unrelated-layer.md +4 -4
  94. package/share/messages/message-explanations.json +3 -1
  95. package/share/messages/redirected-to-ambiguous.md +7 -6
  96. package/share/messages/redirected-to-complex.md +63 -0
  97. package/share/messages/redirected-to-unrelated.md +6 -5
  98. package/share/messages/rewrite-not-supported.md +4 -4
  99. package/share/messages/syntax-expected-integer.md +3 -3
  100. package/share/messages/wildcard-excluding-one.md +37 -0
@@ -60,14 +60,20 @@ function enrichCsn( csn, options = {} ) {
60
60
  $origin,
61
61
  // TODO: excluding
62
62
  '@': () => { /* ignore annotations */ },
63
- }
63
+ };
64
64
  // options.enrichCsn = 'DEBUG';
65
65
  let $$cacheObjectNumber = 0; // for debugging
66
66
  const debugLocationInfo = options.enrichCsn === 'DEBUG' && Object.create(null);
67
67
 
68
68
  setLocations( csn, false, null );
69
- const { inspectRef, artifactRef, getOrigin, initDefinition, __getCache_forEnrichCsnDebugging } =
70
- csnRefs( csn, true );
69
+ const {
70
+ inspectRef,
71
+ artifactRef,
72
+ getOrigin,
73
+ initDefinition,
74
+ // eslint-disable-next-line camelcase
75
+ __getCache_forEnrichCsnDebugging,
76
+ } = csnRefs( csn, true );
71
77
 
72
78
  const csnPath = [];
73
79
  if (csn.definitions)
@@ -87,20 +93,20 @@ function enrichCsn( csn, options = {} ) {
87
93
  obj.forEach( (n, i) => standard( obj, i, n ) );
88
94
  }
89
95
  else {
90
- for (let name of Object.getOwnPropertyNames( obj )) {
96
+ for (const name of Object.getOwnPropertyNames( obj )) {
91
97
  const trans = transformers[name] || transformers[name.charAt(0)] || standard;
92
98
  trans( obj, name, obj[name] );
93
99
  }
94
100
  if (obj.$parens)
95
101
  reveal( obj, '$parens', obj.$parens );
96
- _cache_debug( obj );
102
+ _cacheDebug( obj );
97
103
  }
98
104
  csnPath.pop();
99
105
  }
100
106
 
101
107
  function definition( parent, prop, obj ) {
102
108
  // call getOrigin() before standard() to set implicit protos inside standard():
103
- const origin = handleError( err => err ? err.toString() : getOrigin( obj ) );
109
+ const origin = handleError( err => (err ? err.toString() : getOrigin( obj )) );
104
110
  standard( parent, prop, obj );
105
111
  if (obj.$origin === undefined && !obj.type && origin != null)
106
112
  obj._origin = refLocation( origin );
@@ -110,29 +116,31 @@ function enrichCsn( csn, options = {} ) {
110
116
  if (!dict) // value null for inheritance interruption
111
117
  return;
112
118
  csnPath.push( prop );
113
- for (let name of Object.getOwnPropertyNames( dict )) {
119
+ for (const name of Object.getOwnPropertyNames( dict )) {
114
120
  if (prop === 'definitions')
115
121
  initDefinition( dict[name] );
116
122
  definition( dict, name, dict[name] );
117
123
  }
118
124
  if (!Object.prototype.propertyIsEnumerable.call( parent, prop ))
119
- parent['$'+prop] = dict;
125
+ parent[`$${ prop }`] = dict;
120
126
  csnPath.pop();
121
127
  }
122
128
 
123
129
  function refLocation( art ) {
124
130
  if (!art || typeof art !== 'object' || Array.isArray( art )) {
125
- if (!options.testMode)
131
+ if (!options.testMode) {
126
132
  return (typeof art === 'string')
127
- ? `<illegal ref = ${art}>`
128
- : `<illegal ref: ${typeof art}>`;
133
+ ? `<illegal ref = ${ art }>`
134
+ : `<illegal ref: ${ typeof art }>`;
135
+ }
129
136
  throw new Error( 'Illegal reference' );
130
137
  }
131
- else if (art.$location)
138
+ else if (art.$location) {
132
139
  return art.$location;
140
+ }
133
141
 
134
142
  if (!options.testMode)
135
- return `<${Object.keys( art ).join('+')}+!$location>`;
143
+ return `<${ Object.keys( art ).join('+') }+!$location>`;
136
144
  throw new Error( 'Reference to object without $location' );
137
145
  }
138
146
 
@@ -140,19 +148,19 @@ function enrichCsn( csn, options = {} ) {
140
148
  // try {
141
149
  const notFound = (options.testMode) ? undefined : null;
142
150
  if (Array.isArray( ref )) {
143
- parent['_' + prop] = ref.map( r => refLocation( artifactRef( r, notFound ) ) );
151
+ parent[`_${ prop }`] = ref.map( r => refLocation( artifactRef( r, notFound ) ) );
144
152
  }
145
153
  else if (typeof ref === 'string') {
146
154
  if (!ref.startsWith( 'cds.'))
147
- parent['_' + prop] = refLocation( artifactRef( ref, notFound ) );
155
+ parent[`_${ prop }`] = refLocation( artifactRef( ref, notFound ) );
148
156
  }
149
157
  else if (!ref.elements) {
150
- parent['_' + prop] = refLocation( artifactRef( ref, notFound ) );
158
+ parent[`_${ prop }`] = refLocation( artifactRef( ref, notFound ) );
151
159
  }
152
160
  else { // targetAspect, target
153
161
  csnPath.push( prop );
154
162
  dictionary( ref, 'elements', ref.elements );
155
- _cache_debug( ref );
163
+ _cacheDebug( ref );
156
164
  csnPath.pop();
157
165
  }
158
166
  // } catch (e) {
@@ -160,7 +168,7 @@ function enrichCsn( csn, options = {} ) {
160
168
  }
161
169
 
162
170
  function $origin( parent, prop, ref ) {
163
- handleError( err => {
171
+ handleError( (err) => {
164
172
  if (err)
165
173
  parent._origin = err.toString();
166
174
  else if (Array.isArray( ref ) || typeof ref === 'string') // $origin: […] / "short-ref"
@@ -171,13 +179,13 @@ function enrichCsn( csn, options = {} ) {
171
179
  }
172
180
 
173
181
  function pathRef( parent, prop, path, inspectionPath = csnPath ) {
174
- const inspection = handleError( (err) => {
175
- return (err) ? { scope: err.toString() } : inspectRef( inspectionPath );
176
- });
177
- const { links, art, scope, $env } = inspection;
182
+ const inspection = handleError( err => ((err) ? { scope: err.toString() } : inspectRef( inspectionPath )));
183
+ const {
184
+ links, art, scope, $env,
185
+ } = inspection;
178
186
  if (links)
179
187
  parent._links = links.map( l => refLocation( l.art ) );
180
- if (links && links[links.length-1].art !== art)
188
+ if (links && links[links.length - 1].art !== art)
181
189
  parent._art = refLocation( art );
182
190
  parent._scope = scope;
183
191
  if ($env)
@@ -211,12 +219,13 @@ function enrichCsn( csn, options = {} ) {
211
219
  return callback();
212
220
  try {
213
221
  return callback();
214
- } catch (err) {
222
+ }
223
+ catch (err) {
215
224
  return callback( err );
216
225
  }
217
226
  }
218
227
 
219
- function _cache_debug( obj, subCache ) {
228
+ function _cacheDebug( obj, subCache ) {
220
229
  if (options.enrichCsn !== 'DEBUG')
221
230
  return;
222
231
  const cache = subCache || __getCache_forEnrichCsnDebugging( obj );
@@ -251,7 +260,7 @@ function enrichCsn( csn, options = {} ) {
251
260
  for (const n in val) {
252
261
  const alias = val[n];
253
262
  const c = {};
254
- _cache_debug( c, alias );
263
+ _cacheDebug( c, alias );
255
264
  sub[n] = c.$$cacheObject;
256
265
  }
257
266
  obj.$$cacheObject[name] = sub;
@@ -259,10 +268,11 @@ function enrichCsn( csn, options = {} ) {
259
268
  }
260
269
  else if (name === '$origin$step') { // string value handled above
261
270
  const kind = Object.keys( val )[0];
262
- obj.$$cacheObject[name] = `${kind}: ${ val[kind] }`;
271
+ obj.$$cacheObject[name] = `${ kind }: ${ val[kind] }`;
263
272
  }
264
273
  else if (Array.isArray( val )) {
265
- obj.$$cacheObject[name] = val.map( item => {
274
+ // eslint-disable-next-line no-loop-func
275
+ obj.$$cacheObject[name] = val.map( (item) => {
266
276
  if (!item.$$objectNumber)
267
277
  item.$$objectNumber = -(++$$cacheObjectNumber);
268
278
  return item.$$objectNumber;
@@ -281,7 +291,7 @@ function enrichCsn( csn, options = {} ) {
281
291
  if (debugLocationInfo && !userProvided) {
282
292
  loc = loc.replace( /\([0-9]+\)\^/, '^' );
283
293
  debugLocationInfo[loc] = (debugLocationInfo[loc] || 0) + 1;
284
- loc = `${loc}(${debugLocationInfo[loc]})`;
294
+ loc = `${ loc }(${ debugLocationInfo[loc] })`;
285
295
  }
286
296
  return loc;
287
297
  }
@@ -298,11 +308,11 @@ function enrichCsn( csn, options = {} ) {
298
308
  reveal( node, '$location', debugLocation( loc, !node.$generated ) );
299
309
  }
300
310
  else if (prop === true || prop === 'returns') { // in dictionary or returns
301
- loc = debugLocation( loc + '^' );
311
+ loc = debugLocation( `${ loc }^` );
302
312
  node.$location = loc;
303
313
  }
304
314
  else if (prop === 'items') {
305
- let iloc = loc + '[]';
315
+ let iloc = `${ loc }[]`;
306
316
  let obj = node;
307
317
  while (obj) {
308
318
  // should not appear in --enrich-csn, only for _origin info
@@ -25,10 +25,10 @@ function locationString( loc ) {
25
25
  return '';
26
26
  return (typeof loc === 'object' && loc.file)
27
27
  ? msg.locationString(loc)
28
- : (typeof loc) + ':' + msg.locationString(loc);
28
+ : `${ typeof loc }:${ msg.locationString(loc) }`;
29
29
  }
30
30
 
31
- var unique_id = 0;
31
+ let uniqueId = 0;
32
32
 
33
33
  // some (internal) kinds are normally represented as links
34
34
  const kindsRepresentedAsLinks = {
@@ -36,13 +36,13 @@ const kindsRepresentedAsLinks = {
36
36
  select: (art, parent) => art._main && parent !== art._main.$queries,
37
37
  // represent table alias in from / join-args property as link:
38
38
  $tableAlias: tableAliasAsLink,
39
- // represent "navigation elemens" in _combined as links:
39
+ // represent "navigation elements" in _combined as links:
40
40
  $navElement: (art, parent) => art._parent && parent !== art._parent.elements && art._parent.kind !== 'aspect',
41
41
  // represent mixin in $tableAliases as link:
42
42
  mixin: tableAliasAsLink,
43
43
  // represent $projection as link, as it is just another search name for $self:
44
44
  $self: (_a, _p, name) => name !== '$self',
45
- }
45
+ };
46
46
 
47
47
  function tableAliasAsLink( art, parent, name ) {
48
48
  return art._parent && art._parent.$tableAliases && // initXYZ() is run
@@ -98,8 +98,8 @@ function revealInternalProperties( model, nameOrPath ) {
98
98
  _status: primOrString, // is a string anyway
99
99
  $annotations: as => as.map( $annotation ),
100
100
  $messageFunctions: () => '‹some functions›',
101
- }
102
- unique_id = 1;
101
+ };
102
+ uniqueId = 1;
103
103
  return revealXsnPath(nameOrPath, model);
104
104
 
105
105
  // Returns the desired artifact/dictionary in the XSN.
@@ -132,7 +132,7 @@ function revealInternalProperties( model, nameOrPath ) {
132
132
  if (path.length === 1) {
133
133
  const def = xsn.definitions?.[path[0]] || xsn.vocabularies?.[path[0]];
134
134
  if (!def)
135
- throw new Error(`reveal xsn: Unknown definition: “${path[0]}”`)
135
+ throw new Error(`reveal xsn: Unknown definition: “${ path[0] }”`);
136
136
  return reveal( def );
137
137
  }
138
138
 
@@ -141,11 +141,11 @@ function revealInternalProperties( model, nameOrPath ) {
141
141
 
142
142
  for (const segment of path) {
143
143
  if (xsn[segment])
144
- xsn = xsn[segment]
144
+ xsn = xsn[segment];
145
145
  else if (segment) // huh, this should be a call error
146
- throw new Error(`Raw Output: Path segment "${ segment }" could not be found. Path: ${ JSON.stringify(path) }!"`)
146
+ throw new Error(`Raw Output: Path segment "${ segment }" could not be found. Path: ${ JSON.stringify(path) }!"`);
147
147
  }
148
- const propName = path[path.length > 1 ? path.length - 2 : 0 ];
148
+ const propName = path[path.length > 1 ? path.length - 2 : 0];
149
149
  const obj = {};
150
150
  obj[propName] = xsn;
151
151
  return reveal( obj );
@@ -175,9 +175,9 @@ function revealInternalProperties( model, nameOrPath ) {
175
175
 
176
176
  function layerExtends( dict ) {
177
177
  const r = Object.create( Object.getPrototypeOf(dict)
178
- ? NOT_A_DICTIONARY.prototype
179
- : Object.prototype );
180
- for (let name in dict)
178
+ ? NOT_A_DICTIONARY.prototype
179
+ : Object.prototype );
180
+ for (const name in dict)
181
181
  r[name] = true;
182
182
  return r;
183
183
  }
@@ -185,17 +185,17 @@ function revealInternalProperties( model, nameOrPath ) {
185
185
  function $annotation( anno ) { // property for cds-lsp
186
186
  const { name, $flatten } = anno.value || anno;
187
187
  const value = ($flatten)
188
- ? { name: reveal( name ), $flatten: $flatten.map( $annotation ) }
189
- : `@${name?.absolute}`;
188
+ ? { name: reveal( name ), $flatten: $flatten.map( $annotation ) }
189
+ : `@${ name?.absolute }`;
190
190
  return { value, location: locationString( anno.location || anno.name.location ) };
191
191
  }
192
192
 
193
193
  function columns( nodes, query ) {
194
194
  // If we will have specified elements, we need another test to see columns in --parse-cdl
195
195
  return nodes && array( nodes,
196
- c => (c._parent && c._parent.elements)
197
- ? artifactIdentifier( c, query )
198
- : reveal( c, nodes ) );
196
+ c => ((c._parent && c._parent.elements)
197
+ ? artifactIdentifier( c, query )
198
+ : reveal( c, nodes )) );
199
199
  }
200
200
 
201
201
  function elements( dict, parent ) {
@@ -213,9 +213,9 @@ function revealInternalProperties( model, nameOrPath ) {
213
213
  if (!node || typeof node !== 'object' || !model.definitions || parent === model )
214
214
  return dictionary( node ); // no dictionary or no definitions section
215
215
  const dict = Object.create( Object.getPrototypeOf(node)
216
- ? NOT_A_DICTIONARY.prototype
217
- : Object.prototype );
218
- for (let name in node) {
216
+ ? NOT_A_DICTIONARY.prototype
217
+ : Object.prototype );
218
+ for (const name in node) {
219
219
  const art = node[name];
220
220
  dict[name] = (art.kind !== 'using')
221
221
  ? artifactIdentifier( art )
@@ -231,9 +231,9 @@ function revealInternalProperties( model, nameOrPath ) {
231
231
  return array( node, reveal );
232
232
  // Make unexpected prototype visible with node-10+:
233
233
  const r = Object.create( Object.getPrototypeOf(node)
234
- ? NOT_A_DICTIONARY.prototype
235
- : Object.prototype );
236
- for (let prop of Object.getOwnPropertyNames( node )) { // also non-enumerable
234
+ ? NOT_A_DICTIONARY.prototype
235
+ : Object.prototype );
236
+ for (const prop of Object.getOwnPropertyNames( node )) { // also non-enumerable
237
237
  r[prop] = reveal( node[prop], node, prop );
238
238
  }
239
239
  if (node[$inferred] && !node['[$inferred]'])
@@ -246,8 +246,7 @@ function revealInternalProperties( model, nameOrPath ) {
246
246
  function origin( node, parent ) {
247
247
  if (!node || node.$inferred === 'REDIRECTED')
248
248
  return reveal( node, parent );
249
- else
250
- return artifactIdentifier( node, parent );
249
+ return artifactIdentifier( node, parent );
251
250
  }
252
251
 
253
252
  function revealNonEnum( node, parent ) {
@@ -263,20 +262,20 @@ function revealInternalProperties( model, nameOrPath ) {
263
262
 
264
263
  function reveal( node, parent, name ) {
265
264
  if (node == null || typeof node !== 'object' )
266
- return node
265
+ return node;
267
266
  if (Array.isArray(node))
268
267
  return array( node, n => reveal( n, node, name ) );
269
268
 
270
- const asLinkTest = kindsRepresentedAsLinks[ node.kind ];
269
+ const asLinkTest = kindsRepresentedAsLinks[node.kind];
271
270
  if (asLinkTest && asLinkTest( node, parent, name ))
272
271
  return artifactIdentifier( node, parent );
273
272
 
274
- let r = Object.create( Object.getPrototypeOf( node ) );
273
+ const r = Object.create( Object.getPrototypeOf( node ) );
275
274
  // property to recognize === objects
276
275
  if (node.kind && node.__unique_id__ == null)
277
- Object.defineProperty( node, '__unique_id__', { value: ++unique_id } );
276
+ Object.defineProperty( node, '__unique_id__', { value: ++uniqueId } );
278
277
 
279
- for (let prop of Object.getOwnPropertyNames( node )) { // also non-enumerable
278
+ for (const prop of Object.getOwnPropertyNames( node )) { // also non-enumerable
280
279
  const func = transformers[prop] ||
281
280
  ({}.propertyIsEnumerable.call( node, prop ) ? reveal : revealNonEnum);
282
281
  r[prop] = func( node[prop], node );
@@ -285,8 +284,8 @@ function revealInternalProperties( model, nameOrPath ) {
285
284
  }
286
285
 
287
286
  function targetAspect( node, parent ) {
288
- if (node.elements && unique_id && node.__unique_id__ == null)
289
- Object.defineProperty( node, '__unique_id__', { value: ++unique_id } );
287
+ if (node.elements && uniqueId && node.__unique_id__ == null)
288
+ Object.defineProperty( node, '__unique_id__', { value: ++uniqueId } );
290
289
  return reveal( node, parent );
291
290
  }
292
291
 
@@ -305,28 +304,33 @@ function array( node, fn ) {
305
304
  function artifactIdentifier( node, parent ) {
306
305
  if (Array.isArray(node))
307
306
  return node.map( a => artifactIdentifier( a, node ) );
308
- if (unique_id && node.__unique_id__ == null)
309
- Object.defineProperty( node, '__unique_id__', { value: ++unique_id } );
310
- let outer = unique_id ? '##' + node.__unique_id__ : '';
307
+ if (uniqueId && node.__unique_id__ == null)
308
+ Object.defineProperty( node, '__unique_id__', { value: ++uniqueId } );
309
+ let outer = uniqueId ? `##${ node.__unique_id__ }` : '';
311
310
  if (node._outer) {
312
- if (node.$inferred === 'REDIRECTED')
313
- outer = '/redirected' + outer;
314
- else
315
- outer = (node._outer.items === node) ? '/items' + outer
316
- : (node._outer.returns === node) ? '/returns' + outer
317
- : (node._outer.targetAspect === node) ? '/target' + outer
318
- : '/returns/items' + outer;
311
+ if (node.$inferred === 'REDIRECTED') {
312
+ outer = `/redirected${ outer }`;
313
+ }
314
+ else {
315
+ // eslint-disable-next-line no-nested-ternary
316
+ outer = (node._outer.items === node) ? `/items${ outer }`
317
+ // eslint-disable-next-line no-nested-ternary
318
+ : (node._outer.returns === node) ? `/returns${ outer }`
319
+ // eslint-disable-next-line no-nested-ternary
320
+ : (node._outer.targetAspect === node) ? `/target${ outer }`
321
+ : `/returns/items${ outer }`;
322
+ }
319
323
  node = node._outer;
320
324
  }
321
325
  if (node === parent)
322
326
  return 'this';
323
327
  if (node.kind === 'source')
324
- return 'source:' + quoted( node.location.file );
328
+ return `source:${ quoted( node.location.file ) }`;
325
329
  if (node.kind === '$magicVariables')
326
330
  return '$magicVariables';
327
331
  if (!node.name) {
328
332
  try {
329
- return (locationString( node.location ) || '') + '##' + node.__unique_id__;
333
+ return `${ locationString( node.location ) || '' }##${ node.__unique_id__ }`;
330
334
  // return JSON.stringify(node);
331
335
  }
332
336
  catch (e) {
@@ -339,47 +343,47 @@ function artifactIdentifier( node, parent ) {
339
343
  ? artifactIdentifier( node._artifact )
340
344
  : JSON.stringify(node.name);
341
345
  case 'builtin':
342
- return '$magicVariables/' + msg.artName(node);
346
+ return `$magicVariables/${ msg.artName(node) }`;
343
347
  case 'source':
344
348
  case 'using':
345
- return 'source:' + quoted( node.location && node.location.file ) +
346
- '/using:' + quoted( node.name.id )
349
+ return `source:${ quoted( node.location && node.location.file )
350
+ }/using:${ quoted( node.name.id ) }`;
347
351
  default: {
348
352
  let main = node._main;
349
353
  while (main && main._outer) // anonymous aspect
350
354
  main = main._outer._main;
351
- return ((main || node).kind || '<kind>') + ':' + msg.artName( node ) + outer;
355
+ return `${ (main || node).kind || '<kind>' }:${ msg.artName( node ) }${ outer }`;
352
356
  }
353
357
  }
354
358
  }
355
359
 
356
360
  function primOrString( node ) {
357
361
  if (node == null || typeof node !== 'object')
358
- return node
362
+ return node;
359
363
  if (Array.isArray(node))
360
364
  return array( node, primOrString );
361
365
  if (Object.getPrototypeOf( node ))
362
- return '' + node;
363
- else
364
- return '<dict>';
366
+ return `${ node }`;
367
+ return '<dict>';
365
368
  }
366
369
 
367
370
  function quoted( name, undef = '‹undefined›' ) {
368
- return (typeof name === 'number')
369
- ? name
370
- : name ? '“' + name + '”' : undef;
371
+ if (typeof name === 'number')
372
+ return name;
373
+ return (name ? `“${ name }”` : undef);
371
374
  }
372
375
 
373
376
  // To be used for tracing, e.g. by
374
377
  // require('../model/revealInternalProperties').log(model, 'E_purposes')
375
378
  function logXsnModel( model, name ) {
379
+ // eslint-disable-next-line no-console, global-require
376
380
  console.log( require('util').inspect( revealInternalProperties( model, name ), false, null ) );
377
381
  }
378
382
 
379
383
  // To be used for tracing, e.g. by
380
384
  // console.log(require('../model/revealInternalProperties').ref(type._artifact))
381
385
  function xsnRef( node ) {
382
- unique_id = 0;
386
+ uniqueId = 0;
383
387
  return artifactIdentifier( node );
384
388
  }
385
389
 
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
- const {setDependencies} = require('./csnUtils');
3
- const { ModelError } = require("../base/error");
2
+
3
+ const { setDependencies } = require('./csnUtils');
4
+ const { ModelError } = require('../base/error');
4
5
 
5
6
  /**
6
7
  * @typedef {Object} Layers
@@ -19,22 +20,22 @@ const { ModelError } = require("../base/error");
19
20
  * @param {Symbol} _dependencies Symbol used to attach the dependencies
20
21
  * @returns {Layers}
21
22
  */
22
- function sortTopologically(csn, _dependents, _dependencies){
23
+ function sortTopologically(csn, _dependents, _dependencies) {
23
24
  const layers = [];
24
25
  let { zero, nonZero } = _calculateDepth(Object.entries(csn.definitions), _dependents, _dependencies);
25
- while (zero.length !== 0){
26
+ while (zero.length !== 0) {
26
27
  const currentLayer = [];
27
- zero.forEach(([artifactName, artifact]) => {
28
+ zero.forEach(([ artifactName, artifact ]) => {
28
29
  currentLayer.push(artifactName);
29
- if(artifact[_dependents]) {
30
+ if (artifact[_dependents]) {
30
31
  Object.values(artifact[_dependents]).forEach((dependant) => {
31
- dependant.$pointers = dependant.$pointers - 1;
32
+ dependant.$pointers -= 1;
32
33
  dependant[_dependencies].delete(artifact);
33
34
  });
34
35
  }
35
36
  });
36
37
  layers.push(currentLayer);
37
- ({zero, nonZero} = _findWithXPointers(nonZero, 0, _dependents, _dependencies));
38
+ ({ zero, nonZero } = _findWithXPointers(nonZero, 0, _dependents, _dependencies));
38
39
  }
39
40
 
40
41
  return { layers, leftover: nonZero };
@@ -44,37 +45,37 @@ function _calculateDepth(definitionsArray, _dependents, _dependencies) {
44
45
  const zero = [];
45
46
  const nonZero = [];
46
47
 
47
- definitionsArray.forEach(([artifactName, artifact]) => {
48
- if(artifact[_dependencies]) {
48
+ definitionsArray.forEach(([ artifactName, artifact ]) => {
49
+ if (artifact[_dependencies]) {
49
50
  artifact.$pointers = artifact[_dependencies].size;
50
- nonZero.push([artifactName, artifact]);
51
- } else {
51
+ nonZero.push([ artifactName, artifact ]);
52
+ }
53
+ else {
52
54
  artifact.$pointers = 0;
53
- zero.push([artifactName, artifact]);
55
+ zero.push([ artifactName, artifact ]);
54
56
  }
55
57
  });
56
58
  return {
57
59
  zero,
58
- nonZero
59
- }
60
+ nonZero,
61
+ };
60
62
  }
61
63
 
62
- function _findWithXPointers(definitionsArray, x, _dependents, _dependencies){
64
+ function _findWithXPointers(definitionsArray, x, _dependents, _dependencies) {
63
65
  const zero = [];
64
66
  const nonZero = [];
65
67
 
66
- definitionsArray.forEach(([artifactName, artifact]) => {
67
- if(artifact.$pointers !== undefined && artifact.$pointers === x) {
68
- zero.push([artifactName, artifact]);
69
- } else {
70
- nonZero.push([artifactName, artifact]);
71
- }
68
+ definitionsArray.forEach(([ artifactName, artifact ]) => {
69
+ if (artifact.$pointers !== undefined && artifact.$pointers === x)
70
+ zero.push([ artifactName, artifact ]);
71
+ else
72
+ nonZero.push([ artifactName, artifact ]);
72
73
  });
73
74
 
74
75
  return {
75
76
  zero,
76
- nonZero
77
- }
77
+ nonZero,
78
+ };
78
79
  }
79
80
 
80
81
  /**
@@ -86,24 +87,23 @@ function _findWithXPointers(definitionsArray, x, _dependents, _dependencies){
86
87
  * @param {CSN.Model} csn
87
88
  *
88
89
  * @returns {{name: string, sql: string}[]} Sorted array of artifact name / "CREATE STATEMENTS" pairs
89
- *
90
90
  */
91
- module.exports = function({sql, csn}){
92
- const {cleanup, _dependents, _dependencies} = setDependencies(csn);
91
+ module.exports = function sortViews({ sql, csn }) {
92
+ const { cleanup, _dependents, _dependencies } = setDependencies(csn);
93
93
  const { layers, leftover } = sortTopologically(csn, _dependents, _dependencies);
94
94
  cleanup.forEach(fn => fn());
95
- if(leftover.length > 0)
95
+ if (leftover.length > 0)
96
96
  throw new ModelError('Unable to build a correct dependency graph! Are there cycles?');
97
97
 
98
98
  const result = [];
99
99
  // keep the "artifact name" - needed for to.hdi sorting
100
- layers.forEach(layer => layer.forEach(objName => result.push({name: objName, sql: sql[objName]})));
100
+ layers.forEach(layer => layer.forEach(objName => result.push({ name: objName, sql: sql[objName] })));
101
101
  // attach sql artifacts which are not considered during the view sorting algorithm
102
102
  // --> this is the case for "ALTER TABLE ADD CONSTRAINT" statements,
103
103
  // because their identifiers are not part of the csn.definitions
104
104
  Object.entries(sql).forEach(([ name, sqlString ]) => {
105
105
  if (!result.some( o => o.name === name )) // not in result but in incoming sql
106
- result.push({ name, sql: sqlString })
106
+ result.push({ name, sql: sqlString });
107
107
  });
108
108
  return result;
109
- }
109
+ };
@@ -46,17 +46,17 @@ function validateCsnVersions(beforeModel, afterModel, options) {
46
46
 
47
47
  if (!beforeVersionParts || beforeVersionParts.length < 2) {
48
48
  const { error, throwWithAnyError } = makeMessageFunction(beforeModel, options, 'modelCompare');
49
- error(null, null, `Invalid CSN version: ${beforeVersion}`);
49
+ error(null, null, {}, `Invalid CSN version: ${beforeVersion}`);
50
50
  throwWithAnyError();
51
51
  }
52
52
  if (!afterVersionParts || afterVersionParts.length < 2) {
53
53
  const { error, throwWithAnyError } = makeMessageFunction(afterModel, options, 'modelCompare');
54
- error(null, null, `Invalid CSN version: ${afterVersion}`);
54
+ error(null, null, {}, `Invalid CSN version: ${afterVersion}`);
55
55
  throwWithAnyError();
56
56
  }
57
57
  if (beforeVersionParts[0] > afterVersionParts[0] && !(options && options.allowCsnDowngrade)) {
58
58
  const { error, throwWithAnyError } = makeMessageFunction(afterModel, options, 'modelCompare');
59
- error(null, null, `Incompatible CSN versions: ${afterVersion} is a major downgrade from ${beforeVersion}. Is @sap/cds-compiler version ${require('../../package.json').version} outdated?`);
59
+ error(null, null, {}, `Incompatible CSN versions: ${afterVersion} is a major downgrade from ${beforeVersion}. Is @sap/cds-compiler version ${require('../../package.json').version} outdated?`);
60
60
  throwWithAnyError();
61
61
  }
62
62
  }
@@ -65,7 +65,7 @@ function getArtifactComparator(otherModel, options, addedEntities, deletedEntiti
65
65
  return function compareArtifacts(artifact, name) {
66
66
  function addElements() {
67
67
  const elements = {};
68
- forEachMember(artifact, getElementComparator(otherArtifact, elements));
68
+ forEachMember(artifact, getElementComparator(otherArtifact, elements), [ 'definitions', name ], true, { elementsOnly: true });
69
69
  if (Object.keys(elements).length > 0) {
70
70
  elementAdditions.push(addedElements(name, elements));
71
71
  }
@@ -92,12 +92,12 @@ function getArtifactComparator(otherModel, options, addedEntities, deletedEntiti
92
92
  migration.properties = changedProperties;
93
93
  }
94
94
 
95
- forEachMember(otherArtifact, getElementComparator(artifact, removedElements));
95
+ forEachMember(otherArtifact, getElementComparator(artifact, removedElements), [ 'definitions', name ], true, { elementsOnly: true });
96
96
  if (Object.keys(removedElements).length > 0) {
97
97
  migration.remove = removedElements;
98
98
  }
99
99
 
100
- forEachMember(artifact, getElementComparator(otherArtifact, null, changedElements));
100
+ forEachMember(artifact, getElementComparator(otherArtifact, null, changedElements), [ 'definitions', name ], true, { elementsOnly: true });
101
101
  if (Object.keys(changedElements).length > 0) {
102
102
  migration.change = changedElements;
103
103
  }
@@ -142,6 +142,11 @@ optionProcessor
142
142
  manageConstraints [options] <files...> (internal) Generate ALTER TABLE statements to
143
143
  add / modify referential constraints.
144
144
  inspect [options] <files...> (internal) Inspect the given CDS files.
145
+
146
+ Environment variables
147
+ NO_COLOR If set, compiler messages (/output) will not be colored.
148
+ Can be overwritten by '--color'
149
+ CDSC_TIMETRACING If set, additional timing information is printed to stderr.
145
150
  `);
146
151
 
147
152
  // ----------- toHana -----------