@sap/cds-compiler 4.0.2 → 4.2.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 +200 -5
- package/bin/cdsc.js +18 -15
- package/doc/CHANGELOG_BETA.md +16 -0
- package/doc/CHANGELOG_DEPRECATED.md +15 -0
- package/lib/api/main.js +33 -13
- package/lib/api/options.js +2 -2
- package/lib/api/validate.js +25 -25
- package/lib/base/location.js +6 -7
- package/lib/base/message-registry.js +123 -42
- package/lib/base/messages.js +18 -10
- package/lib/base/model.js +43 -10
- package/lib/checks/defaultValues.js +6 -6
- package/lib/checks/elements.js +11 -10
- package/lib/checks/foreignKeys.js +0 -5
- package/lib/checks/manyNavigations.js +33 -0
- package/lib/checks/onConditions.js +22 -14
- package/lib/checks/queryNoDbArtifacts.js +132 -73
- package/lib/checks/selectItems.js +4 -55
- package/lib/checks/sql-snippets.js +15 -4
- package/lib/checks/types.js +3 -3
- package/lib/checks/utils.js +4 -3
- package/lib/checks/validator.js +3 -1
- package/lib/compiler/.eslintrc.json +2 -1
- package/lib/compiler/assert-consistency.js +71 -40
- package/lib/compiler/base.js +7 -2
- package/lib/compiler/builtins.js +40 -41
- package/lib/compiler/checks.js +415 -367
- package/lib/compiler/classes.js +62 -0
- package/lib/compiler/cycle-detector.js +9 -9
- package/lib/compiler/define.js +124 -90
- package/lib/compiler/extend.js +115 -88
- package/lib/compiler/finalize-parse-cdl.js +26 -25
- package/lib/compiler/generate.js +57 -49
- package/lib/compiler/index.js +56 -56
- package/lib/compiler/kick-start.js +10 -7
- package/lib/compiler/moduleLayers.js +1 -1
- package/lib/compiler/populate.js +180 -144
- package/lib/compiler/propagator.js +10 -9
- package/lib/compiler/resolve.js +321 -246
- package/lib/compiler/shared.js +812 -433
- package/lib/compiler/tweak-assocs.js +114 -50
- package/lib/compiler/utils.js +241 -46
- package/lib/edm/.eslintrc.json +40 -1
- package/lib/edm/annotations/genericTranslation.js +721 -707
- package/lib/edm/annotations/preprocessAnnotations.js +88 -77
- package/lib/edm/csn2edm.js +389 -378
- package/lib/edm/edm.js +679 -770
- package/lib/edm/edmAnnoPreprocessor.js +132 -146
- package/lib/edm/edmInboundChecks.js +29 -27
- package/lib/edm/edmPreprocessor.js +689 -648
- package/lib/edm/edmUtils.js +279 -300
- package/lib/gen/Dictionary.json +34 -10
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +2857 -2856
- package/lib/json/from-csn.js +77 -51
- package/lib/json/to-csn.js +15 -15
- package/lib/language/antlrParser.js +2 -1
- package/lib/language/genericAntlrParser.js +52 -43
- package/lib/language/language.g4 +61 -64
- package/lib/language/multiLineStringParser.js +2 -0
- package/lib/main.d.ts +65 -0
- package/lib/model/csnRefs.js +37 -19
- package/lib/model/csnUtils.js +51 -18
- package/lib/model/revealInternalProperties.js +30 -22
- package/lib/modelCompare/compare.js +149 -41
- package/lib/modelCompare/utils/filter.js +55 -25
- package/lib/optionProcessor.js +21 -9
- package/lib/render/manageConstraints.js +20 -17
- package/lib/render/toCdl.js +63 -23
- package/lib/render/toHdbcds.js +2 -2
- package/lib/render/toRename.js +4 -9
- package/lib/render/toSql.js +82 -35
- package/lib/render/utils/common.js +11 -9
- package/lib/render/utils/unique.js +52 -0
- package/lib/transform/db/applyTransformations.js +62 -21
- package/lib/transform/db/assertUnique.js +7 -8
- package/lib/transform/db/associations.js +2 -2
- package/lib/transform/db/cdsPersistence.js +9 -9
- package/lib/transform/db/constraints.js +47 -17
- package/lib/transform/db/expansion.js +138 -68
- package/lib/transform/db/flattening.js +98 -30
- package/lib/transform/db/rewriteCalculatedElements.js +20 -14
- package/lib/transform/db/temporal.js +1 -1
- package/lib/transform/db/transformExists.js +8 -7
- package/lib/transform/db/views.js +73 -33
- package/lib/transform/draft/db.js +11 -9
- package/lib/transform/draft/odata.js +1 -1
- package/lib/transform/{forOdataNew.js → forOdata.js} +10 -7
- package/lib/transform/forRelationalDB.js +148 -136
- package/lib/transform/localized.js +92 -54
- package/lib/transform/odata/toFinalBaseType.js +3 -3
- package/lib/transform/{transformUtilsNew.js → transformUtils.js} +13 -111
- package/lib/transform/translateAssocsToJoins.js +14 -28
- package/lib/utils/file.js +7 -7
- package/lib/utils/moduleResolve.js +210 -121
- package/lib/utils/objectUtils.js +1 -1
- package/package.json +5 -5
- package/share/messages/check-proper-type-of.md +1 -1
- package/share/messages/{check-proper-type.md → def-missing-type.md} +3 -5
- package/share/messages/message-explanations.json +1 -1
package/lib/model/csnRefs.js
CHANGED
|
@@ -49,14 +49,14 @@
|
|
|
49
49
|
// inspectRef() - to enable caching.
|
|
50
50
|
//
|
|
51
51
|
// If any of these conditions are not given, our functions usually simply
|
|
52
|
-
//
|
|
52
|
+
// throw an exception (which might even be a plain TypeError), but it might
|
|
53
53
|
// also just return any value. CSN processors can provide user-friendly error
|
|
54
54
|
// messages by calling the Core Compiler in case of exceptions. For details,
|
|
55
55
|
// see internalDoc/CoreCompiler.md#use-of-the-core-compiler-for-csn-processors.
|
|
56
56
|
|
|
57
57
|
// During a transformation, care must be taken to adhere to these conditions.
|
|
58
58
|
// E.g. a structure flattening function cannot create an element `s_x` and
|
|
59
|
-
// delete `s` and then still
|
|
59
|
+
// delete `s` and then still expect inspectRef() to be able to resolve a
|
|
60
60
|
// reference `['s', 'x']`.
|
|
61
61
|
|
|
62
62
|
// There are currently 3 (SQL) backend issues for which we provide a workaround:
|
|
@@ -205,15 +205,14 @@ const artifactProperties = [ 'elements', 'columns', 'keys', 'mixin', 'enum',
|
|
|
205
205
|
// - lexical: false | Function - determines where to look first for “lexical names”
|
|
206
206
|
// - dynamic: String - describes the dynamic environment (if in query)
|
|
207
207
|
// - assoc: String, with dynamic: 'global' - what to do with assoc steps
|
|
208
|
-
// * 'static': visit elements of anonymous aspect if not last ref item
|
|
209
208
|
// * 'target': always follow target, including last ref item
|
|
210
|
-
// * other (& not provided) = follow target if not last ref item
|
|
209
|
+
// * other (& not provided) = follow target (targetAspect if no target) if not last ref item
|
|
211
210
|
const referenceSemantics = {
|
|
212
211
|
$init: { $initOnly: true },
|
|
213
|
-
type: { lexical: false, dynamic: 'global'
|
|
214
|
-
includes: { lexical: false, dynamic: 'global'
|
|
215
|
-
target: { lexical: false, dynamic: 'global'
|
|
216
|
-
targetAspect: { lexical: false, dynamic: 'global'
|
|
212
|
+
type: { lexical: false, dynamic: 'global' },
|
|
213
|
+
includes: { lexical: false, dynamic: 'global' },
|
|
214
|
+
target: { lexical: false, dynamic: 'global' },
|
|
215
|
+
targetAspect: { lexical: false, dynamic: 'global' },
|
|
217
216
|
from: { lexical: false, dynamic: 'global', assoc: 'target' },
|
|
218
217
|
keys: { lexical: false, dynamic: 'target' },
|
|
219
218
|
keys_origin: { lexical: false, dynamic: 'target' },
|
|
@@ -265,6 +264,9 @@ function csnRefs( csn, universalReady ) {
|
|
|
265
264
|
queryOrMain,
|
|
266
265
|
getColumn: elem => getCache( elem, '_column' ),
|
|
267
266
|
getElement: col => getCache( col, '_element' ),
|
|
267
|
+
/** Returns the column's name; either explicit, implicit or internal one. */
|
|
268
|
+
getColumnName: col => getCache( col, '$as' ),
|
|
269
|
+
$getQueries: def => getCache( def, '$queries' ), // unstable API
|
|
268
270
|
initDefinition,
|
|
269
271
|
dropDefinitionCache,
|
|
270
272
|
targetAspect,
|
|
@@ -314,7 +316,7 @@ function csnRefs( csn, universalReady ) {
|
|
|
314
316
|
env = effectiveType( env.items );
|
|
315
317
|
if (env.elements) // shortcut
|
|
316
318
|
return env;
|
|
317
|
-
const target = (staticAssoc ? targetAspect( env ) : env.target);
|
|
319
|
+
const target = (staticAssoc ? targetAspect( env ) : env.target || env.targetAspect);
|
|
318
320
|
if (typeof target !== 'string')
|
|
319
321
|
return target || env;
|
|
320
322
|
const def = csn.definitions[target];
|
|
@@ -352,7 +354,7 @@ function csnRefs( csn, universalReady ) {
|
|
|
352
354
|
|
|
353
355
|
function fromArtifactRef( ref ) {
|
|
354
356
|
// do not cache while there is second param
|
|
355
|
-
const art = artifactFromRef( ref
|
|
357
|
+
const art = artifactFromRef( ref );
|
|
356
358
|
if (art)
|
|
357
359
|
return art;
|
|
358
360
|
throw new ModelError( `Unknown artifact reference: ${ typeof ref !== 'string' ? JSON.stringify(ref.ref) : ref }` );
|
|
@@ -363,7 +365,7 @@ function csnRefs( csn, universalReady ) {
|
|
|
363
365
|
let art = csn.definitions[pathId( head )];
|
|
364
366
|
initDefinition( art );
|
|
365
367
|
for (const elem of tail) {
|
|
366
|
-
const env = navigationEnv( art
|
|
368
|
+
const env = navigationEnv( art );
|
|
367
369
|
art = env.elements[pathId( elem )];
|
|
368
370
|
}
|
|
369
371
|
return art;
|
|
@@ -758,7 +760,7 @@ function csnRefs( csn, universalReady ) {
|
|
|
758
760
|
qcache.elements = elements;
|
|
759
761
|
const { columns } = qcache._select;
|
|
760
762
|
if (elements && columns)
|
|
761
|
-
columns.map(
|
|
763
|
+
columns.map( (col, colIndex) => initColumnElement( col, colIndex, qcache ) );
|
|
762
764
|
else if (columns && !elements)
|
|
763
765
|
throw new ModelError( `Query elements not available: ${ Object.keys( (index ? qcache._select : main) ).join('+') }`);
|
|
764
766
|
} );
|
|
@@ -784,16 +786,19 @@ function csnRefs( csn, universalReady ) {
|
|
|
784
786
|
: { $aliases: Object.create(null), $next: pcache.$next };
|
|
785
787
|
}
|
|
786
788
|
|
|
787
|
-
function initColumnElement( col, parentElementOrQueryCache ) {
|
|
789
|
+
function initColumnElement( col, colIndex, parentElementOrQueryCache ) {
|
|
788
790
|
if (col === '*')
|
|
789
791
|
return;
|
|
790
792
|
if (col.inline) {
|
|
791
|
-
col.inline.map( c => initColumnElement( c, parentElementOrQueryCache ) );
|
|
793
|
+
col.inline.map( c => initColumnElement( c, null, parentElementOrQueryCache ) );
|
|
792
794
|
return;
|
|
793
795
|
}
|
|
794
796
|
setCache( col, '_parent', // not set for query (has property _select)
|
|
795
797
|
!parentElementOrQueryCache._select && parentElementOrQueryCache );
|
|
796
|
-
|
|
798
|
+
let as = columnAlias( col );
|
|
799
|
+
if (!as && colIndex !== null)
|
|
800
|
+
as = `$_column_${ colIndex + 1 }`;
|
|
801
|
+
setCache( col, '$as', as );
|
|
797
802
|
let type = parentElementOrQueryCache;
|
|
798
803
|
while (type.items)
|
|
799
804
|
type = type.items;
|
|
@@ -801,7 +806,7 @@ function csnRefs( csn, universalReady ) {
|
|
|
801
806
|
if (elem) // TODO to.sql: something is strange if this is not set
|
|
802
807
|
setCache( elem, '_column', col );
|
|
803
808
|
if (col.expand)
|
|
804
|
-
col.expand.map( c => initColumnElement( c, elem ) );
|
|
809
|
+
col.expand.map( c => initColumnElement( c, null, elem ) );
|
|
805
810
|
}
|
|
806
811
|
|
|
807
812
|
// property name convention in cache:
|
|
@@ -843,10 +848,11 @@ function csnRefs( csn, universalReady ) {
|
|
|
843
848
|
}
|
|
844
849
|
}
|
|
845
850
|
|
|
846
|
-
// Return value of a query SELECT for the query node, or the main artifact,
|
|
847
|
-
// i.e. a value with an `elements` property.
|
|
848
|
-
// TODO: only used in forRelationalDB - move somewhere else
|
|
849
851
|
/**
|
|
852
|
+
* Return value of a query SELECT for the query node, or the main artifact,
|
|
853
|
+
* i.e. a value with an `elements` property.
|
|
854
|
+
* TODO: only used in forRelationalDB - move somewhere else
|
|
855
|
+
*
|
|
850
856
|
* @param {object} query node (object with SET or SELECT property)
|
|
851
857
|
* @param {object} main definition
|
|
852
858
|
*/
|
|
@@ -1122,6 +1128,17 @@ function isSelectQuery( query ) {
|
|
|
1122
1128
|
return true;
|
|
1123
1129
|
}
|
|
1124
1130
|
|
|
1131
|
+
/**
|
|
1132
|
+
* Alias is either explicit or implicit from reference or function without arguments.
|
|
1133
|
+
* If the column is an expression without explicit alias, `false` is returned.
|
|
1134
|
+
* Use csnRefs.getColumnName() instead.
|
|
1135
|
+
*
|
|
1136
|
+
* @returns {string|false}
|
|
1137
|
+
*/
|
|
1138
|
+
function columnAlias( col ) {
|
|
1139
|
+
return col.as || (!col.args && col.func) || (col.ref && implicitAs( col.ref ));
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1125
1142
|
module.exports = {
|
|
1126
1143
|
csnRefs,
|
|
1127
1144
|
traverseQuery,
|
|
@@ -1129,4 +1146,5 @@ module.exports = {
|
|
|
1129
1146
|
implicitAs,
|
|
1130
1147
|
analyseCsnPath,
|
|
1131
1148
|
pathId,
|
|
1149
|
+
columnAlias,
|
|
1132
1150
|
};
|
package/lib/model/csnUtils.js
CHANGED
|
@@ -69,7 +69,8 @@ function getUtils( model, universalReady ) {
|
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
|
-
* Compute and return $combined for the given query
|
|
72
|
+
* Compute and return $combined sources for the given query,
|
|
73
|
+
* that is, a map of elements that combine e.g. UNION sources.
|
|
73
74
|
*
|
|
74
75
|
* @param {CSN.Query} query
|
|
75
76
|
* @returns {object}
|
|
@@ -291,11 +292,8 @@ function getUtils( model, universalReady ) {
|
|
|
291
292
|
if (!absoluteName.startsWith('@'))
|
|
292
293
|
throw new CompilerAssertion(`Annotation name should start with "@": ${ absoluteName }`);
|
|
293
294
|
|
|
294
|
-
//
|
|
295
|
-
|
|
296
|
-
// Assemble the annotation
|
|
297
|
-
node[absoluteName] = theValue;
|
|
298
|
-
}
|
|
295
|
+
// Assemble the annotation
|
|
296
|
+
node[absoluteName] ??= theValue;
|
|
299
297
|
}
|
|
300
298
|
|
|
301
299
|
/**
|
|
@@ -332,12 +330,18 @@ function getUtils( model, universalReady ) {
|
|
|
332
330
|
* - Does _not_ return the underlying type definition! It is an object with all relevant
|
|
333
331
|
* type properties collected while traversing the type chain!
|
|
334
332
|
*
|
|
335
|
-
* @
|
|
333
|
+
* @param {string|object} type
|
|
334
|
+
* Type as string or type ref, i.e. `{ ref: [...] }`
|
|
335
|
+
*
|
|
336
|
+
* @param {(string)=>CSN.Artifact} getArtifactRef
|
|
337
|
+
* Function used to get an artifact for a reference. Useful in case that the caller
|
|
338
|
+
* has a custom cache or a CSN that is in in-between state.
|
|
339
|
+
* TODO: Can we make getUtils() more modular, so that this argument is already
|
|
340
|
+
* passed to it?
|
|
336
341
|
*
|
|
337
|
-
* @param {string|object} type Type as string or type ref, i.e. `{ ref: [...] }`
|
|
338
342
|
* @returns {object|null}
|
|
339
343
|
*/
|
|
340
|
-
function getFinalTypeInfo( type ) {
|
|
344
|
+
function getFinalTypeInfo( type, getArtifactRef = artifactRef ) {
|
|
341
345
|
type = normalizeTypeRef(type);
|
|
342
346
|
if (!type)
|
|
343
347
|
return null;
|
|
@@ -362,7 +366,7 @@ function getUtils( model, universalReady ) {
|
|
|
362
366
|
if (typeof type === 'string' && (isBuiltinType( type ) || type === special$self))
|
|
363
367
|
return _cacheResolved({ type });
|
|
364
368
|
|
|
365
|
-
const typeRef =
|
|
369
|
+
const typeRef = getArtifactRef(type); // default artifactRef() throws if not found
|
|
366
370
|
const isNonScalar = _cacheNonScalar({ ...typeRef, type });
|
|
367
371
|
if (isNonScalar)
|
|
368
372
|
return finalBaseTypeCache[resolvedKey];
|
|
@@ -380,7 +384,7 @@ function getUtils( model, universalReady ) {
|
|
|
380
384
|
finalBaseTypeCache[resolvedKey] = true;
|
|
381
385
|
|
|
382
386
|
// Continue the search
|
|
383
|
-
const finalBase = getFinalTypeInfo(type);
|
|
387
|
+
const finalBase = getFinalTypeInfo(type, getArtifactRef);
|
|
384
388
|
if (!finalBase) // Reference has no proper type, e.g. due to `type of View:calculated`.
|
|
385
389
|
return _cacheResolved(null);
|
|
386
390
|
|
|
@@ -515,8 +519,8 @@ function forEachDefinition( csn, callback, iterateOptions = {} ) {
|
|
|
515
519
|
*/
|
|
516
520
|
function forEachMember( construct, callback, path = [], ignoreIgnore = true, iterateOptions = {},
|
|
517
521
|
constructCallback = (_construct, _prop, _path) => {} ) {
|
|
518
|
-
// Allow processing
|
|
519
|
-
if (ignoreIgnore && construct
|
|
522
|
+
// Allow processing $ignored elements if requested
|
|
523
|
+
if (ignoreIgnore && construct.$ignore)
|
|
520
524
|
return;
|
|
521
525
|
|
|
522
526
|
// `items` itself is a structure that can contain "elements", and more.
|
|
@@ -775,7 +779,7 @@ function getArtifactDatabaseNameOf( artifactName, sqlMapping, csn, sqlDialect =
|
|
|
775
779
|
* @returns {string} The resulting name
|
|
776
780
|
*/
|
|
777
781
|
function getResultingName( csn, namingMode, artifactName ) {
|
|
778
|
-
if (namingMode === 'plain' || artifactName.
|
|
782
|
+
if (namingMode === 'plain' || !artifactName.includes('.'))
|
|
779
783
|
return artifactName;
|
|
780
784
|
|
|
781
785
|
const namespace = getNamespace(csn, artifactName);
|
|
@@ -964,7 +968,7 @@ function isPersistedOnDatabase( art ) {
|
|
|
964
968
|
*/
|
|
965
969
|
function isPersistedAsView( artifact ) {
|
|
966
970
|
return artifact && artifact.kind === 'entity' &&
|
|
967
|
-
!artifact
|
|
971
|
+
!artifact.$ignore &&
|
|
968
972
|
!artifact.abstract &&
|
|
969
973
|
((artifact.query || artifact.projection) && !hasAnnotationValue(artifact, '@cds.persistence.table')) &&
|
|
970
974
|
!hasAnnotationValue(artifact, '@cds.persistence.skip') &&
|
|
@@ -978,7 +982,7 @@ function isPersistedAsView( artifact ) {
|
|
|
978
982
|
*/
|
|
979
983
|
function isPersistedAsTable( artifact ) {
|
|
980
984
|
return artifact.kind === 'entity' &&
|
|
981
|
-
!artifact
|
|
985
|
+
!artifact.$ignore &&
|
|
982
986
|
!artifact.abstract &&
|
|
983
987
|
(!artifact.query && !artifact.projection || hasAnnotationValue(artifact, '@cds.persistence.table')) &&
|
|
984
988
|
!hasAnnotationValue(artifact, '@cds.persistence.skip') &&
|
|
@@ -1077,6 +1081,9 @@ function getLastPartOfRef( ref ) {
|
|
|
1077
1081
|
*
|
|
1078
1082
|
* Overwrite existing ones only if 'overwrite' is true.
|
|
1079
1083
|
*
|
|
1084
|
+
* IMPORTANT: Consider using copyAnnotationsAndDoc() instead!
|
|
1085
|
+
* Don't forget about doc comments!
|
|
1086
|
+
*
|
|
1080
1087
|
* @param {object} fromNode
|
|
1081
1088
|
* @param {object} toNode
|
|
1082
1089
|
* @param {boolean} [overwrite]
|
|
@@ -1120,6 +1127,32 @@ function copyAnnotationsAndDoc( fromNode, toNode, overwrite = false ) {
|
|
|
1120
1127
|
}
|
|
1121
1128
|
}
|
|
1122
1129
|
|
|
1130
|
+
/**
|
|
1131
|
+
* Same as `copyAnnotationsAndDoc()` but deletes the annotations on source
|
|
1132
|
+
* side after copying them. Useful when applying annotations from `cds.extensions`.
|
|
1133
|
+
*
|
|
1134
|
+
* Overwrite existing ones only if 'overwrite' is true.
|
|
1135
|
+
*
|
|
1136
|
+
* @param {object} sourceNode
|
|
1137
|
+
* @param {object} targetNode
|
|
1138
|
+
* @param {boolean} [overwrite]
|
|
1139
|
+
*/
|
|
1140
|
+
function moveAnnotationsAndDoc( sourceNode, targetNode, overwrite = false ) {
|
|
1141
|
+
// Ignore if no targetNode (in case of errors)
|
|
1142
|
+
if (!targetNode)
|
|
1143
|
+
return;
|
|
1144
|
+
|
|
1145
|
+
const annotations = Object.keys(sourceNode)
|
|
1146
|
+
.filter(key => key.startsWith('@') || key === 'doc');
|
|
1147
|
+
|
|
1148
|
+
for (const anno of annotations) {
|
|
1149
|
+
if (targetNode[anno] === undefined || overwrite) {
|
|
1150
|
+
targetNode[anno] = sourceNode[anno];
|
|
1151
|
+
delete sourceNode[anno];
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1123
1156
|
/**
|
|
1124
1157
|
* Applies annotations from `csn.extensions` to definitions and their elements.
|
|
1125
1158
|
*
|
|
@@ -1147,7 +1180,7 @@ function applyAnnotationsFromExtensions( csn, config ) {
|
|
|
1147
1180
|
if (name && filter(name)) {
|
|
1148
1181
|
const def = csn.definitions[name];
|
|
1149
1182
|
if (def) {
|
|
1150
|
-
|
|
1183
|
+
moveAnnotationsAndDoc(ext, def, config.override);
|
|
1151
1184
|
applyAnnotationsToElements(ext, def);
|
|
1152
1185
|
}
|
|
1153
1186
|
else if (config.notFound) {
|
|
@@ -1169,7 +1202,7 @@ function applyAnnotationsFromExtensions( csn, config ) {
|
|
|
1169
1202
|
forEach(ext.elements, (key, sourceElem) => {
|
|
1170
1203
|
const targetElem = def.elements[key];
|
|
1171
1204
|
if (targetElem) {
|
|
1172
|
-
|
|
1205
|
+
moveAnnotationsAndDoc(sourceElem, targetElem, config.override);
|
|
1173
1206
|
applyAnnotationsToElements(sourceElem, targetElem);
|
|
1174
1207
|
}
|
|
1175
1208
|
});
|
|
@@ -17,7 +17,7 @@ const { CompilerAssertion } = require('../base/error');
|
|
|
17
17
|
const $inferred = Symbol.for('cds.$inferred');
|
|
18
18
|
const $location = Symbol.for('cds.$location');
|
|
19
19
|
|
|
20
|
-
class NOT_A_DICTIONARY {} // used for
|
|
20
|
+
class NOT_A_DICTIONARY {} // used for console.log display
|
|
21
21
|
|
|
22
22
|
function locationString( loc ) {
|
|
23
23
|
if (Array.isArray(loc))
|
|
@@ -102,8 +102,10 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
102
102
|
_status: primOrString, // is a string anyway
|
|
103
103
|
$annotations: as => as.map( $annotation ),
|
|
104
104
|
$messageFunctions: () => '‹some functions›',
|
|
105
|
+
$functions: () => '‹some functions›',
|
|
106
|
+
$builtins: nameOrPath === '++' ? builtinsDictionary : () => '‹reveal with -R ++›',
|
|
105
107
|
};
|
|
106
|
-
uniqueId = 1;
|
|
108
|
+
uniqueId = -1;
|
|
107
109
|
return revealXsnPath(nameOrPath, model);
|
|
108
110
|
|
|
109
111
|
// Returns the desired artifact/dictionary in the XSN.
|
|
@@ -129,7 +131,7 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
129
131
|
// `name.space/S/E/elements/a/kind/`
|
|
130
132
|
// `name.space/S/E/elements/a/type/scope/`
|
|
131
133
|
function revealXsnPath( path, xsn ) {
|
|
132
|
-
if (!path || path === '+')
|
|
134
|
+
if (!path || path === '+' || path === '++')
|
|
133
135
|
return reveal( xsn );
|
|
134
136
|
|
|
135
137
|
path = path.split('/');
|
|
@@ -173,7 +175,9 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
173
175
|
if (!Array.isArray(deps))
|
|
174
176
|
return primOrString( deps );
|
|
175
177
|
return deps
|
|
176
|
-
.map( d =>
|
|
178
|
+
.map( d => (d.location
|
|
179
|
+
? `${ artifactIdentifier( d.art ) } @${ locationString( d.location ) }`
|
|
180
|
+
: artifactIdentifier( d.art )) );
|
|
177
181
|
}
|
|
178
182
|
|
|
179
183
|
function layerExtends( dict ) {
|
|
@@ -213,7 +217,13 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
213
217
|
}
|
|
214
218
|
|
|
215
219
|
function artifactDictionary( node, parent ) {
|
|
216
|
-
if (
|
|
220
|
+
if (parent === model )
|
|
221
|
+
return dictionary( node ); // no dictionary or no definitions section
|
|
222
|
+
return builtinsDictionary( node );
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function builtinsDictionary( node, parent ) {
|
|
226
|
+
if (!node || typeof node !== 'object' || !model.definitions )
|
|
217
227
|
return dictionary( node ); // no dictionary or no definitions section
|
|
218
228
|
const dict = Object.create( Object.getPrototypeOf(node)
|
|
219
229
|
? NOT_A_DICTIONARY.prototype
|
|
@@ -237,7 +247,8 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
237
247
|
? NOT_A_DICTIONARY.prototype
|
|
238
248
|
: Object.prototype );
|
|
239
249
|
for (const prop of Object.getOwnPropertyNames( node )) { // also non-enumerable
|
|
240
|
-
|
|
250
|
+
if (node !== model.definitions || nameOrPath === '++' || !node[prop].builtin)
|
|
251
|
+
r[prop] = reveal( node[prop], node, prop );
|
|
241
252
|
}
|
|
242
253
|
if (node[$inferred] && !node['[$inferred]'])
|
|
243
254
|
r['[$inferred]'] = node[$inferred];
|
|
@@ -275,8 +286,8 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
275
286
|
|
|
276
287
|
const r = Object.create( Object.getPrototypeOf( node ) );
|
|
277
288
|
// property to recognize === objects
|
|
278
|
-
if (node.kind && node.__unique_id__ == null)
|
|
279
|
-
Object.defineProperty( node, '__unique_id__', { value:
|
|
289
|
+
if (node.kind && node.__unique_id__ == null && node.$effectiveSeqNo == null && !node.builtin)
|
|
290
|
+
Object.defineProperty( node, '__unique_id__', { value: uniqueId-- } );
|
|
280
291
|
|
|
281
292
|
for (const prop of Object.getOwnPropertyNames( node )) { // also non-enumerable
|
|
282
293
|
const func = transformers[prop] ||
|
|
@@ -287,8 +298,8 @@ function revealInternalProperties( model, nameOrPath ) {
|
|
|
287
298
|
}
|
|
288
299
|
|
|
289
300
|
function targetAspect( node, parent ) {
|
|
290
|
-
if (node.elements &&
|
|
291
|
-
Object.defineProperty( node, '__unique_id__', { value:
|
|
301
|
+
if (node.elements && node.__unique_id__ == null && node.$effectiveSeqNo == null)
|
|
302
|
+
Object.defineProperty( node, '__unique_id__', { value: uniqueId-- } );
|
|
292
303
|
return reveal( node, parent );
|
|
293
304
|
}
|
|
294
305
|
|
|
@@ -305,19 +316,16 @@ function array( node, fn ) {
|
|
|
305
316
|
}
|
|
306
317
|
|
|
307
318
|
function artifactIdentifier( node, parent ) {
|
|
319
|
+
if (!node)
|
|
320
|
+
return `${ node }`;
|
|
308
321
|
if (Array.isArray(node))
|
|
309
322
|
return node.map( a => artifactIdentifier( a, node ) );
|
|
310
|
-
if (uniqueId && node.__unique_id__ == null)
|
|
311
|
-
Object.defineProperty( node, '__unique_id__', { value:
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
outer = (node._outer.
|
|
316
|
-
// eslint-disable-next-line no-nested-ternary
|
|
317
|
-
: (node._outer.returns === node) ? `/returns${ outer }` // TODO returns now normal
|
|
318
|
-
// eslint-disable-next-line no-nested-ternary
|
|
319
|
-
: (node._outer.targetAspect === node) ? `/target${ outer }`
|
|
320
|
-
: `/returns/items${ outer }`;
|
|
323
|
+
if (uniqueId && node.__unique_id__ == null && node.$effectiveSeqNo == null && !node.builtin)
|
|
324
|
+
Object.defineProperty( node, '__unique_id__', { value: uniqueId-- } );
|
|
325
|
+
const outerNum = node.$effectiveSeqNo || node.__unique_id__;
|
|
326
|
+
let outer = outerNum != null ? `##${ outerNum }` : '';
|
|
327
|
+
if (node._outer) { // anon aspect in targetAspect | items
|
|
328
|
+
outer = (node._outer.targetAspect === node) ? `/target${ outer }` : `/items${ outer }`;
|
|
321
329
|
node = node._outer;
|
|
322
330
|
}
|
|
323
331
|
if (node === parent)
|
|
@@ -328,7 +336,7 @@ function artifactIdentifier( node, parent ) {
|
|
|
328
336
|
return '$magicVariables';
|
|
329
337
|
if (!node.name) {
|
|
330
338
|
try {
|
|
331
|
-
return `${ locationString( node.location ) || '' }##${
|
|
339
|
+
return `${ locationString( node.location ) || '' }##${ outerNum }`;
|
|
332
340
|
// return JSON.stringify(node);
|
|
333
341
|
}
|
|
334
342
|
catch (e) {
|