@sap/cds-compiler 3.4.2 → 3.5.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 +80 -0
- package/README.md +1 -0
- package/bin/cds_update_identifiers.js +5 -5
- package/bin/cdsc.js +15 -16
- package/bin/cdshi.js +19 -6
- package/doc/CHANGELOG_ARCHIVE.md +2 -2
- package/doc/CHANGELOG_BETA.md +9 -1
- package/doc/CHANGELOG_DEPRECATED.md +2 -0
- package/lib/api/main.js +61 -59
- package/lib/api/options.js +4 -2
- package/lib/api/validate.js +2 -2
- package/lib/base/cleanSymbols.js +2 -3
- package/lib/base/dictionaries.js +6 -6
- package/lib/base/error.js +2 -2
- package/lib/base/keywords.js +6 -6
- package/lib/base/location.js +11 -12
- package/lib/base/message-registry.js +177 -58
- package/lib/base/messages.js +252 -180
- package/lib/base/model.js +14 -11
- package/lib/base/node-helpers.js +9 -10
- package/lib/base/optionProcessorHelper.js +138 -129
- package/lib/checks/.eslintrc.json +2 -0
- package/lib/checks/actionsFunctions.js +5 -5
- package/lib/checks/annotationsOData.js +4 -4
- package/lib/checks/arrayOfs.js +1 -1
- package/lib/checks/cdsPersistence.js +1 -1
- package/lib/checks/checkForTypes.js +3 -3
- package/lib/checks/defaultValues.js +3 -3
- package/lib/checks/elements.js +7 -7
- package/lib/checks/emptyOrOnlyVirtual.js +2 -2
- package/lib/checks/foreignKeys.js +1 -1
- package/lib/checks/invalidTarget.js +4 -4
- package/lib/checks/managedInType.js +1 -1
- package/lib/checks/managedWithoutKeys.js +1 -1
- package/lib/checks/nonexpandableStructured.js +5 -3
- package/lib/checks/nullableKeys.js +1 -1
- package/lib/checks/onConditions.js +5 -6
- package/lib/checks/parameters.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +2 -2
- package/lib/checks/selectItems.js +4 -4
- package/lib/checks/sql-snippets.js +4 -4
- package/lib/checks/types.js +7 -7
- package/lib/checks/utils.js +4 -4
- package/lib/checks/validator.js +16 -13
- package/lib/compiler/.eslintrc.json +4 -1
- package/lib/compiler/assert-consistency.js +8 -7
- package/lib/compiler/builtins.js +14 -14
- package/lib/compiler/checks.js +123 -48
- package/lib/compiler/define.js +12 -13
- package/lib/compiler/extend.js +266 -60
- package/lib/compiler/finalize-parse-cdl.js +10 -5
- package/lib/compiler/index.js +17 -14
- package/lib/compiler/populate.js +14 -6
- package/lib/compiler/propagator.js +2 -0
- package/lib/compiler/resolve.js +2 -15
- package/lib/compiler/shared.js +27 -16
- package/lib/compiler/tweak-assocs.js +5 -6
- package/lib/compiler/utils.js +20 -0
- package/lib/edm/annotations/genericTranslation.js +604 -358
- package/lib/edm/annotations/preprocessAnnotations.js +39 -35
- package/lib/edm/csn2edm.js +275 -222
- package/lib/edm/edm.js +17 -3
- package/lib/edm/edmAnnoPreprocessor.js +6 -6
- package/lib/edm/edmInboundChecks.js +2 -2
- package/lib/edm/edmPreprocessor.js +107 -77
- package/lib/edm/edmUtils.js +44 -5
- package/lib/gen/Dictionary.json +210 -8
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +67 -63
- package/lib/gen/language.tokens +81 -81
- package/lib/gen/languageLexer.interp +4 -10
- package/lib/gen/languageLexer.js +854 -869
- package/lib/gen/languageLexer.tokens +79 -81
- package/lib/gen/languageParser.js +14309 -13832
- package/lib/inspect/inspectModelStatistics.js +2 -2
- package/lib/inspect/inspectPropagation.js +6 -6
- package/lib/inspect/inspectUtils.js +2 -2
- package/lib/json/from-csn.js +102 -55
- package/lib/json/to-csn.js +119 -198
- package/lib/language/antlrParser.js +5 -2
- package/lib/language/docCommentParser.js +6 -6
- package/lib/language/errorStrategy.js +43 -23
- package/lib/language/genericAntlrParser.js +113 -133
- package/lib/language/language.g4 +1550 -1506
- package/lib/language/multiLineStringParser.js +3 -3
- package/lib/language/textUtils.js +2 -2
- package/lib/main.js +3 -3
- package/lib/model/csnRefs.js +5 -0
- package/lib/model/csnUtils.js +130 -122
- package/lib/model/revealInternalProperties.js +1 -1
- package/lib/model/sortViews.js +4 -6
- package/lib/modelCompare/compare.js +2 -2
- package/lib/modelCompare/utils/.eslintrc.json +22 -0
- package/lib/modelCompare/utils/filter.js +100 -0
- package/lib/optionProcessor.js +5 -0
- package/lib/render/.eslintrc.json +1 -0
- package/lib/render/DuplicateChecker.js +1 -1
- package/lib/render/manageConstraints.js +12 -12
- package/lib/render/toCdl.js +311 -276
- package/lib/render/toHdbcds.js +97 -94
- package/lib/render/toRename.js +5 -5
- package/lib/render/toSql.js +127 -223
- package/lib/render/utils/common.js +141 -108
- package/lib/render/utils/delta.js +227 -0
- package/lib/render/utils/sql.js +22 -6
- package/lib/render/utils/stringEscapes.js +3 -3
- package/lib/transform/db/.eslintrc.json +2 -0
- package/lib/transform/db/applyTransformations.js +3 -3
- package/lib/transform/db/assertUnique.js +13 -12
- package/lib/transform/db/associations.js +5 -5
- package/lib/transform/db/cdsPersistence.js +10 -8
- package/lib/transform/db/constraints.js +14 -14
- package/lib/transform/db/expansion.js +20 -22
- package/lib/transform/db/flattening.js +24 -42
- package/lib/transform/db/groupByOrderBy.js +3 -3
- package/lib/transform/db/temporal.js +6 -6
- package/lib/transform/db/transformExists.js +23 -23
- package/lib/transform/db/views.js +16 -16
- package/lib/transform/draft/.eslintrc.json +1 -35
- package/lib/transform/draft/db.js +10 -10
- package/lib/transform/draft/odata.js +2 -2
- package/lib/transform/forOdataNew.js +8 -29
- package/lib/transform/forRelationalDB.js +16 -6
- package/lib/transform/localized.js +11 -10
- package/lib/transform/odata/toFinalBaseType.js +41 -27
- package/lib/transform/odata/typesExposure.js +113 -47
- package/lib/transform/parseExpr.js +209 -106
- package/lib/transform/transformUtilsNew.js +17 -10
- package/lib/transform/translateAssocsToJoins.js +24 -19
- package/lib/transform/universalCsn/coreComputed.js +10 -10
- package/lib/transform/universalCsn/universalCsnEnricher.js +26 -26
- package/lib/transform/universalCsn/utils.js +3 -3
- package/lib/utils/file.js +5 -5
- package/lib/utils/moduleResolve.js +13 -13
- package/lib/utils/objectUtils.js +6 -6
- package/lib/utils/term.js +5 -2
- package/lib/utils/timetrace.js +51 -24
- package/package.json +5 -8
- package/share/messages/check-proper-type-of.md +1 -1
- package/share/messages/message-explanations.json +1 -1
- package/share/messages/redirected-to-complex.md +4 -4
- package/share/messages/{syntax-expecting-integer.md → syntax-expecting-unsigned-int.md} +7 -4
- package/lib/modelCompare/filter.js +0 -83
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
const { setProp } = require('../../base/model');
|
|
10
10
|
const { defNameWithoutServiceOrContextName, isArtifactInService } = require('./utils');
|
|
11
|
-
const { cloneCsnNonDict, isBuiltinType, forEachDefinition, forEachMember } = require('../../model/csnUtils');
|
|
11
|
+
const { cloneCsnNonDict, isBuiltinType, forEachDefinition, forEachMember, forEachGeneric } = require('../../model/csnUtils');
|
|
12
12
|
const { copyAnnotations } = require('../../model/csnUtils');
|
|
13
13
|
const { isBetaEnabled } = require('../../base/model.js');
|
|
14
14
|
|
|
@@ -49,6 +49,31 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
+
if(isBetaEnabled(options, 'odataTerms')) {
|
|
53
|
+
forEachGeneric(csn, 'vocabularies', (def, defName, _propertyName, path) => {
|
|
54
|
+
// we do expose types only for definition from inside services
|
|
55
|
+
const serviceName = whatsMyServiceName(defName, false);
|
|
56
|
+
// run type exposure only on requested services if not in multi schema mode
|
|
57
|
+
// multi schema mode requires a proper type exposure for all services as a prerequisite
|
|
58
|
+
// for the proxy exposure
|
|
59
|
+
if (serviceName && requestedServiceNames.includes(serviceName)) {
|
|
60
|
+
if(csn.definitions[defName]) {
|
|
61
|
+
// error, duplicate definitions not allowed!
|
|
62
|
+
// TODO: Use path as error location as soon as refs outside definitions are supported
|
|
63
|
+
error('odata-definition-exists', ['vocabularies', defName], { anno: defName, '#':'anno' });
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// link def into definitions for later use
|
|
67
|
+
def.kind = 'annotation';
|
|
68
|
+
csn.definitions[defName] = def;
|
|
69
|
+
const artificialName = `term_${defName.replace(/\./g, '_')}`;//_${paramName}`;
|
|
70
|
+
const newTypeName = getNewTypeName(undefined, undefined, artificialName, serviceName);
|
|
71
|
+
exposeTypeOf(def, false, defName, defName, serviceName, newTypeName, path.concat(['vocabularies', defName]), undefined, true);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
52
77
|
return schemas;
|
|
53
78
|
|
|
54
79
|
/**
|
|
@@ -82,14 +107,14 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
82
107
|
* @param {String} serviceName
|
|
83
108
|
* @param {String} newTypeName
|
|
84
109
|
*/
|
|
85
|
-
function exposeTypeOf(node, isKey, memberName, defName, serviceName, newTypeName, path, parentName) {
|
|
86
|
-
const { isExposable, typeDef, typeName, elements, isAnonymous } = isTypeExposable(
|
|
110
|
+
function exposeTypeOf(node, isKey, memberName, defName, serviceName, newTypeName, path, parentName, isTermDef=false) {
|
|
111
|
+
const { isExposable, typeDef, typeName, elements, isAnonymous } = isTypeExposable();
|
|
87
112
|
if (isExposable) {
|
|
88
113
|
// this is the name used to register the new type in csn.definitions
|
|
89
114
|
let fullQualifiedNewTypeName =
|
|
90
115
|
isMultiSchema
|
|
91
|
-
? (node.type || (node.items
|
|
92
|
-
? getTypeNameInMultiSchema(node.type|| (node.items
|
|
116
|
+
? (node.type || (node.items?.type)
|
|
117
|
+
? getTypeNameInMultiSchema(node.type|| (node.items?.type), serviceName)
|
|
93
118
|
: getAnonymousTypeNameInMultiSchema(newTypeName, parentName || defName))
|
|
94
119
|
: `${serviceName}.${newTypeName}`;
|
|
95
120
|
|
|
@@ -100,7 +125,7 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
100
125
|
isKey = false;
|
|
101
126
|
// in case this was a named type and if the openess does not match the type definition
|
|
102
127
|
// expose the type as a new one not changing the original definition.
|
|
103
|
-
if((!!node['@open'] !== !!typeDef['@open']) && isBetaEnabled(options, 'odataOpenType'))
|
|
128
|
+
if(elements && (!!node['@open'] !== !!typeDef['@open']) && isBetaEnabled(options, 'odataOpenType'))
|
|
104
129
|
fullQualifiedNewTypeName += node['@open'] ? '_open' : '_closed';
|
|
105
130
|
}
|
|
106
131
|
// check if that type is already defined
|
|
@@ -108,41 +133,73 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
108
133
|
if (newType) {
|
|
109
134
|
// error, if it was not exposed by us
|
|
110
135
|
if (!exposedTypes[fullQualifiedNewTypeName]) {
|
|
136
|
+
setProp(node, '$NameClashReported', true);
|
|
111
137
|
error(null, path, { type: fullQualifiedNewTypeName, name: memberName },
|
|
112
138
|
'Can\'t create artificial type $(TYPE) for $(NAME) because the name is already used');
|
|
113
|
-
return;
|
|
139
|
+
return { isExposable, typeDef, typeName, isAnonymous };
|
|
114
140
|
}
|
|
115
141
|
}
|
|
116
142
|
else {
|
|
117
143
|
/* Expose new structured type
|
|
118
144
|
* Treat items.elements as ordinary elements for now.
|
|
119
145
|
*/
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
146
|
+
if(elements) {
|
|
147
|
+
newType = createNewStructType(elements);
|
|
148
|
+
// if using node enforces open/closed, set it on type
|
|
149
|
+
if(node['@open'] !== undefined)
|
|
150
|
+
newType['@open'] = node['@open']
|
|
151
|
+
if (node.$location)
|
|
152
|
+
setProp(newType, '$location', node.$location);
|
|
126
153
|
|
|
127
|
-
|
|
128
|
-
|
|
154
|
+
csn.definitions[fullQualifiedNewTypeName] = newType;
|
|
155
|
+
exposedTypes[fullQualifiedNewTypeName] = 1;
|
|
129
156
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
157
|
+
// Recurse into elements of 'type' (if any) and expose them as well (is needed)
|
|
158
|
+
newType.elements && Object.entries(newType.elements).forEach(([elemName, newElem]) => {
|
|
159
|
+
if (node.elements && node.elements[elemName].$location)
|
|
160
|
+
setProp(newElem, '$location', node.elements[elemName].$location);
|
|
161
|
+
defName = typeDef.kind === 'type' ? typeName : defName;
|
|
162
|
+
{
|
|
163
|
+
const { isExposable, typeDef, typeName } = exposeTypeOf(newElem, isKey, elemName, defName, serviceName,
|
|
164
|
+
getNewTypeName(newElem, elemName, newTypeName, serviceName), path, fullQualifiedNewTypeName, isTermDef);
|
|
165
|
+
// if the type for the newElem was not exposed it may be a scalar type def from an external service that hasn't
|
|
166
|
+
// been catched by expandToFinalBaseType() (forODataNew must not modify external imported services)
|
|
167
|
+
if(!isExposable && isBuiltinType(typeName) && !isBuiltinType((newElem.items?.type || newElem.type))) {
|
|
168
|
+
if(typeDef.items) {
|
|
169
|
+
newElem.items = typeDef.items;
|
|
170
|
+
delete newElem.type;
|
|
171
|
+
}
|
|
172
|
+
else if(newElem.items) {
|
|
173
|
+
newElem.items.type = typeName;
|
|
174
|
+
if(typeDef.enum)
|
|
175
|
+
newElem.items.enum = typeDef.enum;
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
newElem.type = typeName;
|
|
179
|
+
if(typeDef.enum)
|
|
180
|
+
newElem.enum = typeDef.enum;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
copyAnnotations(typeDef, newType);
|
|
186
|
+
// if the origin type had items, add items to exposed type
|
|
187
|
+
if(typeDef.kind === 'type') {
|
|
188
|
+
if(typeDef.items) {
|
|
189
|
+
newType.items = { elements: newType.elements };
|
|
190
|
+
delete newType.elements;
|
|
191
|
+
}
|
|
144
192
|
}
|
|
145
193
|
}
|
|
194
|
+
else if(isTermDef) {
|
|
195
|
+
newType = Object.create(null);
|
|
196
|
+
for(let n in typeDef) {
|
|
197
|
+
newType[n] = typeDef[n];
|
|
198
|
+
}
|
|
199
|
+
newType.kind = 'type';
|
|
200
|
+
csn.definitions[fullQualifiedNewTypeName] = newType;
|
|
201
|
+
exposedTypes[fullQualifiedNewTypeName] = 1;
|
|
202
|
+
}
|
|
146
203
|
}
|
|
147
204
|
// adjust current node to new type
|
|
148
205
|
if(node.items) {
|
|
@@ -155,6 +212,7 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
155
212
|
node.type = fullQualifiedNewTypeName;
|
|
156
213
|
}
|
|
157
214
|
}
|
|
215
|
+
return { isExposable, typeDef, typeName, isAnonymous };
|
|
158
216
|
|
|
159
217
|
/**
|
|
160
218
|
* Check if the node's type can be exposed:
|
|
@@ -166,38 +224,46 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
166
224
|
* - the elements dictionary that needs to be cloned
|
|
167
225
|
* - the typeDef, either the resolved type def or the node itself
|
|
168
226
|
* - if structured type was anonymously defined
|
|
169
|
-
* @param {object} node
|
|
170
227
|
* @returns {object} { isExposable, typeDef, typeName, elements, isAnonymous }
|
|
171
228
|
*/
|
|
172
|
-
function isTypeExposable(
|
|
229
|
+
function isTypeExposable() {
|
|
173
230
|
let typeName = undefined;
|
|
174
231
|
let typeDef = node;
|
|
175
|
-
let elements = (node.items
|
|
232
|
+
let elements = (node.items?.elements || node.elements)
|
|
176
233
|
// anonymous structured type
|
|
177
234
|
if(elements)
|
|
178
235
|
return { isExposable: true, typeDef, typeName, elements, isAnonymous: true };
|
|
179
236
|
// named type, resolve the type to inspect it
|
|
180
|
-
let type = node.items
|
|
237
|
+
let type = node.items?.type || node.type;
|
|
181
238
|
if(type) {
|
|
182
239
|
typeName = (type.ref && csnUtils.getFinalType(type)) || type;
|
|
183
|
-
typeDef = csnUtils.getFinalTypeDef(typeName);
|
|
184
240
|
const rc = { isExposable: true, typeDef, typeName, isAnonymous: false };
|
|
185
|
-
if(!isBuiltinType(typeName)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
241
|
+
if(!isBuiltinType(typeName)) {
|
|
242
|
+
rc.typeDef = typeDef = csnUtils.getFinalTypeDef(typeName);
|
|
243
|
+
if(!isArtifactInService(typeName, serviceName)) {
|
|
244
|
+
while(!isBuiltinType(typeName)) {
|
|
245
|
+
typeDef = csnUtils.getFinalTypeDef(typeName);
|
|
246
|
+
if(typeDef) {
|
|
247
|
+
if((isTermDef && typeDef.enum) || (rc.elements = (typeDef.items?.elements || typeDef.elements)) !== undefined)
|
|
248
|
+
return rc;
|
|
249
|
+
type = typeDef.items?.type || typeDef.type;
|
|
250
|
+
typeName = (type.ref && csnUtils.getFinalType(type)) || type;
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
throw Error(`Please debug me: ${typeName} not found`);
|
|
254
|
+
}
|
|
196
255
|
}
|
|
197
256
|
}
|
|
257
|
+
else {
|
|
258
|
+
rc.isExposable = false;
|
|
259
|
+
return rc;
|
|
260
|
+
}
|
|
198
261
|
}
|
|
262
|
+
// else if(isTermDef && typeDef.enum) {
|
|
263
|
+
// return rc;
|
|
264
|
+
// }
|
|
199
265
|
}
|
|
200
|
-
return { isExposable: false };
|
|
266
|
+
return { isExposable: false, typeDef, typeName, isAnonymous: false };
|
|
201
267
|
}
|
|
202
268
|
|
|
203
269
|
|
|
@@ -286,7 +352,7 @@ function typesExposure(csn, whatsMyServiceName, requestedServiceNames, fallBackS
|
|
|
286
352
|
*/
|
|
287
353
|
function getNewTypeName(element, elementName, typeNamePrefix, serviceName) {
|
|
288
354
|
// for the new type name node.type has precedence over node.items.type
|
|
289
|
-
const typeName = (!element
|
|
355
|
+
const typeName = (!element?.elements && element?.type || !element?.items?.elements && element?.items?.type);
|
|
290
356
|
return typeName
|
|
291
357
|
? `${isMultiSchema
|
|
292
358
|
? typeName.split('.').pop() // use leaf element
|