@sap/cds-compiler 3.4.4 → 3.5.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.
- package/CHANGELOG.md +58 -0
- package/README.md +1 -0
- package/bin/cds_update_identifiers.js +5 -5
- package/bin/cdsc.js +12 -12
- package/doc/CHANGELOG_ARCHIVE.md +1 -1
- package/doc/CHANGELOG_BETA.md +9 -1
- package/doc/CHANGELOG_DEPRECATED.md +2 -0
- package/lib/api/main.js +58 -59
- package/lib/api/options.js +4 -2
- package/lib/api/validate.js +2 -2
- package/lib/base/cleanSymbols.js +2 -3
- package/lib/base/dictionaries.js +6 -6
- package/lib/base/error.js +2 -2
- package/lib/base/keywords.js +6 -6
- package/lib/base/location.js +11 -12
- package/lib/base/message-registry.js +124 -28
- package/lib/base/messages.js +247 -179
- package/lib/base/model.js +14 -11
- package/lib/base/node-helpers.js +9 -10
- package/lib/base/optionProcessorHelper.js +138 -129
- package/lib/checks/actionsFunctions.js +5 -5
- package/lib/checks/annotationsOData.js +4 -4
- package/lib/checks/arrayOfs.js +1 -1
- package/lib/checks/cdsPersistence.js +1 -1
- package/lib/checks/checkForTypes.js +3 -3
- package/lib/checks/defaultValues.js +3 -3
- package/lib/checks/elements.js +7 -7
- package/lib/checks/emptyOrOnlyVirtual.js +2 -2
- package/lib/checks/foreignKeys.js +1 -1
- package/lib/checks/invalidTarget.js +4 -4
- package/lib/checks/managedInType.js +1 -1
- package/lib/checks/managedWithoutKeys.js +1 -1
- package/lib/checks/nonexpandableStructured.js +5 -3
- package/lib/checks/nullableKeys.js +1 -1
- package/lib/checks/onConditions.js +5 -6
- package/lib/checks/parameters.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +2 -2
- package/lib/checks/selectItems.js +4 -4
- package/lib/checks/sql-snippets.js +4 -4
- package/lib/checks/types.js +7 -7
- package/lib/checks/utils.js +4 -4
- package/lib/checks/validator.js +16 -13
- package/lib/compiler/.eslintrc.json +1 -1
- package/lib/compiler/assert-consistency.js +0 -1
- package/lib/compiler/builtins.js +1 -1
- package/lib/compiler/checks.js +73 -15
- package/lib/compiler/define.js +3 -7
- package/lib/compiler/extend.js +212 -32
- package/lib/compiler/finalize-parse-cdl.js +7 -2
- package/lib/compiler/index.js +17 -14
- package/lib/compiler/populate.js +2 -5
- package/lib/compiler/propagator.js +2 -0
- package/lib/compiler/shared.js +23 -12
- package/lib/compiler/tweak-assocs.js +5 -6
- package/lib/compiler/utils.js +6 -0
- package/lib/edm/annotations/genericTranslation.js +553 -319
- package/lib/edm/annotations/preprocessAnnotations.js +39 -35
- package/lib/edm/csn2edm.js +88 -75
- package/lib/edm/edm.js +17 -3
- package/lib/edm/edmAnnoPreprocessor.js +5 -5
- package/lib/edm/edmPreprocessor.js +106 -76
- package/lib/edm/edmUtils.js +41 -2
- package/lib/gen/Dictionary.json +34 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +66 -63
- package/lib/gen/language.tokens +81 -81
- package/lib/gen/languageLexer.interp +4 -10
- package/lib/gen/languageLexer.js +854 -869
- package/lib/gen/languageLexer.tokens +79 -81
- package/lib/gen/languageParser.js +14360 -14146
- package/lib/inspect/inspectModelStatistics.js +2 -2
- package/lib/inspect/inspectPropagation.js +6 -6
- package/lib/inspect/inspectUtils.js +2 -2
- package/lib/json/from-csn.js +82 -40
- package/lib/json/to-csn.js +82 -157
- package/lib/language/.eslintrc.json +1 -4
- package/lib/language/genericAntlrParser.js +59 -38
- package/lib/language/language.g4 +1508 -1490
- package/lib/language/multiLineStringParser.js +1 -1
- package/lib/main.js +3 -3
- package/lib/model/csnUtils.js +130 -122
- package/lib/model/revealInternalProperties.js +1 -1
- package/lib/model/sortViews.js +4 -6
- package/lib/modelCompare/utils/filter.js +4 -3
- package/lib/optionProcessor.js +5 -0
- package/lib/render/DuplicateChecker.js +1 -1
- package/lib/render/manageConstraints.js +12 -12
- package/lib/render/toCdl.js +225 -159
- package/lib/render/toHdbcds.js +63 -63
- package/lib/render/toRename.js +5 -5
- package/lib/render/toSql.js +55 -65
- package/lib/render/utils/common.js +20 -37
- package/lib/render/utils/delta.js +3 -3
- package/lib/render/utils/sql.js +22 -6
- package/lib/render/utils/stringEscapes.js +3 -3
- package/lib/transform/db/applyTransformations.js +3 -3
- package/lib/transform/db/assertUnique.js +13 -12
- package/lib/transform/db/associations.js +5 -5
- package/lib/transform/db/cdsPersistence.js +10 -8
- package/lib/transform/db/constraints.js +14 -14
- package/lib/transform/db/expansion.js +20 -22
- package/lib/transform/db/flattening.js +24 -42
- package/lib/transform/db/groupByOrderBy.js +3 -3
- package/lib/transform/db/temporal.js +6 -6
- package/lib/transform/db/transformExists.js +23 -23
- package/lib/transform/db/views.js +16 -16
- package/lib/transform/draft/db.js +10 -10
- package/lib/transform/draft/odata.js +2 -2
- package/lib/transform/forOdataNew.js +12 -40
- package/lib/transform/forRelationalDB.js +17 -7
- package/lib/transform/localized.js +2 -2
- package/lib/transform/odata/toFinalBaseType.js +41 -27
- package/lib/transform/odata/typesExposure.js +106 -62
- package/lib/transform/parseExpr.js +209 -106
- package/lib/transform/transformUtilsNew.js +2 -2
- package/lib/transform/translateAssocsToJoins.js +24 -19
- package/lib/transform/universalCsn/coreComputed.js +10 -10
- package/lib/transform/universalCsn/universalCsnEnricher.js +26 -26
- package/lib/transform/universalCsn/utils.js +3 -3
- package/lib/utils/file.js +5 -5
- package/lib/utils/moduleResolve.js +13 -13
- package/lib/utils/objectUtils.js +6 -6
- package/lib/utils/term.js +5 -2
- package/lib/utils/timetrace.js +51 -24
- package/package.json +5 -7
- package/share/messages/check-proper-type-of.md +1 -1
- package/share/messages/message-explanations.json +1 -1
- package/share/messages/redirected-to-complex.md +4 -4
- package/share/messages/{syntax-expecting-integer.md → syntax-expecting-unsigned-int.md} +7 -4
package/lib/model/csnUtils.js
CHANGED
|
@@ -43,7 +43,7 @@ const { version } = require('../../package.json');
|
|
|
43
43
|
* Get utility functions for a given CSN. Re-exports functions of `csnRefs()`.
|
|
44
44
|
* @param {CSN.Model} model (Compact) CSN model
|
|
45
45
|
*/
|
|
46
|
-
function getUtils(model, universalReady) {
|
|
46
|
+
function getUtils( model, universalReady ) {
|
|
47
47
|
const _csnRefs = csnRefs(model, universalReady);
|
|
48
48
|
const { artifactRef } = _csnRefs;
|
|
49
49
|
/** Cache for getFinalBaseTypeWithProps(). Specific to the current model. */
|
|
@@ -77,7 +77,7 @@ function getUtils(model, universalReady) {
|
|
|
77
77
|
* @param {CSN.Query} query
|
|
78
78
|
* @returns {object}
|
|
79
79
|
*/
|
|
80
|
-
function get$combined(query) {
|
|
80
|
+
function get$combined( query ) {
|
|
81
81
|
return getSources(query);
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -91,7 +91,7 @@ function getUtils(model, universalReady) {
|
|
|
91
91
|
* @param {boolean} [isSubquery]
|
|
92
92
|
* @returns {object} Map of sources
|
|
93
93
|
*/
|
|
94
|
-
function getSources(query, isSubquery = false) {
|
|
94
|
+
function getSources( query, isSubquery = false ) {
|
|
95
95
|
// Remark CW: better just a while along query.SET.args[0]
|
|
96
96
|
if (query.SET) {
|
|
97
97
|
if (query.SET.args[0].SELECT && query.SET.args[0].SELECT.elements)
|
|
@@ -124,7 +124,7 @@ function getUtils(model, universalReady) {
|
|
|
124
124
|
return {};
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
function walkArgs(args) {
|
|
127
|
+
function walkArgs( args ) {
|
|
128
128
|
let elements = Object.create(null);
|
|
129
129
|
for (const arg of args) {
|
|
130
130
|
if (arg.args) {
|
|
@@ -149,7 +149,7 @@ function getUtils(model, universalReady) {
|
|
|
149
149
|
* @param {object} mapB Map b - will not be returned
|
|
150
150
|
* @returns {object} mapA
|
|
151
151
|
*/
|
|
152
|
-
function mergeElementMaps(mapA, mapB) {
|
|
152
|
+
function mergeElementMaps( mapA, mapB ) {
|
|
153
153
|
for (const elementName in mapB) {
|
|
154
154
|
if (!mapA[elementName])
|
|
155
155
|
mapA[elementName] = [];
|
|
@@ -170,7 +170,7 @@ function getUtils(model, universalReady) {
|
|
|
170
170
|
* @param {any} [errorParent] Parent name to use for error messages, ref before alias
|
|
171
171
|
* @returns {object} existingMap
|
|
172
172
|
*/
|
|
173
|
-
function mergeElementsIntoMap(existingMap, elements, $location, parent, errorParent) {
|
|
173
|
+
function mergeElementsIntoMap( existingMap, elements, $location, parent, errorParent ) {
|
|
174
174
|
for (const elementName in elements) {
|
|
175
175
|
const element = elements[elementName];
|
|
176
176
|
if (!existingMap[elementName])
|
|
@@ -188,7 +188,7 @@ function getUtils(model, universalReady) {
|
|
|
188
188
|
* Return the name part of the artifact name - no namespace etc.
|
|
189
189
|
* @param {string|object} name Absolute name of the artifact
|
|
190
190
|
*/
|
|
191
|
-
function getBaseName(name) {
|
|
191
|
+
function getBaseName( name ) {
|
|
192
192
|
if (!name)
|
|
193
193
|
return name;
|
|
194
194
|
|
|
@@ -202,7 +202,7 @@ function getUtils(model, universalReady) {
|
|
|
202
202
|
* Return the left-most, primary source of the given query.
|
|
203
203
|
* @param {*} query Definition's query object
|
|
204
204
|
*/
|
|
205
|
-
function getQueryPrimarySource(query) {
|
|
205
|
+
function getQueryPrimarySource( query ) {
|
|
206
206
|
if (!query)
|
|
207
207
|
return undefined;
|
|
208
208
|
else if (query.SELECT)
|
|
@@ -224,7 +224,7 @@ function getUtils(model, universalReady) {
|
|
|
224
224
|
* Create an object to track visited objects identified by a unique string.
|
|
225
225
|
* @param {string} [initialId] Initial entry (optional)
|
|
226
226
|
*/
|
|
227
|
-
function createVisited(initialId) {
|
|
227
|
+
function createVisited( initialId ) {
|
|
228
228
|
const visited = Object.create(null);
|
|
229
229
|
check(initialId);
|
|
230
230
|
return { check };
|
|
@@ -234,7 +234,7 @@ function getUtils(model, universalReady) {
|
|
|
234
234
|
* add it to the list of visited identifiers.
|
|
235
235
|
* @param {string} id unique identifier
|
|
236
236
|
*/
|
|
237
|
-
function check(id) {
|
|
237
|
+
function check( id ) {
|
|
238
238
|
if (!id)
|
|
239
239
|
return;
|
|
240
240
|
if (visited[id])
|
|
@@ -248,7 +248,7 @@ function getUtils(model, universalReady) {
|
|
|
248
248
|
* Get the CSN definition for an artifact name.
|
|
249
249
|
* @param {string} defName Absolute name of the artifact
|
|
250
250
|
*/
|
|
251
|
-
function getCsnDef(defName) {
|
|
251
|
+
function getCsnDef( defName ) {
|
|
252
252
|
if (model.definitions[defName])
|
|
253
253
|
return model.definitions[defName];
|
|
254
254
|
throw new ModelError(`Nonexistent definition in the model: '${ defName }'`);
|
|
@@ -261,7 +261,7 @@ function getUtils(model, universalReady) {
|
|
|
261
261
|
* @param {object} obj
|
|
262
262
|
* @returns {boolean}
|
|
263
263
|
*/
|
|
264
|
-
function isStructured(obj) {
|
|
264
|
+
function isStructured( obj ) {
|
|
265
265
|
return !!(obj.elements || (obj.type && getFinalBaseTypeWithProps(obj.type)?.elements));
|
|
266
266
|
}
|
|
267
267
|
|
|
@@ -272,7 +272,7 @@ function getUtils(model, universalReady) {
|
|
|
272
272
|
* @param {string} typeName Absolute type name
|
|
273
273
|
* @returns {object}
|
|
274
274
|
*/
|
|
275
|
-
function getFinalTypeDef(typeName) {
|
|
275
|
+
function getFinalTypeDef( typeName ) {
|
|
276
276
|
const visited = createVisited(typeName);
|
|
277
277
|
let type = model.definitions[typeName];
|
|
278
278
|
if (!type)
|
|
@@ -291,7 +291,7 @@ function getUtils(model, universalReady) {
|
|
|
291
291
|
* @param {string} typeName Absolute type name
|
|
292
292
|
* @returns {string}
|
|
293
293
|
*/
|
|
294
|
-
function getFinalType(typeName) {
|
|
294
|
+
function getFinalType( typeName ) {
|
|
295
295
|
const visited = createVisited(typeName);
|
|
296
296
|
let type = model.definitions[typeName];
|
|
297
297
|
while (type && type.type) {
|
|
@@ -304,7 +304,7 @@ function getUtils(model, universalReady) {
|
|
|
304
304
|
|
|
305
305
|
// Return true if 'node' is a managed association element
|
|
306
306
|
// TODO: what about elements having a type, which (finally) is an assoc?
|
|
307
|
-
function isManagedAssociation(node) {
|
|
307
|
+
function isManagedAssociation( node ) {
|
|
308
308
|
return node.target !== undefined && node.on === undefined && node.keys;
|
|
309
309
|
}
|
|
310
310
|
|
|
@@ -313,7 +313,7 @@ function getUtils(model, universalReady) {
|
|
|
313
313
|
* to any of them.
|
|
314
314
|
* @param {string} typeName Absolute type name
|
|
315
315
|
*/
|
|
316
|
-
function isAssocOrComposition(typeName) {
|
|
316
|
+
function isAssocOrComposition( typeName ) {
|
|
317
317
|
if (typeName === 'cds.Association' || typeName === 'cds.Composition')
|
|
318
318
|
return true;
|
|
319
319
|
const visited = createVisited(typeName);
|
|
@@ -331,7 +331,7 @@ function getUtils(model, universalReady) {
|
|
|
331
331
|
* Returns if a type is an association or a typedef to it.
|
|
332
332
|
* @param {string} typeName Absolute type name
|
|
333
333
|
*/
|
|
334
|
-
function isAssociation(typeName) {
|
|
334
|
+
function isAssociation( typeName ) {
|
|
335
335
|
if (typeName === 'cds.Association')
|
|
336
336
|
return true;
|
|
337
337
|
const visited = createVisited(typeName);
|
|
@@ -349,7 +349,7 @@ function getUtils(model, universalReady) {
|
|
|
349
349
|
* Returns if a type is an composition or a typedef to it.
|
|
350
350
|
* @param {string} typeName Absolute type name
|
|
351
351
|
*/
|
|
352
|
-
function isComposition(typeName) {
|
|
352
|
+
function isComposition( typeName ) {
|
|
353
353
|
if (typeName === 'cds.Composition')
|
|
354
354
|
return true;
|
|
355
355
|
const visited = createVisited(typeName);
|
|
@@ -367,7 +367,7 @@ function getUtils(model, universalReady) {
|
|
|
367
367
|
* Return the namespace part of the artifact name.
|
|
368
368
|
* @param {string} name Absolute name of artifact
|
|
369
369
|
*/
|
|
370
|
-
function getNamespaceOfArtifact(name) {
|
|
370
|
+
function getNamespaceOfArtifact( name ) {
|
|
371
371
|
let lastDotIdx = name.lastIndexOf('.');
|
|
372
372
|
if (lastDotIdx === -1)
|
|
373
373
|
return undefined;
|
|
@@ -386,7 +386,7 @@ function getUtils(model, universalReady) {
|
|
|
386
386
|
* Return the context part of the artifact name if any.
|
|
387
387
|
* @param {string} name Absolute name of artifact
|
|
388
388
|
*/
|
|
389
|
-
function getContextOfArtifact(name) {
|
|
389
|
+
function getContextOfArtifact( name ) {
|
|
390
390
|
let lastDotIdx = name.lastIndexOf('.');
|
|
391
391
|
while (model.definitions[name]) {
|
|
392
392
|
if (model.definitions[name].kind === 'context' || model.definitions[name].kind === 'service')
|
|
@@ -406,7 +406,7 @@ function getUtils(model, universalReady) {
|
|
|
406
406
|
* @param {any} theValue string value of the annotation
|
|
407
407
|
* @param {any} node Node to add the annotation to
|
|
408
408
|
*/
|
|
409
|
-
function addStringAnnotationTo(absoluteName, theValue, node) {
|
|
409
|
+
function addStringAnnotationTo( absoluteName, theValue, node ) {
|
|
410
410
|
// Sanity check
|
|
411
411
|
if (!absoluteName.startsWith('@'))
|
|
412
412
|
throw Error(`Annotation name should start with "@": ${ absoluteName }`);
|
|
@@ -425,7 +425,7 @@ function getUtils(model, universalReady) {
|
|
|
425
425
|
* @param {string} artifactName Absolute name of artifact
|
|
426
426
|
* @returns {string|null}
|
|
427
427
|
*/
|
|
428
|
-
function getServiceName(artifactName) {
|
|
428
|
+
function getServiceName( artifactName ) {
|
|
429
429
|
for (;;) {
|
|
430
430
|
const idx = artifactName.lastIndexOf('.');
|
|
431
431
|
if (idx === -1)
|
|
@@ -455,11 +455,11 @@ function getUtils(model, universalReady) {
|
|
|
455
455
|
* @param {any} transformers Object defining transformer functions
|
|
456
456
|
* @returns {object}
|
|
457
457
|
*/
|
|
458
|
-
function cloneWithTransformations(rootNode, transformers) {
|
|
458
|
+
function cloneWithTransformations( rootNode, transformers ) {
|
|
459
459
|
return transformNode(rootNode);
|
|
460
460
|
|
|
461
461
|
// This general transformation function will be applied to each node recursively
|
|
462
|
-
function transformNode(node) {
|
|
462
|
+
function transformNode( node ) {
|
|
463
463
|
// Return primitive values and null unchanged, but let objects and dictionaries through
|
|
464
464
|
// (Note that 'node instanceof Object' would be false for dictionaries).
|
|
465
465
|
if (node === null || typeof node !== 'object')
|
|
@@ -488,7 +488,7 @@ function getUtils(model, universalReady) {
|
|
|
488
488
|
}
|
|
489
489
|
}
|
|
490
490
|
|
|
491
|
-
function _normalizeTypeRef(type) {
|
|
491
|
+
function _normalizeTypeRef( type ) {
|
|
492
492
|
if (type && typeof type === 'object' && type.ref?.length === 1)
|
|
493
493
|
type = type.ref[0]; // simplify type: no element -> simple string can be used
|
|
494
494
|
return type;
|
|
@@ -512,7 +512,7 @@ function getUtils(model, universalReady) {
|
|
|
512
512
|
* @param {string|object} type Type as string or type ref, i.e. `{ ref: [...] }`
|
|
513
513
|
* @returns {object|null}
|
|
514
514
|
*/
|
|
515
|
-
function getFinalBaseTypeWithProps(type) {
|
|
515
|
+
function getFinalBaseTypeWithProps( type ) {
|
|
516
516
|
type = _normalizeTypeRef(type);
|
|
517
517
|
if (!type)
|
|
518
518
|
return null;
|
|
@@ -566,7 +566,7 @@ function getUtils(model, universalReady) {
|
|
|
566
566
|
*
|
|
567
567
|
* @param {object} typeProps
|
|
568
568
|
*/
|
|
569
|
-
function _cacheResolved(typeProps) {
|
|
569
|
+
function _cacheResolved( typeProps ) {
|
|
570
570
|
finalBaseTypeCache[resolvedKey] = typeProps;
|
|
571
571
|
return typeProps;
|
|
572
572
|
}
|
|
@@ -577,7 +577,7 @@ function getUtils(model, universalReady) {
|
|
|
577
577
|
* @param obj
|
|
578
578
|
* @returns {boolean} True, if structured/arrayed/invalid, false if scalar.
|
|
579
579
|
*/
|
|
580
|
-
function _cacheNonScalar(obj) {
|
|
580
|
+
function _cacheNonScalar( obj ) {
|
|
581
581
|
if (!obj) { // Reference has no proper type, e.g. due to `type of View:calculated`.
|
|
582
582
|
_cacheResolved(null);
|
|
583
583
|
return true;
|
|
@@ -597,7 +597,7 @@ function getUtils(model, universalReady) {
|
|
|
597
597
|
* @param {object} target
|
|
598
598
|
* @param {object} source
|
|
599
599
|
*/
|
|
600
|
-
function _copyTypeProps(target, source) {
|
|
600
|
+
function _copyTypeProps( target, source ) {
|
|
601
601
|
target.type = source.type;
|
|
602
602
|
const typeProps = [ ...typeParameters.list, 'enum', 'default', 'localized' ];
|
|
603
603
|
for (const param of typeProps) {
|
|
@@ -622,7 +622,7 @@ function getUtils(model, universalReady) {
|
|
|
622
622
|
* @param {object} csn Top-level CSN. You can pass non-dictionary values.
|
|
623
623
|
* @param {CSN.Options} options CSN Options, only used for `dictionaryPrototype`, `testMode`, and `testSortCsn`
|
|
624
624
|
*/
|
|
625
|
-
function cloneCsnNonDict(csn, options) {
|
|
625
|
+
function cloneCsnNonDict( csn, options ) {
|
|
626
626
|
return sortCsn(csn, options);
|
|
627
627
|
}
|
|
628
628
|
|
|
@@ -641,7 +641,7 @@ function cloneCsnNonDict(csn, options) {
|
|
|
641
641
|
* @param {CSN.Options} options Only cloneOptions.dictionaryPrototype is
|
|
642
642
|
* used and cloneOptions are passed to sortCsn().
|
|
643
643
|
*/
|
|
644
|
-
function cloneCsnDictionary(csn, options) {
|
|
644
|
+
function cloneCsnDictionary( csn, options ) {
|
|
645
645
|
return _cloneCsnDictionary(csn, options);
|
|
646
646
|
}
|
|
647
647
|
|
|
@@ -652,7 +652,7 @@ function cloneCsnDictionary(csn, options) {
|
|
|
652
652
|
* @param {any} value
|
|
653
653
|
* @returns {any}
|
|
654
654
|
*/
|
|
655
|
-
function cloneAnnotationValue(value) {
|
|
655
|
+
function cloneAnnotationValue( value ) {
|
|
656
656
|
return _cloneAnnotationValue( value );
|
|
657
657
|
}
|
|
658
658
|
|
|
@@ -685,7 +685,7 @@ function forEachDefinition( csn, callback, iterateOptions = {} ) {
|
|
|
685
685
|
* @param constructCallback
|
|
686
686
|
*/
|
|
687
687
|
function forEachMember( construct, callback, path = [], ignoreIgnore = true, iterateOptions = {},
|
|
688
|
-
constructCallback = (_construct, _prop, _path) => {}) {
|
|
688
|
+
constructCallback = (_construct, _prop, _path) => {} ) {
|
|
689
689
|
// Allow processing _ignored elements if requested
|
|
690
690
|
if (ignoreIgnore && construct._ignore)
|
|
691
691
|
return;
|
|
@@ -728,7 +728,7 @@ function forEachMember( construct, callback, path = [], ignoreIgnore = true, ite
|
|
|
728
728
|
* @param {constructCallback|constructCallback[]} callback
|
|
729
729
|
*/
|
|
730
730
|
function forEachMemberWithQuery( construct, callback, path = [], ignoreIgnore = true, iterateOptions = {},
|
|
731
|
-
constructCallback = (_construct, _prop, _path) => {}) {
|
|
731
|
+
constructCallback = (_construct, _prop, _path) => {} ) {
|
|
732
732
|
forEachMember(construct, callback, path, ignoreIgnore, iterateOptions, constructCallback);
|
|
733
733
|
if (construct.query) {
|
|
734
734
|
forAllQueries(construct.query, (q, p) => {
|
|
@@ -751,7 +751,7 @@ function forEachMemberWithQuery( construct, callback, path = [], ignoreIgnore =
|
|
|
751
751
|
* @param {constructCallback|constructCallback[]} callback
|
|
752
752
|
*/
|
|
753
753
|
function forEachMemberRecursively( construct, callback, path = [], ignoreIgnore = true, iterateOptions = {},
|
|
754
|
-
constructCallback = (_construct, _prop, _path) => {}) {
|
|
754
|
+
constructCallback = (_construct, _prop, _path) => {} ) {
|
|
755
755
|
forEachMember( construct, ( member, memberName, prop, subpath, parent ) => {
|
|
756
756
|
if (Array.isArray(callback))
|
|
757
757
|
callback.forEach(cb => cb( member, memberName, prop, subpath, parent ));
|
|
@@ -775,7 +775,7 @@ function forEachMemberRecursively( construct, callback, path = [], ignoreIgnore
|
|
|
775
775
|
* @param {constructCallback|constructCallback[]} callback
|
|
776
776
|
*/
|
|
777
777
|
function forEachMemberRecursivelyWithQuery( construct, callback, path = [], ignoreIgnore = true, iterateOptions = {},
|
|
778
|
-
constructCallback = (_construct, _prop, _path) => {}) {
|
|
778
|
+
constructCallback = (_construct, _prop, _path) => {} ) {
|
|
779
779
|
forEachMemberRecursively(construct, callback, path, ignoreIgnore, iterateOptions, constructCallback);
|
|
780
780
|
if (construct.query) {
|
|
781
781
|
forAllQueries(construct.query, (q, p) => {
|
|
@@ -798,7 +798,7 @@ function forEachMemberRecursivelyWithQuery( construct, callback, path = [], igno
|
|
|
798
798
|
* @param {CSN.Path} path
|
|
799
799
|
* @param {object} iterateOptions can be used to skip certain kinds from being iterated
|
|
800
800
|
*/
|
|
801
|
-
function forEachGeneric( construct, prop, callback, path = [], iterateOptions = {}) {
|
|
801
|
+
function forEachGeneric( construct, prop, callback, path = [], iterateOptions = {} ) {
|
|
802
802
|
const dict = construct[prop];
|
|
803
803
|
for (const name in dict) {
|
|
804
804
|
if (!Object.prototype.hasOwnProperty.call(dict, name))
|
|
@@ -810,7 +810,7 @@ function forEachGeneric( construct, prop, callback, path = [], iterateOptions =
|
|
|
810
810
|
continue;
|
|
811
811
|
executeCallbacks( dictObj, name );
|
|
812
812
|
}
|
|
813
|
-
function executeCallbacks(o, name ) {
|
|
813
|
+
function executeCallbacks( o, name ) {
|
|
814
814
|
const p = iterateOptions.pathWithoutProp ? [ name ] : [ prop, name ];
|
|
815
815
|
|
|
816
816
|
if (Array.isArray(callback))
|
|
@@ -820,72 +820,66 @@ function forEachGeneric( construct, prop, callback, path = [], iterateOptions =
|
|
|
820
820
|
}
|
|
821
821
|
}
|
|
822
822
|
|
|
823
|
+
const queryTraversalProperties = [ 'args', 'xpr', 'columns', 'where', 'having' ];
|
|
824
|
+
|
|
823
825
|
/**
|
|
824
|
-
* @param {CSN.Query}
|
|
825
|
-
* @param {queryCallback
|
|
826
|
+
* @param {CSN.Query} query
|
|
827
|
+
* @param {queryCallback} queryCallback
|
|
826
828
|
* @param {CSN.Path} path
|
|
827
829
|
*/
|
|
828
|
-
function forAllQueries(
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
query = query.SET;
|
|
843
|
-
}
|
|
830
|
+
function forAllQueries( query, queryCallback, path ) {
|
|
831
|
+
if (query.SELECT) {
|
|
832
|
+
// The projection is turned into a normalized query - there
|
|
833
|
+
// is no real SELECT, it is fake
|
|
834
|
+
if (!(path.length === 3 && path[2] === 'projection'))
|
|
835
|
+
path.push('SELECT');
|
|
836
|
+
queryCallback( query, path );
|
|
837
|
+
query = query.SELECT;
|
|
838
|
+
}
|
|
839
|
+
else if (query.SET) {
|
|
840
|
+
path.push('SET');
|
|
841
|
+
queryCallback( query, path );
|
|
842
|
+
query = query.SET;
|
|
843
|
+
}
|
|
844
844
|
|
|
845
|
-
|
|
846
|
-
|
|
845
|
+
if (query.from)
|
|
846
|
+
traverseFrom( query.from, queryCallback, [ ...path, 'from' ] );
|
|
847
847
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
}
|
|
848
|
+
for (const prop of queryTraversalProperties) {
|
|
849
|
+
// all properties which could have sub queries (directly or indirectly)
|
|
850
|
+
const expr = query[prop];
|
|
851
|
+
if (expr && typeof expr === 'object') {
|
|
852
|
+
if (Array.isArray(expr)) {
|
|
853
|
+
for (let i = 0; i < expr.length; i++)
|
|
854
|
+
forAllQueries(expr[i], queryCallback, [ ...path, prop, i ]);
|
|
855
|
+
}
|
|
856
|
+
else {
|
|
857
|
+
for (const argName of Object.keys( expr ))
|
|
858
|
+
forAllQueries(expr[argName], queryCallback, [ ...path, prop, argName ]);
|
|
860
859
|
}
|
|
861
|
-
}
|
|
862
|
-
function executeCallbacks() {
|
|
863
|
-
if (Array.isArray(callback))
|
|
864
|
-
callback.forEach(cb => cb( query, queryPath ));
|
|
865
|
-
else
|
|
866
|
-
callback( query, queryPath );
|
|
867
860
|
}
|
|
868
861
|
}
|
|
862
|
+
}
|
|
869
863
|
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
} // sub query in FROM
|
|
864
|
+
/**
|
|
865
|
+
* @param {CSN.QueryFrom} from
|
|
866
|
+
* @param {queryCallback} queryCallback
|
|
867
|
+
* @param {CSN.Path} path
|
|
868
|
+
*/
|
|
869
|
+
function traverseFrom( from, queryCallback, path = [] ) {
|
|
870
|
+
if (from.ref) {
|
|
871
|
+
// ignore
|
|
872
|
+
}
|
|
873
|
+
else if (from.args) { // join
|
|
874
|
+
for (let i = 0; i < from.args.length; i++)
|
|
875
|
+
traverseFrom(from.args[i], queryCallback, [ ...path, 'args', i ]);
|
|
876
|
+
}
|
|
877
|
+
else {
|
|
878
|
+
forAllQueries( from, queryCallback, path ); // sub query in FROM
|
|
886
879
|
}
|
|
887
880
|
}
|
|
888
881
|
|
|
882
|
+
|
|
889
883
|
/**
|
|
890
884
|
* Compare a given annotation value with an expectation value and return
|
|
891
885
|
*
|
|
@@ -907,7 +901,7 @@ function forAllQueries(mainQuery, queryCallback, path = []) {
|
|
|
907
901
|
* @param {boolean} caseInsensitive
|
|
908
902
|
* @returns {boolean}
|
|
909
903
|
*/
|
|
910
|
-
function hasAnnotationValue(artifact, annotationName, expected = true, caseInsensitive = false) {
|
|
904
|
+
function hasAnnotationValue( artifact, annotationName, expected = true, caseInsensitive = false ) {
|
|
911
905
|
if (expected === false)
|
|
912
906
|
return artifact[annotationName] === expected || artifact[annotationName] === null;
|
|
913
907
|
else if (typeof artifact[annotationName] === 'string' && caseInsensitive === true)
|
|
@@ -925,7 +919,7 @@ function hasAnnotationValue(artifact, annotationName, expected = true, caseInsen
|
|
|
925
919
|
* @param {CSN.Element} elementCsn
|
|
926
920
|
* @param {ODataOptions} options EDM specific options
|
|
927
921
|
*/
|
|
928
|
-
function isEdmPropertyRendered(elementCsn, options) {
|
|
922
|
+
function isEdmPropertyRendered( elementCsn, options ) {
|
|
929
923
|
// FKs are rendered in
|
|
930
924
|
// V2/V4 flat: always on
|
|
931
925
|
// V4 struct: on/off
|
|
@@ -962,7 +956,7 @@ function isEdmPropertyRendered(elementCsn, options) {
|
|
|
962
956
|
* @returns {string} The resulting database name for (absolute) 'artifactName', depending on the current naming mode.
|
|
963
957
|
*/
|
|
964
958
|
// eslint-disable-next-line no-unused-vars
|
|
965
|
-
function getArtifactDatabaseNameOf(artifactName, sqlMapping, csn, sqlDialect = 'plain') {
|
|
959
|
+
function getArtifactDatabaseNameOf( artifactName, sqlMapping, csn, sqlDialect = 'plain' ) {
|
|
966
960
|
if (csn && typeof csn === 'object' && csn.definitions) {
|
|
967
961
|
isValidMappingDialectCombi(sqlDialect, sqlMapping);
|
|
968
962
|
if (sqlMapping === 'quoted' || sqlMapping === 'hdbcds')
|
|
@@ -992,7 +986,7 @@ function getArtifactDatabaseNameOf(artifactName, sqlMapping, csn, sqlDialect = '
|
|
|
992
986
|
* @param {string} artifactName Artifact name to use
|
|
993
987
|
* @returns {string} The resulting name
|
|
994
988
|
*/
|
|
995
|
-
function getResultingName(csn, namingMode, artifactName) {
|
|
989
|
+
function getResultingName( csn, namingMode, artifactName ) {
|
|
996
990
|
if (namingMode === 'plain' || artifactName.indexOf('.') === -1)
|
|
997
991
|
return artifactName;
|
|
998
992
|
|
|
@@ -1026,7 +1020,7 @@ function getResultingName(csn, namingMode, artifactName) {
|
|
|
1026
1020
|
* @param {CSN.Model} csn
|
|
1027
1021
|
* @returns {string[]|null} Array of at most 2 strings: if both: [prefix, suffix], otherwise just one - or null
|
|
1028
1022
|
*/
|
|
1029
|
-
function getUnderscoredName(startIndex, parts, csn) {
|
|
1023
|
+
function getUnderscoredName( startIndex, parts, csn ) {
|
|
1030
1024
|
for (let i = startIndex; i < parts.length; i++) {
|
|
1031
1025
|
const namePart = parts.slice(0, i).join('.');
|
|
1032
1026
|
const art = csn.definitions[namePart];
|
|
@@ -1058,7 +1052,7 @@ function getUnderscoredName(startIndex, parts, csn) {
|
|
|
1058
1052
|
return null;
|
|
1059
1053
|
}
|
|
1060
1054
|
|
|
1061
|
-
function isValidMappingDialectCombi(sqlDialect, sqlMapping) {
|
|
1055
|
+
function isValidMappingDialectCombi( sqlDialect, sqlMapping ) {
|
|
1062
1056
|
if (sqlMapping === 'hdbcds' && sqlDialect !== 'hana')
|
|
1063
1057
|
throw new Error(`sqlMapping "hdbcds" must only be used with sqlDialect "hana" - found: ${ sqlDialect }`);
|
|
1064
1058
|
return true;
|
|
@@ -1082,7 +1076,7 @@ function isValidMappingDialectCombi(sqlDialect, sqlMapping) {
|
|
|
1082
1076
|
* @returns {string} The resulting database element name for 'elemName', depending on the current naming mode.
|
|
1083
1077
|
*/
|
|
1084
1078
|
// eslint-disable-next-line no-unused-vars
|
|
1085
|
-
function getElementDatabaseNameOf(elemName, sqlMapping, sqlDialect = 'plain') {
|
|
1079
|
+
function getElementDatabaseNameOf( elemName, sqlMapping, sqlDialect = 'plain' ) {
|
|
1086
1080
|
isValidMappingDialectCombi(sqlDialect, sqlMapping);
|
|
1087
1081
|
if (sqlMapping === 'hdbcds')
|
|
1088
1082
|
return elemName;
|
|
@@ -1134,7 +1128,7 @@ function setDependencies( csn, refs = csnRefs(csn) ) {
|
|
|
1134
1128
|
cleanup, csn, _dependents, _dependencies,
|
|
1135
1129
|
};
|
|
1136
1130
|
|
|
1137
|
-
function handleArgs(artifact, artifactName, args) {
|
|
1131
|
+
function handleArgs( artifact, artifactName, args ) {
|
|
1138
1132
|
for (const arg of args) {
|
|
1139
1133
|
if (arg.args)
|
|
1140
1134
|
handleArgs(artifact, artifactName, arg.args);
|
|
@@ -1143,20 +1137,20 @@ function setDependencies( csn, refs = csnRefs(csn) ) {
|
|
|
1143
1137
|
}
|
|
1144
1138
|
}
|
|
1145
1139
|
|
|
1146
|
-
function handleDependency(dependency, dependant, dependantName) {
|
|
1140
|
+
function handleDependency( dependency, dependant, dependantName ) {
|
|
1147
1141
|
dependant[_dependencies].add(dependency);
|
|
1148
1142
|
initDependents(dependency);
|
|
1149
1143
|
dependency[_dependents][dependantName] = dependant;
|
|
1150
1144
|
}
|
|
1151
1145
|
|
|
1152
|
-
function initDependents(obj) {
|
|
1146
|
+
function initDependents( obj ) {
|
|
1153
1147
|
if (!obj[_dependents]) {
|
|
1154
1148
|
obj[_dependents] = Object.create(null);
|
|
1155
1149
|
cleanup.push(() => delete obj[_dependents]);
|
|
1156
1150
|
}
|
|
1157
1151
|
}
|
|
1158
1152
|
|
|
1159
|
-
function initDependencies(obj) {
|
|
1153
|
+
function initDependencies( obj ) {
|
|
1160
1154
|
if (!obj[_dependencies]) {
|
|
1161
1155
|
obj[_dependencies] = new Set();
|
|
1162
1156
|
cleanup.push(() => delete obj[_dependencies]);
|
|
@@ -1171,7 +1165,7 @@ function setDependencies( csn, refs = csnRefs(csn) ) {
|
|
|
1171
1165
|
* @param {CSN.Artifact} art
|
|
1172
1166
|
* @returns {boolean}
|
|
1173
1167
|
*/
|
|
1174
|
-
function isPersistedOnDatabase(art) {
|
|
1168
|
+
function isPersistedOnDatabase( art ) {
|
|
1175
1169
|
return !(art.kind === 'entity' && (art.abstract || hasAnnotationValue(art, '@cds.persistence.skip')));
|
|
1176
1170
|
}
|
|
1177
1171
|
/**
|
|
@@ -1180,7 +1174,7 @@ function isPersistedOnDatabase(art) {
|
|
|
1180
1174
|
* @param {CSN.Artifact} artifact
|
|
1181
1175
|
* @returns {boolean}
|
|
1182
1176
|
*/
|
|
1183
|
-
function isPersistedAsView(artifact) {
|
|
1177
|
+
function isPersistedAsView( artifact ) {
|
|
1184
1178
|
return artifact && artifact.kind === 'entity' &&
|
|
1185
1179
|
!artifact._ignore &&
|
|
1186
1180
|
!artifact.abstract &&
|
|
@@ -1194,7 +1188,7 @@ function isPersistedAsView(artifact) {
|
|
|
1194
1188
|
* @param {CSN.Artifact} artifact
|
|
1195
1189
|
* @returns {boolean}
|
|
1196
1190
|
*/
|
|
1197
|
-
function isPersistedAsTable(artifact) {
|
|
1191
|
+
function isPersistedAsTable( artifact ) {
|
|
1198
1192
|
return artifact.kind === 'entity' &&
|
|
1199
1193
|
!artifact._ignore &&
|
|
1200
1194
|
!artifact.abstract &&
|
|
@@ -1219,7 +1213,7 @@ function generatedByCompilerVersion() {
|
|
|
1219
1213
|
* @param {CSN.Artifact} art Artifact with a query or a projection
|
|
1220
1214
|
* @returns {object} Object with a query property.
|
|
1221
1215
|
*/
|
|
1222
|
-
function getNormalizedQuery(art) {
|
|
1216
|
+
function getNormalizedQuery( art ) {
|
|
1223
1217
|
if (art.projection)
|
|
1224
1218
|
return { query: { SELECT: art.projection } };
|
|
1225
1219
|
|
|
@@ -1234,7 +1228,7 @@ function getNormalizedQuery(art) {
|
|
|
1234
1228
|
* @param {CSN.Model} csn
|
|
1235
1229
|
* @returns {string} Name of the root
|
|
1236
1230
|
*/
|
|
1237
|
-
function getRootArtifactName(artifactName, csn) {
|
|
1231
|
+
function getRootArtifactName( artifactName, csn ) {
|
|
1238
1232
|
const parts = artifactName.split('.');
|
|
1239
1233
|
|
|
1240
1234
|
if (parts.length === 1)
|
|
@@ -1262,7 +1256,7 @@ function getRootArtifactName(artifactName, csn) {
|
|
|
1262
1256
|
// 'foo.bar.wiz' => 'wiz'
|
|
1263
1257
|
// 'foo' => 'foo';
|
|
1264
1258
|
// 'foo::bar' => 'bar'
|
|
1265
|
-
function getLastPartOf(name) {
|
|
1259
|
+
function getLastPartOf( name ) {
|
|
1266
1260
|
return name.substring(name.search(/[^.:]+$/));
|
|
1267
1261
|
}
|
|
1268
1262
|
|
|
@@ -1272,7 +1266,7 @@ function getLastPartOf(name) {
|
|
|
1272
1266
|
// ['foo.bar.wiz'] => 'wiz'
|
|
1273
1267
|
// ['foo'] => 'foo';
|
|
1274
1268
|
// ['foo::bar'] => 'bar'
|
|
1275
|
-
function getLastPartOfRef(ref) {
|
|
1269
|
+
function getLastPartOfRef( ref ) {
|
|
1276
1270
|
const lastPathStep = ref[ref.length - 1];
|
|
1277
1271
|
return getLastPartOf(lastPathStep.id || lastPathStep);
|
|
1278
1272
|
}
|
|
@@ -1286,7 +1280,7 @@ function getLastPartOfRef(ref) {
|
|
|
1286
1280
|
* @param {object} toNode
|
|
1287
1281
|
* @param {boolean} [overwrite]
|
|
1288
1282
|
*/
|
|
1289
|
-
function copyAnnotations(fromNode, toNode, overwrite = false) {
|
|
1283
|
+
function copyAnnotations( fromNode, toNode, overwrite = false ) {
|
|
1290
1284
|
// Ignore if no toNode (in case of errors)
|
|
1291
1285
|
if (!toNode)
|
|
1292
1286
|
return;
|
|
@@ -1310,7 +1304,7 @@ function copyAnnotations(fromNode, toNode, overwrite = false) {
|
|
|
1310
1304
|
* @param {object} toNode
|
|
1311
1305
|
* @param {boolean} [overwrite]
|
|
1312
1306
|
*/
|
|
1313
|
-
function copyAnnotationsAndDoc(fromNode, toNode, overwrite = false) {
|
|
1307
|
+
function copyAnnotationsAndDoc( fromNode, toNode, overwrite = false ) {
|
|
1314
1308
|
// Ignore if no toNode (in case of errors)
|
|
1315
1309
|
if (!toNode)
|
|
1316
1310
|
return;
|
|
@@ -1340,7 +1334,7 @@ function copyAnnotationsAndDoc(fromNode, toNode, overwrite = false) {
|
|
|
1340
1334
|
* filter: Positive filter. If it returns true, annotations for the referenced artifact
|
|
1341
1335
|
* will be applied.
|
|
1342
1336
|
*/
|
|
1343
|
-
function applyAnnotationsFromExtensions(csn, config) {
|
|
1337
|
+
function applyAnnotationsFromExtensions( csn, config ) {
|
|
1344
1338
|
if (!csn.extensions)
|
|
1345
1339
|
return;
|
|
1346
1340
|
|
|
@@ -1360,7 +1354,7 @@ function applyAnnotationsFromExtensions(csn, config) {
|
|
|
1360
1354
|
}
|
|
1361
1355
|
}
|
|
1362
1356
|
|
|
1363
|
-
function applyAnnotationsToElements(ext, def) {
|
|
1357
|
+
function applyAnnotationsToElements( ext, def ) {
|
|
1364
1358
|
// Only the definition is arrayed but the extension is not since
|
|
1365
1359
|
// `items` is not expected in `extensions` by the CSN frontend and not
|
|
1366
1360
|
// generated by the CDL parser for `annotate E:arrayed.elem`.
|
|
@@ -1380,7 +1374,7 @@ function applyAnnotationsFromExtensions(csn, config) {
|
|
|
1380
1374
|
}
|
|
1381
1375
|
}
|
|
1382
1376
|
|
|
1383
|
-
function isAspect(node) {
|
|
1377
|
+
function isAspect( node ) {
|
|
1384
1378
|
return node && node.kind === 'aspect';
|
|
1385
1379
|
}
|
|
1386
1380
|
|
|
@@ -1390,7 +1384,7 @@ function isAspect(node) {
|
|
|
1390
1384
|
* @param {CSN.Artifact} artifact
|
|
1391
1385
|
* @returns {boolean}
|
|
1392
1386
|
*/
|
|
1393
|
-
function hasValidSkipOrExists(artifact) {
|
|
1387
|
+
function hasValidSkipOrExists( artifact ) {
|
|
1394
1388
|
return artifact.kind === 'entity' &&
|
|
1395
1389
|
(hasAnnotationValue(artifact, '@cds.persistence.exists', true) || hasAnnotationValue(artifact, '@cds.persistence.skip', true));
|
|
1396
1390
|
}
|
|
@@ -1402,7 +1396,7 @@ function hasValidSkipOrExists(artifact) {
|
|
|
1402
1396
|
* @param {string} artifactName artifact name to get the namespace for
|
|
1403
1397
|
* @returns {string | null} The namespace name
|
|
1404
1398
|
*/
|
|
1405
|
-
function getNamespace(csn, artifactName) {
|
|
1399
|
+
function getNamespace( csn, artifactName ) {
|
|
1406
1400
|
const parts = artifactName.split('.');
|
|
1407
1401
|
let seen = parts[0];
|
|
1408
1402
|
const art = csn.definitions[seen];
|
|
@@ -1432,7 +1426,7 @@ function getNamespace(csn, artifactName) {
|
|
|
1432
1426
|
* @param {CSN.Model} csn
|
|
1433
1427
|
* @param {CSN.Options} options
|
|
1434
1428
|
*/
|
|
1435
|
-
function sortCsnDefinitionsForTests(csn, options) {
|
|
1429
|
+
function sortCsnDefinitionsForTests( csn, options ) {
|
|
1436
1430
|
if (!options.testMode && !options.testSortCsn)
|
|
1437
1431
|
return;
|
|
1438
1432
|
const sorted = Object.create(null);
|
|
@@ -1448,7 +1442,7 @@ function sortCsnDefinitionsForTests(csn, options) {
|
|
|
1448
1442
|
* @param {CSN.Model} csn
|
|
1449
1443
|
* @returns {string[]}
|
|
1450
1444
|
*/
|
|
1451
|
-
function getServiceNames(csn) {
|
|
1445
|
+
function getServiceNames( csn ) {
|
|
1452
1446
|
const result = [];
|
|
1453
1447
|
forEachDefinition(csn, (artifact, artifactName) => {
|
|
1454
1448
|
if (artifact.kind === 'service' && !artifact.abstract)
|
|
@@ -1464,7 +1458,7 @@ function getServiceNames(csn) {
|
|
|
1464
1458
|
* @param {CSN.Path} path
|
|
1465
1459
|
* @returns {object} Whatever is at the end of path
|
|
1466
1460
|
*/
|
|
1467
|
-
function walkCsnPath(csn, path) {
|
|
1461
|
+
function walkCsnPath( csn, path ) {
|
|
1468
1462
|
/** @type {object} */
|
|
1469
1463
|
let obj = csn;
|
|
1470
1464
|
for (const segment of path)
|
|
@@ -1482,7 +1476,7 @@ function walkCsnPath(csn, path) {
|
|
|
1482
1476
|
* @param {CSN.Options} options
|
|
1483
1477
|
* @returns {string|null}
|
|
1484
1478
|
*/
|
|
1485
|
-
function getVariableReplacement(ref, options) {
|
|
1479
|
+
function getVariableReplacement( ref, options ) {
|
|
1486
1480
|
if (options && options.variableReplacements) {
|
|
1487
1481
|
let replacement = options.variableReplacements;
|
|
1488
1482
|
for (const segment of ref) {
|
|
@@ -1511,7 +1505,7 @@ function getVariableReplacement(ref, options) {
|
|
|
1511
1505
|
* the comparison. This eliminates false negatives such as
|
|
1512
1506
|
* mismatching $locations or @odata.foreignKey4.
|
|
1513
1507
|
*/
|
|
1514
|
-
function isDeepEqual(obj, other, noExtendedProps) {
|
|
1508
|
+
function isDeepEqual( obj, other, noExtendedProps ) {
|
|
1515
1509
|
let objectKeys = Object.keys(obj);
|
|
1516
1510
|
let otherKeys = Object.keys(other);
|
|
1517
1511
|
|
|
@@ -1537,6 +1531,19 @@ function isDeepEqual(obj, other, noExtendedProps) {
|
|
|
1537
1531
|
return true;
|
|
1538
1532
|
}
|
|
1539
1533
|
|
|
1534
|
+
/**
|
|
1535
|
+
* Returns a function that, if called, calls all functions inside
|
|
1536
|
+
* the given `functions` array with the same arguments.
|
|
1537
|
+
*
|
|
1538
|
+
* @param {Function[]} functions
|
|
1539
|
+
* @param {object} thisArg Argument that will be passed to all functions as `this`.
|
|
1540
|
+
*/
|
|
1541
|
+
function functionList( functions, thisArg ) {
|
|
1542
|
+
return function iterateFunctions(...args) {
|
|
1543
|
+
return functions.map(f => f.apply(thisArg, args));
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1540
1547
|
module.exports = {
|
|
1541
1548
|
getUtils,
|
|
1542
1549
|
cloneCsn: cloneCsnNonDict, // Umbrella relies on this name
|
|
@@ -1581,4 +1588,5 @@ module.exports = {
|
|
|
1581
1588
|
getVariableReplacement,
|
|
1582
1589
|
implicitAs,
|
|
1583
1590
|
isDeepEqual,
|
|
1591
|
+
functionList,
|
|
1584
1592
|
};
|