@sap/cds-compiler 4.8.0 → 4.9.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 +38 -4
- package/bin/cds_remove_invalid_whitespace.js +135 -0
- package/bin/cds_update_annotations.js +180 -0
- package/bin/cds_update_identifiers.js +3 -4
- package/bin/cdsc.js +30 -17
- package/doc/CHANGELOG_BETA.md +19 -0
- package/lib/api/main.js +59 -24
- package/lib/api/options.js +12 -1
- package/lib/api/validate.js +1 -5
- package/lib/base/builtins.js +27 -0
- package/lib/base/message-registry.js +38 -21
- package/lib/base/messages.js +51 -20
- package/lib/base/model.js +4 -5
- package/lib/checks/actionsFunctions.js +2 -2
- package/lib/checks/annotationsOData.js +3 -0
- package/lib/checks/defaultValues.js +5 -2
- package/lib/checks/queryNoDbArtifacts.js +3 -2
- package/lib/checks/validator.js +2 -34
- package/lib/compiler/assert-consistency.js +10 -3
- package/lib/compiler/checks.js +44 -18
- package/lib/compiler/define.js +38 -30
- package/lib/compiler/extend.js +33 -10
- package/lib/compiler/index.js +0 -1
- package/lib/compiler/lsp-api.js +5 -0
- package/lib/compiler/populate.js +0 -2
- package/lib/compiler/propagator.js +23 -19
- package/lib/compiler/resolve.js +48 -29
- package/lib/compiler/shared.js +60 -20
- package/lib/compiler/tweak-assocs.js +72 -116
- package/lib/compiler/xpr-rewrite.js +762 -0
- package/lib/edm/annotations/edmJson.js +24 -7
- package/lib/edm/annotations/genericTranslation.js +81 -61
- package/lib/edm/edm.js +4 -4
- package/lib/edm/edmInboundChecks.js +33 -0
- package/lib/edm/edmPreprocessor.js +9 -6
- package/lib/gen/Dictionary.json +129 -14
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +1523 -1518
- package/lib/json/from-csn.js +13 -4
- package/lib/json/to-csn.js +12 -12
- package/lib/language/genericAntlrParser.js +14 -6
- package/lib/main.d.ts +67 -14
- package/lib/main.js +1 -0
- package/lib/model/cloneCsn.js +6 -3
- package/lib/model/csnRefs.js +23 -11
- package/lib/model/csnUtils.js +13 -7
- package/lib/model/enrichCsn.js +3 -1
- package/lib/model/revealInternalProperties.js +2 -1
- package/lib/model/sortViews.js +14 -6
- package/lib/modelCompare/compare.js +33 -34
- package/lib/optionProcessor.js +27 -2
- package/lib/render/DuplicateChecker.js +6 -6
- package/lib/render/manageConstraints.js +1 -0
- package/lib/render/toCdl.js +3 -1
- package/lib/transform/db/applyTransformations.js +33 -0
- package/lib/transform/db/constraints.js +75 -28
- package/lib/transform/db/expansion.js +8 -3
- package/lib/transform/db/flattening.js +2 -2
- package/lib/transform/db/groupByOrderBy.js +2 -2
- package/lib/transform/db/temporal.js +6 -3
- package/lib/transform/db/transformExists.js +2 -2
- package/lib/transform/effective/annotations.js +194 -0
- package/lib/transform/effective/main.js +6 -8
- package/lib/transform/effective/misc.js +31 -10
- package/lib/transform/forOdata.js +23 -7
- package/lib/transform/forRelationalDB.js +3 -3
- package/lib/transform/localized.js +7 -6
- package/lib/transform/odata/flattening.js +221 -124
- package/lib/transform/odata/toFinalBaseType.js +1 -1
- package/lib/transform/odata/typesExposure.js +15 -12
- package/lib/transform/parseExpr.js +4 -4
- package/lib/transform/transformUtils.js +47 -42
- package/lib/transform/translateAssocsToJoins.js +47 -47
- package/lib/transform/universalCsn/universalCsnEnricher.js +16 -19
- package/package.json +1 -1
- package/share/messages/anno-missing-rewrite.md +45 -0
- package/share/messages/message-explanations.json +1 -0
- package/bin/.eslintrc.json +0 -17
- package/lib/api/.eslintrc.json +0 -37
- package/lib/checks/.eslintrc.json +0 -31
- package/lib/compiler/.eslintrc.json +0 -8
- package/lib/edm/.eslintrc.json +0 -46
- package/lib/inspect/.eslintrc.json +0 -4
- package/lib/json/.eslintrc.json +0 -4
- package/lib/language/.eslintrc.json +0 -4
- package/lib/model/.eslintrc.json +0 -13
- package/lib/modelCompare/utils/.eslintrc.json +0 -22
- package/lib/render/.eslintrc.json +0 -22
- package/lib/transform/.eslintrc.json +0 -13
- package/lib/transform/db/.eslintrc.json +0 -41
- package/lib/transform/draft/.eslintrc.json +0 -4
- package/lib/transform/effective/.eslintrc.json +0 -4
- package/lib/transform/universalCsn/.eslintrc.json +0 -37
- package/lib/utils/.eslintrc.json +0 -7
|
@@ -248,8 +248,15 @@ function xpr2edmJson( carrier, anno, location, options, messageFunctions ) {
|
|
|
248
248
|
transform['<='] = op('$Le');
|
|
249
249
|
transform.$Le = noOp;
|
|
250
250
|
transform.in = (parent, prop, xpr) => {
|
|
251
|
-
|
|
252
|
-
|
|
251
|
+
let args = xpr[1].list;
|
|
252
|
+
if (!args) {
|
|
253
|
+
if (Array.isArray(xpr[1].xpr))
|
|
254
|
+
args = xpr[1].xpr;
|
|
255
|
+
else
|
|
256
|
+
args = [ xpr[1] ];
|
|
257
|
+
}
|
|
258
|
+
evalArgs({ min: 1 }, args, prop);
|
|
259
|
+
parent.$In = [ xpr[0], args ];
|
|
253
260
|
delete parent[prop];
|
|
254
261
|
transformExpression(parent, undefined, transform);
|
|
255
262
|
};
|
|
@@ -293,9 +300,9 @@ function xpr2edmJson( carrier, anno, location, options, messageFunctions ) {
|
|
|
293
300
|
transform.$Neg = noOp;
|
|
294
301
|
transform['*'] = op('$Mul');
|
|
295
302
|
transform.$Mul = noOp;
|
|
296
|
-
transform['/'] = op('$
|
|
297
|
-
transform.$
|
|
298
|
-
// $
|
|
303
|
+
transform['/'] = op('$DivBy');
|
|
304
|
+
transform.$DivBy = noOp;
|
|
305
|
+
// $Div, $Mod are functions
|
|
299
306
|
//----------------------------------
|
|
300
307
|
// LITERALS
|
|
301
308
|
transform.val = (parent, prop, xpr, csnPath, parentparent, parentprop) => {
|
|
@@ -575,6 +582,15 @@ function xpr2edmJson( carrier, anno, location, options, messageFunctions ) {
|
|
|
575
582
|
}
|
|
576
583
|
}
|
|
577
584
|
else {
|
|
585
|
+
// Error out for arbitrary types until we know better
|
|
586
|
+
// probably todo: Check for reachability of arb type names such as namespace
|
|
587
|
+
// reqDef entry etc...
|
|
588
|
+
if (typeDef) { // eslint-disable-line no-lonely-if
|
|
589
|
+
error('odata-anno-xpr-type', location, {
|
|
590
|
+
anno, op: `${xpr}(…)`, type: `${typeDef}`, '#': 'edm',
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
/*
|
|
578
594
|
typeFacets.forEach((facet) => {
|
|
579
595
|
if (facet.args.length === 1 && facet.args[0].val) {
|
|
580
596
|
const facetName = facet.func.startsWith('$') ? facet.func.slice(1) : facet.func;
|
|
@@ -582,6 +598,7 @@ function xpr2edmJson( carrier, anno, location, options, messageFunctions ) {
|
|
|
582
598
|
parent[`$${facetName}`] = facet.args[0].val;
|
|
583
599
|
}
|
|
584
600
|
});
|
|
601
|
+
*/
|
|
585
602
|
}
|
|
586
603
|
|
|
587
604
|
delete typeProp.args;
|
|
@@ -648,8 +665,8 @@ function xpr2edmJson( carrier, anno, location, options, messageFunctions ) {
|
|
|
648
665
|
const funcDefs = {
|
|
649
666
|
$Has: twoArgs,
|
|
650
667
|
Has: [ twoArgs, dollar ],
|
|
651
|
-
$
|
|
652
|
-
|
|
668
|
+
$Div: twoArgs,
|
|
669
|
+
Div: [ twoArgs, dollar ],
|
|
653
670
|
$Mod: twoArgs,
|
|
654
671
|
Mod: [ twoArgs, dollar ],
|
|
655
672
|
$Apply: () => {
|
|
@@ -102,7 +102,9 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
102
102
|
// qualified with #$parameters or if its applicable to an EntitySet or Singleton
|
|
103
103
|
const scopeCheck = {
|
|
104
104
|
ref: (elemref, prop, xpr, path) => {
|
|
105
|
-
if (scopeCheck.scope === 'param' &&
|
|
105
|
+
if (scopeCheck.scope === 'param' &&
|
|
106
|
+
(!elemref.param ||
|
|
107
|
+
(xpr[0].id || xpr[0]) === '$self' && !def.elements.$self)) {
|
|
106
108
|
error('odata-anno-xpr-ref', path, { anno: scopeCheck.anno, elemref, '#': 'notaparam' });
|
|
107
109
|
// don't try to resolve those paths later on
|
|
108
110
|
delete elemref[prop];
|
|
@@ -111,9 +113,13 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
111
113
|
error('odata-anno-xpr-ref', path, { anno: scopeCheck.anno, elemref, '#': 'notaneelement' });
|
|
112
114
|
delete elemref[prop];
|
|
113
115
|
}
|
|
114
|
-
if (scopeCheck.scope === 'param' && elemref.param)
|
|
116
|
+
if (scopeCheck.scope === 'param' && elemref.param) {
|
|
115
117
|
// make sure that path is resolvable as element path later on
|
|
116
118
|
delete elemref.param;
|
|
119
|
+
const head = xpr[0].id || xpr[0];
|
|
120
|
+
if (head[0] === '$')
|
|
121
|
+
xpr.unshift('$self');
|
|
122
|
+
}
|
|
117
123
|
},
|
|
118
124
|
};
|
|
119
125
|
const checkDict = (dict, scope) => {
|
|
@@ -156,7 +162,8 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
156
162
|
const steps = prefix.replace(`@${ns}.`, '').split('.');
|
|
157
163
|
const paramAnnoParts = steps[0].split('#$parameters');
|
|
158
164
|
const dictTerm = getDictTerm(`${ns}.${paramAnnoParts[0]}`, options);
|
|
159
|
-
if (paramAnnoParts.length > 1 ||
|
|
165
|
+
if (paramAnnoParts.length > 1 ||
|
|
166
|
+
[ 'Singleton', 'EntitySet' ].some(y => dictTerm?.AppliesTo?.includes(y))) {
|
|
160
167
|
steps[0] = `@${ns}.${paramAnnoParts.join('')}`;
|
|
161
168
|
let newAnno = steps.join('.');
|
|
162
169
|
if (innerAnnotation)
|
|
@@ -185,12 +192,14 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
185
192
|
There is one exception (Schema), see below
|
|
186
193
|
|
|
187
194
|
carrier = service
|
|
188
|
-
the target is the EntityContainer, unless the annotation has an "AppliesTo"
|
|
189
|
-
|
|
195
|
+
the target is the EntityContainer, unless the annotation has an "AppliesTo"
|
|
196
|
+
where only Schema is given, but not EntityContainer then the <Annotation ...>
|
|
197
|
+
is directly put into <Schema ...> without an enclosing <Annotations ...>
|
|
190
198
|
|
|
191
199
|
carrier = entity (incl. view/projection)
|
|
192
|
-
the target is the corresponding EntityType, unless the annotation has an
|
|
193
|
-
|
|
200
|
+
the target is the corresponding EntityType, unless the annotation has an
|
|
201
|
+
"AppliesTo" where only EntitySet is given, but not EntityType then the target
|
|
202
|
+
is the corresponding EntitySet
|
|
194
203
|
|
|
195
204
|
carrier = structured type
|
|
196
205
|
the target is the corresponding ComplexType
|
|
@@ -217,7 +226,8 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
217
226
|
if (def.$elementsAnnoProxies) {
|
|
218
227
|
Object.entries(def.$elementsAnnoProxies).forEach(([ elemPath, element ]) => {
|
|
219
228
|
const edmTargetName = `${defName}/${elemPath}`;
|
|
220
|
-
handleAnnotations(edmTargetName, element, element.$path,
|
|
229
|
+
handleAnnotations(edmTargetName, element, element.$path,
|
|
230
|
+
[ ...location, '$elementsAnnoProxies', elemPath ]);
|
|
221
231
|
});
|
|
222
232
|
}
|
|
223
233
|
// element bound annotations
|
|
@@ -278,24 +288,28 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
278
288
|
if (cAction.$paramsAnnoProxies) {
|
|
279
289
|
Object.entries(cAction.$paramsAnnoProxies).forEach(([ paramPath, param ]) => {
|
|
280
290
|
const edmTargetName = `${actionName}/${paramPath}`;
|
|
281
|
-
handleAnnotations(edmTargetName, param, param.$path,
|
|
291
|
+
handleAnnotations(edmTargetName, param, param.$path,
|
|
292
|
+
[ ...location, '$paramsAnnoProxies', paramPath ]);
|
|
282
293
|
});
|
|
283
294
|
}
|
|
284
295
|
Object.entries(cAction.params).forEach(([ n, p ]) => {
|
|
285
296
|
const edmTargetName = `${actionName}/${n}`;
|
|
286
|
-
handleAnnotations(edmTargetName, p,
|
|
297
|
+
handleAnnotations(edmTargetName, p,
|
|
298
|
+
[ ...location, 'params', n ]);
|
|
287
299
|
});
|
|
288
300
|
}
|
|
289
301
|
if (cAction.returns) {
|
|
290
302
|
if (cAction.$returnsAnnoProxies) {
|
|
291
303
|
Object.entries(cAction.$returnsAnnoProxies).forEach(([ returnsPath, returns ]) => {
|
|
292
304
|
const edmTargetName = `${actionName}/${returnsPath}`;
|
|
293
|
-
handleAnnotations(edmTargetName, returns, returns.$path,
|
|
305
|
+
handleAnnotations(edmTargetName, returns, returns.$path,
|
|
306
|
+
[ ...location, '$returnsAnnoProxies', returnsPath ]);
|
|
294
307
|
});
|
|
295
308
|
}
|
|
296
309
|
const edmTargetName = `${actionName}/$ReturnType`;
|
|
297
310
|
setProp(cAction.returns, '$appliesToReturnType', true);
|
|
298
|
-
handleAnnotations(edmTargetName, cAction.returns,
|
|
311
|
+
handleAnnotations(edmTargetName, cAction.returns,
|
|
312
|
+
[ ...location, 'returns' ]);
|
|
299
313
|
delete cAction.returns.$appliesToReturnType;
|
|
300
314
|
}
|
|
301
315
|
|
|
@@ -304,12 +318,19 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
304
318
|
const params = [];
|
|
305
319
|
if (entityNameIfBound) {
|
|
306
320
|
// If this is an action and has an explicit binding parameter add it here
|
|
307
|
-
if (cAction.$bindingParam && cAction.kind === 'action')
|
|
308
|
-
params.push(
|
|
309
|
-
|
|
321
|
+
if (cAction.$bindingParam && cAction.kind === 'action') {
|
|
322
|
+
params.push(
|
|
323
|
+
cAction.$bindingParam.items
|
|
324
|
+
? `Collection(${entityNameIfBound})`
|
|
325
|
+
: entityNameIfBound
|
|
326
|
+
);
|
|
327
|
+
}
|
|
310
328
|
// If action/function has no explicit binding parameter add it here
|
|
311
|
-
else if (!cAction.$bindingParam)
|
|
312
|
-
params.push(cAction['@cds.odata.bindingparameter.collection']
|
|
329
|
+
else if (!cAction.$bindingParam) {
|
|
330
|
+
params.push(cAction['@cds.odata.bindingparameter.collection']
|
|
331
|
+
? `Collection(${entityNameIfBound})`
|
|
332
|
+
: entityNameIfBound);
|
|
333
|
+
}
|
|
313
334
|
}
|
|
314
335
|
// In case this is a function the explicit binding parameter is part of
|
|
315
336
|
// the functions params dictionary. Only for functions all parameters must
|
|
@@ -369,50 +390,49 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
369
390
|
if (knownAnnos.length === 0)
|
|
370
391
|
return;
|
|
371
392
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
}
|
|
393
|
+
|
|
394
|
+
knownAnnos.forEach((knownAnno) => {
|
|
395
|
+
if (knownAnno.search(/\.\$edmJson\./g) < 0) {
|
|
396
|
+
transformExpression(carrier, knownAnno, {
|
|
397
|
+
ref: (elemref, prop, xpr, csnPath) => {
|
|
398
|
+
if (options.isV2() && elemref.$bparam) {
|
|
399
|
+
error('odata-anno-xpr-ref', location, {
|
|
400
|
+
elemref, anno: knownAnno, version: '2.0', '#': 'bparam_v2',
|
|
401
|
+
});
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
const { links, scope } = reqDefsUtils.inspectRef(csnPath);
|
|
405
|
+
let i = scope === '$self' ? 1 : 0;
|
|
406
|
+
if (scope === '$magic') {
|
|
407
|
+
error('odata-anno-xpr-ref', location, {
|
|
408
|
+
elemref, anno: knownAnno, '#': 'magic',
|
|
409
|
+
});
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
let stop = false;
|
|
413
|
+
for (; i < links.length && !stop; i++) {
|
|
414
|
+
if (!isEdmPropertyRendered(links[i].art, csnPath)) {
|
|
415
|
+
error('odata-anno-xpr-ref', location, {
|
|
416
|
+
count: i + 1, elemref, anno: knownAnno, '#': 'notrendered',
|
|
417
|
+
});
|
|
418
|
+
stop = true;
|
|
419
|
+
}
|
|
420
|
+
if (links[i].art?._target?.$proxy && i < links.length - 1) {
|
|
421
|
+
const proxy = links[i].art?._target;
|
|
422
|
+
const eltName = links[i + 1].art?.name;
|
|
423
|
+
if (!proxy.elements[eltName]) {
|
|
424
|
+
error('odata-anno-xpr-ref', location, {
|
|
425
|
+
count: i + 2, elemref, anno: knownAnno, '#': 'notrendered',
|
|
426
|
+
});
|
|
427
|
+
stop = true;
|
|
408
428
|
}
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
}
|
|
415
|
-
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
}, csnPathResolutionLocation);
|
|
433
|
+
xpr2edmJson(carrier, knownAnno, location, options, messageFunctions);
|
|
434
|
+
}
|
|
435
|
+
});
|
|
416
436
|
|
|
417
437
|
const prefixTree = createPrefixTree();
|
|
418
438
|
|
|
@@ -1014,7 +1034,7 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
1014
1034
|
typeName = dTypeName.split('.')[1];
|
|
1015
1035
|
}
|
|
1016
1036
|
|
|
1017
|
-
if (value) {
|
|
1037
|
+
if (typeof value === 'string') {
|
|
1018
1038
|
// replace all occurrences of '.' by '/' up to first '@'
|
|
1019
1039
|
value = value.split('@').map((o, i) => (i === 0 ? o.replace(/\./g, '/') : o)).join('@');
|
|
1020
1040
|
}
|
package/lib/edm/edm.js
CHANGED
|
@@ -19,11 +19,11 @@ function getEdm( options, messageFunctions ) {
|
|
|
19
19
|
*/
|
|
20
20
|
constructor(version, attributes = Object.create(null), csn = undefined) {
|
|
21
21
|
if (!attributes || typeof attributes !== 'object')
|
|
22
|
-
error(null, '
|
|
22
|
+
error(null, 'Debug me: attributes must be a dictionary');
|
|
23
23
|
if (!Array.isArray(version))
|
|
24
|
-
error(null, `
|
|
24
|
+
error(null, `Debug me: v is either undefined or not an array: ${version}`);
|
|
25
25
|
if (version.filter(v => v).length !== 1)
|
|
26
|
-
error(null, '
|
|
26
|
+
error(null, 'Debug me: exactly one version must be set');
|
|
27
27
|
|
|
28
28
|
// Common attributes of JSON and XML.
|
|
29
29
|
// Note: Can't assign attributes directly, due to the input object being modified.
|
|
@@ -1108,7 +1108,7 @@ function getEdm( options, messageFunctions ) {
|
|
|
1108
1108
|
json.$OnDelete = c._edmAttributes.Action;
|
|
1109
1109
|
break;
|
|
1110
1110
|
default:
|
|
1111
|
-
error(null, `
|
|
1111
|
+
error(null, `Debug me: Unhandled NavProp child: ${c.kind}`);
|
|
1112
1112
|
}
|
|
1113
1113
|
});
|
|
1114
1114
|
// TODO Annotations
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const { setProp, isBetaEnabled } = require('../base/model');
|
|
4
4
|
const {
|
|
5
5
|
forEachDefinition, forEachMemberRecursively, getUtils,
|
|
6
|
+
transformExpression, findAnnotationExpression,
|
|
6
7
|
} = require('../model/csnUtils');
|
|
7
8
|
const { isBuiltinType } = require('../base/builtins');
|
|
8
9
|
const { assignAnnotation } = require('./edmUtils.js');
|
|
@@ -55,8 +56,10 @@ function inboundQualificationChecks( csn, options, messageFunctions,
|
|
|
55
56
|
Object.entries(def.actions).forEach(([ n, action ]) => {
|
|
56
57
|
const aLoc = location.concat('actions', n);
|
|
57
58
|
checkIfItemsOfItems(action, undefined, undefined, aLoc);
|
|
59
|
+
markBindingParamPaths(action, aLoc);
|
|
58
60
|
forEachMemberRecursively(action, checkIfItemsOfItems, aLoc);
|
|
59
61
|
checkIfItemsOfItems(action.returns, undefined, undefined, aLoc.concat('returns'));
|
|
62
|
+
markBindingParamPaths(action, aLoc);
|
|
60
63
|
});
|
|
61
64
|
}
|
|
62
65
|
|
|
@@ -124,6 +127,36 @@ function inboundQualificationChecks( csn, options, messageFunctions,
|
|
|
124
127
|
message('chained-array-of', path);
|
|
125
128
|
}
|
|
126
129
|
}
|
|
130
|
+
|
|
131
|
+
// we need to know if the first path step is the bindind param
|
|
132
|
+
// for the rejection of V2 paths where the BP is ignored
|
|
133
|
+
function markBindingParamPaths( action, loc ) {
|
|
134
|
+
const special$self = !csn?.definitions?.$self && '$self';
|
|
135
|
+
if (action.params) {
|
|
136
|
+
const params = Object.entries(action.params);
|
|
137
|
+
const firstParam = params[0][1];
|
|
138
|
+
const type = firstParam?.items?.type || firstParam?.type;
|
|
139
|
+
if (type === special$self) {
|
|
140
|
+
const bindingParamName = params[0][0];
|
|
141
|
+
const markBindingParam = {
|
|
142
|
+
ref: (parent, prop, xpr) => {
|
|
143
|
+
if ((xpr[0].id || xpr[0]) === bindingParamName)
|
|
144
|
+
parent.$bparam = true;
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
let exprAnnos = Object.keys(action).filter(pn => findAnnotationExpression(action, pn));
|
|
148
|
+
exprAnnos.forEach((pn) => {
|
|
149
|
+
transformExpression(action, pn, markBindingParam, loc);
|
|
150
|
+
});
|
|
151
|
+
forEachMemberRecursively(action, (member, _memberName, _prop, path, _parent) => {
|
|
152
|
+
exprAnnos = Object.keys(member).filter(pn => findAnnotationExpression(member, pn));
|
|
153
|
+
exprAnnos.forEach((pn) => {
|
|
154
|
+
transformExpression(member, pn, markBindingParam, path);
|
|
155
|
+
});
|
|
156
|
+
}, loc);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
127
160
|
}
|
|
128
161
|
|
|
129
162
|
function checkNestedContextsAndServices() {
|
|
@@ -127,7 +127,7 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
127
127
|
const mySchemaName = whatsMySchemaName(defName);
|
|
128
128
|
if (mySchemaName)
|
|
129
129
|
setProp(def, '$mySchemaName', mySchemaName);
|
|
130
|
-
if (isMyServiceRequested(defName) && def.kind !== 'aspect')
|
|
130
|
+
if (isMyServiceRequested(defName) && def.kind !== 'aspect' && def.kind !== 'event')
|
|
131
131
|
reqDefs.definitions[defName] = def;
|
|
132
132
|
},
|
|
133
133
|
linkAssociationTarget,
|
|
@@ -1641,7 +1641,10 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
1641
1641
|
if (art.type && !isBuiltinType(art.type))
|
|
1642
1642
|
art = art._type || csnUtils.getCsnDef(art.type);
|
|
1643
1643
|
}
|
|
1644
|
-
|
|
1644
|
+
if (art === eltCsn)
|
|
1645
|
+
error('odata-key-recursive', path, { name: prefix });
|
|
1646
|
+
else
|
|
1647
|
+
keyPaths.push(...produceKeyRefPaths(art, prefix + options.pathDelimiter + k.ref.join(options.pathDelimiter), path));
|
|
1645
1648
|
});
|
|
1646
1649
|
}
|
|
1647
1650
|
else {
|
|
@@ -2176,7 +2179,6 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
2176
2179
|
let isSubTreeSpan = true;
|
|
2177
2180
|
|
|
2178
2181
|
let rootPrefix = absPath.slice(1, absPath.length - 1);
|
|
2179
|
-
const isExprAnno = (obj, pn) => isBetaEnabled(options, 'odataPathsInAnnotationExpressions') && findAnnotationExpression(obj, pn);
|
|
2180
2182
|
|
|
2181
2183
|
const subTreeSpan = {
|
|
2182
2184
|
ref: (parent, _prop, xpr) => {
|
|
@@ -2228,7 +2230,7 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
2228
2230
|
if (absPath.length > 2) {
|
|
2229
2231
|
const [ xprANames, nxprANames ] = Object.keys(carrier).reduce((acc, pn) => {
|
|
2230
2232
|
if (pn[0] === '@')
|
|
2231
|
-
acc[
|
|
2233
|
+
acc[findAnnotationExpression(carrier, pn) ? 0 : 1].push(pn);
|
|
2232
2234
|
return acc;
|
|
2233
2235
|
}, [ [], [] ]);
|
|
2234
2236
|
|
|
@@ -2244,8 +2246,10 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
2244
2246
|
if (scope === 'actions' && def[scope][carrier.$path[3]]) {
|
|
2245
2247
|
def = def[scope][carrier.$path[3]];
|
|
2246
2248
|
scope = carrier.$path[4];
|
|
2247
|
-
if (scope === 'params')
|
|
2249
|
+
if (scope === 'params') {
|
|
2248
2250
|
rootPrefix = absPath.slice(2, absPath.length - 1);
|
|
2251
|
+
eltPath = absPath.slice(2).join('/');
|
|
2252
|
+
}
|
|
2249
2253
|
if (scope === 'returns') {
|
|
2250
2254
|
absPath[2] = '$ReturnType';
|
|
2251
2255
|
rootPrefix = absPath.slice(3, absPath.length - 1);
|
|
@@ -2263,7 +2267,6 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
2263
2267
|
else {
|
|
2264
2268
|
absolutize.scope = scope;
|
|
2265
2269
|
transformExpression(carrier, xprAName, absolutize);
|
|
2266
|
-
|
|
2267
2270
|
if (!def[proxyDict])
|
|
2268
2271
|
setProp(def, proxyDict, Object.create(null));
|
|
2269
2272
|
let proxyCarrier = def[proxyDict][eltPath];
|