@sap/cds-compiler 3.8.0 → 3.8.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 +8 -0
- package/lib/compiler/assert-consistency.js +1 -1
- package/lib/compiler/base.js +14 -12
- package/lib/compiler/extend.js +17 -1
- package/lib/compiler/shared.js +8 -5
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +948 -940
- package/lib/json/from-csn.js +1 -2
- package/lib/language/genericAntlrParser.js +2 -1
- package/lib/language/language.g4 +18 -21
- package/lib/model/csnRefs.js +5 -2
- package/package.json +1 -1
package/lib/json/from-csn.js
CHANGED
|
@@ -1409,8 +1409,7 @@ function annotation( val, spec, xsn, csn, name ) {
|
|
|
1409
1409
|
return undefined;
|
|
1410
1410
|
n.absolute = absolute;
|
|
1411
1411
|
if (variantIndex < absolute.length)
|
|
1412
|
-
n.variant =
|
|
1413
|
-
|
|
1412
|
+
n.variant = refSplit( name.substring( variantIndex ), null );
|
|
1414
1413
|
const r = annoValue( val, spec );
|
|
1415
1414
|
r.name = n;
|
|
1416
1415
|
return r;
|
|
@@ -974,7 +974,8 @@ function pushIdent( path, ident, prefix ) {
|
|
|
974
974
|
}
|
|
975
975
|
|
|
976
976
|
// For :param, #variant, #symbol, @(…) and @Begin and `@` inside annotation paths
|
|
977
|
-
function reportUnexpectedSpace( prefix
|
|
977
|
+
function reportUnexpectedSpace( prefix = this._input.LT(-1),
|
|
978
|
+
location = this.tokenLocation( this._input.LT(1) ) ) {
|
|
978
979
|
const prefixLoc = this.tokenLocation( prefix );
|
|
979
980
|
if (prefixLoc.endLine !== location.line ||
|
|
980
981
|
prefixLoc.endCol !== location.col) {
|
package/lib/language/language.g4
CHANGED
|
@@ -2583,7 +2583,7 @@ annotationAssignment_fix[ art ] locals[ assignment ]
|
|
|
2583
2583
|
|
|
|
2584
2584
|
{ $assignment = { name: {} }; }
|
|
2585
2585
|
annotationPath[ $assignment.name, 'anno' ]
|
|
2586
|
-
annotationPathVariant[ $assignment.name ]?
|
|
2586
|
+
( '#' annotationPathVariant[ $assignment.name ] )?
|
|
2587
2587
|
{ this.warnIfColonFollows( $assignment ); }
|
|
2588
2588
|
)
|
|
2589
2589
|
;
|
|
@@ -2601,7 +2601,7 @@ annotationAssignment_ll1[ art ] locals[ assignment ]
|
|
|
2601
2601
|
|
|
|
2602
2602
|
{ $assignment = { name: {} }; }
|
|
2603
2603
|
annotationPath[ $assignment.name, 'anno' ]
|
|
2604
|
-
annotationPathVariant[ $assignment.name ]?
|
|
2604
|
+
( '#' annotationPathVariant[ $assignment.name ] )?
|
|
2605
2605
|
(
|
|
2606
2606
|
':' { this.meltKeywordToIdentifier(true); } // allow path as anno value start with reserved
|
|
2607
2607
|
val=annoValue[ $assignment ]
|
|
@@ -2627,11 +2627,7 @@ annotationAssignment_atn[ art ] locals[ assignment ]
|
|
|
2627
2627
|
// before an "expression" which can start with a '#' for an enum value
|
|
2628
2628
|
// -> used to introduce variant name if and only if in same line as previous token
|
|
2629
2629
|
{ this.setLocalToken( '#', 'HelperToken1', null, true ); }
|
|
2630
|
-
(
|
|
2631
|
-
hash=HelperToken1
|
|
2632
|
-
{ this.meltKeywordToIdentifier();; this.reportUnexpectedSpace( $hash ); }
|
|
2633
|
-
variant=ident['variant'] { $assignment.name.variant = $variant.id; }
|
|
2634
|
-
)?
|
|
2630
|
+
( hash=HelperToken1 annotationPathVariant[ $assignment.name ] )?
|
|
2635
2631
|
// ':' is in the follow set of this rule, as it is used in rule "selectItemDef"
|
|
2636
2632
|
// before an "expression" which can start with a ':' for a parameter reference
|
|
2637
2633
|
// -> used to introduce assignment value if and only if in same line as previous token
|
|
@@ -2643,11 +2639,7 @@ annotationAssignment_atn[ art ] locals[ assignment ]
|
|
|
2643
2639
|
|
|
|
2644
2640
|
atv='@'? annotationPath[ $assignment, 'ref', $atv ]
|
|
2645
2641
|
{ this.setLocalToken( '#', 'HelperToken1', null, true ); } // see above
|
|
2646
|
-
(
|
|
2647
|
-
hash=HelperToken1
|
|
2648
|
-
{ this.meltKeywordToIdentifier();; this.reportUnexpectedSpace( $hash ); }
|
|
2649
|
-
variant=ident['variant'] { $assignment.variant = $variant.id; }
|
|
2650
|
-
)?
|
|
2642
|
+
( hash=HelperToken1 annotationPathVariant[ $assignment ] )?
|
|
2651
2643
|
)
|
|
2652
2644
|
)?
|
|
2653
2645
|
)
|
|
@@ -2658,11 +2650,11 @@ annotationAssignment_paren[ art ]
|
|
|
2658
2650
|
'('
|
|
2659
2651
|
// allow completely useless `@()`; no warning anymore - who cares?
|
|
2660
2652
|
{
|
|
2661
|
-
this.meltKeywordToIdentifier();
|
|
2662
2653
|
if (this.isStraightBefore(')')) {
|
|
2663
2654
|
this.matchWildcard(); // we know it is the ')' - we do not reach the final match
|
|
2664
2655
|
return $ctx;
|
|
2665
2656
|
}
|
|
2657
|
+
this.meltKeywordToIdentifier();
|
|
2666
2658
|
}
|
|
2667
2659
|
annotationAssignment_1[ $art ]
|
|
2668
2660
|
( ','
|
|
@@ -2679,7 +2671,7 @@ annotationAssignment_1[ art ] locals[ assignment = { name: {} } ]
|
|
|
2679
2671
|
@after { this.assignAnnotation( $art, $assignment ); }
|
|
2680
2672
|
:
|
|
2681
2673
|
annotationPath[ $assignment.name, 'anno' ]
|
|
2682
|
-
annotationPathVariant[ $assignment.name ]?
|
|
2674
|
+
( '#' annotationPathVariant[ $assignment.name ] )?
|
|
2683
2675
|
(
|
|
2684
2676
|
':' { this.meltKeywordToIdentifier(true); } // allow path as anno value start with reserved
|
|
2685
2677
|
val=annoValue[ $assignment ]
|
|
@@ -2704,11 +2696,11 @@ annotationPath[ art, category, headat = null ] locals[ _sync = 'nop' ]
|
|
|
2704
2696
|
)*
|
|
2705
2697
|
;
|
|
2706
2698
|
|
|
2699
|
+
// Before calling this rule, match '#'
|
|
2707
2700
|
annotationPathVariant[ art ] locals[ variant = {} ]
|
|
2708
2701
|
@after { this.attachLocation($art); }
|
|
2709
2702
|
:
|
|
2710
|
-
|
|
2711
|
-
hash='#' { this.meltKeywordToIdentifier();; this.reportUnexpectedSpace( $hash ); }
|
|
2703
|
+
{ this.reportUnexpectedSpace();; this.meltKeywordToIdentifier(); }
|
|
2712
2704
|
simplePath[ $variant, 'variant' ] { $art.variant = $variant; }
|
|
2713
2705
|
;
|
|
2714
2706
|
|
|
@@ -2719,7 +2711,7 @@ annoValue[ assignment ]
|
|
|
2719
2711
|
// no docComment() here
|
|
2720
2712
|
// this alternative is done with token rewrite in rule "annotationAssignment_atn"
|
|
2721
2713
|
at='@'? annotationPath[ $assignment, 'ref', $at ]
|
|
2722
|
-
annotationPathVariant[ $assignment ]?
|
|
2714
|
+
( '#' annotationPathVariant[ $assignment ] )?
|
|
2723
2715
|
;
|
|
2724
2716
|
|
|
2725
2717
|
annoValueBase[ assignment ] locals [ seenEllipsis = false ]
|
|
@@ -2739,6 +2731,7 @@ annoValueBase[ assignment ] locals [ seenEllipsis = false ]
|
|
|
2739
2731
|
|
|
|
2740
2732
|
'[' // no need for createArray() here, $assignment.location is set
|
|
2741
2733
|
{ $assignment.val = []; $assignment.literal = 'array'; }
|
|
2734
|
+
{ this.meltKeywordToIdentifier(true); }
|
|
2742
2735
|
(
|
|
2743
2736
|
(
|
|
2744
2737
|
head=annoSubValue { $assignment.val.push( $head.val ); }
|
|
@@ -2753,6 +2746,7 @@ annoValueBase[ assignment ] locals [ seenEllipsis = false ]
|
|
|
2753
2746
|
)
|
|
2754
2747
|
(
|
|
2755
2748
|
',' { if (this.isStraightBefore(']')) break; } // allow ',' before ']'
|
|
2749
|
+
{ this.meltKeywordToIdentifier(true); }
|
|
2756
2750
|
(
|
|
2757
2751
|
tail=annoSubValue { $assignment.val.push( $tail.val ); }
|
|
2758
2752
|
|
|
|
@@ -2794,7 +2788,7 @@ annoValueBase[ assignment ] locals [ seenEllipsis = false ]
|
|
|
2794
2788
|
flattenedValue[ assignment ] locals[ val = { name: {} } ]
|
|
2795
2789
|
:
|
|
2796
2790
|
at='@'? annotationPath[ $val.name, 'name', $at ]
|
|
2797
|
-
( annotationPathVariant[ $val.name ] )?
|
|
2791
|
+
( '#' annotationPathVariant[ $val.name ] )?
|
|
2798
2792
|
(
|
|
2799
2793
|
':' { this.meltKeywordToIdentifier(true); } // allow path as anno value start with reserved
|
|
2800
2794
|
annoValue[ $val ]
|
|
@@ -2805,7 +2799,8 @@ flattenedValue[ assignment ] locals[ val = { name: {} } ]
|
|
|
2805
2799
|
namedValue[ struct ] locals[ val = { name: {} } ]
|
|
2806
2800
|
:
|
|
2807
2801
|
at='@'? annotationPath[ $val.name, 'name', $at ]
|
|
2808
|
-
( ':'
|
|
2802
|
+
( ':' { this.meltKeywordToIdentifier(true); }
|
|
2803
|
+
sub=annoSubValue { Object.assign( $val, $sub.val ); } )?
|
|
2809
2804
|
{
|
|
2810
2805
|
if (!$val.location) $val.location = $val.name.location;
|
|
2811
2806
|
this.addDef( $val, $struct, 'struct', null, $val.name ); // TODO: re-check name
|
|
@@ -2830,8 +2825,10 @@ annoSubValue returns[ val = {} ]
|
|
|
2830
2825
|
|
|
|
2831
2826
|
'[' // no need for createArray() here, $val.location is set
|
|
2832
2827
|
{ $val.val = []; $val.literal = 'array'; }
|
|
2828
|
+
{ this.meltKeywordToIdentifier(true); }
|
|
2833
2829
|
( head=annoSubValue { $val.val.push( $head.val ); }
|
|
2834
2830
|
( ',' { if (this.isStraightBefore(']')) break; } // allow ',' before ']'
|
|
2831
|
+
{ this.meltKeywordToIdentifier(true); }
|
|
2835
2832
|
tail=annoSubValue { $val.val.push( $tail.val ); }
|
|
2836
2833
|
)*
|
|
2837
2834
|
)?
|
|
@@ -2843,7 +2840,7 @@ annoSubValue returns[ val = {} ]
|
|
|
2843
2840
|
{ Object.assign( $val, this.numberLiteral( $num, $plus||$min ) ); }
|
|
2844
2841
|
|
|
|
2845
2842
|
at='@'? annotationPath[ $val, 'ref', $at ]
|
|
2846
|
-
( annotationPathVariant[ $val ] )?
|
|
2843
|
+
( '#' annotationPathVariant[ $val ] )?
|
|
2847
2844
|
|
|
|
2848
2845
|
'('
|
|
2849
2846
|
cond=condition
|
|
@@ -2857,7 +2854,7 @@ literalValue returns[ val ] locals[ tok ]
|
|
|
2857
2854
|
@init{ $tok = this.getCurrentToken(); }
|
|
2858
2855
|
@after { this.attachLocation($val); }
|
|
2859
2856
|
:
|
|
2860
|
-
hash='#' { this.
|
|
2857
|
+
hash='#' { this.reportUnexpectedSpace( $hash );; this.meltKeywordToIdentifier(); }
|
|
2861
2858
|
name=ident['enumref'] // TODO v4: remove from this rule (not in enum!)
|
|
2862
2859
|
{ $val = { literal: 'enum', sym: $name.id } }
|
|
2863
2860
|
|
|
package/lib/model/csnRefs.js
CHANGED
|
@@ -620,6 +620,9 @@ function csnRefs( csn, universalReady ) {
|
|
|
620
620
|
return resolvePath( path, art, parent, 'parent' );
|
|
621
621
|
}
|
|
622
622
|
|
|
623
|
+
if (!qcache)
|
|
624
|
+
throw new CompilerAssertion( `Query not in cache at: ${ locationString(query.$location) }` );
|
|
625
|
+
|
|
623
626
|
if (semantics.dynamic === 'query')
|
|
624
627
|
// TODO: for ON condition in expand, would need to use cached _element
|
|
625
628
|
return resolvePath( path, qcache.elements[head], null, 'query' );
|
|
@@ -882,8 +885,8 @@ function traverseFrom( from, fromSelect, parentQuery, callback ) {
|
|
|
882
885
|
}
|
|
883
886
|
else if (from.args) { // join
|
|
884
887
|
from.args.forEach( arg => traverseFrom( arg, fromSelect, parentQuery, callback ) );
|
|
885
|
-
if (from.on) // join-on, potentially having a sub query
|
|
886
|
-
from.on.forEach(
|
|
888
|
+
if (from.on) // join-on, potentially having a sub query (in xpr)
|
|
889
|
+
from.on.forEach(arg => traverseExpr(arg, fromSelect, callback));
|
|
887
890
|
}
|
|
888
891
|
else { // sub query in FROM
|
|
889
892
|
traverseQuery( from, fromSelect, parentQuery, callback );
|