@sap/cds-compiler 5.1.2 → 5.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 +58 -0
- package/bin/cdsc.js +7 -2
- package/bin/cdshi.js +24 -17
- package/bin/cdsse.js +17 -18
- package/doc/CHANGELOG_BETA.md +9 -4
- package/lib/api/main.js +19 -2
- package/lib/api/options.js +4 -1
- package/lib/api/validate.js +5 -0
- package/lib/base/builtins.js +1 -0
- package/lib/base/message-registry.js +40 -3
- package/lib/base/messages.js +1 -1
- package/lib/base/model.js +0 -11
- package/lib/checks/actionsFunctions.js +0 -12
- package/lib/checks/structuredAnnoExpressions.js +10 -14
- package/lib/compiler/assert-consistency.js +21 -13
- package/lib/compiler/builtins.js +2 -2
- package/lib/compiler/checks.js +25 -6
- package/lib/compiler/define.js +27 -31
- package/lib/compiler/extend.js +16 -18
- package/lib/compiler/generate.js +3 -3
- package/lib/compiler/populate.js +22 -16
- package/lib/compiler/propagator.js +3 -2
- package/lib/compiler/resolve.js +87 -94
- package/lib/compiler/shared.js +12 -13
- package/lib/compiler/tweak-assocs.js +390 -86
- package/lib/compiler/utils.js +41 -33
- package/lib/compiler/xpr-rewrite.js +45 -58
- package/lib/edm/annotations/genericTranslation.js +17 -13
- package/lib/edm/csn2edm.js +28 -4
- package/lib/edm/edm.js +68 -28
- package/lib/edm/edmInboundChecks.js +5 -8
- package/lib/edm/edmPreprocessor.js +66 -40
- package/lib/edm/edmUtils.js +1 -1
- package/lib/gen/BaseParser.js +778 -0
- package/lib/gen/CdlParser.js +4477 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +4072 -4024
- package/lib/inspect/inspectPropagation.js +1 -1
- package/lib/json/from-csn.js +5 -3
- package/lib/json/to-csn.js +7 -10
- package/lib/language/antlrParser.js +96 -0
- package/lib/language/errorStrategy.js +1 -1
- package/lib/language/genericAntlrParser.js +32 -4
- package/lib/language/multiLineStringParser.js +1 -1
- package/lib/main.d.ts +23 -0
- package/lib/model/cloneCsn.js +22 -13
- package/lib/model/csnUtils.js +2 -0
- package/lib/model/revealInternalProperties.js +2 -0
- package/lib/modelCompare/utils/filter.js +70 -42
- package/lib/optionProcessor.js +16 -10
- package/lib/parsers/AstBuildingParser.js +1290 -0
- package/lib/parsers/CdlGrammar.g4 +2013 -0
- package/lib/parsers/Lexer.js +249 -0
- package/lib/render/toCdl.js +46 -45
- package/lib/render/toSql.js +5 -5
- package/lib/transform/addTenantFields.js +4 -4
- package/lib/transform/db/applyTransformations.js +54 -16
- package/lib/transform/draft/odata.js +10 -11
- package/lib/transform/effective/flattening.js +10 -14
- package/lib/transform/forRelationalDB.js +7 -6
- package/lib/transform/odata/flattening.js +42 -31
- package/lib/transform/odata/toFinalBaseType.js +7 -6
- package/lib/transform/universalCsn/universalCsnEnricher.js +1 -0
- package/lib/utils/moduleResolve.js +1 -1
- package/package.json +2 -2
- package/share/messages/redirected-to-ambiguous.md +5 -4
- package/share/messages/redirected-to-complex.md +6 -3
package/lib/edm/edm.js
CHANGED
|
@@ -31,6 +31,7 @@ function getEdm( options, messageFunctions ) {
|
|
|
31
31
|
this._edmAttributes = Object.assign(Object.create(null), attributes);
|
|
32
32
|
this._xmlOnlyAttributes = Object.create(null);
|
|
33
33
|
this._jsonOnlyAttributes = Object.create(null);
|
|
34
|
+
this._openApiHints = Object.create(null);
|
|
34
35
|
|
|
35
36
|
this._children = [];
|
|
36
37
|
this._ignoreChildren = false;
|
|
@@ -38,6 +39,8 @@ function getEdm( options, messageFunctions ) {
|
|
|
38
39
|
|
|
39
40
|
if (this.v2)
|
|
40
41
|
this.setSapVocabularyAsAttributes(csn);
|
|
42
|
+
|
|
43
|
+
this.setOpenApiHints(csn);
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
get v2() {
|
|
@@ -103,6 +106,17 @@ function getEdm( options, messageFunctions ) {
|
|
|
103
106
|
return this;
|
|
104
107
|
}
|
|
105
108
|
|
|
109
|
+
setOpenApiHints(csn) {
|
|
110
|
+
if (csn && options.odataOpenapiHints) {
|
|
111
|
+
const jsonAttr = Object.create(null);
|
|
112
|
+
Object.entries(csn).filter(([ k, _v ] ) => k.startsWith('@OpenAPI.')).forEach(([ k, v ]) => {
|
|
113
|
+
jsonAttr[k] = v;
|
|
114
|
+
});
|
|
115
|
+
Object.assign(this._openApiHints, jsonAttr);
|
|
116
|
+
}
|
|
117
|
+
return this._openApiHints;
|
|
118
|
+
}
|
|
119
|
+
|
|
106
120
|
// virtual
|
|
107
121
|
toJSON() {
|
|
108
122
|
const json = Object.create(null);
|
|
@@ -110,17 +124,24 @@ function getEdm( options, messageFunctions ) {
|
|
|
110
124
|
if (!(this.kind in Node.noJsonKinds))
|
|
111
125
|
json.$Kind = this.kind;
|
|
112
126
|
|
|
113
|
-
this.toJSONattributes(json);
|
|
114
|
-
this.toJSONchildren(json);
|
|
115
|
-
return json;
|
|
127
|
+
return this.toJSONchildren(this.toJSONattributes(json));
|
|
116
128
|
}
|
|
117
129
|
|
|
118
130
|
// virtual
|
|
119
|
-
toJSONattributes(json) {
|
|
131
|
+
toJSONattributes(json, withHints = true) {
|
|
120
132
|
forEach(this._edmAttributes, (p, v) => {
|
|
121
133
|
if (p !== 'Name')
|
|
122
134
|
json[p[0] === '@' ? p : `$${p}`] = v;
|
|
123
135
|
});
|
|
136
|
+
return (withHints ? this.toOpenApiHints(json) : json);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
toOpenApiHints(json) {
|
|
140
|
+
if (options.odataOpenapiHints && this._openApiHints) {
|
|
141
|
+
Object.entries(this._openApiHints).forEach(([ p, v ]) => {
|
|
142
|
+
json[p[0] === '@' ? p : `$${p}`] = v;
|
|
143
|
+
});
|
|
144
|
+
}
|
|
124
145
|
return json;
|
|
125
146
|
}
|
|
126
147
|
|
|
@@ -131,6 +152,7 @@ function getEdm( options, messageFunctions ) {
|
|
|
131
152
|
this._children.filter(c => c._edmAttributes.Name).forEach((c) => {
|
|
132
153
|
json[c._edmAttributes.Name] = c.toJSON();
|
|
133
154
|
});
|
|
155
|
+
return json;
|
|
134
156
|
}
|
|
135
157
|
|
|
136
158
|
// virtual
|
|
@@ -243,6 +265,10 @@ function getEdm( options, messageFunctions ) {
|
|
|
243
265
|
super.setSapVocabularyAsAttributes(csn, true);
|
|
244
266
|
}
|
|
245
267
|
|
|
268
|
+
toJSONattributes(json) {
|
|
269
|
+
return super.toJSONattributes(json, false);
|
|
270
|
+
}
|
|
271
|
+
|
|
246
272
|
register(entry) {
|
|
247
273
|
if (!this._registry[entry._edmAttributes.Name])
|
|
248
274
|
this._registry[entry._edmAttributes.Name] = [ entry ];
|
|
@@ -258,6 +284,7 @@ function getEdm( options, messageFunctions ) {
|
|
|
258
284
|
if (alias !== undefined)
|
|
259
285
|
props.Alias = alias;
|
|
260
286
|
super(version, props);
|
|
287
|
+
this.setOpenApiHints(serviceCsn);
|
|
261
288
|
this._annotations = annotations;
|
|
262
289
|
this._actions = Object.create(null);
|
|
263
290
|
this.setXml( { xmlns: (this.v2) ? 'http://schemas.microsoft.com/ado/2008/09/edm' : 'http://docs.oasis-open.org/odata/ns/edm' } );
|
|
@@ -321,11 +348,17 @@ function getEdm( options, messageFunctions ) {
|
|
|
321
348
|
json[p[0] === '@' ? p : `$${p}`] = v;
|
|
322
349
|
});
|
|
323
350
|
}
|
|
351
|
+
return this.toOpenApiHints(json);
|
|
324
352
|
}
|
|
325
353
|
|
|
326
354
|
toJSONchildren(json) {
|
|
327
355
|
// 'edmx:DataServices' should not appear in JSON
|
|
328
|
-
|
|
356
|
+
// Annotations first
|
|
357
|
+
this._children.filter(c => c._edmAttributes.Term).forEach((c) => {
|
|
358
|
+
json = { ...json, ...c.toJSON() };
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
json = super.toJSONchildren(json);
|
|
329
362
|
if (this._annotations.length > 0) {
|
|
330
363
|
this._annotations.filter(a => a._edmAttributes.Term).forEach((a) => {
|
|
331
364
|
Object.entries(a.toJSON()).forEach(([ n, v ]) => {
|
|
@@ -445,8 +478,7 @@ function getEdm( options, messageFunctions ) {
|
|
|
445
478
|
json.$Reference = referenceJson;
|
|
446
479
|
|
|
447
480
|
this._service.toJSONattributes(json);
|
|
448
|
-
this._service.toJSONchildren(json);
|
|
449
|
-
return json;
|
|
481
|
+
return this._service.toJSONchildren(json);
|
|
450
482
|
}
|
|
451
483
|
|
|
452
484
|
// all(default), metadata, annotations
|
|
@@ -546,8 +578,8 @@ function getEdm( options, messageFunctions ) {
|
|
|
546
578
|
*/
|
|
547
579
|
|
|
548
580
|
class ActionFunctionBase extends Node {
|
|
549
|
-
constructor(version, details) {
|
|
550
|
-
super(version, details);
|
|
581
|
+
constructor(version, details, csn) {
|
|
582
|
+
super(version, details, csn);
|
|
551
583
|
this._returnType = undefined;
|
|
552
584
|
}
|
|
553
585
|
|
|
@@ -698,7 +730,7 @@ function getEdm( options, messageFunctions ) {
|
|
|
698
730
|
if (this.$isCollection)
|
|
699
731
|
json.$Collection = this.$isCollection;
|
|
700
732
|
|
|
701
|
-
return json;
|
|
733
|
+
return this.toOpenApiHints(json);
|
|
702
734
|
}
|
|
703
735
|
}
|
|
704
736
|
|
|
@@ -749,11 +781,11 @@ function getEdm( options, messageFunctions ) {
|
|
|
749
781
|
else
|
|
750
782
|
this._keys = undefined;
|
|
751
783
|
|
|
752
|
-
if (
|
|
784
|
+
if (this._openApiHints) {
|
|
753
785
|
if (csn['@cds.autoexpose'])
|
|
754
|
-
this.
|
|
786
|
+
this._openApiHints['@cds.autoexpose'] = true;
|
|
755
787
|
if (csn['@cds.autoexposed'])
|
|
756
|
-
this.
|
|
788
|
+
this._openApiHints['@cds.autoexposed'] = true;
|
|
757
789
|
}
|
|
758
790
|
}
|
|
759
791
|
|
|
@@ -802,7 +834,7 @@ function getEdm( options, messageFunctions ) {
|
|
|
802
834
|
class Member extends Node {
|
|
803
835
|
toJSONattributes(json) {
|
|
804
836
|
json[this._edmAttributes.Name] = this._edmAttributes.Value;
|
|
805
|
-
return json;
|
|
837
|
+
return super.toOpenApiHints(json);
|
|
806
838
|
}
|
|
807
839
|
}
|
|
808
840
|
|
|
@@ -819,11 +851,6 @@ function getEdm( options, messageFunctions ) {
|
|
|
819
851
|
}
|
|
820
852
|
}
|
|
821
853
|
|
|
822
|
-
toJSONattributes(json) {
|
|
823
|
-
super.toJSONattributes(json);
|
|
824
|
-
return json;
|
|
825
|
-
}
|
|
826
|
-
|
|
827
854
|
toJSONchildren(json) {
|
|
828
855
|
this._children.forEach(c => c.toJSONattributes(json));
|
|
829
856
|
return json;
|
|
@@ -1154,8 +1181,11 @@ function getEdm( options, messageFunctions ) {
|
|
|
1154
1181
|
toJSON() {
|
|
1155
1182
|
const json = Object.create(null);
|
|
1156
1183
|
this.toJSONattributes(json);
|
|
1157
|
-
this.toJSONchildren(json);
|
|
1158
|
-
|
|
1184
|
+
return this.toJSONchildren(json);
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
toJSONattributes(json) {
|
|
1188
|
+
return super.toJSONattributes(json, false);
|
|
1159
1189
|
}
|
|
1160
1190
|
|
|
1161
1191
|
getConstantExpressionValue() {
|
|
@@ -1226,6 +1256,7 @@ function getEdm( options, messageFunctions ) {
|
|
|
1226
1256
|
json[n] = v;
|
|
1227
1257
|
});
|
|
1228
1258
|
});
|
|
1259
|
+
return json;
|
|
1229
1260
|
}
|
|
1230
1261
|
}
|
|
1231
1262
|
|
|
@@ -1242,8 +1273,9 @@ function getEdm( options, messageFunctions ) {
|
|
|
1242
1273
|
// since it was discovered, that in JSON the EnumMember type must be
|
|
1243
1274
|
// transported this is no longer the case....
|
|
1244
1275
|
class Annotation extends AnnotationBase {
|
|
1245
|
-
constructor(version, termName) {
|
|
1276
|
+
constructor(version, termName, ...children) {
|
|
1246
1277
|
super(version, { Term: termName } );
|
|
1278
|
+
this.append(...children);
|
|
1247
1279
|
}
|
|
1248
1280
|
|
|
1249
1281
|
toJSON() {
|
|
@@ -1263,6 +1295,11 @@ function getEdm( options, messageFunctions ) {
|
|
|
1263
1295
|
}
|
|
1264
1296
|
|
|
1265
1297
|
class Collection extends AnnotationBase {
|
|
1298
|
+
constructor(version, ...children) {
|
|
1299
|
+
super(version);
|
|
1300
|
+
this.append(...children);
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1266
1303
|
toJSON() {
|
|
1267
1304
|
// EDM JSON doesn't mention annotations on collections
|
|
1268
1305
|
return this._children.map(a => a.toJSON());
|
|
@@ -1270,12 +1307,17 @@ function getEdm( options, messageFunctions ) {
|
|
|
1270
1307
|
}
|
|
1271
1308
|
|
|
1272
1309
|
class Record extends AnnotationBase {
|
|
1310
|
+
constructor(version, ...children) {
|
|
1311
|
+
super(version);
|
|
1312
|
+
this.append(...children);
|
|
1313
|
+
}
|
|
1273
1314
|
toJSONattributes(json) {
|
|
1274
1315
|
if (this._jsonOnlyAttributes.Type)
|
|
1275
1316
|
json['@type'] = this._jsonOnlyAttributes.Type;
|
|
1276
1317
|
const keys = Object.keys(this._edmAttributes).filter(k => k !== 'Type');
|
|
1277
1318
|
for (const key of keys)
|
|
1278
1319
|
json[`$${key}`] = this._edmAttributes[key];
|
|
1320
|
+
return json;
|
|
1279
1321
|
}
|
|
1280
1322
|
|
|
1281
1323
|
toJSONchildren(json) {
|
|
@@ -1300,6 +1342,7 @@ function getEdm( options, messageFunctions ) {
|
|
|
1300
1342
|
error(null, `Pease debug me: Unhandled Record child: ${c.kind}`);
|
|
1301
1343
|
}
|
|
1302
1344
|
});
|
|
1345
|
+
return json;
|
|
1303
1346
|
}
|
|
1304
1347
|
}
|
|
1305
1348
|
|
|
@@ -1382,8 +1425,7 @@ function getEdm( options, messageFunctions ) {
|
|
|
1382
1425
|
toJSON() {
|
|
1383
1426
|
const json = this.mergeJSONAnnotations();
|
|
1384
1427
|
json[`$${this.kind}`] = this._children.filter(c => c.kind !== 'Annotation').map(c => c.toJSON());
|
|
1385
|
-
this.toJSONattributes(json);
|
|
1386
|
-
return json;
|
|
1428
|
+
return this.toJSONattributes(json);
|
|
1387
1429
|
}
|
|
1388
1430
|
}
|
|
1389
1431
|
class Cast extends AnnotationBase {
|
|
@@ -1402,8 +1444,7 @@ function getEdm( options, messageFunctions ) {
|
|
|
1402
1444
|
// first expression only, if any
|
|
1403
1445
|
const children = this._children.filter(child => child.kind !== 'Annotation');
|
|
1404
1446
|
json[`$${this.kind}`] = children.length ? children[0].toJSON() : {};
|
|
1405
|
-
this.toJSONattributes(json);
|
|
1406
|
-
return json;
|
|
1447
|
+
return this.toJSONattributes(json);
|
|
1407
1448
|
}
|
|
1408
1449
|
toJSONattributes(json) {
|
|
1409
1450
|
super.toJSONattributes(json);
|
|
@@ -1430,8 +1471,7 @@ function getEdm( options, messageFunctions ) {
|
|
|
1430
1471
|
// first expression only, if any
|
|
1431
1472
|
const children = this._children.filter(child => child.kind !== 'Annotation');
|
|
1432
1473
|
json[`$${this.kind}`] = children.length ? children[0].toJSON() : '';
|
|
1433
|
-
this.toJSONattributes(json);
|
|
1434
|
-
return json;
|
|
1474
|
+
return this.toJSONattributes(json);
|
|
1435
1475
|
}
|
|
1436
1476
|
|
|
1437
1477
|
toJSONattributes(json) { // including Name
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const { setProp, isBetaEnabled } = require('../base/model');
|
|
4
4
|
const {
|
|
5
5
|
forEachDefinition, forEachMemberRecursively, getUtils,
|
|
6
|
-
|
|
6
|
+
transformAnnotationExpression,
|
|
7
7
|
} = require('../model/csnUtils');
|
|
8
8
|
const { isBuiltinType } = require('../base/builtins');
|
|
9
9
|
const { assignAnnotation } = require('./edmUtils.js');
|
|
@@ -59,7 +59,6 @@ function inboundQualificationChecks( csn, options, messageFunctions,
|
|
|
59
59
|
markBindingParamPaths(action, aLoc);
|
|
60
60
|
forEachMemberRecursively(action, checkIfItemsOfItems, aLoc);
|
|
61
61
|
checkIfItemsOfItems(action.returns, undefined, undefined, aLoc.concat('returns'));
|
|
62
|
-
markBindingParamPaths(action, aLoc);
|
|
63
62
|
});
|
|
64
63
|
}
|
|
65
64
|
|
|
@@ -144,14 +143,12 @@ function inboundQualificationChecks( csn, options, messageFunctions,
|
|
|
144
143
|
parent.$bparam = true;
|
|
145
144
|
},
|
|
146
145
|
};
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
transformExpression(action, pn, markBindingParam, loc);
|
|
146
|
+
Object.keys(action).filter(pn => pn[0] === '@').forEach((pn) => {
|
|
147
|
+
transformAnnotationExpression(action, pn, markBindingParam, loc);
|
|
150
148
|
});
|
|
151
149
|
forEachMemberRecursively(action, (member, _memberName, _prop, path, _parent) => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
transformExpression(member, pn, markBindingParam, path);
|
|
150
|
+
Object.keys(member).filter(pn => pn[0] === '@').forEach((pn) => {
|
|
151
|
+
transformAnnotationExpression(member, pn, markBindingParam, path);
|
|
155
152
|
});
|
|
156
153
|
}, loc);
|
|
157
154
|
}
|
|
@@ -5,7 +5,7 @@ const { setProp, isDeprecatedEnabled, isBetaEnabled } = require('../base/model')
|
|
|
5
5
|
const {
|
|
6
6
|
forEachDefinition, forEachGeneric, forEachMemberRecursively,
|
|
7
7
|
isEdmPropertyRendered, getUtils,
|
|
8
|
-
applyTransformations,
|
|
8
|
+
applyTransformations, transformAnnotationExpression, findAnnotationExpression,
|
|
9
9
|
cardinality2str,
|
|
10
10
|
} = require('../model/csnUtils');
|
|
11
11
|
const { isBuiltinType, isMagicVariable } = require('../base/builtins');
|
|
@@ -160,6 +160,7 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
160
160
|
forEachDefinition(reqDefs, [
|
|
161
161
|
exposeTargetsAsProxiesOrSchemaRefs,
|
|
162
162
|
determineEntitySet,
|
|
163
|
+
annotateOptionalActFuncParams,
|
|
163
164
|
]);
|
|
164
165
|
// finalize proxy creation
|
|
165
166
|
mergeProxiesIntoModel();
|
|
@@ -170,7 +171,6 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
170
171
|
forEachDefinition(reqDefs, [
|
|
171
172
|
initEdmNavPropBindingTargets,
|
|
172
173
|
pullupCapabilitiesAnnotations,
|
|
173
|
-
annotateOptionalActFuncParams,
|
|
174
174
|
]);
|
|
175
175
|
}
|
|
176
176
|
|
|
@@ -685,8 +685,8 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
685
685
|
return;
|
|
686
686
|
|
|
687
687
|
let keys = Object.create(null);
|
|
688
|
-
const validFrom = [];
|
|
689
|
-
|
|
688
|
+
const validFrom = [];
|
|
689
|
+
const validKey = [];
|
|
690
690
|
|
|
691
691
|
// Iterate all struct elements
|
|
692
692
|
forEachMemberRecursively(def.items || def, (element, elementName, prop, _path, construct) => {
|
|
@@ -796,7 +796,7 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
796
796
|
Do not render (ignore) elements as properties
|
|
797
797
|
In V4:
|
|
798
798
|
1) If this is a foreign key of an association to a container which *is* used
|
|
799
|
-
to establish the
|
|
799
|
+
to establish the relation via composition and $self comparison.
|
|
800
800
|
The $self comparison can only be evaluated after the ON conditions have been
|
|
801
801
|
parsed in prepareConstraints().
|
|
802
802
|
2) For all other foreign keys let isEdmPropertyRendered() decide.
|
|
@@ -1890,12 +1890,12 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
1890
1890
|
mapCdsToEdmProp(def.returns);
|
|
1891
1891
|
annotateAllowedValues(def.returns, [ ...defLocation, 'returns' ]);
|
|
1892
1892
|
}
|
|
1893
|
-
forEachMemberRecursively(def, (member, _memberName,
|
|
1893
|
+
forEachMemberRecursively(def, (member, _memberName, prop, location) => {
|
|
1894
1894
|
edmUtils.assignAnnotation(member, '@Core.Description', member.doc);
|
|
1895
1895
|
markCollection(member);
|
|
1896
1896
|
mapCdsToEdmProp(member);
|
|
1897
1897
|
annotateAllowedValues(member, location);
|
|
1898
|
-
ComputedDefaultValue(member);
|
|
1898
|
+
ComputedDefaultValue(member, prop, location);
|
|
1899
1899
|
rewriteAnnotationExpressions(member);
|
|
1900
1900
|
if (member.returns) {
|
|
1901
1901
|
edmUtils.assignAnnotation(member.returns, '@Core.Description', member.returns.doc);
|
|
@@ -2082,8 +2082,6 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
2082
2082
|
parameters appear rightmost.
|
|
2083
2083
|
*/
|
|
2084
2084
|
function annotateOptionalActFuncParams( def, defName ) {
|
|
2085
|
-
if (!isBetaEnabled(options, 'optionalActionFunctionParameters'))
|
|
2086
|
-
return;
|
|
2087
2085
|
// return if there is nothing to do
|
|
2088
2086
|
const loc = [ 'definitions', defName ];
|
|
2089
2087
|
if (def.kind === 'function' || def.kind === 'action')
|
|
@@ -2097,33 +2095,57 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
2097
2095
|
|
|
2098
2096
|
function iterateParams( action, location ) {
|
|
2099
2097
|
let optPns = [];
|
|
2098
|
+
const isBP = p => (p.items?.type || p.type) === special$self;
|
|
2099
|
+
|
|
2100
2100
|
if (action.params) {
|
|
2101
|
-
Object.
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2101
|
+
Object.entries(action.params).forEach(([ pn, p ]) => {
|
|
2102
|
+
// user assigned annotation, don't touch it
|
|
2103
|
+
const defT = reqDefs.definitions[p.items?.type || p.type];
|
|
2104
|
+
const isStructType = !!(defT?.items?.elements || defT?.elements);
|
|
2105
|
+
const isItems = !!(p.items || defT?.items);
|
|
2106
|
+
|
|
2107
|
+
if (Object.keys(p).some(a => a.startsWith('@Core.OptionalParameter') && p[a] != null)) {
|
|
2108
|
+
// expand short cut annotation for unspecified default value
|
|
2109
|
+
if (typeof p['@Core.OptionalParameter'] === 'boolean') {
|
|
2110
|
+
if (p['@Core.OptionalParameter'] && !isBP(p) && !options.isV2()) {
|
|
2111
|
+
if (p.default?.val !== undefined) {
|
|
2112
|
+
if (p.default.val !== null && (isStructType || isItems))
|
|
2113
|
+
warning('odata-ignoring-param-default', location.concat(pn), { '#': 'colitem' });
|
|
2114
|
+
else
|
|
2115
|
+
p['@Core.OptionalParameter'] = { DefaultValue: p.default.val };
|
|
2116
|
+
}
|
|
2117
|
+
else {
|
|
2118
|
+
p['@Core.OptionalParameter'] = { $Type: '' };
|
|
2119
|
+
}
|
|
2120
|
+
optPns.push(p);
|
|
2121
|
+
}
|
|
2122
|
+
else { // reset falsy annotation, param is NOT optional
|
|
2123
|
+
p['@Core.OptionalParameter'] = null;
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
else {
|
|
2127
|
+
optPns.push(p);
|
|
2128
|
+
}
|
|
2118
2129
|
}
|
|
2119
|
-
else {
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2130
|
+
else if (!isBP(p) && !options.isV2()) {
|
|
2131
|
+
// default value automatically makes param optional
|
|
2132
|
+
if (p.default?.val !== undefined) {
|
|
2133
|
+
if (p.default.val !== null && (isStructType || isItems))
|
|
2134
|
+
warning('odata-ignoring-param-default', location.concat(pn), { '#': 'colitem' });
|
|
2135
|
+
else
|
|
2136
|
+
edmUtils.assignAnnotation(p, '@Core.OptionalParameter.DefaultValue', p.default.val);
|
|
2137
|
+
optPns.push(p);
|
|
2138
|
+
}
|
|
2139
|
+
// nullable action params are optional (implicit default null)
|
|
2140
|
+
else if (!p.notNull && action.kind === 'action') {
|
|
2141
|
+
optPns.push(p);
|
|
2142
|
+
}
|
|
2143
|
+
else if (action.kind === 'function') {
|
|
2144
|
+
// this is a mandatory parameter, warn about all previously collected optional parameters
|
|
2145
|
+
if (optPns.filter(op => (op.items?.type || op.type) !== special$self).length)
|
|
2146
|
+
error('odata-parameter-order', location.concat(pn));
|
|
2147
|
+
optPns = [];
|
|
2148
|
+
}
|
|
2127
2149
|
}
|
|
2128
2150
|
});
|
|
2129
2151
|
}
|
|
@@ -2152,7 +2174,7 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
2152
2174
|
}
|
|
2153
2175
|
}
|
|
2154
2176
|
|
|
2155
|
-
function ComputedDefaultValue( member ) {
|
|
2177
|
+
function ComputedDefaultValue( member, prop, location ) {
|
|
2156
2178
|
if (member.default && !csn['@Core.ComputedDefaultValue']) {
|
|
2157
2179
|
let def = member.default;
|
|
2158
2180
|
let noTailExpr = false;
|
|
@@ -2166,8 +2188,12 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
2166
2188
|
def = def.xpr[i];
|
|
2167
2189
|
}
|
|
2168
2190
|
// it is a computed value if it is not a simple value or an annotation
|
|
2169
|
-
if (!((def.val !== undefined && !noTailExpr) || def['#']))
|
|
2170
|
-
|
|
2191
|
+
if (!((def.val !== undefined && !noTailExpr) || def['#'])) {
|
|
2192
|
+
if (prop === 'params')
|
|
2193
|
+
warning('odata-ignoring-param-default', location, { '#': 'xpr' });
|
|
2194
|
+
else
|
|
2195
|
+
edmUtils.assignAnnotation(member, '@Core.ComputedDefaultValue', true);
|
|
2196
|
+
}
|
|
2171
2197
|
}
|
|
2172
2198
|
}
|
|
2173
2199
|
|
|
@@ -2258,13 +2284,13 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
2258
2284
|
|
|
2259
2285
|
xprANames.forEach((xprAName) => {
|
|
2260
2286
|
isSubTreeSpan = true;
|
|
2261
|
-
|
|
2287
|
+
transformAnnotationExpression(carrier, xprAName, subTreeSpan);
|
|
2262
2288
|
if (isSubTreeSpan) {
|
|
2263
|
-
|
|
2289
|
+
transformAnnotationExpression(carrier, xprAName, relativize);
|
|
2264
2290
|
}
|
|
2265
2291
|
else {
|
|
2266
2292
|
absolutize.scope = scope;
|
|
2267
|
-
|
|
2293
|
+
transformAnnotationExpression(carrier, xprAName, absolutize);
|
|
2268
2294
|
if (!def[proxyDict])
|
|
2269
2295
|
setProp(def, proxyDict, Object.create(null));
|
|
2270
2296
|
let proxyCarrier = def[proxyDict][eltPath];
|
package/lib/edm/edmUtils.js
CHANGED
|
@@ -386,7 +386,7 @@ function finalizeReferentialConstraints( csn, assocCsn, options, info ) {
|
|
|
386
386
|
// If this association points to a redirected Parameter EntityType, do not calculate any constraints,
|
|
387
387
|
// continue with multiplicity
|
|
388
388
|
if (assocCsn._target.$isParamEntity)
|
|
389
|
-
assocCsn._constraints.constraints =
|
|
389
|
+
assocCsn._constraints.constraints = {};
|
|
390
390
|
|
|
391
391
|
return assocCsn._constraints;
|
|
392
392
|
|