@sap/cds-compiler 4.0.2 → 4.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +200 -5
- package/bin/cdsc.js +18 -15
- package/doc/CHANGELOG_BETA.md +16 -0
- package/doc/CHANGELOG_DEPRECATED.md +15 -0
- package/lib/api/main.js +33 -13
- package/lib/api/options.js +2 -2
- package/lib/api/validate.js +25 -25
- package/lib/base/location.js +6 -7
- package/lib/base/message-registry.js +123 -42
- package/lib/base/messages.js +18 -10
- package/lib/base/model.js +43 -10
- package/lib/checks/defaultValues.js +6 -6
- package/lib/checks/elements.js +11 -10
- package/lib/checks/foreignKeys.js +0 -5
- package/lib/checks/manyNavigations.js +33 -0
- package/lib/checks/onConditions.js +22 -14
- package/lib/checks/queryNoDbArtifacts.js +132 -73
- package/lib/checks/selectItems.js +4 -55
- package/lib/checks/sql-snippets.js +15 -4
- package/lib/checks/types.js +3 -3
- package/lib/checks/utils.js +4 -3
- package/lib/checks/validator.js +3 -1
- package/lib/compiler/.eslintrc.json +2 -1
- package/lib/compiler/assert-consistency.js +71 -40
- package/lib/compiler/base.js +7 -2
- package/lib/compiler/builtins.js +40 -41
- package/lib/compiler/checks.js +415 -367
- package/lib/compiler/classes.js +62 -0
- package/lib/compiler/cycle-detector.js +9 -9
- package/lib/compiler/define.js +124 -90
- package/lib/compiler/extend.js +115 -88
- package/lib/compiler/finalize-parse-cdl.js +26 -25
- package/lib/compiler/generate.js +57 -49
- package/lib/compiler/index.js +56 -56
- package/lib/compiler/kick-start.js +10 -7
- package/lib/compiler/moduleLayers.js +1 -1
- package/lib/compiler/populate.js +180 -144
- package/lib/compiler/propagator.js +10 -9
- package/lib/compiler/resolve.js +321 -246
- package/lib/compiler/shared.js +812 -433
- package/lib/compiler/tweak-assocs.js +114 -50
- package/lib/compiler/utils.js +241 -46
- package/lib/edm/.eslintrc.json +40 -1
- package/lib/edm/annotations/genericTranslation.js +721 -707
- package/lib/edm/annotations/preprocessAnnotations.js +88 -77
- package/lib/edm/csn2edm.js +389 -378
- package/lib/edm/edm.js +679 -770
- package/lib/edm/edmAnnoPreprocessor.js +132 -146
- package/lib/edm/edmInboundChecks.js +29 -27
- package/lib/edm/edmPreprocessor.js +689 -648
- package/lib/edm/edmUtils.js +279 -300
- package/lib/gen/Dictionary.json +34 -10
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +2857 -2856
- package/lib/json/from-csn.js +77 -51
- package/lib/json/to-csn.js +15 -15
- package/lib/language/antlrParser.js +2 -1
- package/lib/language/genericAntlrParser.js +52 -43
- package/lib/language/language.g4 +61 -64
- package/lib/language/multiLineStringParser.js +2 -0
- package/lib/main.d.ts +65 -0
- package/lib/model/csnRefs.js +37 -19
- package/lib/model/csnUtils.js +51 -18
- package/lib/model/revealInternalProperties.js +30 -22
- package/lib/modelCompare/compare.js +149 -41
- package/lib/modelCompare/utils/filter.js +55 -25
- package/lib/optionProcessor.js +21 -9
- package/lib/render/manageConstraints.js +20 -17
- package/lib/render/toCdl.js +63 -23
- package/lib/render/toHdbcds.js +2 -2
- package/lib/render/toRename.js +4 -9
- package/lib/render/toSql.js +82 -35
- package/lib/render/utils/common.js +11 -9
- package/lib/render/utils/unique.js +52 -0
- package/lib/transform/db/applyTransformations.js +62 -21
- package/lib/transform/db/assertUnique.js +7 -8
- package/lib/transform/db/associations.js +2 -2
- package/lib/transform/db/cdsPersistence.js +9 -9
- package/lib/transform/db/constraints.js +47 -17
- package/lib/transform/db/expansion.js +138 -68
- package/lib/transform/db/flattening.js +98 -30
- package/lib/transform/db/rewriteCalculatedElements.js +20 -14
- package/lib/transform/db/temporal.js +1 -1
- package/lib/transform/db/transformExists.js +8 -7
- package/lib/transform/db/views.js +73 -33
- package/lib/transform/draft/db.js +11 -9
- package/lib/transform/draft/odata.js +1 -1
- package/lib/transform/{forOdataNew.js → forOdata.js} +10 -7
- package/lib/transform/forRelationalDB.js +148 -136
- package/lib/transform/localized.js +92 -54
- package/lib/transform/odata/toFinalBaseType.js +3 -3
- package/lib/transform/{transformUtilsNew.js → transformUtils.js} +13 -111
- package/lib/transform/translateAssocsToJoins.js +14 -28
- package/lib/utils/file.js +7 -7
- package/lib/utils/moduleResolve.js +210 -121
- package/lib/utils/objectUtils.js +1 -1
- package/package.json +5 -5
- package/share/messages/check-proper-type-of.md +1 -1
- package/share/messages/{check-proper-type.md → def-missing-type.md} +3 -5
- package/share/messages/message-explanations.json +1 -1
package/lib/language/language.g4
CHANGED
|
@@ -216,7 +216,7 @@ usingProxy[ outer, proxy ]
|
|
|
216
216
|
)
|
|
217
217
|
;
|
|
218
218
|
|
|
219
|
-
artifactDefOrExtend[ outer, defOnly = false ] locals[ art =
|
|
219
|
+
artifactDefOrExtend[ outer, defOnly = false ] locals[ art = new parser.XsnArtifact() ] // cannot use `parent` as parameter name!
|
|
220
220
|
@after{ /* #ATN 1 */ }
|
|
221
221
|
:
|
|
222
222
|
{ $art.location = this.startLocation(); this.docComment( $art ); }
|
|
@@ -285,13 +285,13 @@ optionalSemi
|
|
|
285
285
|
|
|
286
286
|
// Annotation def and main definitions ------------------------------------------
|
|
287
287
|
|
|
288
|
-
annotationDef[ art, outer ] locals[ name =
|
|
288
|
+
annotationDef[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
289
289
|
@after { this.attachLocation( $art ); }
|
|
290
290
|
:
|
|
291
291
|
annotation=ANNOTATION simplePath[ $name, 'AnnoDef' ]
|
|
292
292
|
{ if ($outer.kind !== 'source') { // this is a syntax restriction to avoid confusion
|
|
293
293
|
this.error( 'syntax-unexpected-vocabulary', $annotation, { '#': $outer.kind } );
|
|
294
|
-
$art =
|
|
294
|
+
$art = new this.XsnArtifact(); }
|
|
295
295
|
else {
|
|
296
296
|
if (!$outer.vocabularies) $outer.vocabularies = Object.create(null);
|
|
297
297
|
this.addDef( $art, $outer, 'vocabularies', 'annotation', $name );
|
|
@@ -301,7 +301,7 @@ annotationDef[ art, outer ] locals[ name = {} ]
|
|
|
301
301
|
typeSpecSemi[ $art ] // also 'includes'...
|
|
302
302
|
;
|
|
303
303
|
|
|
304
|
-
serviceDef[ art, outer, defOnly = false ] locals[ name =
|
|
304
|
+
serviceDef[ art, outer, defOnly = false ] locals[ name = new parser.XsnName(); ]
|
|
305
305
|
@after { this.attachLocation( $art ); }
|
|
306
306
|
:
|
|
307
307
|
SERVICE simplePath[ $name, 'Service' ]
|
|
@@ -309,7 +309,7 @@ serviceDef[ art, outer, defOnly = false ] locals[ name = {} ]
|
|
|
309
309
|
optArtifactsBlock[ $art, defOnly ]
|
|
310
310
|
;
|
|
311
311
|
|
|
312
|
-
contextDef[ art, outer, defOnly = false ] locals[ name =
|
|
312
|
+
contextDef[ art, outer, defOnly = false ] locals[ name = new parser.XsnName(); ]
|
|
313
313
|
@after { this.attachLocation( $art ); }
|
|
314
314
|
:
|
|
315
315
|
CONTEXT simplePath[ $name, 'Context' ]
|
|
@@ -317,7 +317,7 @@ contextDef[ art, outer, defOnly = false ] locals[ name = {} ]
|
|
|
317
317
|
optArtifactsBlock[ $art, defOnly ]
|
|
318
318
|
;
|
|
319
319
|
|
|
320
|
-
eventDef[ art, outer ] locals[ name =
|
|
320
|
+
eventDef[ art, outer ] locals[ name = new parser.XsnName(); ]
|
|
321
321
|
@after { /* #ATN 1 */ this.attachLocation( $art ); }
|
|
322
322
|
:
|
|
323
323
|
EVENT simplePath[ $name, 'Event' ]
|
|
@@ -353,7 +353,7 @@ eventDef[ art, outer ] locals[ name = {} ]
|
|
|
353
353
|
)
|
|
354
354
|
;
|
|
355
355
|
|
|
356
|
-
viewDef[ art, outer ] locals[ name =
|
|
356
|
+
viewDef[ art, outer ] locals[ name = new parser.XsnName(); ]
|
|
357
357
|
@after { this.attachLocation( $art ); }
|
|
358
358
|
:
|
|
359
359
|
v=VIEW simplePath[ $name, 'Entity' ]
|
|
@@ -376,7 +376,7 @@ viewDef[ art, outer ] locals[ name = {} ]
|
|
|
376
376
|
requiredSemi
|
|
377
377
|
;
|
|
378
378
|
|
|
379
|
-
entityDef[ art, outer ] locals[ name =
|
|
379
|
+
entityDef[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
380
380
|
@after { this.attachLocation( $art ); }
|
|
381
381
|
:
|
|
382
382
|
ENTITY simplePath[ $name, 'Entity' ]
|
|
@@ -424,7 +424,7 @@ entityDef[ art, outer ] locals[ name = {} ]
|
|
|
424
424
|
)
|
|
425
425
|
;
|
|
426
426
|
|
|
427
|
-
aspectDef[ art, outer ] locals[ name =
|
|
427
|
+
aspectDef[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
428
428
|
@after { this.attachLocation( $art ); }
|
|
429
429
|
:
|
|
430
430
|
( ASPECT | ( abs=ABSTRACT | HideAlternatives ) ent=ENTITY )
|
|
@@ -453,12 +453,11 @@ aspectDef[ art, outer ] locals[ name = {} ]
|
|
|
453
453
|
)?
|
|
454
454
|
optionalSemi
|
|
455
455
|
| // `aspect MyAspect;`, e.g. for annotation aspects.
|
|
456
|
-
{ this.aspectWithoutElements( $art ); }
|
|
457
456
|
requiredSemi
|
|
458
457
|
)
|
|
459
458
|
;
|
|
460
459
|
|
|
461
|
-
typeDef[ art, outer ] locals[ name =
|
|
460
|
+
typeDef[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
462
461
|
@after { this.attachLocation( $art ); }
|
|
463
462
|
:
|
|
464
463
|
TYPE simplePath[ $name, 'Type' ]
|
|
@@ -468,7 +467,7 @@ typeDef[ art, outer ] locals[ name = {} ]
|
|
|
468
467
|
typeSpecSemi[ $art ]
|
|
469
468
|
;
|
|
470
469
|
|
|
471
|
-
actionFunctionMainDef[ art, outer ] locals[ name =
|
|
470
|
+
actionFunctionMainDef[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
472
471
|
@after { this.attachLocation( $art ); }
|
|
473
472
|
:
|
|
474
473
|
ACTION simplePath[ $name, 'Action' ]
|
|
@@ -488,7 +487,7 @@ actionFunctionMainDef[ art, outer ] locals[ name = {} ]
|
|
|
488
487
|
|
|
489
488
|
// Member definitions: actions, elements, enums, parameters: --------------------
|
|
490
489
|
|
|
491
|
-
actionFunctionDef[ outer ] locals[ art =
|
|
490
|
+
actionFunctionDef[ outer ] locals[ art = new parser.XsnArtifact() ]
|
|
492
491
|
@after { this.attachLocation( $art ); }
|
|
493
492
|
:
|
|
494
493
|
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
@@ -510,7 +509,7 @@ actionFunctionDef[ outer ] locals[ art = {} ]
|
|
|
510
509
|
)
|
|
511
510
|
;
|
|
512
511
|
|
|
513
|
-
parameterDef[ outer ] locals[ art =
|
|
512
|
+
parameterDef[ outer ] locals[ art = new parser.XsnArtifact() ]
|
|
514
513
|
@after { this.attachLocation( $art ); }
|
|
515
514
|
:
|
|
516
515
|
{ this.meltKeywordToIdentifier();; this.docComment( $art ); }
|
|
@@ -546,7 +545,7 @@ parameterListDef[ art ]
|
|
|
546
545
|
')' { this.finalizeDictOrArray( $art.params ); }
|
|
547
546
|
;
|
|
548
547
|
|
|
549
|
-
enumSymbolDef[ outer ] locals[ art =
|
|
548
|
+
enumSymbolDef[ outer ] locals[ art = new parser.XsnArtifact() ]
|
|
550
549
|
@after { this.attachLocation( $art ); }
|
|
551
550
|
:
|
|
552
551
|
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
@@ -570,14 +569,14 @@ enumSymbolDef[ outer ] locals[ art = {} ]
|
|
|
570
569
|
requiredSemi
|
|
571
570
|
;
|
|
572
571
|
|
|
573
|
-
elementDef[ outer ] locals[ $art =
|
|
572
|
+
elementDef[ outer ] locals[ $art = new parser.XsnArtifact() ]
|
|
574
573
|
:
|
|
575
574
|
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
576
575
|
annotationAssignment_ll1[ $art ]*
|
|
577
|
-
elementDefInner[ $art, $outer
|
|
576
|
+
elementDefInner[ $art, $outer ]
|
|
578
577
|
;
|
|
579
578
|
|
|
580
|
-
elementDefInner[ art, outer,
|
|
579
|
+
elementDefInner[ art, outer, explicitElement = false ]
|
|
581
580
|
@after{ this.attachLocation( $art ); }
|
|
582
581
|
:
|
|
583
582
|
// VIRTUAL is keyword, except if before the following tokens texts:
|
|
@@ -592,7 +591,7 @@ elementDefInner[ art, outer, mightBeEnum ]
|
|
|
592
591
|
}
|
|
593
592
|
)?
|
|
594
593
|
{ this.setLocalToken( 'ELEMENT', 'ELEMENT', /^[;:{@=}]$/ ); }
|
|
595
|
-
( ELEMENT { $
|
|
594
|
+
( ELEMENT { $explicitElement = true; } )? // auto-recognizable at other places
|
|
596
595
|
name=ident['Element']
|
|
597
596
|
{ this.addDef( $art, $outer, 'elements', 'element', $name.id );
|
|
598
597
|
this.docComment( $art ); }
|
|
@@ -605,7 +604,7 @@ elementDefInner[ art, outer, mightBeEnum ]
|
|
|
605
604
|
)
|
|
606
605
|
|
|
|
607
606
|
':'
|
|
608
|
-
elementType[ $art
|
|
607
|
+
elementType[ $art ]
|
|
609
608
|
|
|
|
610
609
|
eq='=' e=expression // SQL has syntax variant using AS - we DO NOT
|
|
611
610
|
stored=STORED?
|
|
@@ -613,10 +612,8 @@ elementDefInner[ art, outer, mightBeEnum ]
|
|
|
613
612
|
// this.setIntroLocation( eq ); -- future
|
|
614
613
|
if ($stored)
|
|
615
614
|
$art.value.stored = this.valueWithTokenLocation( true, $stored );
|
|
616
|
-
if ($
|
|
617
|
-
|
|
618
|
-
!$virtual && !$key && !$masked && !$art.elements && !$art.type)
|
|
619
|
-
$art['$'+'syntax'] = 'enum';
|
|
615
|
+
if ($explicitElement)
|
|
616
|
+
$art['$'+'syntax'] = 'element';
|
|
620
617
|
}
|
|
621
618
|
{ this.docComment( $art ); }
|
|
622
619
|
annotationAssignment_ll1[ $art ]* // for enum symbol def via EXTEND
|
|
@@ -750,7 +747,7 @@ defaultValue[ art ] locals[ elem, elements = {} ]
|
|
|
750
747
|
|
|
751
748
|
// Extend and annotate ----------------------------------------------------------
|
|
752
749
|
|
|
753
|
-
extendArtifact[ art, outer ] locals[ name =
|
|
750
|
+
extendArtifact[ art, outer ] locals[ name = new parser.XsnName(), elemName = new parser.XsnName() ]
|
|
754
751
|
@after{ /* #ATN 1 */ this.attachLocation( $art ); }
|
|
755
752
|
:
|
|
756
753
|
simplePath[ $name, 'Extend' ]
|
|
@@ -771,7 +768,7 @@ extendArtifact[ art, outer ] locals[ name = {}, elemName = {} ]
|
|
|
771
768
|
(
|
|
772
769
|
// all the alternatives from `extendWithOptElementsOrType` --------------
|
|
773
770
|
'{' { $art.elements = this.createDict(); }
|
|
774
|
-
elementDefOrExtend[ $art
|
|
771
|
+
elementDefOrExtend[ $art ]*
|
|
775
772
|
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
776
773
|
{ this.checkExtensionDict( $art.elements ); }
|
|
777
774
|
optionalSemi
|
|
@@ -779,7 +776,7 @@ extendArtifact[ art, outer ] locals[ name = {}, elemName = {} ]
|
|
|
779
776
|
requiredSemi
|
|
780
777
|
|
|
|
781
778
|
ELEMENTS { $art.elements = this.createDict(); } '{'
|
|
782
|
-
elementDefOrExtend[ $art ]*
|
|
779
|
+
elementDefOrExtend[ $art, true ]*
|
|
783
780
|
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
784
781
|
{ this.checkExtensionDict( $art.elements ); }
|
|
785
782
|
optionalSemi
|
|
@@ -823,7 +820,7 @@ extendArtifact[ art, outer ] locals[ name = {}, elemName = {} ]
|
|
|
823
820
|
)
|
|
824
821
|
;
|
|
825
822
|
|
|
826
|
-
extendService[ art, outer ] locals[ name =
|
|
823
|
+
extendService[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
827
824
|
@after { this.attachLocation( $art ); }
|
|
828
825
|
:
|
|
829
826
|
SERVICE { $art.expectedKind = this.valueWithTokenLocation(); }
|
|
@@ -833,7 +830,7 @@ extendService[ art, outer ] locals[ name = {} ]
|
|
|
833
830
|
optArtifactsBlock[ art, 'service' ]
|
|
834
831
|
;
|
|
835
832
|
|
|
836
|
-
extendContext[ art, outer ] locals[ name =
|
|
833
|
+
extendContext[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
837
834
|
@after { this.attachLocation( $art ); }
|
|
838
835
|
:
|
|
839
836
|
CONTEXT { $art.expectedKind = this.valueWithTokenLocation(); }
|
|
@@ -843,7 +840,7 @@ extendContext[ art, outer ] locals[ name = {} ]
|
|
|
843
840
|
optArtifactsBlock[ art, 'context' ]
|
|
844
841
|
;
|
|
845
842
|
|
|
846
|
-
extendEntityOrAspect[ art, outer ] locals[ name =
|
|
843
|
+
extendEntityOrAspect[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
847
844
|
@after { /* #ATN 1 */ this.attachLocation( $art ); }
|
|
848
845
|
:
|
|
849
846
|
(ASPECT | ENTITY) { $art.expectedKind = this.valueWithTokenLocation(); }
|
|
@@ -888,7 +885,7 @@ extendForEntity[ art ]
|
|
|
888
885
|
requiredSemi
|
|
889
886
|
;
|
|
890
887
|
|
|
891
|
-
extendProjection[ art, outer ] locals[ name =
|
|
888
|
+
extendProjection[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
892
889
|
@after { this.attachLocation( $art ); }
|
|
893
890
|
:
|
|
894
891
|
PROJECTION { $art.expectedKind = this.valueWithTokenLocation( 'entity' ); }
|
|
@@ -924,7 +921,7 @@ extendProjection[ art, outer ] locals[ name = {} ]
|
|
|
924
921
|
)
|
|
925
922
|
;
|
|
926
923
|
|
|
927
|
-
extendType[ art, outer ] locals[ name =
|
|
924
|
+
extendType[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
928
925
|
@after { this.attachLocation( $art ); }
|
|
929
926
|
:
|
|
930
927
|
TYPE { $art.expectedKind = this.valueWithTokenLocation(); }
|
|
@@ -940,7 +937,7 @@ extendType[ art, outer ] locals[ name = {} ]
|
|
|
940
937
|
annotationAssignment_ll1[ $art ]*
|
|
941
938
|
(
|
|
942
939
|
'{' { $art.elements = this.createDict(); }
|
|
943
|
-
elementDefOrExtend[ $art
|
|
940
|
+
elementDefOrExtend[ $art ]*
|
|
944
941
|
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
945
942
|
{ this.checkExtensionDict( $art.elements ); }
|
|
946
943
|
optionalSemi
|
|
@@ -965,13 +962,13 @@ extendWithOptElementsOrType[ art ]
|
|
|
965
962
|
annotationAssignment_ll1[ $art ]*
|
|
966
963
|
(
|
|
967
964
|
'{' { $art.elements = this.createDict(); }
|
|
968
|
-
elementDefOrExtend[ $art
|
|
965
|
+
elementDefOrExtend[ $art ]*
|
|
969
966
|
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
970
967
|
{ this.checkExtensionDict( $art.elements ); }
|
|
971
968
|
optionalSemi
|
|
972
969
|
|
|
|
973
970
|
ELEMENTS { $art.elements = this.createDict(); } '{'
|
|
974
|
-
elementDefOrExtend[ $art ]*
|
|
971
|
+
elementDefOrExtend[ $art, true ]*
|
|
975
972
|
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
976
973
|
{ this.checkExtensionDict( $art.elements ); }
|
|
977
974
|
optionalSemi
|
|
@@ -995,7 +992,7 @@ extendWithOptElementsNoWith[ art ]
|
|
|
995
992
|
annotationAssignment_ll1[ $art ]*
|
|
996
993
|
(
|
|
997
994
|
'{' { $art.elements = this.createDict(); }
|
|
998
|
-
elementDefOrExtend[ $art
|
|
995
|
+
elementDefOrExtend[ $art ]*
|
|
999
996
|
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
1000
997
|
{ this.checkExtensionDict( $art.elements ); }
|
|
1001
998
|
optionalSemi
|
|
@@ -1006,7 +1003,7 @@ extendWithOptElementsNoWith[ art ]
|
|
|
1006
1003
|
|
|
1007
1004
|
// For `extend … with elements` or `extend entity … with`, `extend aspect … with`,
|
|
1008
1005
|
// i.e. definitions in { … } are never enums
|
|
1009
|
-
elementDefOrExtend[ outer,
|
|
1006
|
+
elementDefOrExtend[ outer, explicitElement = false ] locals[ art = new parser.XsnArtifact() ]
|
|
1010
1007
|
@after { /* #ATN 1 */ } // if ($art) this.attachLocation( $art ); }
|
|
1011
1008
|
:
|
|
1012
1009
|
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
@@ -1016,7 +1013,7 @@ elementDefOrExtend[ outer, mightBeEnum = false ] locals[ art = {} ]
|
|
|
1016
1013
|
EXTEND
|
|
1017
1014
|
extendElement[ $art, $outer ]
|
|
1018
1015
|
|
|
|
1019
|
-
elementDefInner[ $art, $outer, $
|
|
1016
|
+
elementDefInner[ $art, $outer, $explicitElement ]
|
|
1020
1017
|
)
|
|
1021
1018
|
;
|
|
1022
1019
|
|
|
@@ -1030,7 +1027,7 @@ extendElement[ art, outer ]
|
|
|
1030
1027
|
extendWithOptElementsOrType[ $art, $art ]
|
|
1031
1028
|
;
|
|
1032
1029
|
|
|
1033
|
-
annotateArtifact[ art, outer ] locals[ name =
|
|
1030
|
+
annotateArtifact[ art, outer ] locals[ name = new parser.XsnName(), elemName = new parser.XsnName() ]
|
|
1034
1031
|
@after { this.attachLocation( $art ); }
|
|
1035
1032
|
:
|
|
1036
1033
|
simplePath[ $name, 'Annotate' ]
|
|
@@ -1090,7 +1087,7 @@ annotateArtifact[ art, outer ] locals[ name = {}, elemName = {} ]
|
|
|
1090
1087
|
)
|
|
1091
1088
|
;
|
|
1092
1089
|
|
|
1093
|
-
annotateElement[ outer ] locals[ art =
|
|
1090
|
+
annotateElement[ outer ] locals[ art = new parser.XsnArtifact() ]
|
|
1094
1091
|
@after{ this.attachLocation( $art ); }
|
|
1095
1092
|
:
|
|
1096
1093
|
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
@@ -1110,7 +1107,7 @@ annotateElement[ outer ] locals[ art = {} ]
|
|
|
1110
1107
|
)
|
|
1111
1108
|
;
|
|
1112
1109
|
|
|
1113
|
-
annotateAction [ outer ] locals [ art =
|
|
1110
|
+
annotateAction [ outer ] locals [ art = new parser.XsnArtifact() ]
|
|
1114
1111
|
@after{ this.attachLocation( $art ); }
|
|
1115
1112
|
:
|
|
1116
1113
|
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
@@ -1138,7 +1135,7 @@ annotateAction [ outer ] locals [ art = {} ]
|
|
|
1138
1135
|
annotateReturns[ art ]
|
|
1139
1136
|
@after{ this.attachLocation( $art.returns ); }
|
|
1140
1137
|
:
|
|
1141
|
-
ret=RETURNS { $art.returns =
|
|
1138
|
+
ret=RETURNS { $art.returns = new this.XsnArtifact();; $art.returns.kind = 'annotate'; }
|
|
1142
1139
|
{ this.docComment( $art.returns ); }
|
|
1143
1140
|
annotationAssignment_ll1[ $art.returns ]*
|
|
1144
1141
|
( '{' { $art.returns.elements = this.createDict(); }
|
|
@@ -1150,7 +1147,7 @@ annotateReturns[ art ]
|
|
|
1150
1147
|
)
|
|
1151
1148
|
;
|
|
1152
1149
|
|
|
1153
|
-
annotateParam [ outer ] locals [ art =
|
|
1150
|
+
annotateParam [ outer ] locals [ art = new parser.XsnArtifact() ]
|
|
1154
1151
|
@after{ this.attachLocation( $art ); }
|
|
1155
1152
|
:
|
|
1156
1153
|
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
@@ -1424,9 +1421,12 @@ typeAssociationCont[ art ]
|
|
|
1424
1421
|
)*
|
|
1425
1422
|
)?
|
|
1426
1423
|
'}' { this.finalizeDictOrArray( $art.foreignKeys ); }
|
|
1424
|
+
defaultAndNullability[ $art ]?
|
|
1427
1425
|
|
|
|
1428
1426
|
ON cond=condition
|
|
1429
1427
|
{ $art.on=$cond.cond; }
|
|
1428
|
+
|
|
|
1429
|
+
defaultAndNullability[ $art ]
|
|
1430
1430
|
)
|
|
1431
1431
|
;
|
|
1432
1432
|
|
|
@@ -1442,12 +1442,12 @@ typeAssociationElementCont[ art ] // including Composition
|
|
|
1442
1442
|
)*
|
|
1443
1443
|
)?
|
|
1444
1444
|
'}' { this.finalizeDictOrArray( $art.foreignKeys ); }
|
|
1445
|
-
|
|
1445
|
+
defaultAndNullability[ $art ]?
|
|
1446
1446
|
|
|
|
1447
1447
|
ON cond=condition
|
|
1448
1448
|
{ $art.on=$cond.cond; }
|
|
1449
1449
|
|
|
|
1450
|
-
|
|
1450
|
+
defaultAndNullability[ $art ]
|
|
1451
1451
|
)?
|
|
1452
1452
|
{ this.docComment( $art ); }
|
|
1453
1453
|
annotationAssignment_ll1[ $art ]*
|
|
@@ -1515,7 +1515,7 @@ nullability[ art ]
|
|
|
1515
1515
|
| n1=NULL
|
|
1516
1516
|
;
|
|
1517
1517
|
|
|
1518
|
-
foreignKey[ outer ] locals[ art =
|
|
1518
|
+
foreignKey[ outer ] locals[ art = new parser.XsnArtifact(), elem = {} ]
|
|
1519
1519
|
@after { this.attachLocation($art); }
|
|
1520
1520
|
:
|
|
1521
1521
|
simplePath[ $elem, 'ref' ] { $art.targetElement = $elem; }
|
|
@@ -1784,7 +1784,7 @@ tableTerm returns [ table ]
|
|
|
1784
1784
|
}
|
|
1785
1785
|
':' fromPath[ $table, 'ref']
|
|
1786
1786
|
)?
|
|
1787
|
-
( AS n1=ident['FromAlias'] { $table.name = $n1.id }
|
|
1787
|
+
( AS n1=ident['FromAlias'] { $table.name = $n1.id; }
|
|
1788
1788
|
| n2=identNoKeyword['FromAlias'] { $table.name = this.fragileAlias( $n2.id ); }
|
|
1789
1789
|
// if we would use rule `ident`, we would either had to make all JOIN
|
|
1790
1790
|
// kinds reserved or introduce ATN
|
|
@@ -1823,7 +1823,7 @@ fromPath[ qp, idkind ] returns[ dotAfterFilter = null ]
|
|
|
1823
1823
|
if (!$qp.scope) $qp.scope = $qp.path.length;
|
|
1824
1824
|
} }
|
|
1825
1825
|
'.' id=ident[$idkind] { this.pushIdent( $qp.path, $id.id ); }
|
|
1826
|
-
( fromArguments[ $id.id ] cardinalityAndFilter[ $id.id ]?
|
|
1826
|
+
( fromArguments[ $id.id ] cardinalityAndFilter[ $id.id ]?
|
|
1827
1827
|
{ if (!$dotAfterFilter) $dotAfterFilter = false; }
|
|
1828
1828
|
| cardinalityAndFilter[ $id.id ]
|
|
1829
1829
|
{ if (!$dotAfterFilter) $dotAfterFilter = false; }
|
|
@@ -1887,7 +1887,7 @@ selectItemDef[ outer ] locals[ art ]
|
|
|
1887
1887
|
star='*'
|
|
1888
1888
|
{ $outer.push( this.valueWithTokenLocation( '*', $star ) ); }
|
|
1889
1889
|
|
|
|
1890
|
-
{ $art =
|
|
1890
|
+
{ $art = new this.XsnArtifact();; this.docComment( $art ); }
|
|
1891
1891
|
annotationAssignment_atn[ $art ]*
|
|
1892
1892
|
// VIRTUAL is keyword, except if before the following tokens texts:
|
|
1893
1893
|
{ this.setLocalToken( 'VIRTUAL', 'VIRTUAL', /^([,.:\[@]|as)$/i ) ; } // not '{'
|
|
@@ -1904,7 +1904,7 @@ selectItemDefBody[ art, outer ] locals[ assoc ]
|
|
|
1904
1904
|
e=expression { $art.value = $e.expr; }
|
|
1905
1905
|
// we cannot use 'condition' instead, as long as we allow aliases without
|
|
1906
1906
|
// AS (using rule 'ident' instead of 'identNoKeyword') -> ambiguities
|
|
1907
|
-
( as=AS n1=ident['Item'] { $art.name = $n1.id }
|
|
1907
|
+
( as=AS n1=ident['Item'] { $art.name = $n1.id; }
|
|
1908
1908
|
| n2=ident['Item'] { $art.name = this.fragileAlias( $n2.id, true ); }
|
|
1909
1909
|
| { this.classifyImplicitName( 'Item', $e.expr ); }
|
|
1910
1910
|
)
|
|
@@ -1929,7 +1929,7 @@ selectItemDefBody[ art, outer ] locals[ assoc ]
|
|
|
1929
1929
|
|
|
|
1930
1930
|
selectItemInlineList[ $art, 'expand' ]
|
|
1931
1931
|
excludingClause[ $art ]?
|
|
1932
|
-
AS n1=ident['Item'] { $art.name = $n1.id }
|
|
1932
|
+
AS n1=ident['Item'] { $art.name = $n1.id; }
|
|
1933
1933
|
)
|
|
1934
1934
|
{ this.docComment( $art ); }
|
|
1935
1935
|
annotationAssignment_fix[ $art ]*
|
|
@@ -1995,7 +1995,7 @@ selectItemInlineDef[ outer ] locals[ art ]
|
|
|
1995
1995
|
star='*'
|
|
1996
1996
|
{ $outer.push( this.valueWithTokenLocation( '*', $star ) ); }
|
|
1997
1997
|
|
|
|
1998
|
-
{ $art =
|
|
1998
|
+
{ $art = new this.XsnArtifact();; this.docComment( $art ); }
|
|
1999
1999
|
annotationAssignment_atn[ $art ]*
|
|
2000
2000
|
selectItemDefBody[ $art, $outer ]
|
|
2001
2001
|
;
|
|
@@ -2010,11 +2010,8 @@ orderByClause[ inQuery ] returns [ query ]
|
|
|
2010
2010
|
limitClause[ inQuery ] returns [ query ]
|
|
2011
2011
|
:
|
|
2012
2012
|
limkw=LIMIT { $query = this.unaryOpForParens( $inQuery, '$'+'query' ); }
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
literal: 'null', val: null, location: this.tokenLocation($limnull) } }; }
|
|
2016
|
-
)
|
|
2017
|
-
( OFFSET off=Number { $query.limit.offset = this.numberLiteral( $off ); } )? // unsigned integer
|
|
2013
|
+
lim=expression { $query.limit = { rows: $lim.expr }; }
|
|
2014
|
+
( OFFSET off=expression { $query.limit.offset = $off.expr; } )? // unsigned integer
|
|
2018
2015
|
;
|
|
2019
2016
|
|
|
2020
2017
|
orderBySpec returns[ ob ]
|
|
@@ -2312,7 +2309,7 @@ expressionTerm returns [ expr ] locals [ args = [] ]
|
|
|
2312
2309
|
)
|
|
2313
2310
|
;
|
|
2314
2311
|
|
|
2315
|
-
specialFunction returns [ ret = {} ] locals[ art =
|
|
2312
|
+
specialFunction returns [ ret = {} ] locals[ art = new parser.XsnArtifact() ]
|
|
2316
2313
|
:
|
|
2317
2314
|
ca=CAST '(' // see createArray() in action
|
|
2318
2315
|
{
|
|
@@ -2663,7 +2660,7 @@ annotationAssignment_fix[ art ] locals[ assignment ]
|
|
|
2663
2660
|
(
|
|
2664
2661
|
annotationAssignment_paren[ $art ]
|
|
2665
2662
|
|
|
|
2666
|
-
{ $assignment = { name:
|
|
2663
|
+
{ $assignment = { name: new this.XsnName() }; }
|
|
2667
2664
|
annotationPath[ $assignment.name, 'anno' ]
|
|
2668
2665
|
( '#' annotationPathVariant[ $assignment.name ] )?
|
|
2669
2666
|
{ this.warnIfColonFollows( $assignment ); }
|
|
@@ -2681,7 +2678,7 @@ annotationAssignment_ll1[ art ] locals[ assignment ]
|
|
|
2681
2678
|
(
|
|
2682
2679
|
annotationAssignment_paren[ $art ]
|
|
2683
2680
|
|
|
|
2684
|
-
{ $assignment = { name:
|
|
2681
|
+
{ $assignment = { name: new this.XsnName() }; }
|
|
2685
2682
|
annotationPath[ $assignment.name, 'anno' ]
|
|
2686
2683
|
( '#' annotationPathVariant[ $assignment.name ] )?
|
|
2687
2684
|
(
|
|
@@ -2703,7 +2700,7 @@ annotationAssignment_atn[ art ] locals[ assignment ]
|
|
|
2703
2700
|
(
|
|
2704
2701
|
annotationAssignment_paren[ $art ]
|
|
2705
2702
|
|
|
|
2706
|
-
{ $assignment = { name:
|
|
2703
|
+
{ $assignment = { name: new this.XsnName() }; }
|
|
2707
2704
|
annotationPath[ $assignment.name, 'anno' ]
|
|
2708
2705
|
// '#' is in the follow set of this rule, as it is used in rule "selectItemDef"
|
|
2709
2706
|
// before an "expression" which can start with a '#' for an enum value
|
|
@@ -2749,7 +2746,7 @@ annotationAssignment_paren[ art ]
|
|
|
2749
2746
|
')'
|
|
2750
2747
|
;
|
|
2751
2748
|
|
|
2752
|
-
annotationAssignment_1[ art ] locals[ assignment = { name:
|
|
2749
|
+
annotationAssignment_1[ art ] locals[ assignment = { name: new parser.XsnName() } ]
|
|
2753
2750
|
@after { this.assignAnnotation( $art, $assignment ); }
|
|
2754
2751
|
:
|
|
2755
2752
|
annotationPath[ $assignment.name, 'anno' ]
|
|
@@ -2865,7 +2862,7 @@ annoValueBase[ assignment ] locals [ seenEllipsis = false ]
|
|
|
2865
2862
|
')'
|
|
2866
2863
|
;
|
|
2867
2864
|
|
|
2868
|
-
flattenedValue[ assignment ] locals[ val = { name:
|
|
2865
|
+
flattenedValue[ assignment ] locals[ val = { name: new parser.XsnName() } ]
|
|
2869
2866
|
:
|
|
2870
2867
|
at='@'? annotationPath[ $val.name, 'name', $at ]
|
|
2871
2868
|
( '#' annotationPathVariant[ $val.name ] )?
|
|
@@ -2876,7 +2873,7 @@ flattenedValue[ assignment ] locals[ val = { name: {} } ]
|
|
|
2876
2873
|
{ $assignment['$'+'flatten'].push( $val ); }
|
|
2877
2874
|
;
|
|
2878
2875
|
|
|
2879
|
-
namedValue[ struct ] locals[ val = { name:
|
|
2876
|
+
namedValue[ struct ] locals[ val = { name: new parser.XsnName() } ]
|
|
2880
2877
|
:
|
|
2881
2878
|
at='@'? annotationPath[ $val.name, 'name', $at ]
|
|
2882
2879
|
( ':' { this.meltKeywordToIdentifier(true); }
|
|
@@ -6,6 +6,7 @@ const {
|
|
|
6
6
|
cdlNewLineRegEx,
|
|
7
7
|
} = require('./textUtils');
|
|
8
8
|
const { CompilerAssertion } = require('../base/error');
|
|
9
|
+
const { CsnLocation } = require('../compiler/classes');
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Strips and counts the indentation from the given string.
|
|
@@ -462,6 +463,7 @@ class MultiLineStringParser {
|
|
|
462
463
|
*/
|
|
463
464
|
_locationForCharacters(i, width) {
|
|
464
465
|
return {
|
|
466
|
+
__proto__: CsnLocation.prototype,
|
|
465
467
|
file: this.parser.filename,
|
|
466
468
|
line: this.token.line + this._lineInString,
|
|
467
469
|
endLine: this.token.line + this._lineInString,
|
package/lib/main.d.ts
CHANGED
|
@@ -70,6 +70,18 @@ declare namespace compiler {
|
|
|
70
70
|
* - universal : In development (BETA)
|
|
71
71
|
*/
|
|
72
72
|
csnFlavor?: string | 'client' | 'gensrc' | 'universal'
|
|
73
|
+
/**
|
|
74
|
+
* If set, backends will not create localized convenience views for those views,
|
|
75
|
+
* that only have an association to a localized entity/view. Views will only get
|
|
76
|
+
* a convenience view, if they themselves contain localized elements (i.e. either
|
|
77
|
+
* have simple projection on localized elements and CDL-casts to a localized element).
|
|
78
|
+
*
|
|
79
|
+
* The OData backend will not set `$localized: true` markers for such cases.
|
|
80
|
+
*
|
|
81
|
+
* Does not work for backends to.hdi(), to.hdbcds() or to.sql() with `sqlDialect: 'hana'`,
|
|
82
|
+
* since in all those dialects, associations still exist in generated artifacts.
|
|
83
|
+
*/
|
|
84
|
+
fewerLocalizedViews?: boolean
|
|
73
85
|
}
|
|
74
86
|
|
|
75
87
|
/**
|
|
@@ -86,6 +98,30 @@ declare namespace compiler {
|
|
|
86
98
|
* the prefix for SAP CDS packages / CDS files.
|
|
87
99
|
*/
|
|
88
100
|
cdsHome?: string
|
|
101
|
+
/**
|
|
102
|
+
* "Doc comments" (documentation comments) are those comments starting with `/**` in CDL
|
|
103
|
+
* or the `doc` property in CSN. This option is an _output_ option, which can have three
|
|
104
|
+
* values:
|
|
105
|
+
*
|
|
106
|
+
* - `true`:
|
|
107
|
+
* Doc comments will appear in the compiled CSN. Basic sanity checks are performed:
|
|
108
|
+
* In CDL, if a doc comment appears at a not-defined position, where it has no impact,
|
|
109
|
+
* an info message is emitted. For CSN input, it is checked that the `doc` property
|
|
110
|
+
* is a string or `null`.
|
|
111
|
+
*
|
|
112
|
+
* - `false`:
|
|
113
|
+
* Doc comments will not be parsed for CDL, and will be stripped from input CSN,
|
|
114
|
+
* i.e. the compiled CSN (output) does not contain `doc` properties. No checks
|
|
115
|
+
* are performed on doc comments.
|
|
116
|
+
*
|
|
117
|
+
* - `undefined`:
|
|
118
|
+
* Doc comments are checked (see value `true`). For CDL, doc comments are not parsed,
|
|
119
|
+
* i.e. will not appear in the compiled CSN (output).
|
|
120
|
+
* For CSN input, all `doc` properties remain in the CSN.
|
|
121
|
+
*
|
|
122
|
+
* The CDL equivalent of the CSN value `doc: null`, is an empty doc comment.
|
|
123
|
+
*/
|
|
124
|
+
docComment?: boolean
|
|
89
125
|
/**
|
|
90
126
|
* When set to `true`, and the model contains an entity `sap.common.Languages`
|
|
91
127
|
* with an element `code`, all generated texts entities additionally contain
|
|
@@ -95,6 +131,17 @@ declare namespace compiler {
|
|
|
95
131
|
* @since v2.8.0
|
|
96
132
|
*/
|
|
97
133
|
addTextsLanguageAssoc?: boolean
|
|
134
|
+
/**
|
|
135
|
+
* An array of directory names that are used for CDS module lookups.
|
|
136
|
+
* Lookup directory `node_modules/` is appended if not set explicitly.
|
|
137
|
+
*
|
|
138
|
+
* All directories in this array follow the same lookup-pattern as `node_modules/`.
|
|
139
|
+
*
|
|
140
|
+
* See <https://cap.cloud.sap/docs/cds/cdl#model-resolution>
|
|
141
|
+
*
|
|
142
|
+
* @since v4.2.0
|
|
143
|
+
*/
|
|
144
|
+
moduleLookupDirectories?: string[]
|
|
98
145
|
/**
|
|
99
146
|
* Option for {@link compileSources}. If set, all objects inside the
|
|
100
147
|
* provided sources dictionary are interpreted as XSN structures instead
|
|
@@ -466,6 +513,12 @@ declare namespace compiler {
|
|
|
466
513
|
*/
|
|
467
514
|
export class CompilationError extends Error {
|
|
468
515
|
constructor(messages: CompileMessage[], model?: any, text?: string, ...args: any[]);
|
|
516
|
+
/**
|
|
517
|
+
* String to identify this class. Can be used instead of relying on `instanceof`.
|
|
518
|
+
* Always `ERR_CDS_COMPILATION_FAILURE`.
|
|
519
|
+
* @since v4.0.0
|
|
520
|
+
*/
|
|
521
|
+
code: string;
|
|
469
522
|
messages: CompileMessage[];
|
|
470
523
|
toString(): string;
|
|
471
524
|
/**
|
|
@@ -798,6 +851,9 @@ declare namespace compiler {
|
|
|
798
851
|
* identifier in brackets.
|
|
799
852
|
* Otherwise, return the name without brackets.
|
|
800
853
|
*
|
|
854
|
+
* NOTE: If `name` contains newline characters, the resulting delimited identifier
|
|
855
|
+
* will not be parsable by the compiler!
|
|
856
|
+
*
|
|
801
857
|
* Example:
|
|
802
858
|
* ```js
|
|
803
859
|
* to.cdl.smartId('with ![brackets]')
|
|
@@ -812,6 +868,9 @@ declare namespace compiler {
|
|
|
812
868
|
*
|
|
813
869
|
* @param name
|
|
814
870
|
* @param [insideFunction=null]
|
|
871
|
+
* Inside special functions such as SAP HANA's `OCCURRENCES_REGEXPR`, there are more
|
|
872
|
+
* keywords than in other places. Set this value to a function name, if you want to
|
|
873
|
+
* handle those additional keywords as well.
|
|
815
874
|
*/
|
|
816
875
|
function smartId(name: string, insideFunction?: string|null) : string;
|
|
817
876
|
/**
|
|
@@ -819,6 +878,9 @@ declare namespace compiler {
|
|
|
819
878
|
* function identifier in brackets for CDL.
|
|
820
879
|
* Otherwise, return the function name without brackets.
|
|
821
880
|
*
|
|
881
|
+
* NOTE: If `name` contains newline characters, the resulting delimited identifier
|
|
882
|
+
* will not be parsable by the compiler!
|
|
883
|
+
*
|
|
822
884
|
* Example:
|
|
823
885
|
* ```js
|
|
824
886
|
* to.cdl.smartFunctionId('with ![brackets]')
|
|
@@ -834,6 +896,9 @@ declare namespace compiler {
|
|
|
834
896
|
* Escapes the given name according to the CDL language and puts it
|
|
835
897
|
* into `![` and `]`, properly escaping all `]` in the identifier.
|
|
836
898
|
*
|
|
899
|
+
* NOTE: If `name` contains newline characters, the resulting delimited identifier
|
|
900
|
+
* will not be parsable by the compiler!
|
|
901
|
+
*
|
|
837
902
|
* Example:
|
|
838
903
|
* ```js
|
|
839
904
|
* to.cdl.delimitedId('with ![brackets]')
|