@sap/cds-compiler 4.4.4 → 4.6.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 +88 -0
- package/bin/cdsc.js +18 -11
- package/bin/cdsv2m.js +7 -5
- package/doc/CHANGELOG_BETA.md +22 -0
- package/lib/api/main.js +306 -144
- package/lib/api/options.js +18 -6
- package/lib/api/validate.js +1 -1
- package/lib/base/message-registry.js +45 -10
- package/lib/base/messages.js +33 -16
- package/lib/base/model.js +4 -0
- package/lib/base/optionProcessorHelper.js +45 -176
- package/lib/checks/annotationsOData.js +49 -0
- package/lib/checks/elements.js +32 -34
- package/lib/checks/enricher.js +39 -3
- package/lib/checks/validator.js +8 -7
- package/lib/compiler/assert-consistency.js +40 -17
- package/lib/compiler/builtins.js +30 -53
- package/lib/compiler/checks.js +46 -14
- package/lib/compiler/cycle-detector.js +1 -4
- package/lib/compiler/define.js +35 -10
- package/lib/compiler/extend.js +21 -7
- package/lib/compiler/generate.js +3 -0
- package/lib/compiler/populate.js +5 -1
- package/lib/compiler/propagator.js +46 -9
- package/lib/compiler/resolve.js +94 -35
- package/lib/compiler/shared.js +60 -33
- package/lib/compiler/tweak-assocs.js +188 -92
- package/lib/compiler/utils.js +11 -1
- package/lib/edm/annotations/edmJson.js +41 -66
- package/lib/edm/annotations/genericTranslation.js +27 -9
- package/lib/edm/annotations/preprocessAnnotations.js +2 -3
- package/lib/edm/csn2edm.js +28 -11
- package/lib/edm/edmInboundChecks.js +58 -15
- package/lib/edm/edmPreprocessor.js +12 -16
- package/lib/edm/edmUtils.js +5 -2
- package/lib/gen/Dictionary.json +10 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +15 -2
- package/lib/gen/language.tokens +1 -0
- package/lib/gen/languageParser.js +6557 -5618
- package/lib/json/from-csn.js +4 -5
- package/lib/json/to-csn.js +29 -4
- package/lib/language/antlrParser.js +19 -1
- package/lib/language/errorStrategy.js +28 -7
- package/lib/language/genericAntlrParser.js +118 -24
- package/lib/language/textUtils.js +16 -0
- package/lib/main.d.ts +28 -3
- package/lib/main.js +3 -0
- package/lib/model/csnRefs.js +4 -1
- package/lib/model/csnUtils.js +20 -14
- package/lib/model/revealInternalProperties.js +5 -2
- package/lib/optionProcessor.js +23 -22
- package/lib/render/manageConstraints.js +13 -29
- package/lib/render/toCdl.js +47 -26
- package/lib/render/toHdbcds.js +63 -42
- package/lib/render/toRename.js +6 -10
- package/lib/render/toSql.js +71 -117
- package/lib/render/utils/common.js +41 -6
- package/lib/transform/.eslintrc.json +9 -1
- package/lib/transform/addTenantFields.js +228 -0
- package/lib/transform/db/applyTransformations.js +57 -4
- package/lib/transform/db/assertUnique.js +4 -4
- package/lib/transform/db/backlinks.js +13 -1
- package/lib/transform/db/cdsPersistence.js +1 -1
- package/lib/transform/db/expansion.js +24 -3
- package/lib/transform/db/flattening.js +70 -71
- package/lib/transform/db/killAnnotations.js +37 -0
- package/lib/transform/db/rewriteCalculatedElements.js +46 -6
- package/lib/transform/db/temporal.js +1 -1
- package/lib/transform/draft/db.js +2 -16
- package/lib/transform/draft/odata.js +3 -3
- package/lib/transform/effective/associations.js +3 -5
- package/lib/transform/effective/main.js +6 -9
- package/lib/transform/forOdata.js +26 -55
- package/lib/transform/forRelationalDB.js +38 -18
- package/lib/transform/odata/toFinalBaseType.js +3 -3
- package/lib/transform/odata/typesExposure.js +14 -5
- package/lib/transform/transformUtils.js +47 -34
- package/lib/transform/translateAssocsToJoins.js +45 -11
- package/lib/transform/universalCsn/coreComputed.js +1 -1
- package/lib/transform/universalCsn/universalCsnEnricher.js +4 -4
- package/package.json +7 -6
package/lib/api/options.js
CHANGED
|
@@ -31,6 +31,7 @@ const publicOptionsNewAPI = [
|
|
|
31
31
|
'generatedByComment',
|
|
32
32
|
'betterSqliteSessionVariables',
|
|
33
33
|
'fewerLocalizedViews',
|
|
34
|
+
'withHanaAssociations',
|
|
34
35
|
// ODATA
|
|
35
36
|
'odataOpenapiHints',
|
|
36
37
|
'odataVersion',
|
|
@@ -42,7 +43,6 @@ const publicOptionsNewAPI = [
|
|
|
42
43
|
'odataXServiceRefs',
|
|
43
44
|
'odataV2PartialConstr',
|
|
44
45
|
'odataVocabularies',
|
|
45
|
-
'odataOpenType',
|
|
46
46
|
'service',
|
|
47
47
|
'serviceNames',
|
|
48
48
|
//
|
|
@@ -67,6 +67,7 @@ const privateOptions = [
|
|
|
67
67
|
'noRecompile',
|
|
68
68
|
'internalMsg',
|
|
69
69
|
'disableHanaComments', // in case of issues with hana comment rendering
|
|
70
|
+
'tenantAsColumn', // not published yet
|
|
70
71
|
'localizedWithoutCoalesce', // deprecated version of 'localizedLanguageFallback', TODO(v5): Remove option
|
|
71
72
|
];
|
|
72
73
|
|
|
@@ -77,9 +78,9 @@ const overallOptions = publicOptionsNewAPI.concat(privateOptions);
|
|
|
77
78
|
* Apply defaults and make sure that the "hard requirements" are met,
|
|
78
79
|
* i.e. src: sql if to.sql() was called.
|
|
79
80
|
*
|
|
80
|
-
* @param {FlatOptions} [input
|
|
81
|
-
* @param {FlatOptions} [defaults
|
|
82
|
-
* @param {FlatOptions} [hardRequire
|
|
81
|
+
* @param {FlatOptions} [input] Input options
|
|
82
|
+
* @param {FlatOptions} [defaults] Default options to apply
|
|
83
|
+
* @param {FlatOptions} [hardRequire] Hard requirements to enforce
|
|
83
84
|
* @param {object} [customValidators] Custom validations to run instead of defaults
|
|
84
85
|
* @param {string[]} [combinationValidators] Option combinations to validate
|
|
85
86
|
* @param {string} moduleName The called module, e.g. 'for.odata', 'to.hdi'. Needed to initialize the message functions
|
|
@@ -127,14 +128,18 @@ module.exports = {
|
|
|
127
128
|
cdl: options => translateOptions(options, undefined, undefined, undefined, undefined, 'to.cdl'),
|
|
128
129
|
sql: (options) => {
|
|
129
130
|
const hardOptions = { src: 'sql', toSql: true, forHana: true };
|
|
130
|
-
const defaultOptions = {
|
|
131
|
+
const defaultOptions = {
|
|
132
|
+
sqlMapping: 'plain', sqlDialect: 'plain', generatedByComment: true, withHanaAssociations: true,
|
|
133
|
+
};
|
|
131
134
|
const processed = translateOptions(options, defaultOptions, hardOptions, undefined, [ 'sql-dialect-and-naming' ], 'to.sql');
|
|
132
135
|
|
|
133
136
|
return Object.assign({}, processed);
|
|
134
137
|
},
|
|
135
138
|
hdi: (options) => {
|
|
136
139
|
const hardOptions = { src: 'hdi', toSql: true, forHana: true };
|
|
137
|
-
const defaultOptions = {
|
|
140
|
+
const defaultOptions = {
|
|
141
|
+
sqlMapping: 'plain', sqlDialect: 'hana', generatedByComment: false, withHanaAssociations: true,
|
|
142
|
+
};
|
|
138
143
|
return translateOptions(options, defaultOptions, hardOptions, { sqlDialect: generateStringValidator([ 'hana' ]) }, undefined, 'to.hdi');
|
|
139
144
|
},
|
|
140
145
|
hdbcds: (options) => {
|
|
@@ -154,6 +159,13 @@ module.exports = {
|
|
|
154
159
|
};
|
|
155
160
|
return translateOptions(options, defaultOptions, hardOptions, undefined, [ 'valid-structured' ], 'to.edmx');
|
|
156
161
|
},
|
|
162
|
+
odata: (options) => {
|
|
163
|
+
const hardOptions = { combined: true, toOdata: true };
|
|
164
|
+
const defaultOptions = {
|
|
165
|
+
odataVersion: 'v4', odataFormat: 'flat',
|
|
166
|
+
};
|
|
167
|
+
return translateOptions(options, defaultOptions, hardOptions, undefined, [ 'valid-structured' ], 'to.odata');
|
|
168
|
+
},
|
|
157
169
|
},
|
|
158
170
|
for: { // TODO: Rename version to oDataVersion
|
|
159
171
|
odata: (options) => {
|
package/lib/api/validate.js
CHANGED
|
@@ -141,7 +141,7 @@ const allCombinationValidators = {
|
|
|
141
141
|
message.error('api-invalid-combination', null, { '#': 'sql-dialect-and-naming', name: options.sqlDialect, prop: options.sqlMapping });
|
|
142
142
|
},
|
|
143
143
|
'sql-dialect-and-localized': (options, message) => {
|
|
144
|
-
if (options.fewerLocalizedViews && options.sqlDialect === 'hana')
|
|
144
|
+
if (options.fewerLocalizedViews && options.sqlDialect === 'hana' && (options.withHanaAssociations || options.withHanaAssociations === undefined))
|
|
145
145
|
message.error('api-invalid-combination', null, { '#': 'sql-dialect-and-localized', option: 'fewerLocalizedViews', value: 'hana' });
|
|
146
146
|
},
|
|
147
147
|
'beta-no-test': (options, message) => {
|
|
@@ -121,12 +121,12 @@ const centralMessages = {
|
|
|
121
121
|
'ref-undefined-def': { severity: 'Error' },
|
|
122
122
|
'ref-undefined-var': { severity: 'Error' },
|
|
123
123
|
'ref-undefined-element': { severity: 'Error' },
|
|
124
|
-
'anno-undefined-element': { severity: '
|
|
125
|
-
'ref-unknown-var': { severity: 'Info'
|
|
124
|
+
'anno-undefined-element': { severity: 'Error' },
|
|
125
|
+
'ref-unknown-var': { severity: 'Info' },
|
|
126
126
|
'ref-obsolete-parameters': { severity: 'Error', configurableFor: 'v4' },
|
|
127
127
|
// does not hurt us, but makes it tedious to detect parameter refs
|
|
128
128
|
'ref-undefined-param': { severity: 'Error' },
|
|
129
|
-
'anno-undefined-param': { severity: '
|
|
129
|
+
'anno-undefined-param': { severity: 'Error' },
|
|
130
130
|
'ref-rejected-on': { severity: 'Error' },
|
|
131
131
|
'ref-expected-element': { severity: 'Error' },
|
|
132
132
|
|
|
@@ -254,11 +254,16 @@ const centralMessageTexts = {
|
|
|
254
254
|
std: 'Unexpected option combination: $(OPTION) and $(PROP)', // unused
|
|
255
255
|
'beta-no-test':'Option $(OPTION) was used. This option should not be used in productive scenarios!',
|
|
256
256
|
},
|
|
257
|
+
'api-unexpected-option': 'Option $(OPTION) can\'t be used in backend $(MODULE)',
|
|
257
258
|
'api-invalid-lookup-dir': {
|
|
258
259
|
std: '',
|
|
259
260
|
slash: 'Expected directory $(VALUE) in option $(OPTION) to end with $(OTHERVALUE)',
|
|
260
261
|
relative: 'Expected directory $(VALUE) in option $(OPTION) to not start with $(OTHERVALUE)',
|
|
261
262
|
},
|
|
263
|
+
'api-unsupported-csn-flavor': {
|
|
264
|
+
std: 'Module $(NAME) expects a client/inferred CSN, not $(OPTION)',
|
|
265
|
+
'parsed-requires': 'Module $(NAME) expects a client/inferred CSN, or a parsed CSN without dependencies, but found $(PROP) property',
|
|
266
|
+
},
|
|
262
267
|
|
|
263
268
|
'anno-duplicate': {
|
|
264
269
|
std: 'Duplicate assignment with $(ANNO)',
|
|
@@ -281,6 +286,11 @@ const centralMessageTexts = {
|
|
|
281
286
|
view: 'Compiler generated view $(NAME) must not be annotated with $(ANNO) if $(ART) is not skipped',
|
|
282
287
|
},
|
|
283
288
|
|
|
289
|
+
'anno-missing-rewrite': {
|
|
290
|
+
std: 'Assign a value for $(ANNO), the value inherited from $(ART) would contain invalid references like $(ELEMREF)',
|
|
291
|
+
unrelated: 'Assign a value for $(ANNO), the value inherited from $(ART) would contain references like $(ELEMREF) to unrelated elements',
|
|
292
|
+
},
|
|
293
|
+
|
|
284
294
|
'chained-array-of': '"Array of"/"many" must not be chained with another "array of"/"many" inside a service',
|
|
285
295
|
|
|
286
296
|
'check-proper-type-of': {
|
|
@@ -326,6 +336,9 @@ const centralMessageTexts = {
|
|
|
326
336
|
csn: 'Expecting a non-negative integer for property $(PROP)',
|
|
327
337
|
'or-asterisk': 'Expecting a non-negative integer or string $(OP) for property $(PROP)',
|
|
328
338
|
},
|
|
339
|
+
'syntax-ignoring-decimal': {
|
|
340
|
+
std: 'Ignoring decimal places, because an integer was expected'
|
|
341
|
+
},
|
|
329
342
|
'syntax-ignoring-anno': {
|
|
330
343
|
std: 'Annotations can\'t be used in a column with $(CODE)',
|
|
331
344
|
doc: 'Doc comments can\'t be used in a column with $(CODE)',
|
|
@@ -573,6 +586,7 @@ const centralMessageTexts = {
|
|
|
573
586
|
std: 'Variable $(ID) has not been found',
|
|
574
587
|
alias: 'Variable $(ID) has not been found. Use table alias $(ALIAS) to refer an element with the same name',
|
|
575
588
|
self: 'Variable $(ID) has not been found. Use $(ALIAS) to refer an element with the same name',
|
|
589
|
+
value: 'No value found for variable $(ID). Use option $(OPTION) to specify a value for $(ID)',
|
|
576
590
|
},
|
|
577
591
|
'ref-unknown-var': {
|
|
578
592
|
std: 'No replacement found for special variable $(ID)'
|
|
@@ -614,6 +628,7 @@ const centralMessageTexts = {
|
|
|
614
628
|
self: 'A reference to an unmanaged association is only valid when compared via $(CODE)',
|
|
615
629
|
expr: 'Associations can\'t be used as values in expressions',
|
|
616
630
|
'expr-comp': 'Compositions can\'t be used as values in expressions',
|
|
631
|
+
'assoc-stored': 'Associations and compositions can\'t be used as values in stored calculated elements',
|
|
617
632
|
cast: 'Casting to an association is not supported',
|
|
618
633
|
|
|
619
634
|
'managed-filter': 'Unexpected managed association $(NAME) in filter expression of $(ID)',
|
|
@@ -646,9 +661,19 @@ const centralMessageTexts = {
|
|
|
646
661
|
'on-condition': 'ON-conditions must not contain parameters, step $(ID) of path $(ELEMREF)',
|
|
647
662
|
calc: 'Unexpected arguments in path $(ELEMREF) of stored calculated element; only simple paths can be used here'
|
|
648
663
|
},
|
|
664
|
+
'ref-unsupported-type': {
|
|
665
|
+
std: 'Type $(TYPE) is not supported',
|
|
666
|
+
hana: 'Type $(TYPE) is only supported for SQL dialect $(VALUE), not $(OTHERVALUE)',
|
|
667
|
+
hdbcds:'Type $(TYPE) is not supported in HDBCDS',
|
|
668
|
+
odata: 'Type $(TYPE) is not supported for OData'
|
|
669
|
+
},
|
|
649
670
|
|
|
650
671
|
// TODO: Better text ?
|
|
651
672
|
'rewrite-not-supported': 'The ON-condition is not rewritten here - provide an explicit ON-condition',
|
|
673
|
+
'type-unsupported-rewrite': {
|
|
674
|
+
std: 'Rewriting the ON-condition not supported here', // unused: merge with 'rewrite-not-supported'
|
|
675
|
+
'sub-element': 'Rewriting the ON-condition of unmanaged association in sub element is not supported'
|
|
676
|
+
},
|
|
652
677
|
|
|
653
678
|
'type-unexpected-typeof': {
|
|
654
679
|
std: 'Unexpected $(KEYWORD) for the type reference here',
|
|
@@ -835,9 +860,15 @@ const centralMessageTexts = {
|
|
|
835
860
|
param: 'A type, an element, or a service entity is expected here',
|
|
836
861
|
event: 'A type, an element, an event, or a service entity is expected here',
|
|
837
862
|
},
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
863
|
+
'ref-invalid-source': {
|
|
864
|
+
std: 'A query source must be an entity or an association',
|
|
865
|
+
event: 'An event\'s projection source must be an entity, structured type, event or an association',
|
|
866
|
+
},
|
|
867
|
+
'extend-columns': {
|
|
868
|
+
std: 'Artifact $(ART) can\'t be extended with columns, only simple views/projections without JOINs and UNIONs can',
|
|
869
|
+
join: 'Artifact $(ART) can\'t be extended with columns, because it contains a JOIN',
|
|
870
|
+
union: 'Artifact $(ART) can\'t be extended with columns, because it contains a UNION',
|
|
871
|
+
},
|
|
841
872
|
'extend-repeated-intralayer': 'Unstable element order due to repeated extensions in same layer',
|
|
842
873
|
'extend-unexpected-include': 'Can\'t extend $(META) with includes',
|
|
843
874
|
|
|
@@ -889,6 +920,7 @@ const centralMessageTexts = {
|
|
|
889
920
|
std: 'Specified element $(NAME) differs from inferred element in property $(PROP)',
|
|
890
921
|
type: 'Expected type of specified element $(NAME) to be the same as the inferred element\'s type',
|
|
891
922
|
typeName: 'Expected type $(TYPE) of specified element $(NAME) to be the same as the inferred element\'s type $(OTHERTYPE)',
|
|
923
|
+
typeExtra: 'Element $(NAME) does not have an inferred type property, but an unexpected type $(TYPE) was specified',
|
|
892
924
|
missing: 'Specified element $(NAME) differs from inferred element: it is missing property $(PROP)',
|
|
893
925
|
extra: 'Specified element $(NAME) differs from inferred element: it has an additional property $(PROP)',
|
|
894
926
|
target: 'Expected target $(TARGET) of specified element $(NAME) to be the same as the inferred element\'s target $(ART)',
|
|
@@ -937,7 +969,8 @@ const centralMessageTexts = {
|
|
|
937
969
|
'to-structure': 'Can\'t cast to a structured type',
|
|
938
970
|
'from-structure': 'Structured elements can\'t be cast to a different type',
|
|
939
971
|
'expr-to-structure': 'Can\'t cast an expression to a structured type',
|
|
940
|
-
'val-to-structure': 'Can\'t cast $(VALUE) to a structured type'
|
|
972
|
+
'val-to-structure': 'Can\'t cast $(VALUE) to a structured type',
|
|
973
|
+
'from-assoc': 'Invalid type cast on an association'
|
|
941
974
|
},
|
|
942
975
|
|
|
943
976
|
// -----------------------------------------------------------------------------------
|
|
@@ -1018,6 +1051,7 @@ const centralMessageTexts = {
|
|
|
1018
1051
|
},
|
|
1019
1052
|
'odata-parameter-order': 'Unexpected mandatory after optional parameter',
|
|
1020
1053
|
'odata-key-recursive': 'Unexpected recursive key $(NAME)',
|
|
1054
|
+
'odata-key-uuid-default-anno': 'Expected element of type $(TYPE) to be annotated with $(ANNO) when used as primary key in $(ID)',
|
|
1021
1055
|
// -----------------------------------------------------------------------------------
|
|
1022
1056
|
// All odata-anno MUST have a '$(ANNO)' parameter to indicate error location
|
|
1023
1057
|
// -----------------------------------------------------------------------------------
|
|
@@ -1026,7 +1060,7 @@ const centralMessageTexts = {
|
|
|
1026
1060
|
'odata-anno-preproc': {
|
|
1027
1061
|
'std': 'unused message text',
|
|
1028
1062
|
'nokey': 'Expected target $(NAME) to have a key element for $(ANNO)',
|
|
1029
|
-
'multkeys': 'Expected target $(NAME) to have only one key element',
|
|
1063
|
+
'multkeys': 'Expected target $(NAME) to have only one key element for $(ANNO)',
|
|
1030
1064
|
'vhlnokey': 'Expected value help list entity $(NAME) to have a key element for $(ANNO)',
|
|
1031
1065
|
'vhlmultkeys': 'Expected value help list entity $(NAME) to have only one key element for $(ANNO)',
|
|
1032
1066
|
'notforentity': 'Unexpected usage of $(ANNO) for an entity',
|
|
@@ -1034,8 +1068,8 @@ const centralMessageTexts = {
|
|
|
1034
1068
|
'noassoc': 'Expected association $(ID) to exist for $(ANNO)',
|
|
1035
1069
|
'vallistignored': '$(NAME) is ignored for $(ANNO) as $(CODE) is present',
|
|
1036
1070
|
'notastring': 'Expected value to be a string for $(ANNO)',
|
|
1037
|
-
'notexist': '
|
|
1038
|
-
'txtarr': '
|
|
1071
|
+
'notexist': 'Expected entity $(ID) to exist for $(ANNO)',
|
|
1072
|
+
'txtarr': 'Expected $(ANNO) shortcut to have a $(NAME) annotation'
|
|
1039
1073
|
},
|
|
1040
1074
|
// -----------------------------------------------------------------------------------
|
|
1041
1075
|
// GenericTranslation:
|
|
@@ -1074,6 +1108,7 @@ const centralMessageTexts = {
|
|
|
1074
1108
|
'unknown': '$(TYPE) is not a known vocabulary type for $(ANNO)',
|
|
1075
1109
|
'abstract': 'Unexpected abstract type $(TYPE) for $(ANNO), use $(CODE) to specify a concrete type',
|
|
1076
1110
|
'derived': 'Expected specified $(TYPE) to be derived from $(NAME) for $(ANNO)',
|
|
1111
|
+
'literal': 'Expected value $(RAWVALUE) of specified $(CODE) to be a string literal for $(ANNO)'
|
|
1077
1112
|
},
|
|
1078
1113
|
'odata-anno-def': {
|
|
1079
1114
|
// All $(ANNO) w/o sub elements, term qualifiers and context stack
|
package/lib/base/messages.js
CHANGED
|
@@ -305,14 +305,14 @@ function makeMessageFunction( model, options, moduleName = null ) {
|
|
|
305
305
|
throw new CompilerAssertion('makeMessageFunction() expects options.messages to exist in testMode!');
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
-
const hasMessageArray =
|
|
308
|
+
const hasMessageArray = Array.isArray(options.messages);
|
|
309
309
|
/**
|
|
310
310
|
* Array of collected compiler messages. Only use it for debugging. Will not
|
|
311
311
|
* contain the messages created during a `callTransparently` call.
|
|
312
312
|
*
|
|
313
313
|
* @type {CompileMessage[]}
|
|
314
314
|
*/
|
|
315
|
-
let messages = options.messages
|
|
315
|
+
let messages = hasMessageArray ? options.messages : [];
|
|
316
316
|
/**
|
|
317
317
|
* Whether an error was emitted in the module. Also includes reclassified errors.
|
|
318
318
|
* @type {boolean}
|
|
@@ -332,6 +332,7 @@ function makeMessageFunction( model, options, moduleName = null ) {
|
|
|
332
332
|
throwWithAnyError,
|
|
333
333
|
callTransparently,
|
|
334
334
|
moduleName,
|
|
335
|
+
setModel,
|
|
335
336
|
};
|
|
336
337
|
|
|
337
338
|
function _message( id, location, textOrArguments, severity, texts = null ) {
|
|
@@ -550,6 +551,16 @@ function makeMessageFunction( model, options, moduleName = null ) {
|
|
|
550
551
|
messages = backup;
|
|
551
552
|
return collected;
|
|
552
553
|
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Change the model used to calculate CSN locations.
|
|
557
|
+
* This is necessary if you change the model heavily and rely on $paths relative to the new model.
|
|
558
|
+
*
|
|
559
|
+
* @param {CSN.Model} _model
|
|
560
|
+
*/
|
|
561
|
+
function setModel( _model ) {
|
|
562
|
+
model = _model;
|
|
563
|
+
}
|
|
553
564
|
}
|
|
554
565
|
|
|
555
566
|
/**
|
|
@@ -679,6 +690,7 @@ const paramsTransform = {
|
|
|
679
690
|
meta: quote.angle,
|
|
680
691
|
othermeta: quote.angle,
|
|
681
692
|
keyword,
|
|
693
|
+
module: quote.single,
|
|
682
694
|
// more complex convenience:
|
|
683
695
|
names: transformManyWith( quoted ),
|
|
684
696
|
number: quote.single, // number cited from source or expected in source
|
|
@@ -797,15 +809,16 @@ function tokenSymbol( token ) {
|
|
|
797
809
|
* Transform an element reference (/path), e.g. on-condition path.
|
|
798
810
|
*/
|
|
799
811
|
function transformElementRef( arg ) {
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
return quoted(arg
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
812
|
+
const ref = arg.ref || arg.path;
|
|
813
|
+
if (!ref)
|
|
814
|
+
return quoted( arg );
|
|
815
|
+
// Can be used by CSN backends or compiler to create a simple path such as E:elem
|
|
816
|
+
return quoted(
|
|
817
|
+
ref.map(
|
|
818
|
+
item => (typeof item !== 'string'
|
|
819
|
+
? `${ item.id }${item.args ? '(…)' : ''}${item.where ? '[…]' : ''}`
|
|
820
|
+
: item) )
|
|
821
|
+
.join('.') );
|
|
809
822
|
}
|
|
810
823
|
|
|
811
824
|
function transformArg( arg, r, args, texts ) {
|
|
@@ -1299,7 +1312,7 @@ function deduplicateMessages( messages ) {
|
|
|
1299
1312
|
}
|
|
1300
1313
|
|
|
1301
1314
|
function shortArtName( art ) {
|
|
1302
|
-
if (!art.name)
|
|
1315
|
+
if (!art.name || art.kind === '$annotation')
|
|
1303
1316
|
return artName( art );
|
|
1304
1317
|
const name = getArtifactName( art );
|
|
1305
1318
|
if ([ 'select', 'action', 'alias', 'param' ].every( n => name[n] == null || name[n] === 1 ) &&
|
|
@@ -1310,7 +1323,7 @@ function shortArtName( art ) {
|
|
|
1310
1323
|
|
|
1311
1324
|
function artName( art, omit ) {
|
|
1312
1325
|
let suffix = 0;
|
|
1313
|
-
while (!art.name && art._outer) {
|
|
1326
|
+
while (!art.name && art._outer && art.kind !== '$annotation') {
|
|
1314
1327
|
++suffix;
|
|
1315
1328
|
art = art._outer;
|
|
1316
1329
|
}
|
|
@@ -1367,8 +1380,12 @@ function homeName( art, absoluteOnly ) {
|
|
|
1367
1380
|
return art;
|
|
1368
1381
|
if (art._user) // when providing a path item with filter as “user”
|
|
1369
1382
|
return homeName( art._user, absoluteOnly );
|
|
1370
|
-
if (art._outer)
|
|
1371
|
-
|
|
1383
|
+
if (art._outer) { // in items property, or annotation with path
|
|
1384
|
+
const outer = homeName( art._outer, absoluteOnly );
|
|
1385
|
+
return (art.kind === '$annotation')
|
|
1386
|
+
? `${ outer }/${ quoted( '@' + art.name.id ) }`
|
|
1387
|
+
: outer;
|
|
1388
|
+
}
|
|
1372
1389
|
else if (art.kind === 'source' || !art.name) // error reported in parser or on source level
|
|
1373
1390
|
return null;
|
|
1374
1391
|
else if (art.kind === 'using')
|
|
@@ -1578,7 +1595,7 @@ function constructSemanticLocationFromCsnPath( model, options, csnPath ) {
|
|
|
1578
1595
|
else if (step === 'targetAspect') {
|
|
1579
1596
|
// skip
|
|
1580
1597
|
}
|
|
1581
|
-
else if (step === 'xpr' || step === 'ref' || step === 'as' || step === 'value') {
|
|
1598
|
+
else if (step === 'xpr' || step === 'default' || step === 'ref' || step === 'as' || step === 'value') {
|
|
1582
1599
|
break; // don't go into xprs, refs, aliases, values, etc.
|
|
1583
1600
|
}
|
|
1584
1601
|
else if (step === 'returns') {
|
package/lib/base/model.js
CHANGED
|
@@ -27,6 +27,7 @@ const queryOps = {
|
|
|
27
27
|
const availableBetaFlags = {
|
|
28
28
|
// enabled by --beta-mode
|
|
29
29
|
annotationExpressions: true,
|
|
30
|
+
odataAnnotationExpressions: true,
|
|
30
31
|
assocsWithParams: true, // beta, because runtimes don't support it, yet.
|
|
31
32
|
hanaAssocRealCardinality: true,
|
|
32
33
|
mapAssocToJoinCardinality: true, // only SAP HANA HEX engine supports it
|
|
@@ -35,6 +36,9 @@ const availableBetaFlags = {
|
|
|
35
36
|
optionalActionFunctionParameters: true, // not supported by runtime, yet.
|
|
36
37
|
annotateForeignKeys: true,
|
|
37
38
|
effectiveCsn: true,
|
|
39
|
+
tenantVariable: true,
|
|
40
|
+
calcAssoc: true,
|
|
41
|
+
vectorType: true,
|
|
38
42
|
// disabled by --beta-mode
|
|
39
43
|
nestedServices: false,
|
|
40
44
|
};
|