@sap/cds-compiler 6.1.0 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -0
- package/bin/cdsc.js +17 -6
- package/bin/cdsse.js +1 -1
- package/bin/cdsv2m.js +1 -1
- package/lib/api/main.js +29 -7
- package/lib/api/options.js +1 -1
- package/lib/base/builtins.js +9 -0
- package/lib/base/keywords.js +1 -1
- package/lib/base/message-registry.js +41 -10
- package/lib/base/messages.js +13 -6
- package/lib/base/model.js +1 -1
- package/lib/base/optionProcessorHelper.js +7 -2
- package/lib/checks/assocOutsideService.js +17 -30
- package/lib/checks/checkForTypes.js +0 -18
- package/lib/checks/checkPathsInStoredCalcElement.js +2 -1
- package/lib/checks/featureFlags.js +4 -1
- package/lib/checks/onConditions.js +2 -2
- package/lib/checks/queryNoDbArtifacts.js +16 -15
- package/lib/checks/types.js +1 -1
- package/lib/checks/utils.js +30 -6
- package/lib/checks/validator.js +4 -5
- package/lib/compiler/assert-consistency.js +3 -1
- package/lib/compiler/base.js +1 -1
- package/lib/compiler/builtins.js +1 -1
- package/lib/compiler/checks.js +85 -39
- package/lib/compiler/define.js +24 -5
- package/lib/compiler/extend.js +1 -1
- package/lib/compiler/finalize-parse-cdl.js +9 -1
- package/lib/compiler/generate.js +4 -4
- package/lib/compiler/index.js +88 -6
- package/lib/compiler/lsp-api.js +2 -0
- package/lib/compiler/populate.js +8 -8
- package/lib/compiler/propagator.js +1 -1
- package/lib/compiler/resolve.js +22 -21
- package/lib/compiler/shared.js +6 -6
- package/lib/compiler/tweak-assocs.js +53 -31
- package/lib/compiler/utils.js +9 -16
- package/lib/compiler/xpr-rewrite.js +2 -2
- package/lib/gen/BaseParser.js +35 -29
- package/lib/gen/CdlGrammar.checksum +1 -1
- package/lib/gen/CdlParser.js +1424 -1430
- package/lib/gen/Dictionary.json +1 -2
- package/lib/gen/cdlKeywords.json +26 -0
- package/lib/inspect/inspectPropagation.js +1 -1
- package/lib/json/from-csn.js +2 -2
- package/lib/json/to-csn.js +1 -1
- package/lib/language/multiLineStringParser.js +1 -1
- package/lib/model/cloneCsn.js +1 -0
- package/lib/model/csnRefs.js +9 -4
- package/lib/model/csnUtils.js +67 -2
- package/lib/optionProcessor.js +9 -9
- package/lib/parsers/AstBuildingParser.js +28 -26
- package/lib/parsers/identifiers.js +2 -30
- package/lib/render/toCdl.js +73 -13
- package/lib/render/toSql.js +127 -108
- package/lib/render/utils/common.js +4 -2
- package/lib/render/utils/sql.js +67 -0
- package/lib/transform/addTenantFields.js +4 -4
- package/lib/transform/db/assertUnique.js +2 -1
- package/lib/transform/db/associations.js +37 -1
- package/lib/transform/db/assocsToQueries/transformExists.js +21 -32
- package/lib/transform/db/assocsToQueries/utils.js +1 -1
- package/lib/transform/db/cdsPersistence.js +1 -1
- package/lib/transform/db/expansion.js +37 -36
- package/lib/transform/db/killAnnotations.js +1 -0
- package/lib/transform/db/processSqlServices.js +20 -2
- package/lib/transform/draft/db.js +20 -20
- package/lib/transform/draft/odata.js +38 -40
- package/lib/transform/effective/associations.js +1 -1
- package/lib/transform/effective/flattening.js +40 -47
- package/lib/transform/effective/main.js +6 -4
- package/lib/transform/forOdata.js +201 -92
- package/lib/transform/forRelationalDB.js +151 -142
- package/lib/transform/localized.js +116 -109
- package/lib/transform/odata/adaptAnnotationRefs.js +21 -16
- package/lib/transform/odata/createForeignKeys.js +73 -70
- package/lib/transform/odata/flattening.js +216 -200
- package/lib/transform/odata/foreignKeyRefsInXprAnnos.js +47 -45
- package/lib/transform/odata/toFinalBaseType.js +40 -39
- package/lib/transform/odata/typesExposure.js +151 -133
- package/lib/transform/odata/utils.js +7 -6
- package/lib/transform/parseExpr.js +165 -162
- package/lib/transform/transformUtils.js +184 -551
- package/lib/transform/translateAssocsToJoins.js +511 -596
- package/lib/transform/tupleExpansion.js +495 -0
- package/lib/transform/universalCsn/universalCsnEnricher.js +1 -0
- package/lib/utils/moduleResolve.js +1 -1
- package/package.json +2 -2
- package/lib/base/cleanSymbols.js +0 -17
- package/lib/checks/nonexpandableStructured.js +0 -39
|
@@ -4,26 +4,25 @@
|
|
|
4
4
|
// different backends.
|
|
5
5
|
// The sibling of model/transform/TransformUtil.js which works with compacted new CSN.
|
|
6
6
|
|
|
7
|
-
const { setProp
|
|
7
|
+
const { setProp } = require('../base/model');
|
|
8
8
|
|
|
9
|
-
const { copyAnnotations, applyTransformations,
|
|
9
|
+
const { copyAnnotations, applyTransformations, isDeepEqual } = require('../model/csnUtils');
|
|
10
10
|
const { getUtils } = require('../model/csnUtils');
|
|
11
11
|
const { typeParameters } = require('../compiler/builtins');
|
|
12
12
|
const { isBuiltinType } = require('../base/builtins');
|
|
13
|
-
const { ModelError, CompilerAssertion} = require('../base/error');
|
|
13
|
+
const { ModelError, CompilerAssertion } = require('../base/error');
|
|
14
14
|
const { forEach } = require('../utils/objectUtils');
|
|
15
15
|
const { cloneCsnNonDict, cloneCsnDict } = require('../model/cloneCsn');
|
|
16
16
|
const { addTenantFieldToArt } = require('./addTenantFields');
|
|
17
|
+
const { tupleExpansion } = require('./tupleExpansion');
|
|
17
18
|
|
|
18
|
-
const RestrictedOperators = ['<', '>', '>=', '<='];
|
|
19
|
-
const RelationalOperators = ['=', '<>', '==', '!=', 'is' /*, 'like'*/,...RestrictedOperators];
|
|
20
19
|
// Return the public functions of this module, with 'model' captured in a closure (for definitions, options etc).
|
|
21
20
|
// Use 'pathDelimiter' for flattened names (e.g. of struct elements or foreign key elements).
|
|
22
21
|
// 'model' is compacted new style CSN
|
|
23
22
|
// TODO: Error and warnings handling with compacted CSN? - currently just throw new ModelError for everything
|
|
24
23
|
// TODO: check the situation with assocs with values. In compacted CSN such elements have only "@Core.Computed": true
|
|
25
24
|
function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
26
|
-
const {
|
|
25
|
+
const { error, warning } = msgFunctions;
|
|
27
26
|
const csnUtils = getUtils(model);
|
|
28
27
|
const {
|
|
29
28
|
getCsnDef,
|
|
@@ -32,11 +31,10 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
32
31
|
isStructured,
|
|
33
32
|
effectiveType,
|
|
34
33
|
} = csnUtils;
|
|
34
|
+
const tuples = tupleExpansion(model, csnUtils, msgFunctions, options);
|
|
35
35
|
|
|
36
36
|
return {
|
|
37
37
|
csnUtils,
|
|
38
|
-
resolvePath,
|
|
39
|
-
flattenPath,
|
|
40
38
|
addDefaultTypeFacets,
|
|
41
39
|
flattenStructuredElement,
|
|
42
40
|
flattenStructStepsInRef,
|
|
@@ -60,7 +58,8 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
60
58
|
renameAnnotation,
|
|
61
59
|
setAnnotation,
|
|
62
60
|
resetAnnotation,
|
|
63
|
-
expandStructsInExpression,
|
|
61
|
+
expandStructsInExpression: tuples.expandStructsInExpression,
|
|
62
|
+
flattenPath: tuples.flattenPath,
|
|
64
63
|
};
|
|
65
64
|
|
|
66
65
|
/**
|
|
@@ -70,7 +69,7 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
70
69
|
*
|
|
71
70
|
* @param {CSN.Element} element
|
|
72
71
|
* @param {null|object} [internalDefaultLengths] Either null (no implicit default) or an object `{ 'cds.String': N, 'cds.Binary': N }`.
|
|
73
|
-
|
|
72
|
+
* */
|
|
74
73
|
function addDefaultTypeFacets(element, internalDefaultLengths = null) {
|
|
75
74
|
if (!element || !element.type)
|
|
76
75
|
return;
|
|
@@ -89,7 +88,7 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
89
88
|
element.length = options.defaultBinaryLength;
|
|
90
89
|
setProp(element, '$default', true);
|
|
91
90
|
}
|
|
92
|
-
else if(internalDefaultLengths !== null) {
|
|
91
|
+
else if (internalDefaultLengths !== null) {
|
|
93
92
|
element.length = internalDefaultLengths[element.type];
|
|
94
93
|
}
|
|
95
94
|
}
|
|
@@ -128,8 +127,8 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
128
127
|
// type: 'cds.String',
|
|
129
128
|
// length: 42 },
|
|
130
129
|
// }
|
|
131
|
-
function flattenStructuredElement(elem, elemName, parentElementPath=[], pathInCsn=[]) {
|
|
132
|
-
const elementPath=parentElementPath.concat(elemName); // elementPath contains only element names without the csn structure node names
|
|
130
|
+
function flattenStructuredElement(elem, elemName, parentElementPath = [], pathInCsn = []) {
|
|
131
|
+
const elementPath = parentElementPath.concat(elemName); // elementPath contains only element names without the csn structure node names
|
|
133
132
|
// in case the element is of user defined type => take the definition of the type
|
|
134
133
|
// for type of 'x' -> elem.type is an object, not a string -> use directly
|
|
135
134
|
let elemType;
|
|
@@ -144,14 +143,14 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
144
143
|
const result = Object.create(null);
|
|
145
144
|
const addGeneratedFlattenedElement = (e, eName) => {
|
|
146
145
|
if (result[eName])
|
|
147
|
-
error('name-duplicate-element', pathInCsn, { '#': 'flatten-element-gen', name: eName })
|
|
146
|
+
error('name-duplicate-element', pathInCsn, { '#': 'flatten-element-gen', name: eName });
|
|
148
147
|
else
|
|
149
148
|
result[eName] = e;
|
|
150
|
-
}
|
|
149
|
+
};
|
|
151
150
|
forEach(struct, (childName, childElem) => {
|
|
152
151
|
if (isStructured(childElem)) {
|
|
153
152
|
// Descend recursively into structured children
|
|
154
|
-
const grandChildElems = flattenStructuredElement(childElem, childName, elementPath, pathInCsn.concat('elements',childName));
|
|
153
|
+
const grandChildElems = flattenStructuredElement(childElem, childName, elementPath, pathInCsn.concat('elements', childName));
|
|
155
154
|
for (const grandChildName in grandChildElems) {
|
|
156
155
|
const flatElemName = elemName + pathDelimiter + grandChildName;
|
|
157
156
|
const flatElem = grandChildElems[grandChildName];
|
|
@@ -163,7 +162,8 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
163
162
|
// }
|
|
164
163
|
// Preserve the generated element name as it would have been with 'hdbcds' names
|
|
165
164
|
}
|
|
166
|
-
}
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
167
|
// Primitive child - clone it and restore its cross references
|
|
168
168
|
const flatElemName = elemName + pathDelimiter + childName;
|
|
169
169
|
const flatElem = cloneCsnNonDict(childElem, options);
|
|
@@ -184,29 +184,28 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
184
184
|
// When flattening structured elements for OData don't propagate the odata.Type annotations
|
|
185
185
|
// as these would falsify the flattened elements. Type facets must be aligned with
|
|
186
186
|
// EdmTypeFacetMap defined in edm.js
|
|
187
|
-
const excludes = options.toOdata
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
187
|
+
const excludes = options.toOdata
|
|
188
|
+
? {
|
|
189
|
+
'@odata.Type': 1,
|
|
190
|
+
'@odata.Scale': 1,
|
|
191
|
+
'@odata.Precision': 1,
|
|
192
|
+
'@odata.MaxLength': 1,
|
|
193
|
+
'@odata.SRID': 1,
|
|
194
|
+
'@odata.FixedLength': 1,
|
|
195
|
+
'@odata.Collation': 1,
|
|
196
|
+
'@odata.Unicode': 1,
|
|
197
|
+
} : {};
|
|
198
198
|
|
|
199
199
|
copyAnnotations(elem, flatElem, false, excludes);
|
|
200
200
|
|
|
201
201
|
// Copy selected type properties
|
|
202
|
-
const props = ['key', 'virtual', 'masked', 'viaAll'];
|
|
202
|
+
const props = [ 'key', 'virtual', 'masked', 'viaAll' ];
|
|
203
203
|
// 'localized' is needed for OData
|
|
204
|
-
if(options.toOdata)
|
|
204
|
+
if (options.toOdata)
|
|
205
205
|
props.push('localized');
|
|
206
206
|
for (const p of props) {
|
|
207
|
-
if (elem[p])
|
|
207
|
+
if (elem[p])
|
|
208
208
|
flatElem[p] = elem[p];
|
|
209
|
-
}
|
|
210
209
|
}
|
|
211
210
|
});
|
|
212
211
|
return result;
|
|
@@ -232,17 +231,17 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
232
231
|
* @todo: Refactor to take config object instead of N boolean arguments.
|
|
233
232
|
* @returns [string[], bool]
|
|
234
233
|
*/
|
|
235
|
-
function flattenStructStepsInRef(ref, path, links, scope, resolvedLinkTypes=new WeakMap(), suspend=false, suspendPos=0, revokeAtSuspendPos=false, flattenParameters = false) {
|
|
234
|
+
function flattenStructStepsInRef(ref, path, links, scope, resolvedLinkTypes = new WeakMap(), suspend = false, suspendPos = 0, revokeAtSuspendPos = false, flattenParameters = false) {
|
|
236
235
|
// A path is absolute if it starts with $self or a parameter. Then we must not flatten the first path step.
|
|
237
236
|
const pathIsAbsolute = scope === '$self' || (!flattenParameters && scope === 'param');
|
|
238
237
|
// Refs of length 1 cannot contain steps - no need to check
|
|
239
|
-
if (ref.length < 2 || (pathIsAbsolute && ref.length === 2))
|
|
238
|
+
if (ref.length < 2 || (pathIsAbsolute && ref.length === 2))
|
|
240
239
|
return [ ref, false ];
|
|
241
|
-
}
|
|
242
240
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
241
|
+
|
|
242
|
+
const result = pathIsAbsolute ? [ ref[0] ] : [];
|
|
243
|
+
// let stack = []; // IDs of path steps not yet processed or part of a struct traversal
|
|
244
|
+
if (!links && !scope) { // calculate JIT if not supplied
|
|
246
245
|
const res = inspectRef(path);
|
|
247
246
|
links = res.links;
|
|
248
247
|
scope = res.scope;
|
|
@@ -254,23 +253,21 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
254
253
|
let i = pathIsAbsolute ? 1 : 0;
|
|
255
254
|
|
|
256
255
|
// read property from resolved path link
|
|
257
|
-
const art = (propName
|
|
258
|
-
(links[i].art?.[propName] ||
|
|
256
|
+
const art = propName => (links[i].art?.[propName] ||
|
|
259
257
|
effectiveType(links[i].art)[propName] ||
|
|
260
|
-
(resolvedLinkTypes.get(links[i])||{})[propName]);
|
|
258
|
+
(resolvedLinkTypes.get(links[i]) || {})[propName]);
|
|
261
259
|
|
|
262
|
-
|
|
263
|
-
|
|
260
|
+
let refChanged = false;
|
|
261
|
+
let flattenStep = false;
|
|
264
262
|
suspend = !!art('items') || (suspend && i <= suspendPos);
|
|
265
|
-
for(; i < links.length; i++) {
|
|
266
|
-
|
|
263
|
+
for (; i < links.length; i++) {
|
|
267
264
|
if (flattenStep && !suspend) {
|
|
268
265
|
result[result.length - 1] += pathDelimiter + (ref[i].id ? ref[i].id : ref[i]);
|
|
269
266
|
// if we had a filter or args, we had an assoc so this step is done
|
|
270
267
|
// we then keep along the filter/args by updating the id of the current ref
|
|
271
|
-
if(ref[i].id) {
|
|
272
|
-
ref[i].id = result[result.length-1];
|
|
273
|
-
result[result.length-1] = ref[i];
|
|
268
|
+
if (ref[i].id) {
|
|
269
|
+
ref[i].id = result[result.length - 1];
|
|
270
|
+
result[result.length - 1] = ref[i];
|
|
274
271
|
}
|
|
275
272
|
refChanged = true;
|
|
276
273
|
// suspend flattening if the next path step has some 'items'
|
|
@@ -281,7 +278,7 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
281
278
|
suspend ||= !!art('items');
|
|
282
279
|
}
|
|
283
280
|
// revoke items suspension for next assoc step
|
|
284
|
-
if(suspend && art('target') || (revokeAtSuspendPos && i === suspendPos))
|
|
281
|
+
if (suspend && art('target') || (revokeAtSuspendPos && i === suspendPos))
|
|
285
282
|
suspend = false;
|
|
286
283
|
|
|
287
284
|
flattenStep = !links[i].art?.kind &&
|
|
@@ -302,9 +299,9 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
302
299
|
*/
|
|
303
300
|
function toFinalBaseType(nodeWithType, resolved = new WeakMap(), keepLocalized = false) {
|
|
304
301
|
const type = nodeWithType?.type;
|
|
305
|
-
if (!type || nodeWithType.elements || nodeWithType.items || resolved.has(nodeWithType))
|
|
302
|
+
if (!type || nodeWithType.elements || nodeWithType.items || resolved.has(nodeWithType))
|
|
306
303
|
return;
|
|
307
|
-
|
|
304
|
+
|
|
308
305
|
// The caller may use `{ art }` syntax for `{ ref }` objects, but we only use
|
|
309
306
|
// it to indicate that an artifact has been processed.
|
|
310
307
|
resolved.set(nodeWithType, nodeWithType);
|
|
@@ -313,8 +310,8 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
313
310
|
if (typeof type === 'string' && isBuiltinType(type))
|
|
314
311
|
return;
|
|
315
312
|
|
|
316
|
-
const typeRef = getFinalTypeInfo(type,
|
|
317
|
-
if(!typeRef)
|
|
313
|
+
const typeRef = getFinalTypeInfo(type, t => resolved.get(t)?.art || csnUtils.artifactRef(t));
|
|
314
|
+
if (!typeRef)
|
|
318
315
|
return;
|
|
319
316
|
|
|
320
317
|
if (typeRef.elements || typeRef.items) {
|
|
@@ -335,9 +332,8 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
335
332
|
// Copy type and type arguments (+ localized)
|
|
336
333
|
|
|
337
334
|
for (const param of typeParameters.list) {
|
|
338
|
-
if (nodeWithType[param] === undefined && typeRef[param] !== undefined
|
|
335
|
+
if (nodeWithType[param] === undefined && typeRef[param] !== undefined && !typeRef.$default)
|
|
339
336
|
nodeWithType[param] = typeRef[param];
|
|
340
|
-
}
|
|
341
337
|
}
|
|
342
338
|
if (keepLocalized && nodeWithType.localized === undefined && typeRef.localized !== undefined)
|
|
343
339
|
nodeWithType.localized = typeRef.localized;
|
|
@@ -349,39 +345,38 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
349
345
|
// Add the created projection to the model and complain if artifact already exists.
|
|
350
346
|
// Used by Draft generation
|
|
351
347
|
function createExposingProjection(art, artName, projectionId, service) {
|
|
352
|
-
const projectionAbsoluteName = `${service}.${projectionId}`;
|
|
348
|
+
const projectionAbsoluteName = `${ service }.${ projectionId }`;
|
|
353
349
|
// Create elements matching the artifact's elements
|
|
354
350
|
const elements = Object.create(null);
|
|
355
|
-
|
|
356
|
-
const elem = Object.assign({}, artElem);
|
|
351
|
+
Object.entries(art.elements || {}).forEach(([ elemName, artElem ]) => {
|
|
357
352
|
// Transfer xrefs, that are redirected to the projection
|
|
358
353
|
// TODO: shall we remove the transferred elements from the original?
|
|
359
354
|
// if (artElem._xref) {
|
|
360
355
|
// setProp(elem, '_xref', artElem._xref.filter(xref => xref.user && xref.user._main && xref.user._main._service == service));
|
|
361
356
|
// }
|
|
362
357
|
// FIXME: Remove once the compactor no longer renders 'origin'
|
|
363
|
-
elements[elemName] =
|
|
358
|
+
elements[elemName] = Object.assign({}, artElem);
|
|
364
359
|
});
|
|
365
360
|
|
|
366
361
|
const query = {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
artName
|
|
371
|
-
]
|
|
372
|
-
}
|
|
373
|
-
}
|
|
362
|
+
SELECT: {
|
|
363
|
+
from: {
|
|
364
|
+
ref: [
|
|
365
|
+
artName,
|
|
366
|
+
],
|
|
367
|
+
},
|
|
368
|
+
},
|
|
374
369
|
};
|
|
375
370
|
// Assemble the projection itself and add it into the model
|
|
376
371
|
const projection = {
|
|
377
|
-
|
|
372
|
+
kind: 'entity',
|
|
378
373
|
projection: query.SELECT, // it is important that projection and query refer to the same object!
|
|
379
|
-
elements
|
|
374
|
+
elements,
|
|
380
375
|
};
|
|
381
376
|
// copy annotations from art to projection
|
|
382
|
-
for (const a of Object.keys(art).filter(x => x.startsWith('@')))
|
|
377
|
+
for (const a of Object.keys(art).filter(x => x.startsWith('@')))
|
|
383
378
|
projection[a] = art[a];
|
|
384
|
-
|
|
379
|
+
|
|
385
380
|
model.definitions[projectionAbsoluteName] = projection;
|
|
386
381
|
return projection;
|
|
387
382
|
}
|
|
@@ -396,18 +391,17 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
396
391
|
* @param {boolean} [hanaMode=false] Turn UUID into String(36)
|
|
397
392
|
* @returns {CSN.Artifact}
|
|
398
393
|
*/
|
|
399
|
-
function createAndAddDraftAdminDataProjection(service, hanaMode=false) {
|
|
394
|
+
function createAndAddDraftAdminDataProjection(service, hanaMode = false) {
|
|
400
395
|
// Make sure we have a DRAFT.DraftAdministrativeData entity
|
|
401
396
|
let draftAdminDataEntity = model.definitions['DRAFT.DraftAdministrativeData'];
|
|
402
397
|
if (!draftAdminDataEntity) {
|
|
403
398
|
draftAdminDataEntity = createAndAddDraftAdminDataEntity();
|
|
404
399
|
model.definitions['DRAFT.DraftAdministrativeData'] = draftAdminDataEntity;
|
|
405
|
-
if (
|
|
406
|
-
|
|
407
|
-
&& !model.definitions['DRAFT.DraftAdministrativeData_DraftMessage']) {
|
|
400
|
+
if (options.draftMessages && options.transformation === 'odata' &&
|
|
401
|
+
!model.definitions['DRAFT.DraftAdministrativeData_DraftMessage'])
|
|
408
402
|
model.definitions['DRAFT.DraftAdministrativeData_DraftMessage'] = createDraftAdminDataMessagesType();
|
|
409
|
-
|
|
410
|
-
if(options.tenantDiscriminator && options.transformation !== 'odata')
|
|
403
|
+
|
|
404
|
+
if (options.tenantDiscriminator && options.transformation !== 'odata')
|
|
411
405
|
addTenantFieldToArt(model.definitions['DRAFT.DraftAdministrativeData'], options);
|
|
412
406
|
}
|
|
413
407
|
|
|
@@ -424,11 +418,11 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
424
418
|
kind: 'entity',
|
|
425
419
|
elements: Object.create(null),
|
|
426
420
|
'@Common.Label': '{i18n>Draft_DraftAdministrativeData}',
|
|
427
|
-
}
|
|
421
|
+
};
|
|
428
422
|
|
|
429
423
|
// key DraftUUID : UUID
|
|
430
424
|
const draftUuid = createScalarElement('DraftUUID', hanaMode ? 'cds.String' : 'cds.UUID', true);
|
|
431
|
-
if(hanaMode)
|
|
425
|
+
if (hanaMode)
|
|
432
426
|
draftUuid.DraftUUID.length = 36;
|
|
433
427
|
|
|
434
428
|
draftUuid.DraftUUID['@UI.Hidden'] = true;
|
|
@@ -442,10 +436,18 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
442
436
|
|
|
443
437
|
// CreatedByUser : String(256);
|
|
444
438
|
const createdByUser = createScalarElement('CreatedByUser', 'cds.String');
|
|
445
|
-
createdByUser
|
|
439
|
+
createdByUser.CreatedByUser.length = 256;
|
|
446
440
|
createdByUser.CreatedByUser['@Common.Label'] = '{i18n>Draft_CreatedByUser}';
|
|
447
441
|
addElement(createdByUser, artifact, artifactName);
|
|
448
442
|
|
|
443
|
+
if ((options.draftUserDescription && options.transformation === 'odata') || options.transformation !== 'odata') {
|
|
444
|
+
// CreatedByUserDescription : String(256);
|
|
445
|
+
const createdByUserDescription = createScalarElement('CreatedByUserDescription', 'cds.String');
|
|
446
|
+
createdByUserDescription.CreatedByUserDescription.length = 256;
|
|
447
|
+
createdByUserDescription.CreatedByUserDescription['@Common.Label'] = '{i18n>Draft_CreatedByUserDescription}';
|
|
448
|
+
addElement(createdByUserDescription, artifact, artifactName);
|
|
449
|
+
}
|
|
450
|
+
|
|
449
451
|
// DraftIsCreatedByMe : Boolean;
|
|
450
452
|
const draftIsCreatedByMe = createScalarElement('DraftIsCreatedByMe', 'cds.Boolean');
|
|
451
453
|
draftIsCreatedByMe.DraftIsCreatedByMe['@UI.Hidden'] = true;
|
|
@@ -459,31 +461,47 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
459
461
|
|
|
460
462
|
// LastChangedByUser : String(256);
|
|
461
463
|
const lastChangedByUser = createScalarElement('LastChangedByUser', 'cds.String');
|
|
462
|
-
lastChangedByUser
|
|
464
|
+
lastChangedByUser.LastChangedByUser.length = 256;
|
|
463
465
|
lastChangedByUser.LastChangedByUser['@Common.Label'] = '{i18n>Draft_LastChangedByUser}';
|
|
464
466
|
addElement(lastChangedByUser, artifact, artifactName);
|
|
465
467
|
|
|
468
|
+
if (options.transformation !== 'odata' || options.draftUserDescription) {
|
|
469
|
+
// LastChangedByUserDescription : String(256);
|
|
470
|
+
const lastChangedByUserDescription = createScalarElement('LastChangedByUserDescription', 'cds.String');
|
|
471
|
+
lastChangedByUserDescription.LastChangedByUserDescription.length = 256;
|
|
472
|
+
lastChangedByUserDescription.LastChangedByUserDescription['@Common.Label'] = '{i18n>Draft_LastChangedByUserDescription}';
|
|
473
|
+
addElement(lastChangedByUserDescription, artifact, artifactName);
|
|
474
|
+
}
|
|
475
|
+
|
|
466
476
|
// InProcessByUser : String(256);
|
|
467
477
|
const inProcessByUser = createScalarElement('InProcessByUser', 'cds.String');
|
|
468
|
-
inProcessByUser
|
|
478
|
+
inProcessByUser.InProcessByUser.length = 256;
|
|
469
479
|
inProcessByUser.InProcessByUser['@Common.Label'] = '{i18n>Draft_InProcessByUser}';
|
|
470
480
|
addElement(inProcessByUser, artifact, artifactName);
|
|
471
481
|
|
|
482
|
+
if (options.transformation !== 'odata' || options.draftUserDescription) {
|
|
483
|
+
// InProcessByUserDescription : String(256);
|
|
484
|
+
const inProcessByUserDescription = createScalarElement('InProcessByUserDescription', 'cds.String');
|
|
485
|
+
inProcessByUserDescription.InProcessByUserDescription.length = 256;
|
|
486
|
+
inProcessByUserDescription.InProcessByUserDescription['@Common.Label'] = '{i18n>Draft_InProcessByUserDescription}';
|
|
487
|
+
addElement(inProcessByUserDescription, artifact, artifactName);
|
|
488
|
+
}
|
|
489
|
+
|
|
472
490
|
// DraftIsProcessedByMe : Boolean;
|
|
473
491
|
const draftIsProcessedByMe = createScalarElement('DraftIsProcessedByMe', 'cds.Boolean');
|
|
474
492
|
draftIsProcessedByMe.DraftIsProcessedByMe['@UI.Hidden'] = true;
|
|
475
493
|
draftIsProcessedByMe.DraftIsProcessedByMe['@Common.Label'] = '{i18n>Draft_DraftIsProcessedByMe}';
|
|
476
494
|
addElement(draftIsProcessedByMe, artifact, artifactName);
|
|
477
495
|
|
|
478
|
-
if (
|
|
496
|
+
if (options.transformation !== 'odata' || options.draftMessages) {
|
|
479
497
|
const messages = { DraftMessages: { } };
|
|
480
|
-
if (options.transformation === 'odata')
|
|
498
|
+
if (options.transformation === 'odata')
|
|
481
499
|
messages.DraftMessages = { items: { type: 'DRAFT.DraftAdministrativeData_DraftMessage' } };
|
|
482
|
-
|
|
500
|
+
else
|
|
483
501
|
messages.DraftMessages = { type: 'cds.LargeString' };
|
|
484
|
-
|
|
502
|
+
|
|
485
503
|
messages.DraftMessages['@cds.api.ignore'] = true;
|
|
486
|
-
addElement(messages
|
|
504
|
+
addElement(messages, artifact, artifactName);
|
|
487
505
|
}
|
|
488
506
|
|
|
489
507
|
return artifact;
|
|
@@ -495,13 +513,13 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
495
513
|
function createDraftAdminDataMessagesType() {
|
|
496
514
|
const messagesType = {
|
|
497
515
|
kind: 'type',
|
|
498
|
-
elements: Object.create(null)
|
|
499
|
-
}
|
|
516
|
+
elements: Object.create(null),
|
|
517
|
+
};
|
|
500
518
|
|
|
501
519
|
addElement(createScalarElement('code', 'cds.String'), messagesType, 'DRAFT.DraftAdministrativeData_DraftMessage');
|
|
502
520
|
addElement(createScalarElement('message', 'cds.String'), messagesType, 'DRAFT.DraftAdministrativeData_DraftMessage');
|
|
503
521
|
addElement(createScalarElement('target', 'cds.String'), messagesType, 'DRAFT.DraftAdministrativeData_DraftMessage');
|
|
504
|
-
addElement({
|
|
522
|
+
addElement({ additionalTargets: createScalarElement('items', 'cds.String') }, messagesType, 'DRAFT.DraftAdministrativeData_DraftMessage');
|
|
505
523
|
addElement(createScalarElement('transition', 'cds.Boolean'), messagesType, 'DRAFT.DraftAdministrativeData_DraftMessage');
|
|
506
524
|
addElement(createScalarElement('numericSeverity', 'cds.UInt8'), messagesType, 'DRAFT.DraftAdministrativeData_DraftMessage');
|
|
507
525
|
addElement(createScalarElement('longtextUrl', 'cds.String'), messagesType, 'DRAFT.DraftAdministrativeData_DraftMessage');
|
|
@@ -523,26 +541,26 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
523
541
|
// example result: { foo: { type: 'cds.Integer', key: true, default: { val: 6 }, notNull: true } }
|
|
524
542
|
// ^^^ ^^^^^^^^^ ^^^^ ^^ ^^
|
|
525
543
|
// elemName typeName isKey defaultVal notNull
|
|
526
|
-
function createScalarElement(elemName, typeName, isKey = false, defaultVal = undefined, notNull=false) {
|
|
527
|
-
if (!isBuiltinType(typeName) && !model.definitions[typeName])
|
|
528
|
-
throw new ModelError(
|
|
529
|
-
|
|
544
|
+
function createScalarElement(elemName, typeName, isKey = false, defaultVal = undefined, notNull = false) {
|
|
545
|
+
if (!isBuiltinType(typeName) && !model.definitions[typeName])
|
|
546
|
+
throw new ModelError(`Expecting valid type name: ${ typeName }`);
|
|
547
|
+
|
|
530
548
|
const result = {
|
|
531
549
|
[elemName]: {
|
|
532
|
-
type: typeName
|
|
533
|
-
}
|
|
550
|
+
type: typeName,
|
|
551
|
+
},
|
|
534
552
|
};
|
|
535
|
-
if (isKey)
|
|
553
|
+
if (isKey)
|
|
536
554
|
result[elemName].key = true;
|
|
537
|
-
|
|
555
|
+
|
|
538
556
|
if (defaultVal !== undefined) {
|
|
539
557
|
result[elemName].default = {
|
|
540
558
|
val: defaultVal,
|
|
541
|
-
}
|
|
559
|
+
};
|
|
542
560
|
}
|
|
543
|
-
if(notNull)
|
|
561
|
+
if (notNull)
|
|
544
562
|
result[elemName].notNull = true;
|
|
545
|
-
|
|
563
|
+
|
|
546
564
|
return result;
|
|
547
565
|
}
|
|
548
566
|
|
|
@@ -562,7 +580,7 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
562
580
|
if (isManaged) {
|
|
563
581
|
assoc.keys = [];
|
|
564
582
|
const targetArt = getCsnDef(target);
|
|
565
|
-
|
|
583
|
+
Object.entries(targetArt.elements || {}).forEach(([ keyElemName, keyElem ]) => {
|
|
566
584
|
if (keyElem.key) {
|
|
567
585
|
const foreignKey = createForeignKey(keyElemName, keyElem);
|
|
568
586
|
addForeignKey(foreignKey, assoc);
|
|
@@ -579,29 +597,28 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
579
597
|
// assoc foreignElem op elem
|
|
580
598
|
function createAssociationPathComparison(assoc, foreignElem, op, elem) {
|
|
581
599
|
return [
|
|
582
|
-
{ ref: [assoc, foreignElem] }, op, { ref: [elem] }
|
|
583
|
-
]
|
|
600
|
+
{ ref: [ assoc, foreignElem ] }, op, { ref: [ elem ] },
|
|
601
|
+
];
|
|
584
602
|
}
|
|
585
603
|
|
|
586
604
|
// Create an artificial foreign key 'keyElemName' for key element 'keyElem'. Note that this
|
|
587
605
|
// only creates a foreign key, not the generated foreign key element.
|
|
588
606
|
// TODO: check the usage of this function's param 'keyElem' ?
|
|
589
607
|
function createForeignKey(keyElemName, keyElem = undefined) { /* eslint-disable-line no-unused-vars */
|
|
590
|
-
|
|
591
608
|
return {
|
|
592
|
-
ref: [keyElemName]
|
|
609
|
+
ref: [ keyElemName ],
|
|
593
610
|
// TODO: do we need these two?
|
|
594
611
|
// calculated: true,
|
|
595
612
|
// $inferred: 'keys',
|
|
596
|
-
}
|
|
613
|
+
};
|
|
597
614
|
}
|
|
598
615
|
|
|
599
616
|
// Add foreign key 'foreignKey' to association element 'elem'.
|
|
600
617
|
function addForeignKey(foreignKey, elem) {
|
|
601
618
|
// Sanity checks
|
|
602
|
-
if (!elem.target || !elem.keys)
|
|
619
|
+
if (!elem.target || !elem.keys)
|
|
603
620
|
throw new ModelError('Expecting managed association element with foreign keys');
|
|
604
|
-
|
|
621
|
+
|
|
605
622
|
|
|
606
623
|
// Add the foreign key
|
|
607
624
|
elem.keys.push(foreignKey);
|
|
@@ -618,16 +635,16 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
618
635
|
*/
|
|
619
636
|
function addElement(elem, artifact, artifactName) {
|
|
620
637
|
// Sanity check
|
|
621
|
-
if (!artifact.elements)
|
|
622
|
-
throw new ModelError(
|
|
623
|
-
|
|
638
|
+
if (!artifact.elements)
|
|
639
|
+
throw new ModelError(`Expecting artifact with elements: ${ JSON.stringify(artifact) }`);
|
|
640
|
+
|
|
624
641
|
const elemName = Object.keys(elem)[0];
|
|
625
642
|
// Element must not exist
|
|
626
643
|
if (artifact.elements[elemName]) {
|
|
627
644
|
let path = null;
|
|
628
|
-
if (artifactName)
|
|
629
|
-
path = ['definitions', artifactName, 'elements', elemName];
|
|
630
|
-
|
|
645
|
+
if (artifactName)
|
|
646
|
+
path = [ 'definitions', artifactName, 'elements', elemName ];
|
|
647
|
+
|
|
631
648
|
error(null, path, { name: elemName }, 'Generated element $(NAME) conflicts with existing element');
|
|
632
649
|
return;
|
|
633
650
|
}
|
|
@@ -649,18 +666,18 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
649
666
|
* @param {string} elementName
|
|
650
667
|
*/
|
|
651
668
|
function copyAndAddElement(elem, artifact, artifactName, elementName) {
|
|
652
|
-
if (!artifact.elements)
|
|
669
|
+
if (!artifact.elements)
|
|
653
670
|
throw new ModelError('Expected structured artifact');
|
|
654
|
-
|
|
671
|
+
|
|
655
672
|
// Must not already have such an element
|
|
656
673
|
if (artifact.elements[elementName]) {
|
|
657
|
-
const path = ['definitions', artifactName, 'elements', elementName];
|
|
674
|
+
const path = [ 'definitions', artifactName, 'elements', elementName ];
|
|
658
675
|
error(null, path, { name: elementName }, 'Generated element $(NAME) conflicts with existing element');
|
|
659
676
|
}
|
|
660
677
|
|
|
661
678
|
const result = Object.create(null);
|
|
662
679
|
result[elementName] = {};
|
|
663
|
-
|
|
680
|
+
Object.entries(elem || {}).forEach(([ prop, value ]) => {
|
|
664
681
|
result[elementName][prop] = value;
|
|
665
682
|
});
|
|
666
683
|
Object.assign(artifact.elements, result);
|
|
@@ -673,15 +690,15 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
673
690
|
// Assemble the action
|
|
674
691
|
const result = {
|
|
675
692
|
[actionName]: {
|
|
676
|
-
kind: 'action'
|
|
677
|
-
}
|
|
693
|
+
kind: 'action',
|
|
694
|
+
},
|
|
678
695
|
};
|
|
679
696
|
|
|
680
697
|
const action = result[actionName];
|
|
681
698
|
|
|
682
699
|
if (returnTypeName) {
|
|
683
700
|
if (!isBuiltinType(returnTypeName) && !model.definitions[returnTypeName])
|
|
684
|
-
throw new ModelError(
|
|
701
|
+
throw new ModelError(`Expecting valid return type name: ${ returnTypeName }`);
|
|
685
702
|
action.returns = { type: returnTypeName };
|
|
686
703
|
// TODO: What about annotation propagation from return type to `returns`?
|
|
687
704
|
}
|
|
@@ -689,12 +706,12 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
689
706
|
// Add parameter if provided
|
|
690
707
|
if (paramName && paramTypeName) {
|
|
691
708
|
if (!isBuiltinType(paramTypeName) && !model.definitions[paramTypeName])
|
|
692
|
-
throw new ModelError(
|
|
709
|
+
throw new ModelError(`Expecting valid parameter type name: ${ paramTypeName }`);
|
|
693
710
|
|
|
694
711
|
action.params = Object.create(null);
|
|
695
712
|
action.params[paramName] = {
|
|
696
|
-
type: paramTypeName
|
|
697
|
-
}
|
|
713
|
+
type: paramTypeName,
|
|
714
|
+
};
|
|
698
715
|
}
|
|
699
716
|
|
|
700
717
|
return result;
|
|
@@ -706,11 +723,11 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
706
723
|
* @param {object} action Action that shall be added to the given artifact.
|
|
707
724
|
* In form of `{ myAction: { kind: 'action', returns ... } }`
|
|
708
725
|
* @param {CSN.Artifact} artifact Artifact in the form of `{ kind: 'entity', elements: ... }`
|
|
709
|
-
|
|
726
|
+
* */
|
|
710
727
|
function assignAction(action, artifact) {
|
|
711
|
-
if (!artifact.actions)
|
|
728
|
+
if (!artifact.actions)
|
|
712
729
|
artifact.actions = Object.create(null);
|
|
713
|
-
|
|
730
|
+
|
|
714
731
|
|
|
715
732
|
const actionName = Object.keys(action)[0];
|
|
716
733
|
// Element must not exist
|
|
@@ -729,13 +746,18 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
729
746
|
* second field if it has @cds.valid.to. Default value is [] for each field.
|
|
730
747
|
*/
|
|
731
748
|
function extractValidFromToKeyElement(element, path) {
|
|
732
|
-
const validFroms = []
|
|
749
|
+
const validFroms = [];
|
|
733
750
|
if (element['@cds.valid.from'])
|
|
734
|
-
validFroms.push({ element, path: [...path] });
|
|
751
|
+
validFroms.push({ element, path: [ ...path ] });
|
|
752
|
+
|
|
753
|
+
const validTos = [];
|
|
735
754
|
if (element['@cds.valid.to'])
|
|
736
|
-
validTos.push({ element, path: [...path] });
|
|
755
|
+
validTos.push({ element, path: [ ...path ] });
|
|
756
|
+
|
|
757
|
+
const validKeys = [];
|
|
737
758
|
if (element['@cds.valid.key'])
|
|
738
|
-
validKeys.push({ element, path: [...path] });
|
|
759
|
+
validKeys.push({ element, path: [ ...path ] });
|
|
760
|
+
|
|
739
761
|
return [ validFroms, validTos, validKeys ];
|
|
740
762
|
}
|
|
741
763
|
|
|
@@ -778,12 +800,11 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
778
800
|
*/
|
|
779
801
|
function checkMultipleAssignments(array, annoName, artifact, artifactName, err = true) {
|
|
780
802
|
if (array.length > 1) {
|
|
781
|
-
const loc = ['definitions', artifactName];
|
|
782
|
-
if (err === true)
|
|
803
|
+
const loc = [ 'definitions', artifactName ];
|
|
804
|
+
if (err === true)
|
|
783
805
|
error(null, loc, { anno: annoName }, 'Annotation $(ANNO) must be assigned only once');
|
|
784
|
-
|
|
785
|
-
warning(null, loc, { anno: annoName },'Annotation $(ANNO) must be assigned only once');
|
|
786
|
-
}
|
|
806
|
+
else
|
|
807
|
+
warning(null, loc, { anno: annoName }, 'Annotation $(ANNO) must be assigned only once');
|
|
787
808
|
}
|
|
788
809
|
}
|
|
789
810
|
|
|
@@ -796,7 +817,7 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
796
817
|
*/
|
|
797
818
|
function recurseElements(artifact, path, callback) {
|
|
798
819
|
callback(artifact, path);
|
|
799
|
-
const elements = artifact
|
|
820
|
+
const { elements } = artifact;
|
|
800
821
|
if (elements) {
|
|
801
822
|
path.push('elements', null);
|
|
802
823
|
forEach(elements, (name, obj) => {
|
|
@@ -812,16 +833,16 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
812
833
|
function renameAnnotation(node, fromName, toName) {
|
|
813
834
|
const annotation = node && node[fromName];
|
|
814
835
|
// Sanity checks
|
|
815
|
-
if (!fromName.startsWith('@'))
|
|
816
|
-
throw new CompilerAssertion(
|
|
817
|
-
|
|
818
|
-
if (!toName.startsWith('@'))
|
|
819
|
-
throw new CompilerAssertion(
|
|
820
|
-
|
|
821
|
-
if (annotation === undefined)
|
|
822
|
-
throw new CompilerAssertion(
|
|
823
|
-
|
|
824
|
-
if(node[toName] == null) {
|
|
836
|
+
if (!fromName.startsWith('@'))
|
|
837
|
+
throw new CompilerAssertion(`Annotation name should start with "@": ${ fromName }`);
|
|
838
|
+
|
|
839
|
+
if (!toName.startsWith('@'))
|
|
840
|
+
throw new CompilerAssertion(`Annotation name should start with "@": ${ toName }`);
|
|
841
|
+
|
|
842
|
+
if (annotation === undefined)
|
|
843
|
+
throw new CompilerAssertion(`Annotation ${ fromName } not found in ${ JSON.stringify(node) }`);
|
|
844
|
+
|
|
845
|
+
if (node[toName] == null) {
|
|
825
846
|
delete node[fromName];
|
|
826
847
|
node[toName] = annotation;
|
|
827
848
|
}
|
|
@@ -837,12 +858,12 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
837
858
|
* @returns {void}
|
|
838
859
|
*/
|
|
839
860
|
function setAnnotation(node, name, value) {
|
|
840
|
-
if (!name.startsWith('@'))
|
|
841
|
-
throw new CompilerAssertion(
|
|
842
|
-
|
|
843
|
-
if (value === undefined)
|
|
861
|
+
if (!name.startsWith('@'))
|
|
862
|
+
throw new CompilerAssertion(`Annotation name should start with "@": ${ name }`);
|
|
863
|
+
|
|
864
|
+
if (value === undefined)
|
|
844
865
|
throw new CompilerAssertion('Annotation value must not be undefined');
|
|
845
|
-
|
|
866
|
+
|
|
846
867
|
node[name] ??= value;
|
|
847
868
|
}
|
|
848
869
|
|
|
@@ -859,408 +880,22 @@ function getTransformers(model, options, msgFunctions, pathDelimiter = '_') {
|
|
|
859
880
|
* @returns {boolean} wasOverwritten true when the annotation was overwritten
|
|
860
881
|
*/
|
|
861
882
|
function resetAnnotation(node, name, value, info, path) {
|
|
862
|
-
if (!name.startsWith('@'))
|
|
863
|
-
throw new CompilerAssertion(
|
|
864
|
-
|
|
865
|
-
if (value === undefined)
|
|
883
|
+
if (!name.startsWith('@'))
|
|
884
|
+
throw new CompilerAssertion(`Annotation name should start with "@": ${ name }`);
|
|
885
|
+
|
|
886
|
+
if (value === undefined)
|
|
866
887
|
throw new CompilerAssertion('Annotation value must not be undefined');
|
|
867
|
-
|
|
888
|
+
|
|
868
889
|
|
|
869
890
|
const wasOverwritten = node[name] !== undefined && node[name] !== null && node[name] !== value;
|
|
870
891
|
const oldValue = node[name];
|
|
871
892
|
node[name] = value;
|
|
872
|
-
if(wasOverwritten)
|
|
893
|
+
if (wasOverwritten) {
|
|
873
894
|
info(null, path, { anno: name, prop: value, otherprop: oldValue },
|
|
874
|
-
|
|
875
|
-
return wasOverwritten;
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
/*
|
|
879
|
-
Resolve the type of an artifact
|
|
880
|
-
If art is undefined, stop
|
|
881
|
-
If art has elements or items.elements, stop
|
|
882
|
-
If art has a type and the type is scalar, stop
|
|
883
|
-
If art has a named type or a type ref, resolve it
|
|
884
|
-
*/
|
|
885
|
-
function resolveType(art) {
|
|
886
|
-
while(art &&
|
|
887
|
-
!((art.items && art.items.elements) || art.elements) &&
|
|
888
|
-
(art.type &&
|
|
889
|
-
((!art.type.ref && !isBuiltinType(art.type)) || art.type.ref))) {
|
|
890
|
-
if(art.type.ref)
|
|
891
|
-
art = resolvePath(art.type);
|
|
892
|
-
else
|
|
893
|
-
art = model.definitions[art.type];
|
|
894
|
-
}
|
|
895
|
-
return art;
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
/**
|
|
899
|
-
* Path resolution, attach artifact to each path step, if found,
|
|
900
|
-
* Dereference types and follow associations.
|
|
901
|
-
*
|
|
902
|
-
* @param {any} path ref object
|
|
903
|
-
* @param {any} art start environment
|
|
904
|
-
* @returns {any} path with resolved artifacts or artifact
|
|
905
|
-
* (if called with simple ref paths)
|
|
906
|
-
*/
|
|
907
|
-
function resolvePath(path, art=undefined) {
|
|
908
|
-
let notFound = false;
|
|
909
|
-
for(let i = 0; i < path.ref.length && !notFound; i++) {
|
|
910
|
-
const ps = path.ref[i];
|
|
911
|
-
const id = ps.id || ps;
|
|
912
|
-
if(art) {
|
|
913
|
-
if(art.target)
|
|
914
|
-
art = model.definitions[art.target].elements[id];
|
|
915
|
-
else if(art.items && art.items.elements || art.elements) {
|
|
916
|
-
art = (art.items && art.items.elements || art.elements)[id];
|
|
917
|
-
}
|
|
918
|
-
else
|
|
919
|
-
art = undefined;
|
|
920
|
-
}
|
|
921
|
-
else {
|
|
922
|
-
art = model.definitions[id];
|
|
923
|
-
}
|
|
924
|
-
art = resolveType(art);
|
|
925
|
-
|
|
926
|
-
// if path step has id, store art
|
|
927
|
-
if(ps.id && art)
|
|
928
|
-
ps._art = art;
|
|
929
|
-
notFound = !art;
|
|
930
|
-
}
|
|
931
|
-
// if resolve was called on constraint path, path has id.
|
|
932
|
-
// Store art and return path, if called recursively for model ref paths,
|
|
933
|
-
// return artifact only
|
|
934
|
-
if(path.ref[0].id) {
|
|
935
|
-
if(art)
|
|
936
|
-
path._art = art;
|
|
937
|
-
return path;
|
|
938
|
-
}
|
|
939
|
-
else return art;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
/*
|
|
943
|
-
Flatten structured leaf types and return an array of paths.
|
|
944
|
-
|
|
945
|
-
Argument 'path' must be an object of the form
|
|
946
|
-
{ _art: <leaf_artifact>, ref: [...] }
|
|
947
|
-
with _art identifying ref[ref.length-1]
|
|
948
|
-
|
|
949
|
-
A produced path has the form { _art: <ref>, ref: [ <id> (, <id>)* ] }
|
|
950
|
-
|
|
951
|
-
Flattening stops on all non structured elements, if followMgdAssoc=false.
|
|
952
|
-
|
|
953
|
-
If fullRef is true, a path step is produced as { id: <id>, _art: <link> }
|
|
954
|
-
*/
|
|
955
|
-
function flattenPath(path, fullRef=false, followMgdAssoc=false) {
|
|
956
|
-
let art = path._art;
|
|
957
|
-
if(art) {
|
|
958
|
-
if(art && !((art.items && art.items.elements) || art.elements)) {
|
|
959
|
-
if(followMgdAssoc && art.target && art.keys) {
|
|
960
|
-
const rc = [];
|
|
961
|
-
for(const k of art.keys) {
|
|
962
|
-
const nps = { ref: k.ref.map(p => fullRef ? { id: p } : p ) };
|
|
963
|
-
setProp(nps, '_art', k._art);
|
|
964
|
-
const paths = flattenPath( nps, fullRef, followMgdAssoc );
|
|
965
|
-
// prepend prefix path
|
|
966
|
-
paths.forEach(p=>p.ref.splice(0, 0, ...path.ref));
|
|
967
|
-
rc.push(...paths);
|
|
968
|
-
}
|
|
969
|
-
return rc;
|
|
970
|
-
}
|
|
971
|
-
if(art.type && art.type.ref)
|
|
972
|
-
art = resolvePath(art.type);
|
|
973
|
-
else if(art.type && !isBuiltinType(art.type))
|
|
974
|
-
art = model.definitions[art.type];
|
|
975
|
-
}
|
|
976
|
-
const elements = art.items && art.items.elements || art.elements;
|
|
977
|
-
if(elements) {
|
|
978
|
-
const rc = []
|
|
979
|
-
Object.entries(elements).forEach(([en, elt]) => {
|
|
980
|
-
const nps = { ref: [ (fullRef ? { id: en, _art: elt } : en )] };
|
|
981
|
-
setProp(nps, '_art', elt);
|
|
982
|
-
const paths = flattenPath( nps, fullRef, followMgdAssoc );
|
|
983
|
-
// prepend prefix path
|
|
984
|
-
paths.forEach(p=>p.ref.splice(0, 0, ...path.ref));
|
|
985
|
-
rc.push(...paths);
|
|
986
|
-
});
|
|
987
|
-
return rc;
|
|
988
|
-
}
|
|
989
|
-
else
|
|
990
|
-
setProp(path, '_art', art);
|
|
991
|
-
}
|
|
992
|
-
return [path];
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
/**
|
|
996
|
-
* Expand structured expression arguments to flat reference paths.
|
|
997
|
-
* Structured elements are real sub element lists and managed associations.
|
|
998
|
-
* All unmanaged association definitions are rewritten if applicable (elements/mixins).
|
|
999
|
-
* Also, HAVING and WHERE clauses are rewritten. We also check for infix filters and
|
|
1000
|
-
* .xpr in columns.
|
|
1001
|
-
*
|
|
1002
|
-
* @todo Check if can be skipped for abstract entity and or cds.persistence.skip ?
|
|
1003
|
-
* @param {CSN.Model} csn
|
|
1004
|
-
* @param {object} [options={}] "skipArtifact": (artifact, name) => Boolean to skip certain artifacts
|
|
1005
|
-
*/
|
|
1006
|
-
function expandStructsInExpression(csn, options = {}) {
|
|
1007
|
-
applyTransformations(csn, {
|
|
1008
|
-
'on': (parent, name, on, path) => {
|
|
1009
|
-
parent.on = expand(parent.on, path.concat(name));
|
|
1010
|
-
},
|
|
1011
|
-
'having': (parent, name, having, path) => {
|
|
1012
|
-
parent.having = expand(parent.having, path.concat(name));
|
|
1013
|
-
},
|
|
1014
|
-
'where': (parent, name, where, path) => {
|
|
1015
|
-
parent.where = expand(parent.where, path.concat(name));
|
|
1016
|
-
},
|
|
1017
|
-
'xpr': (parent, name, xpr, path) => {
|
|
1018
|
-
parent.xpr = expand(parent.xpr, path.concat(name));
|
|
1019
|
-
}
|
|
1020
|
-
}, [], options);
|
|
1021
|
-
|
|
1022
|
-
/*
|
|
1023
|
-
flatten structured leaf types and return array of paths
|
|
1024
|
-
Flattening stops on all non-structured types.
|
|
1025
|
-
*/
|
|
1026
|
-
function expand(expr, location) {
|
|
1027
|
-
if (!Array.isArray(expr))
|
|
1028
|
-
return expr; // don't traverse strings, etc.
|
|
1029
|
-
const rc = [];
|
|
1030
|
-
for(let i = 0; i < expr.length; i++)
|
|
1031
|
-
{
|
|
1032
|
-
if(Array.isArray(expr[i]))
|
|
1033
|
-
rc.push(expr[i].map(e => expand(e, location)));
|
|
1034
|
-
|
|
1035
|
-
if(i < expr.length-2)
|
|
1036
|
-
{
|
|
1037
|
-
let [lhs, op, not, rhs] = expr.slice(i);
|
|
1038
|
-
if(not !== 'not') {
|
|
1039
|
-
rhs = not;
|
|
1040
|
-
not = false;
|
|
1041
|
-
}
|
|
1042
|
-
if(lhs === undefined || op === undefined || rhs === undefined)
|
|
1043
|
-
return expr;
|
|
1044
|
-
|
|
1045
|
-
// we might have to ad-hoc resolve a ref, since handleExists is run before hand and generates new refs.
|
|
1046
|
-
const lhsArt = lhs._art || lhs.ref && !lhs.$scope && inspectRef(location.concat(i)).art;
|
|
1047
|
-
const rhsArt = rhs._art || rhs.ref && !rhs.$scope && inspectRef(location.concat(i+2)).art;
|
|
1048
|
-
const lhsIsVal = (lhs.val !== undefined);
|
|
1049
|
-
// if ever rhs should be allowed to be a value uncomment this
|
|
1050
|
-
const rhsIsVal = (rhs === 'null' /*|| rhs.val !== undefined*/);
|
|
1051
|
-
|
|
1052
|
-
// lhs & rhs must be expandable types (structures or managed associations)
|
|
1053
|
-
// if ever lhs should be allowed to be a value uncomment this
|
|
1054
|
-
if(!(lhsIsVal /*&& rhsIsVal*/) &&
|
|
1055
|
-
!(isDollarSelfOrProjectionOperand(lhs) || isDollarSelfOrProjectionOperand(rhs)) &&
|
|
1056
|
-
RelationalOperators.includes(op) &&
|
|
1057
|
-
(lhsIsVal || (lhsArt && lhs.ref && isExpandable(lhsArt))) &&
|
|
1058
|
-
(rhsIsVal || (rhsArt && rhs.ref && isExpandable(rhsArt)))
|
|
1059
|
-
) {
|
|
1060
|
-
|
|
1061
|
-
if(RestrictedOperators.includes(op)) {
|
|
1062
|
-
message('expr-unexpected-operator', location, { op }, 'Unexpected operator $(OP) in structural comparison');
|
|
1063
|
-
}
|
|
1064
|
-
// if path is scalar and no assoc or has no type (@Core.Computed) use original expression
|
|
1065
|
-
// only do the expansion on (managed) assocs and (items.)elements, array of check in ON cond is done elsewhere
|
|
1066
|
-
const lhspaths = lhsIsVal ? [] : flattenPath({ _art: lhsArt, ref: lhs.ref }, false, true );
|
|
1067
|
-
const rhspaths = rhsIsVal ? [] : flattenPath({ _art: rhsArt, ref: rhs.ref }, false, true );
|
|
1068
|
-
|
|
1069
|
-
// mapping dict for lhs/rhs for mismatch check
|
|
1070
|
-
// strip lhs/rhs prefix from flattened paths to check remaining common trailing path
|
|
1071
|
-
// if path is idempotent, it doesn't produce new flattened paths (ends on scalar type)
|
|
1072
|
-
// key is then empty string on both sides '' (=> equality)
|
|
1073
|
-
// Path matches if lhs/rhs are available
|
|
1074
|
-
const xref = createXRef(lhspaths, rhspaths, lhs, rhs, lhsIsVal, rhsIsVal);
|
|
1075
|
-
const xrefkeys = Object.keys(xref);
|
|
1076
|
-
const xrefvalues = Object.values(xref);
|
|
1077
|
-
let cont = true;
|
|
1078
|
-
|
|
1079
|
-
const prefix = (lhs, op, rhs) => {
|
|
1080
|
-
return `${lhsIsVal ? lhs.val : lhs.ref.join('.')} ${op} ${rhsIsVal ? rhs : rhs.ref.join('.')}`
|
|
1081
|
-
}
|
|
1082
|
-
if(op === 'like' && xrefvalues.reduce((a, v) => {
|
|
1083
|
-
return (v.lhs && v.rhs) ? a + 1: a;
|
|
1084
|
-
}, 0) === 0) {
|
|
1085
|
-
// error if intersection of paths is zero
|
|
1086
|
-
error(null, location,
|
|
1087
|
-
{
|
|
1088
|
-
prefix: prefix(lhs, op, rhs)
|
|
1089
|
-
},
|
|
1090
|
-
'Expected compatible types for $(PREFIX)');
|
|
1091
|
-
cont = false;
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
cont && xrefkeys.forEach(xn => {
|
|
1095
|
-
const x = xref[xn];
|
|
1096
|
-
// do the paths match?
|
|
1097
|
-
if(op !== 'like' && !(x.lhs && x.rhs)) {
|
|
1098
|
-
if(xn.length) {
|
|
1099
|
-
error('expr-invalid-expansion', location, {
|
|
1100
|
-
value: prefix(lhs, op, rhs),
|
|
1101
|
-
name: xn,
|
|
1102
|
-
alias: (x.lhs ? rhs : lhs).ref.join('.')
|
|
1103
|
-
},
|
|
1104
|
-
'Missing sub path $(NAME) in $(ALIAS) for tuple expansion of $(VALUE); both sides must expand to the same sub paths');
|
|
1105
|
-
}
|
|
1106
|
-
else {
|
|
1107
|
-
error(null, location,
|
|
1108
|
-
{
|
|
1109
|
-
prefix: prefix(lhs, op, rhs),
|
|
1110
|
-
name: (x.lhs ? lhs : rhs).ref.join('.'),
|
|
1111
|
-
alias: (x.lhs ? rhs : lhs).ref.join('.')
|
|
1112
|
-
},
|
|
1113
|
-
'$(PREFIX): Path $(NAME) does not match $(ALIAS)');
|
|
1114
|
-
}
|
|
1115
|
-
cont = false;
|
|
1116
|
-
}
|
|
1117
|
-
// lhs && rhs are present, consistency checks that affect both ends
|
|
1118
|
-
else {
|
|
1119
|
-
// is lhs scalar?
|
|
1120
|
-
// eslint-disable-next-line sonarjs/no-gratuitous-expressions
|
|
1121
|
-
if(!lhsIsVal && x.lhs && !isScalarOrNoType(x.lhs._art)) {
|
|
1122
|
-
error(null, location,
|
|
1123
|
-
{
|
|
1124
|
-
prefix: prefix(lhs, op, rhs),
|
|
1125
|
-
name: `${x.lhs.ref.join('.')}${(xn.length ? '.' + xn : '')}`
|
|
1126
|
-
},
|
|
1127
|
-
'$(PREFIX): Path $(NAME) must end on a scalar type')
|
|
1128
|
-
cont = false;
|
|
1129
|
-
}
|
|
1130
|
-
// is rhs scalar?
|
|
1131
|
-
if(!rhsIsVal && x.rhs && !isScalarOrNoType(x.rhs._art)) {
|
|
1132
|
-
error(null, location,
|
|
1133
|
-
{
|
|
1134
|
-
prefix: prefix(lhs, op, rhs),
|
|
1135
|
-
name: `${x.rhs.ref.join('.')}${(xn.length ? '.' + xn : '')}`
|
|
1136
|
-
},
|
|
1137
|
-
'$(PREFIX): Path $(NAME) must end on a scalar type');
|
|
1138
|
-
cont = false;
|
|
1139
|
-
}
|
|
1140
|
-
// info about type incompatibility if no other errors occurred
|
|
1141
|
-
// eslint-disable-next-line sonarjs/no-gratuitous-expressions
|
|
1142
|
-
if(!(lhsIsVal || rhsIsVal) && x.lhs && x.rhs && xn && cont) {
|
|
1143
|
-
const lhst = getType(x.lhs._art);
|
|
1144
|
-
const rhst = getType(x.rhs._art);
|
|
1145
|
-
if(lhst !== rhst) {
|
|
1146
|
-
info(null, location,
|
|
1147
|
-
{
|
|
1148
|
-
prefix: prefix(lhs, op, rhs),
|
|
1149
|
-
name: xn
|
|
1150
|
-
},
|
|
1151
|
-
'$(PREFIX): Types for sub path $(NAME) don\'t match');
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
});
|
|
1156
|
-
// don't continue if there are path errors
|
|
1157
|
-
if(!cont)
|
|
1158
|
-
return expr;
|
|
1159
|
-
|
|
1160
|
-
// if lhs and rhs are refs set operator from 'like' to '='
|
|
1161
|
-
// eslint-disable-next-line sonarjs/no-gratuitous-expressions
|
|
1162
|
-
if(op === 'like' && !(lhsIsVal || rhsIsVal)) {
|
|
1163
|
-
op = '=';
|
|
1164
|
-
}
|
|
1165
|
-
// t_0 OR ... OR t_n with t = (a <not equal> b)
|
|
1166
|
-
const bop = (op === 'is' && not) || op === '!=' || op === '<>' ? 'or' : 'and';
|
|
1167
|
-
const xpr = { xpr: [] };
|
|
1168
|
-
xrefvalues.filter(x => x.lhs && x.rhs).forEach((x,i) => {
|
|
1169
|
-
xpr.i = i;
|
|
1170
|
-
if(i>0) {
|
|
1171
|
-
xpr.xpr.push(bop);
|
|
1172
|
-
}
|
|
1173
|
-
xpr.xpr.push(x.lhs);
|
|
1174
|
-
xpr.xpr.push(op);
|
|
1175
|
-
if(not)
|
|
1176
|
-
xpr.xpr.push('not')
|
|
1177
|
-
xpr.xpr.push(x.rhs);
|
|
1178
|
-
});
|
|
1179
|
-
if(xpr.i > 0) {
|
|
1180
|
-
delete xpr.i;
|
|
1181
|
-
rc.push(xpr);
|
|
1182
|
-
}
|
|
1183
|
-
else
|
|
1184
|
-
rc.push(...xpr.xpr);
|
|
1185
|
-
i += not ? 3 : 2;
|
|
1186
|
-
}
|
|
1187
|
-
else
|
|
1188
|
-
rc.push(expr[i]);
|
|
1189
|
-
}
|
|
1190
|
-
else
|
|
1191
|
-
rc.push(expr[i]);
|
|
1192
|
-
}
|
|
1193
|
-
return rc;
|
|
1194
|
-
|
|
1195
|
-
function createXRef(lhspaths, rhspaths, lhs, rhs, lhsIsVal, rhsIsVal) {
|
|
1196
|
-
// mapping dict for lhs/rhs for mismatch check
|
|
1197
|
-
// strip lhs/rhs prefix from flattened paths to check remaining common trailing path
|
|
1198
|
-
// if path is idempotent, it doesn't produce new flattened paths (ends on scalar type)
|
|
1199
|
-
// key is then empty string on both sides '' (=> equality)
|
|
1200
|
-
// Path matches if lhs/rhs are available
|
|
1201
|
-
let xref;
|
|
1202
|
-
if(!lhsIsVal) {
|
|
1203
|
-
xref = lhspaths.reduce((a, v) => {
|
|
1204
|
-
a[v.ref.slice(lhs.ref.length).join('.')] = rhsIsVal ? { lhs: v, rhs } : { lhs: v };
|
|
1205
|
-
return a;
|
|
1206
|
-
}, Object.create(null));
|
|
1207
|
-
|
|
1208
|
-
rhspaths.forEach(v => {
|
|
1209
|
-
const k = v.ref.slice(rhs.ref.length).join('.');
|
|
1210
|
-
if(xref[k])
|
|
1211
|
-
xref[k].rhs = v;
|
|
1212
|
-
else
|
|
1213
|
-
xref[k] = { rhs: v };
|
|
1214
|
-
});
|
|
1215
|
-
}
|
|
1216
|
-
else if(!rhsIsVal) {
|
|
1217
|
-
xref = rhspaths.reduce((a, v) => {
|
|
1218
|
-
a[v.ref.slice(rhs.ref.length).join('.')] = lhsIsVal ? { lhs, rhs: v } : { rhs: v };
|
|
1219
|
-
return a;
|
|
1220
|
-
}, Object.create(null));
|
|
1221
|
-
|
|
1222
|
-
lhspaths.forEach(v => {
|
|
1223
|
-
const k = v.ref.slice(lhs.ref.length).join('.');
|
|
1224
|
-
if(xref[k])
|
|
1225
|
-
xref[k].lhs = v;
|
|
1226
|
-
else
|
|
1227
|
-
xref[k] = { lhs: v };
|
|
1228
|
-
});
|
|
1229
|
-
}
|
|
1230
|
-
return xref;
|
|
1231
|
-
}
|
|
1232
|
-
|
|
1233
|
-
function getType(art) {
|
|
1234
|
-
const effArt = effectiveType(art);
|
|
1235
|
-
return Object.keys(effArt).length ? effArt : art.type;
|
|
1236
|
-
}
|
|
1237
|
-
|
|
1238
|
-
function isExpandable(art) {
|
|
1239
|
-
art = effectiveType(art);
|
|
1240
|
-
if(art) {
|
|
1241
|
-
// items in ON conds are illegal but this should be checked elsewhere
|
|
1242
|
-
const elements = art.elements || (art.items && art.items.elements);
|
|
1243
|
-
return !!(elements || art.target && art.keys)
|
|
1244
|
-
}
|
|
1245
|
-
return false;
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
function isScalarOrNoType(art) {
|
|
1249
|
-
art = effectiveType(art);
|
|
1250
|
-
if (art) {
|
|
1251
|
-
const type = art.type || art.items?.type;
|
|
1252
|
-
// items in ON-conditions are illegal but this should be checked elsewhere
|
|
1253
|
-
const elements = art.elements || (art.items && art.items.elements);
|
|
1254
|
-
// @Core.Computed has no type
|
|
1255
|
-
return (!elements && !type ||
|
|
1256
|
-
(type && isBuiltinType(type) &&
|
|
1257
|
-
type !== 'cds.Association' && type !== 'cds.Composition' && type !== 'cds.Map'))
|
|
1258
|
-
}
|
|
1259
|
-
return false;
|
|
1260
|
-
}
|
|
895
|
+
'Value $(OTHERPROP) of annotation $(ANNO) is overwritten with new value $(PROP)');
|
|
1261
896
|
}
|
|
897
|
+
return wasOverwritten;
|
|
1262
898
|
}
|
|
1263
|
-
|
|
1264
899
|
}
|
|
1265
900
|
|
|
1266
901
|
/**
|
|
@@ -1276,19 +911,17 @@ function rewriteBuiltinTypeRef(csn) {
|
|
|
1276
911
|
const special$self = !csn?.definitions?.$self && '$self';
|
|
1277
912
|
applyTransformations(csn, {
|
|
1278
913
|
type: (parent, _prop, type) => {
|
|
1279
|
-
if(type?.ref && (
|
|
914
|
+
if (type?.ref && (
|
|
1280
915
|
isBuiltinType(type.ref[0]) ||
|
|
1281
916
|
type.ref[0] === special$self)
|
|
1282
|
-
)
|
|
917
|
+
)
|
|
1283
918
|
parent.type = type.ref[0];
|
|
1284
|
-
|
|
1285
|
-
}
|
|
919
|
+
},
|
|
1286
920
|
});
|
|
1287
921
|
}
|
|
1288
922
|
|
|
1289
923
|
module.exports = {
|
|
1290
924
|
// This function retrieves the actual exports
|
|
1291
925
|
getTransformers,
|
|
1292
|
-
RelationalOperators,
|
|
1293
926
|
rewriteBuiltinTypeRef,
|
|
1294
927
|
};
|