@sap/cds-compiler 3.6.2 → 3.8.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 +109 -1
- package/README.md +3 -0
- package/bin/cdsc.js +12 -5
- package/doc/CHANGELOG_ARCHIVE.md +6 -6
- package/doc/CHANGELOG_BETA.md +35 -2
- package/doc/CHANGELOG_DEPRECATED.md +2 -2
- package/doc/DeprecatedOptions_v2.md +1 -1
- package/doc/NameResolution.md +1 -1
- package/lib/api/main.js +63 -23
- package/lib/api/options.js +1 -0
- package/lib/api/validate.js +5 -0
- package/lib/base/dictionaries.js +15 -3
- package/lib/base/keywords.js +2 -0
- package/lib/base/message-registry.js +120 -34
- package/lib/base/messages.js +51 -27
- package/lib/base/model.js +4 -2
- package/lib/base/shuffle.js +2 -1
- package/lib/checks/arrayOfs.js +1 -1
- package/lib/checks/defaultValues.js +1 -1
- package/lib/checks/elements.js +29 -1
- package/lib/checks/{emptyOrOnlyVirtual.js → hasPersistedElements.js} +10 -6
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/nonexpandableStructured.js +1 -1
- package/lib/checks/onConditions.js +15 -9
- package/lib/checks/sql-snippets.js +2 -2
- package/lib/checks/types.js +5 -1
- package/lib/checks/validator.js +7 -3
- package/lib/compiler/assert-consistency.js +42 -26
- package/lib/compiler/base.js +50 -4
- package/lib/compiler/builtins.js +17 -8
- package/lib/compiler/checks.js +241 -246
- package/lib/compiler/define.js +113 -146
- package/lib/compiler/extend.js +889 -383
- package/lib/compiler/finalize-parse-cdl.js +5 -58
- package/lib/compiler/index.js +1 -1
- package/lib/compiler/kick-start.js +7 -8
- package/lib/compiler/populate.js +297 -293
- package/lib/compiler/propagator.js +27 -18
- package/lib/compiler/resolve.js +146 -463
- package/lib/compiler/shared.js +36 -79
- package/lib/compiler/tweak-assocs.js +30 -28
- package/lib/compiler/utils.js +31 -5
- package/lib/edm/annotations/genericTranslation.js +131 -59
- package/lib/edm/annotations/preprocessAnnotations.js +3 -0
- package/lib/edm/csn2edm.js +22 -5
- package/lib/edm/edm.js +6 -4
- package/lib/edm/edmAnnoPreprocessor.js +1 -0
- package/lib/edm/edmPreprocessor.js +42 -26
- package/lib/gen/Dictionary.json +38 -2
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +3 -1
- package/lib/gen/languageLexer.js +1 -1
- package/lib/gen/languageParser.js +4828 -4472
- package/lib/inspect/inspectPropagation.js +20 -34
- package/lib/json/from-csn.js +140 -44
- package/lib/json/to-csn.js +114 -122
- package/lib/language/errorStrategy.js +2 -0
- package/lib/language/genericAntlrParser.js +156 -36
- package/lib/language/language.g4 +100 -58
- package/lib/language/textUtils.js +13 -0
- package/lib/main.d.ts +43 -3
- package/lib/main.js +4 -2
- package/lib/model/csnRefs.js +15 -3
- package/lib/model/csnUtils.js +12 -74
- package/lib/model/revealInternalProperties.js +4 -2
- package/lib/modelCompare/compare.js +2 -1
- package/lib/optionProcessor.js +3 -0
- package/lib/render/manageConstraints.js +5 -2
- package/lib/render/toCdl.js +216 -104
- package/lib/render/toHdbcds.js +2 -9
- package/lib/render/toRename.js +14 -51
- package/lib/render/toSql.js +4 -3
- package/lib/render/utils/common.js +9 -5
- package/lib/transform/braceExpression.js +6 -0
- package/lib/transform/db/assertUnique.js +2 -1
- package/lib/transform/db/expansion.js +2 -0
- package/lib/transform/db/flattening.js +37 -36
- package/lib/transform/db/rewriteCalculatedElements.js +600 -0
- package/lib/transform/db/transformExists.js +4 -0
- package/lib/transform/db/views.js +40 -37
- package/lib/transform/forOdataNew.js +20 -15
- package/lib/transform/forRelationalDB.js +58 -41
- package/lib/transform/odata/typesExposure.js +50 -15
- package/lib/transform/parseExpr.js +16 -8
- package/lib/transform/transformUtilsNew.js +42 -14
- package/lib/transform/translateAssocsToJoins.js +60 -37
- package/lib/transform/universalCsn/coreComputed.js +15 -7
- package/lib/transform/universalCsn/universalCsnEnricher.js +4 -4
- package/package.json +2 -1
|
@@ -60,7 +60,7 @@ const centralMessages = {
|
|
|
60
60
|
'anno-undefined-def': { severity: 'Warning' }, // for annotate statement (for CSN or CDL path cont)
|
|
61
61
|
'anno-undefined-element': { severity: 'Warning' },
|
|
62
62
|
'anno-undefined-param': { severity: 'Warning' },
|
|
63
|
-
'anno-unexpected-ellipsis
|
|
63
|
+
'anno-unexpected-ellipsis': { severity: 'Error', configurableFor: 'v3' },
|
|
64
64
|
|
|
65
65
|
'args-expected-named': { severity: 'Error', configurableFor: 'deprecated' }, // future --sloppy
|
|
66
66
|
'args-no-params': { severity: 'Error', configurableFor: 'deprecated' }, // future --sloppy
|
|
@@ -159,6 +159,8 @@ const centralMessages = {
|
|
|
159
159
|
|
|
160
160
|
'def-missing-element': { severity: 'Error' },
|
|
161
161
|
|
|
162
|
+
'def-unsupported-calc-elem': { severity: 'Error', configurableFor: true },
|
|
163
|
+
|
|
162
164
|
'unexpected-keys-for-composition': { severity: 'Error' }, // TODO: more than 30 chars
|
|
163
165
|
'unmanaged-as-key': { severity: 'Error', configurableFor: 'deprecated' }, // is confusing
|
|
164
166
|
'composition-as-key': { severity: 'Error', configurableFor: 'deprecated' }, // is confusing and not supported
|
|
@@ -183,6 +185,7 @@ const centralMessages = {
|
|
|
183
185
|
'odata-spec-violation-property-name': { severity: 'Warning' }, // more than 30 chars
|
|
184
186
|
'odata-anno-preproc': { severity: 'Warning', configurableFor: true },
|
|
185
187
|
'odata-anno-dict': { severity: 'Warning', configurableFor: true },
|
|
188
|
+
'odata-anno-vocref': { severity: 'Warning', configurableFor: true },
|
|
186
189
|
'odata-anno-dict-enum': { severity: 'Error' },
|
|
187
190
|
'odata-anno-value': { severity: 'Warning', configurableFor: true },
|
|
188
191
|
'odata-anno-type': { severity: 'Warning', configurableFor: true },
|
|
@@ -218,27 +221,33 @@ for (const oldName in oldMessageIds) {
|
|
|
218
221
|
|
|
219
222
|
const centralMessageTexts = {
|
|
220
223
|
'api-invalid-option': {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
224
|
+
std: 'Invalid option $(NAME)!',
|
|
225
|
+
deprecated: 'Option $(NAME) is no longer supported! Use latest API options instead',
|
|
226
|
+
magicVars: 'Option $(PROP) is no longer supported! Use $(OTHERPROP) instead. See <https://cap.cloud.sap/docs/guides/databases#configuring-variables> for details',
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
'api-invalid-variable-replacement': {
|
|
230
|
+
std: 'Option $(OPTION) does not support $(NAME)',
|
|
231
|
+
user: 'Option $(OPTION) expects $(PROP) instead of $(OTHERPROP). See <https://cap.cloud.sap/docs/guides/databases#configuring-variables> for details',
|
|
232
|
+
locale: 'Option $(OPTION) expects $(PROP) instead of $(OTHERPROP). See <https://cap.cloud.sap/docs/guides/databases#configuring-variables> for details',
|
|
233
|
+
'noDollar': 'Option $(OPTION) does not know $(NAME). Did you forget a leading $(CODE)?'
|
|
228
234
|
},
|
|
229
235
|
|
|
230
236
|
'anno-duplicate': {
|
|
231
237
|
std: 'Duplicate assignment with $(ANNO)',
|
|
232
238
|
doc: 'Duplicate assignment with a doc comment',
|
|
233
239
|
},
|
|
240
|
+
'anno-duplicate-same-file': {
|
|
241
|
+
std: 'Duplicate assignment with $(ANNO), using last',
|
|
242
|
+
doc: 'Duplicate assignment with a doc comment, using last',
|
|
243
|
+
},
|
|
234
244
|
'anno-duplicate-unrelated-layer': {
|
|
235
245
|
std: 'Duplicate assignment with $(ANNO)',
|
|
236
246
|
doc: 'Duplicate assignment with a doc comment',
|
|
237
247
|
},
|
|
238
|
-
'anno-unstable-array': 'Unstable order of array items due to repeated assignments for $(ANNO)
|
|
248
|
+
'anno-unstable-array': 'Unstable order of array items due to repeated assignments for $(ANNO)',
|
|
239
249
|
'anno-mismatched-ellipsis': 'An array with $(CODE) can only be used if there is an assignment below with an array value',
|
|
240
250
|
'anno-unexpected-ellipsis': 'No base annotation available to apply $(CODE)',
|
|
241
|
-
'anno-unexpected-ellipsis-layers': 'No base annotation available to apply $(CODE)',
|
|
242
251
|
'chained-array-of': '"Array of"/"many" must not be chained with another "array of"/"many" inside a service',
|
|
243
252
|
|
|
244
253
|
'check-proper-type-of': {
|
|
@@ -262,6 +271,12 @@ const centralMessageTexts = {
|
|
|
262
271
|
mixin: 'A mixin name starting with $(NAME) might shadow a special variable - replace by another name',
|
|
263
272
|
},
|
|
264
273
|
|
|
274
|
+
'name-missing-alias': {
|
|
275
|
+
std: 'Missing table alias for this subquery',
|
|
276
|
+
duplicate: 'Missing table alias for this subquery; add $(CODE) to fix name clash of internal and explicit table alias',
|
|
277
|
+
hdbcds: 'Missing table alias for a subquery; SAP HANA CDS requires table aliases'
|
|
278
|
+
},
|
|
279
|
+
|
|
265
280
|
// Syntax messages, both CDL and CSN parser: ----------------------------------
|
|
266
281
|
'syntax-deprecated-abstract': {
|
|
267
282
|
std: 'Abstract entity definitions are deprecated; use aspect definitions instead',
|
|
@@ -294,9 +309,9 @@ const centralMessageTexts = {
|
|
|
294
309
|
'std': 'Invalid literal value',
|
|
295
310
|
'uneven-hex': 'A binary literal must have an even number of characters',
|
|
296
311
|
'invalid-hex': 'A binary literal must only contain characters ‹0-9›, ‹a-f› and ‹A-F›',
|
|
297
|
-
'time': 'A time literal must look like ‹hh:mm:ss› or ‹hh:mm› where each letter represents a digit',
|
|
312
|
+
'time': 'A time literal must look like ‹hh:mm:ss› or ‹hh:mm› where each letter represents a digit. A timezone is optional',
|
|
298
313
|
'date': 'A date literal must look like ‹YYYY-MM-DD› where each letter represents a digit',
|
|
299
|
-
'timestamp': 'A timestamp literal must look like ‹YYYY-MM-DD hh:mm:ss.u…u› or ‹YYYY-MM-DD hh:mm› where each letter represents a digit, ‹u…u› represents 1 to 7 digits',
|
|
314
|
+
'timestamp': 'A timestamp literal must look like ‹YYYY-MM-DD hh:mm:ss.u…u› or ‹YYYY-MM-DD hh:mm› where each letter represents a digit, ‹u…u› represents 1 to 7 digits. A timezone is optional',
|
|
300
315
|
'number': 'The string value in property $(PROP) does not represent a number',
|
|
301
316
|
'expecting': 'Expecting literal type $(OP) for the value in property $(OTHERPROP)',
|
|
302
317
|
'typeof': 'String $(RAWVALUE) is no valid literal type for the string value in property $(OTHERPROP)',
|
|
@@ -360,7 +375,6 @@ const centralMessageTexts = {
|
|
|
360
375
|
dynamic: 'Dynamic parameter $(CODE) is not supported',
|
|
361
376
|
positional: 'Positional parameter $(CODE) is not supported',
|
|
362
377
|
},
|
|
363
|
-
// 'syntax-unsupported-method', 'syntax-unsupported-new'
|
|
364
378
|
|
|
365
379
|
// Syntax messages, CSN parser - default: Error ------------------------------
|
|
366
380
|
'syntax-deprecated-dollar-syntax': {
|
|
@@ -379,6 +393,10 @@ const centralMessageTexts = {
|
|
|
379
393
|
'zero-parens': 'Deprecated CSN v.0.1.0 representation of expressions in parentheses',
|
|
380
394
|
'zero-replace': 'Replace CSN v0.1.0 value in $(PROP) by $(VALUE)',
|
|
381
395
|
},
|
|
396
|
+
'syntax-deprecated-type-ref': {
|
|
397
|
+
std: 'Expecting a string as value for property $(PROP) for a reference to a definition',
|
|
398
|
+
'ref-item': 'Expecting a string as value for property $(PROP) for a type reference to an element',
|
|
399
|
+
},
|
|
382
400
|
|
|
383
401
|
'syntax-expecting-object': {
|
|
384
402
|
std: 'Expecting object for property $(PROP)',
|
|
@@ -420,7 +438,7 @@ const centralMessageTexts = {
|
|
|
420
438
|
extend: 'CSN property $(PROP) is not expected by an extend in $(PARENTPROP)',
|
|
421
439
|
annotate: 'CSN property $(PROP) is not expected by an annotate in $(PARENTPROP)',
|
|
422
440
|
},
|
|
423
|
-
'
|
|
441
|
+
'def-invalid-calc-elem': {
|
|
424
442
|
std: 'Invalid calculated element',
|
|
425
443
|
key: 'A primary key element can\'t be calculated',
|
|
426
444
|
virtual: 'A virtual element can\'t be calculated',
|
|
@@ -430,7 +448,18 @@ const centralMessageTexts = {
|
|
|
430
448
|
type: 'A type can\'t have calculated elements',
|
|
431
449
|
action: 'An action can\'t have calculated elements',
|
|
432
450
|
function: 'A function can\'t have calculated elements',
|
|
433
|
-
annotation: 'Annotation definitions can\'t have calculated elements'
|
|
451
|
+
annotation: 'Annotation definitions can\'t have calculated elements',
|
|
452
|
+
param: 'Parameters can\'t have calculated elements',
|
|
453
|
+
},
|
|
454
|
+
'ref-invalid-calc-elem': {
|
|
455
|
+
std: 'Can\'t include artifact with calculated element',
|
|
456
|
+
event: 'An event can\'t include an entity with calculated elements',
|
|
457
|
+
type: 'A type can\'t include an entity with calculated elements',
|
|
458
|
+
annotation: 'An annotation can\'t include an entity with calculated elements',
|
|
459
|
+
},
|
|
460
|
+
'def-unsupported-calc-elem': {
|
|
461
|
+
std: 'Calculated elements are not supported',
|
|
462
|
+
nested: 'Calculated elements in structures are not supported, yet'
|
|
434
463
|
},
|
|
435
464
|
// 'syntax-unknown-property' (Warning? Better configurable Error)
|
|
436
465
|
|
|
@@ -489,6 +518,10 @@ const centralMessageTexts = {
|
|
|
489
518
|
std: '$(ART) can\'t be extended because it originates from an include',
|
|
490
519
|
elements: '$(ART) can\'t be extended by elements/enums because it originates from an include',
|
|
491
520
|
},
|
|
521
|
+
'ref-unexpected-scope': {
|
|
522
|
+
std: 'Unexpected parameter reference',
|
|
523
|
+
calc: 'Calculated elements can\'t use parameter references',
|
|
524
|
+
},
|
|
492
525
|
'ref-unexpected-structured': {
|
|
493
526
|
std: 'Unexpected usage of structured type $(ELEMREF)',
|
|
494
527
|
expr: 'Structured elements can\'t be used in expressions',
|
|
@@ -503,6 +536,17 @@ const centralMessageTexts = {
|
|
|
503
536
|
expr: 'Associations can\'t be used as values in expressions',
|
|
504
537
|
cast: 'Casting to an association is not supported',
|
|
505
538
|
},
|
|
539
|
+
'ref-unexpected-calculated': {
|
|
540
|
+
std: 'Unexpected reference to calculated element',
|
|
541
|
+
on: 'Calculated elements can\'t be used in ON-conditions of unmanaged associations',
|
|
542
|
+
fkey: 'Calculated elements can\'t be used as foreign keys for managed associations',
|
|
543
|
+
},
|
|
544
|
+
|
|
545
|
+
'ref-unexpected-navigation': {
|
|
546
|
+
std: 'Can\'t follow association $(ID) of path $(ELEMREF) in an ON-condition; only foreign keys can be referred to, but not $(NAME)',
|
|
547
|
+
unmanaged: 'Can\'t follow unmanaged association $(ID) of path $(ELEMREF) in an ON-condition; only foreign keys can be referred to',
|
|
548
|
+
unmanagedleaf: 'Unexpected unmanged association as final path step of $(ELEMREF) in an ON-condition',
|
|
549
|
+
},
|
|
506
550
|
|
|
507
551
|
'type-unexpected-typeof': {
|
|
508
552
|
std: 'Unexpected $(KEYWORD) for the type reference here',
|
|
@@ -533,26 +577,32 @@ const centralMessageTexts = {
|
|
|
533
577
|
element: 'Artifact $(ART) has no element $(NAME)',
|
|
534
578
|
enum: 'Artifact $(ART) has no enum $(NAME)',
|
|
535
579
|
returns: 'Return value of $(ART) has no element $(NAME)',
|
|
536
|
-
'
|
|
580
|
+
'enum-returns': 'Return value of $(ART) has no enum $(NAME)',
|
|
537
581
|
},
|
|
538
582
|
'anno-undefined-action': {
|
|
539
583
|
std: 'Action $(ART) has not been found',
|
|
540
|
-
action: 'Artifact $(ART) has no action $(
|
|
584
|
+
action: 'Artifact $(ART) has no action $(NAME)'
|
|
541
585
|
},
|
|
542
586
|
'anno-undefined-param': {
|
|
543
587
|
std: 'Parameter $(ART) has not been found',
|
|
544
|
-
param: 'Artifact $(ART) has no parameter $(
|
|
588
|
+
param: 'Artifact $(ART) has no parameter $(NAME)'
|
|
589
|
+
},
|
|
590
|
+
|
|
591
|
+
// annotation checks against their definition
|
|
592
|
+
'anno-expecting-value': {
|
|
593
|
+
'std': 'Expecting a value for the annotation; see annotation definition for $(ANNO)',
|
|
594
|
+
'type': 'Expecting a value of type $(TYPE) for the annotation'
|
|
545
595
|
},
|
|
546
596
|
|
|
547
597
|
'def-unexpected-paramview-assoc': {
|
|
548
|
-
std: 'SAP HANA
|
|
549
|
-
view: 'SAP HANA
|
|
550
|
-
target: 'SAP HANA
|
|
598
|
+
std: 'SAP HANA doesn\'t support associations in/to parameterized entities',
|
|
599
|
+
view: 'SAP HANA doesn\'t support associations in parameterized entities',
|
|
600
|
+
target: 'SAP HANA doesn\'t support associations to parameterized entities',
|
|
551
601
|
},
|
|
552
602
|
'def-unexpected-calcview-assoc': {
|
|
553
|
-
std: 'SAP HANA
|
|
554
|
-
'entity-persistence': 'SAP HANA
|
|
555
|
-
'target-persistence': 'SAP HANA
|
|
603
|
+
std: 'SAP HANA doesn\'t allow associations in/to entities annotated with $(ANNO)',
|
|
604
|
+
'entity-persistence': 'SAP HANA doesn\'t allow associations in entities annotated with $(ANNO)',
|
|
605
|
+
'target-persistence': 'SAP HANA doesn\'t allow associations pointing to entities annotated with $(ANNO)',
|
|
556
606
|
},
|
|
557
607
|
'def-unexpected-key': {
|
|
558
608
|
std: '$(ART) can\'t have additional keys',
|
|
@@ -566,9 +616,13 @@ const centralMessageTexts = {
|
|
|
566
616
|
include: '$(ART) can\'t have localized elements (through include)',
|
|
567
617
|
},
|
|
568
618
|
'def-unexpected-localized-anno': 'Annotations can\'t have localized elements',
|
|
619
|
+
'type-unexpected-structure': {
|
|
620
|
+
std: 'Unexpected structured type', // unused variant
|
|
621
|
+
calc: 'A structured type can\'t be used for calculated elements',
|
|
622
|
+
},
|
|
569
623
|
|
|
570
624
|
'def-missing-element': {
|
|
571
|
-
std: 'Expecting entity to have at least one
|
|
625
|
+
std: 'Expecting entity to have at least one element which is neither virtual nor calculated',
|
|
572
626
|
view: 'Expecting view to have at least one non-virtual element'
|
|
573
627
|
},
|
|
574
628
|
|
|
@@ -594,6 +648,14 @@ const centralMessageTexts = {
|
|
|
594
648
|
action: 'Duplicate definition of action or function $(NAME)',
|
|
595
649
|
param: 'Duplicate definition of parameter $(NAME)',
|
|
596
650
|
alias: 'Duplicate definition of table alias or mixin $(NAME)',
|
|
651
|
+
'include-elements': 'Duplicate element $(NAME) through multiple includes $(SORTED_ARTS)',
|
|
652
|
+
'include-actions': 'Duplicate action or function $(NAME) through multiple includes $(SORTED_ARTS)',
|
|
653
|
+
},
|
|
654
|
+
// TODO: Remove in v4, use duplicate-definition
|
|
655
|
+
'ref-duplicate-include-member': {
|
|
656
|
+
std: 'Duplicate member $(NAME) through multiple includes $(SORTED_ARTS)',
|
|
657
|
+
elements: 'Duplicate element $(NAME) through multiple includes $(SORTED_ARTS)',
|
|
658
|
+
actions: 'Duplicate action or function $(NAME) through multiple includes $(SORTED_ARTS)',
|
|
597
659
|
},
|
|
598
660
|
|
|
599
661
|
// TODO: rename to ref-expected-XYZ
|
|
@@ -612,18 +674,18 @@ const centralMessageTexts = {
|
|
|
612
674
|
'extend-unexpected-include': 'Can\'t extend $(META) with includes',
|
|
613
675
|
'ref-expecting-bare-aspect': 'An aspect without elements is expected here',
|
|
614
676
|
|
|
677
|
+
'ext-duplicate-same-file': 'Duplicate extension with $(PROP) in same file',
|
|
615
678
|
'ext-duplicate-extend-type': 'Duplicate type extension for type $(TYPE)',
|
|
616
679
|
'ext-duplicate-extend-type-unrelated-layer': 'Duplicate type extension for type $(TYPE)',
|
|
617
680
|
'ext-invalid-type-property': {
|
|
618
|
-
std: '
|
|
619
|
-
'
|
|
681
|
+
std: 'Type property $(PROP) can only be extended',
|
|
682
|
+
'indirect': 'Type property $(PROP) can only be extended if directly provided at the definition',
|
|
683
|
+
'new-prop': 'Type property $(PROP) can only be extended, not added',
|
|
684
|
+
string: 'Only numerical properties can be extended, but found string for $(PROP)',
|
|
620
685
|
// eslint-disable-next-line max-len
|
|
621
|
-
|
|
686
|
+
number: 'Value of type property $(PROP) must be $(NUMBER) or higher, it can\'t be smaller than originally provided',
|
|
622
687
|
// eslint-disable-next-line max-len
|
|
623
|
-
|
|
624
|
-
prop: 'Type property $(PROP) can\'t be extended',
|
|
625
|
-
scale: 'If property $(PROP) is increased, then so must $(OTHERPROP)',
|
|
626
|
-
string: 'Only numerical properties can be extended, but found string for $(PROP)',
|
|
688
|
+
scale: 'With the extension for type property $(OTHERPROP), the value of $(PROP) must be $(NUMBER) or higher',
|
|
627
689
|
},
|
|
628
690
|
'ref-expected-scalar-type': {
|
|
629
691
|
std: 'Only scalar type definitions can be extended with type properties',
|
|
@@ -645,12 +707,21 @@ const centralMessageTexts = {
|
|
|
645
707
|
std: 'Expected identifier for select item',
|
|
646
708
|
assoc: 'Expected identifier as the association\'s name',
|
|
647
709
|
},
|
|
648
|
-
|
|
710
|
+
'query-unsupported-calc': {
|
|
711
|
+
std: 'Using nested projections next to calculated elements is not supported, yet',
|
|
712
|
+
inside: 'Using calculated elements in nested projections is not supported, yet'
|
|
713
|
+
},
|
|
649
714
|
'ref-sloppy-type': 'A type or an element is expected here',
|
|
650
715
|
'ref-sloppy-actionparam-type': 'A type, an element, or a service entity is expected here',
|
|
651
716
|
'ref-sloppy-target': 'An entity or an aspect (not type) is expected here',
|
|
652
717
|
'ref-sloppy-event-type': 'A type, an element, an event, or a service entity is expected here',
|
|
653
718
|
|
|
719
|
+
'ref-ambiguous': {
|
|
720
|
+
std: 'Replace ambiguous $(ID) by $(NAMES)',
|
|
721
|
+
few: 'Replace ambiguous $(ID) by $(NAMES) or a new table alias for sub-queries that don\'t have one',
|
|
722
|
+
none: 'Ambiguous $(ID) requires an explicit table alias, but there are none: add table aliases to all sub-queries to disambiguate $(ID)',
|
|
723
|
+
},
|
|
724
|
+
|
|
654
725
|
'type-managed-composition': {
|
|
655
726
|
std: 'Managed compositions can\'t be used in types', // yet
|
|
656
727
|
sub: 'Managed compositions can\'t be used in sub elements',
|
|
@@ -658,6 +729,14 @@ const centralMessageTexts = {
|
|
|
658
729
|
entity: 'Entity $(ART) with managed compositions can\'t be used in types', // yet
|
|
659
730
|
},
|
|
660
731
|
|
|
732
|
+
// -----------------------------------------------------------------------------------
|
|
733
|
+
// Expressions
|
|
734
|
+
// -----------------------------------------------------------------------------------
|
|
735
|
+
'expr-invalid-operator': 'Comparing $(ID) is only allowed with $(OP)',
|
|
736
|
+
'expr-missing-comparison': {
|
|
737
|
+
std: 'Expected a comparison with $(OP) when using $(ID) in an ON-condition',
|
|
738
|
+
},
|
|
739
|
+
|
|
661
740
|
'i18n-different-value': 'Different translation for key $(PROP) of language $(OTHERPROP) in unrelated layers',
|
|
662
741
|
|
|
663
742
|
// OData version dependent messages
|
|
@@ -669,7 +748,8 @@ const centralMessageTexts = {
|
|
|
669
748
|
'odata-spec-violation-id': {
|
|
670
749
|
std: 'Expected EDM name $(ID) to start with a letter or underscore, followed by at most 127 letters, underscores or digits',
|
|
671
750
|
'v2firstchar': 'Unexpected first character $(PROP) of EDM Name $(ID) for OData $(VERSION)',
|
|
672
|
-
'qualifier': 'Expected annotation qualifier $(ID) to start with a letter or underscore, followed by at most 127 letters, underscores or digits'
|
|
751
|
+
'qualifier': 'Expected annotation qualifier $(ID) to start with a letter or underscore, followed by at most 127 letters, underscores or digits',
|
|
752
|
+
'vocrefalias': 'Expected value $(VALUE) of vocabulary reference attribute $(ID) to start with a letter or underscore, followed by at most 127 letters, underscores or digits'
|
|
673
753
|
},
|
|
674
754
|
// version independent messages
|
|
675
755
|
'odata-spec-violation-key-array': {
|
|
@@ -738,6 +818,12 @@ const centralMessageTexts = {
|
|
|
738
818
|
'experimental': '$(ANNO) is experimental and can be changed or removed at any time, do not use productively!',
|
|
739
819
|
'redefinition': '$(ANNO) is an official OASIS/SAP annotation and can\'t be redefined'
|
|
740
820
|
},
|
|
821
|
+
'odata-anno-vocref': {
|
|
822
|
+
'std': 'Vocabulary reference $(ID) doesn\'t match alias $(NAME), reference is ignored',
|
|
823
|
+
'redef': 'Vocabulary reference $(ID) is the alias of the official OASIS/SAP vocabulary $(TYPE) which can\'t be redefined, reference is ignored',
|
|
824
|
+
'service': 'Vocabulary reference collides with service $(NAME), reference is ignored',
|
|
825
|
+
'malformed': 'Vocabulary reference $(ID) has invalid or missing value for attribute $(NAME), reference is ignored'
|
|
826
|
+
},
|
|
741
827
|
'odata-anno-dict-enum': {
|
|
742
828
|
'std' : 'Unexpected annotation definition $(NAME) with many enum type',
|
|
743
829
|
'type': 'Unexpected annotation definition $(NAME) with many enum type $(TYPE)',
|
package/lib/base/messages.js
CHANGED
|
@@ -11,6 +11,7 @@ const { centralMessages, centralMessageTexts, oldMessageIds } = require('./messa
|
|
|
11
11
|
const _messageIdsWithExplanation = require('../../share/messages/message-explanations.json').messages;
|
|
12
12
|
const { analyseCsnPath, traverseQuery } = require('../model/csnRefs');
|
|
13
13
|
const { CompilerAssertion } = require('./error');
|
|
14
|
+
const { getArtifactName } = require('../compiler/base');
|
|
14
15
|
|
|
15
16
|
const fs = require('fs');
|
|
16
17
|
const path = require('path');
|
|
@@ -766,6 +767,12 @@ function transformManyWith( t, sorted ) {
|
|
|
766
767
|
};
|
|
767
768
|
}
|
|
768
769
|
|
|
770
|
+
/**
|
|
771
|
+
* Quote the given string. Performs a type sanity check.
|
|
772
|
+
*
|
|
773
|
+
* @param {string} name
|
|
774
|
+
* @return {string}
|
|
775
|
+
*/
|
|
769
776
|
function quoted( name ) {
|
|
770
777
|
if (typeof name === 'string')
|
|
771
778
|
return quote.double( name );
|
|
@@ -835,6 +842,7 @@ const nameProp = {
|
|
|
835
842
|
function: 'action',
|
|
836
843
|
};
|
|
837
844
|
|
|
845
|
+
// TODO: very likely delete this function
|
|
838
846
|
function searchName( art, id, variant ) {
|
|
839
847
|
if (!variant) {
|
|
840
848
|
// used to mention the "effective" type in the message, not the
|
|
@@ -912,16 +920,16 @@ function weakLocation( loc ) {
|
|
|
912
920
|
* @param {boolean} [noHome]
|
|
913
921
|
* @returns {string}
|
|
914
922
|
*/
|
|
915
|
-
function messageString( err, normalizeFilename, noMessageId, noHome ) {
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
923
|
+
function messageString( err, normalizeFilename, noMessageId, noHome, moduleName = undefined ) {
|
|
924
|
+
const location = (err.$location?.file ? `${ locationString( err.$location, normalizeFilename ) }: ` : '');
|
|
925
|
+
const severity = err.severity || 'Error';
|
|
926
|
+
const downgradable = severity === 'Error' && moduleName &&
|
|
927
|
+
isDowngradable(err.messageId, moduleName, false) ? '‹↓›' : '';
|
|
928
|
+
// even with noHome, print err.home if the location is weak
|
|
929
|
+
const home = !err.home || noHome && err.$location?.endLine ? '' : ` (in ${ err.home })`;
|
|
930
|
+
// TODO: the plan was with brackets = `Error[ref-undefined-def]`
|
|
931
|
+
const id = err.messageId && !noMessageId ? ` ${ err.messageId }` : '';
|
|
932
|
+
return `${ location }${ severity }${ downgradable }${ id }: ${ err.message }${ home }`;
|
|
925
933
|
}
|
|
926
934
|
|
|
927
935
|
/**
|
|
@@ -1180,7 +1188,7 @@ function deduplicateMessages( messages ) {
|
|
|
1180
1188
|
}
|
|
1181
1189
|
|
|
1182
1190
|
function shortArtName( art ) {
|
|
1183
|
-
const
|
|
1191
|
+
const name = getArtifactName( art );
|
|
1184
1192
|
if ([ 'select', 'action', 'alias', 'param' ].every( n => name[n] == null || name[n] === 1 ) &&
|
|
1185
1193
|
!name.absolute.includes(':'))
|
|
1186
1194
|
return quote.double( name.element ? `${ name.absolute }:${ name.element }` : name.absolute );
|
|
@@ -1188,13 +1196,13 @@ function shortArtName( art ) {
|
|
|
1188
1196
|
}
|
|
1189
1197
|
|
|
1190
1198
|
function artName( art, omit ) {
|
|
1191
|
-
const
|
|
1199
|
+
const name = getArtifactName( art );
|
|
1192
1200
|
const r = (name.absolute) ? [ quoted( name.absolute ) ] : [];
|
|
1193
1201
|
if (name.select && name.select > 1 || name.select != null && art.kind !== 'element') // Yes, omit select:1 for element - TODO: re-check
|
|
1194
1202
|
r.push( (art.kind === 'extend' ? 'block:' : 'query:') + name.select ); // TODO: rename to 'select:1' and consider whether there are more selects
|
|
1195
1203
|
if (name.action && omit !== 'action')
|
|
1196
1204
|
r.push( `${ memberActionName(art) }:${ quoted( name.action ) }` );
|
|
1197
|
-
if (name.alias && art.kind !== '$self')
|
|
1205
|
+
if (name.alias && art.kind !== '$self' && name.$inferred !== '$internal')
|
|
1198
1206
|
r.push( (art.kind === 'mixin' ? 'mixin:' : 'alias:') + quoted( name.alias ) );
|
|
1199
1207
|
if (name.param != null && omit !== 'param')
|
|
1200
1208
|
r.push( name.param ? `param:${ quoted( name.param ) }` : 'returns' ); // TODO: join
|
|
@@ -1225,7 +1233,7 @@ function memberActionName( art ) {
|
|
|
1225
1233
|
function homeName( art, absoluteOnly ) {
|
|
1226
1234
|
if (!art)
|
|
1227
1235
|
return art;
|
|
1228
|
-
if (art._outer) // in
|
|
1236
|
+
if (art._outer) // in items property
|
|
1229
1237
|
return homeName( art._outer, absoluteOnly );
|
|
1230
1238
|
else if (art.kind === 'source' || !art.name) // error reported in parser or on source level
|
|
1231
1239
|
return null;
|
|
@@ -1245,7 +1253,10 @@ function homeName( art, absoluteOnly ) {
|
|
|
1245
1253
|
|
|
1246
1254
|
// The "home" for extensions is handled differently because `_artifact` is not
|
|
1247
1255
|
// set for unknown extensions, and we could have nested extensions.
|
|
1256
|
+
// TODO: delete this function, just set correct name/_parent for extensions
|
|
1248
1257
|
function homeNameForExtend( art ) {
|
|
1258
|
+
if (!art.name.absolute && art._main) // new-style member name
|
|
1259
|
+
return `${ art._main.kind }:${ artName( art ) }`;
|
|
1249
1260
|
const kind = art.kind || 'extend';
|
|
1250
1261
|
// TODO: fix the following - do like in collectArtifactExtensions() or
|
|
1251
1262
|
// basically resolveUncheckedPath()
|
|
@@ -1309,6 +1320,12 @@ function homeNameForExtend( art ) {
|
|
|
1309
1320
|
function constructSemanticLocationFromCsnPath( model, options, csnPath ) {
|
|
1310
1321
|
if (!model)
|
|
1311
1322
|
return null;
|
|
1323
|
+
|
|
1324
|
+
if (options.testMode)
|
|
1325
|
+
sanitizeCsnPath(csnPath);
|
|
1326
|
+
|
|
1327
|
+
const _quoted = options.testMode ? quoted : quote.double;
|
|
1328
|
+
|
|
1312
1329
|
let result = '';
|
|
1313
1330
|
const csnDictionaries = [
|
|
1314
1331
|
'args', 'params', 'enum', 'mixin', 'elements', 'actions', 'definitions',
|
|
@@ -1338,12 +1355,12 @@ function constructSemanticLocationFromCsnPath( model, options, csnPath ) {
|
|
|
1338
1355
|
if (step === 'definitions') {
|
|
1339
1356
|
next(); // "definitions"
|
|
1340
1357
|
const kind = currentThing?.kind || 'artifact';
|
|
1341
|
-
result += `${ kind }:${
|
|
1358
|
+
result += `${ kind }:${ _quoted(step) }`;
|
|
1342
1359
|
}
|
|
1343
1360
|
else if (step === 'vocabularies') {
|
|
1344
1361
|
next(); // dictionary name
|
|
1345
1362
|
if (index < csnPath.length)
|
|
1346
|
-
result += `annotation:${
|
|
1363
|
+
result += `annotation:${ _quoted(csnPath[index]) }`;
|
|
1347
1364
|
else
|
|
1348
1365
|
result += 'vocabularies';
|
|
1349
1366
|
}
|
|
@@ -1355,7 +1372,7 @@ function constructSemanticLocationFromCsnPath( model, options, csnPath ) {
|
|
|
1355
1372
|
else {
|
|
1356
1373
|
const name = currentThing.annotate || currentThing.extend;
|
|
1357
1374
|
const kind = currentThing.annotate ? 'annotate' : 'extend';
|
|
1358
|
-
result += `${ kind }:${
|
|
1375
|
+
result += `${ kind }:${ _quoted(name) }`;
|
|
1359
1376
|
}
|
|
1360
1377
|
}
|
|
1361
1378
|
|
|
@@ -1381,7 +1398,7 @@ function constructSemanticLocationFromCsnPath( model, options, csnPath ) {
|
|
|
1381
1398
|
next();
|
|
1382
1399
|
}
|
|
1383
1400
|
if (elementHierarchy.length > 0)
|
|
1384
|
-
result += `/element:${
|
|
1401
|
+
result += `/element:${ _quoted(elementHierarchy.join('.')) }`;
|
|
1385
1402
|
// no trailing /elements or /items
|
|
1386
1403
|
continue;
|
|
1387
1404
|
}
|
|
@@ -1389,7 +1406,7 @@ function constructSemanticLocationFromCsnPath( model, options, csnPath ) {
|
|
|
1389
1406
|
next(); // "actions"
|
|
1390
1407
|
if (index < csnPath.length) {
|
|
1391
1408
|
const kind = currentThing?.kind || 'action';
|
|
1392
|
-
result += `/${ kind }:${
|
|
1409
|
+
result += `/${ kind }:${ _quoted(csnPath[index]) }`;
|
|
1393
1410
|
}
|
|
1394
1411
|
else { // actions is last segment
|
|
1395
1412
|
result += '/actions';
|
|
@@ -1419,7 +1436,7 @@ function constructSemanticLocationFromCsnPath( model, options, csnPath ) {
|
|
|
1419
1436
|
}
|
|
1420
1437
|
else if (step === 'target') {
|
|
1421
1438
|
if (currentThing)
|
|
1422
|
-
result += '/target:' +
|
|
1439
|
+
result += '/target:' + _quoted(currentThing);
|
|
1423
1440
|
else
|
|
1424
1441
|
result += '/target';
|
|
1425
1442
|
break;
|
|
@@ -1447,14 +1464,14 @@ function constructSemanticLocationFromCsnPath( model, options, csnPath ) {
|
|
|
1447
1464
|
next(); // "keys"
|
|
1448
1465
|
if (index < csnPath.length) {
|
|
1449
1466
|
const key = aliasOrReference();
|
|
1450
|
-
result += `/key:${ key ?
|
|
1467
|
+
result += `/key:${ key ? _quoted(key) : step }`;
|
|
1451
1468
|
}
|
|
1452
1469
|
break;
|
|
1453
1470
|
}
|
|
1454
1471
|
else if (step[0] === '@') {
|
|
1455
1472
|
// Annotations are always the last step.
|
|
1456
1473
|
// Nothing comes after them, everything is user defined.
|
|
1457
|
-
result += `/${
|
|
1474
|
+
result += `/${ _quoted(csnPath[index]) }`;
|
|
1458
1475
|
break;
|
|
1459
1476
|
}
|
|
1460
1477
|
else {
|
|
@@ -1470,7 +1487,7 @@ function constructSemanticLocationFromCsnPath( model, options, csnPath ) {
|
|
|
1470
1487
|
function dictEntry( prefix ) {
|
|
1471
1488
|
next(); // dictionary name
|
|
1472
1489
|
if (index < csnPath.length)
|
|
1473
|
-
result += `/${ prefix }:${
|
|
1490
|
+
result += `/${ prefix }:${ _quoted(csnPath[index]) }`;
|
|
1474
1491
|
}
|
|
1475
1492
|
|
|
1476
1493
|
/**
|
|
@@ -1548,7 +1565,7 @@ function constructSemanticLocationFromCsnPath( model, options, csnPath ) {
|
|
|
1548
1565
|
} while (index < csnPath.length);
|
|
1549
1566
|
|
|
1550
1567
|
if (elementHierarchy.length > 0)
|
|
1551
|
-
result += `/column:${
|
|
1568
|
+
result += `/column:${ _quoted(elementHierarchy.join('.')) }`;
|
|
1552
1569
|
}
|
|
1553
1570
|
else if(step === 'args') {
|
|
1554
1571
|
// Should only be reached for cases, where no SELECT in a union is picked.
|
|
@@ -1578,11 +1595,11 @@ function queryDepthForMessage( csnPath, model, view ) {
|
|
|
1578
1595
|
if (!targetQuery)
|
|
1579
1596
|
return 0;
|
|
1580
1597
|
const rootQuery = view.query || { SELECT: view.projection };
|
|
1581
|
-
let depth =
|
|
1598
|
+
let depth = 0;
|
|
1582
1599
|
let totalDepth = 0;
|
|
1583
1600
|
let isFound = false;
|
|
1584
|
-
traverseQuery(rootQuery, null, null, (q
|
|
1585
|
-
if (
|
|
1601
|
+
traverseQuery(rootQuery, null, null, (q) => {
|
|
1602
|
+
if (q.SELECT) {
|
|
1586
1603
|
totalDepth += 1;
|
|
1587
1604
|
if (!isFound)
|
|
1588
1605
|
depth += 1;
|
|
@@ -1595,6 +1612,13 @@ function queryDepthForMessage( csnPath, model, view ) {
|
|
|
1595
1612
|
return 0;
|
|
1596
1613
|
}
|
|
1597
1614
|
|
|
1615
|
+
function sanitizeCsnPath(csnPath) {
|
|
1616
|
+
for (const step of csnPath) {
|
|
1617
|
+
if (typeof step !== 'string' && typeof step !== 'number')
|
|
1618
|
+
throw new CompilerAssertion(`Found CSN path step that is neither string nor number: ${step} ${ JSON.stringify(csnPath) }`)
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1598
1622
|
/**
|
|
1599
1623
|
* Get the explanation string for the given message-id.
|
|
1600
1624
|
* Ensure to have called hasMessageExplanation() before.
|
package/lib/base/model.js
CHANGED
|
@@ -21,7 +21,7 @@ const queryOps = {
|
|
|
21
21
|
*/
|
|
22
22
|
const availableBetaFlags = {
|
|
23
23
|
// enabled by --beta-mode
|
|
24
|
-
|
|
24
|
+
annotationExpressions: true,
|
|
25
25
|
toRename: true,
|
|
26
26
|
assocsWithParams: true,
|
|
27
27
|
hanaAssocRealCardinality: true,
|
|
@@ -35,6 +35,7 @@ const availableBetaFlags = {
|
|
|
35
35
|
optionalActionFunctionParameters: true,
|
|
36
36
|
// disabled by --beta-mode
|
|
37
37
|
nestedServices: false,
|
|
38
|
+
v4preview: false,
|
|
38
39
|
};
|
|
39
40
|
|
|
40
41
|
const availableDeprecatedFlags = {
|
|
@@ -110,7 +111,7 @@ function isDeprecatedEnabled( options, feature = null ) {
|
|
|
110
111
|
* to change their code, emit an error if one of such removed flags was used.
|
|
111
112
|
*
|
|
112
113
|
* @param {CSN.Options} options
|
|
113
|
-
* @param error Error message function returned by
|
|
114
|
+
* @param error Error message function returned by makeMessageFunction().
|
|
114
115
|
*/
|
|
115
116
|
function checkRemovedDeprecatedFlags( options, { error } ) {
|
|
116
117
|
// Assume that we emitted these errors once if a message with this ID was found.
|
|
@@ -127,6 +128,7 @@ function checkRemovedDeprecatedFlags( options, { error } ) {
|
|
|
127
128
|
|
|
128
129
|
// Apply function `callback` to all artifacts in dictionary
|
|
129
130
|
// `model.definitions`. See function `forEachGeneric` for details.
|
|
131
|
+
// TODO: should we skip "namespaces" already here?
|
|
130
132
|
function forEachDefinition( model, callback ) {
|
|
131
133
|
forEachGeneric( model, 'definitions', callback );
|
|
132
134
|
}
|
package/lib/base/shuffle.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
// By <https://github.com/bryc/code/blob/c97a26ad27a9f9d4f48cd3307fd8ee6f1772d4eb/jshash/PRNGs.md>:
|
|
4
4
|
|
|
5
|
-
// The random seed must be an integer between
|
|
5
|
+
// The random seed must be an integer between 1 and 4294967296 (= 2**32),
|
|
6
|
+
// otherwise no shuffling takes place.
|
|
6
7
|
function shuffleGen( seed ) {
|
|
7
8
|
return (Number.isSafeInteger( seed ) && seed > 0)
|
|
8
9
|
? { shuffleArray, shuffleDict }
|
package/lib/checks/arrayOfs.js
CHANGED
|
@@ -32,7 +32,7 @@ function validateAssociationsInItems( member ) {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
|
-
if (this.artifact &&
|
|
35
|
+
if (this.artifact && this.artifact.kind === 'entity' && member && member.items && member.$path[2] === 'elements') {
|
|
36
36
|
if (member.items.type) {
|
|
37
37
|
const type = member.items.type.ref
|
|
38
38
|
? this.artifactRef(member.items.type)
|
|
@@ -53,7 +53,7 @@ function rejectParamDefaultsInHanaCds( member, memberName, prop, path ) {
|
|
|
53
53
|
*/
|
|
54
54
|
function warnAboutDefaultOnAssociationForHanaCds( member, memberName, prop, path ) {
|
|
55
55
|
const art = this.csn.definitions[path[1]];
|
|
56
|
-
if (!art.query && this.options.transformation === 'hdbcds' && member.target && member.default) {
|
|
56
|
+
if (!art.query && !art.projection && this.options.transformation === 'hdbcds' && member.target && member.default) {
|
|
57
57
|
this.warning(null, path, { '#': member._type.type === 'cds.Association' ? 'std' : 'comp' },
|
|
58
58
|
{
|
|
59
59
|
std: 'Unexpected default defined on association',
|
package/lib/checks/elements.js
CHANGED
|
@@ -208,6 +208,34 @@ function checkRecursiveTypeUsage( art ) {
|
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Member validator to check that certain annotations (@cds.valid { from, to, key }) are not
|
|
214
|
+
* assigned to calculated elements in an entity.
|
|
215
|
+
*
|
|
216
|
+
* TODO: Allow @cds.valid on persisted calculated elements (when they become available).
|
|
217
|
+
*
|
|
218
|
+
* @param {CSN.Element} member the element to be checked
|
|
219
|
+
* @param {string} _memberName the elements name
|
|
220
|
+
* @param {string} _prop which kind of member are we looking at -> only prop "elements"
|
|
221
|
+
* @param {CSN.Path} _path the path to the member
|
|
222
|
+
*/
|
|
223
|
+
function rejectAnnotationsOnCalcElement( member, _memberName, _prop, _path ) {
|
|
224
|
+
if (this.artifact.kind === 'entity' && !(this.artifact.query && this.artifact.projection)) {
|
|
225
|
+
if (member.value) {
|
|
226
|
+
for (const anno in member) {
|
|
227
|
+
if (anno.startsWith('@cds.valid.')) {
|
|
228
|
+
this.error('anno-unexpected-temporal', member.$path, { anno },
|
|
229
|
+
'Unexpected $(ANNO) assigned to a calculated element');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
211
235
|
module.exports = {
|
|
212
|
-
checkPrimaryKey,
|
|
236
|
+
checkPrimaryKey,
|
|
237
|
+
checkVirtualElement,
|
|
238
|
+
checkManagedAssoc,
|
|
239
|
+
checkRecursiveTypeUsage,
|
|
240
|
+
rejectAnnotationsOnCalcElement,
|
|
213
241
|
};
|