@@ -509,7 +509,14 @@ func (g *generator) genInterface(name string, v cue.Value) []ts.Decl {
509
509
// Theoretically, lattice equality can be defined as bijective
510
510
// subsumption. In practice, Subsume() seems to ignore optional
511
511
// fields, and Equals() doesn't. So, use Equals().
512
- if sub .Exists () && sub .Equals (iter .Value ()) {
512
+
513
+ // We need to check if the child overrides the parent. In that case, we have an AndOp that
514
+ // tell us that it is setting a value.
515
+ op , _ := iter .Value ().Expr ()
516
+ // Also we need to check if the sub operator to discard the one that have validators and if it has a default
517
+ subOp , _ := sub .Expr ()
518
+ _ , def := iter .Value ().Default ()
519
+ if sub .Exists () && sub .Equals (iter .Value ()) && (subOp == cue .AndOp || op != cue .AndOp || ! def ) {
513
520
continue
514
521
}
515
522
}
@@ -741,28 +748,28 @@ func (g *generator) genEnumReference(v cue.Value) (*typeRef, error) {
741
748
panic ("unreachable" )
742
749
case 1 :
743
750
case 2 :
744
- // The only case we actually want to support, at least for now, is this:
745
- //
746
- // enum: "foo" | "bar" @cuetsy(kind="enum")
747
- // enumref: enum & "foo" @cuetsy(kind="type")
748
- //
749
- // Where we render enumref to TS as `Enumref: Enum.Foo`.
750
- // For that case, we allow at most two conjuncts, and make sure they
751
- // fit the pattern of the two operands above.
752
- aref , bref := isReference (conjuncts [0 ]), isReference (conjuncts [1 ])
753
- aconc , bconc := conjuncts [0 ].IsConcrete (), conjuncts [1 ].IsConcrete ()
754
- var cr cue.Value
755
- if aref {
756
- cr , lit = conjuncts [0 ], & (conjuncts [1 ])
757
- } else {
758
- cr , lit = conjuncts [1 ], & (conjuncts [0 ])
751
+ var err error
752
+ lit , err = getEnumLiteral (conjuncts )
753
+ if err != nil {
754
+ ve := valError (v , err .Error ())
755
+ g .addErr (ve )
756
+ return nil , ve
759
757
}
760
- if aref == bref || aconc == bconc || cr .Subsume (* lit ) != nil {
761
- ve := valError (v , "may only unify a referenced enum with a concrete literal member of that enum" )
758
+ case 3 :
759
+ // It could happen when we are setting a default value into a parent field.
760
+ if ! conjuncts [0 ].Equals (conjuncts [1 ]) {
761
+ ve := valError (v , "complex unifications containing references to enums without overriding parent are not currently supported" )
762
762
g .addErr (ve )
763
763
return nil , ve
764
764
}
765
765
766
+ var err error
767
+ lit , err = getEnumLiteral (conjuncts [1 :])
768
+ if err != nil {
769
+ ve := valError (v , err .Error ())
770
+ g .addErr (ve )
771
+ return nil , ve
772
+ }
766
773
default :
767
774
ve := valError (v , "complex unifications containing references to enums are not currently supported" )
768
775
g .addErr (ve )
@@ -807,20 +814,50 @@ func (g *generator) genEnumReference(v cue.Value) (*typeRef, error) {
807
814
return nil , err
808
815
}
809
816
}
810
- case 2 :
811
- if typeIdent , err := findIdent (ev , * lit ); err == nil {
812
- ref .T = tsast.SelectorExpr {
813
- Expr : ref .T ,
814
- Sel : * typeIdent ,
815
- }
817
+ case 2 , 3 :
818
+ var rr tsast.Expr
819
+ if defaultIdent , err := findIdent (ev , * lit ); err == nil {
820
+ rr = tsast.SelectorExpr {Expr : ref .T , Sel : * defaultIdent }
816
821
} else {
817
822
return nil , err
818
823
}
824
+
825
+ if _ , has := v .Default (); has {
826
+ ref .D = rr
827
+ } else {
828
+ ref .T = rr
829
+ }
819
830
}
820
831
821
832
return ref , nil
822
833
}
823
834
835
+ func getEnumLiteral (conjuncts []cue.Value ) (* cue.Value , error ) {
836
+ var lit * cue.Value
837
+ // The only case we actually want to support, at least for now, is this:
838
+ //
839
+ // enum: "foo" | "bar" @cuetsy(kind="enum")
840
+ // enumref: enum & "foo" @cuetsy(kind="type")
841
+ //
842
+ // Where we render enumref to TS as `Enumref: Enum.Foo`.
843
+ // For that case, we allow at most two conjuncts, and make sure they
844
+ // fit the pattern of the two operands above.
845
+ aref , bref := isReference (conjuncts [0 ]), isReference (conjuncts [1 ])
846
+ aconc , bconc := conjuncts [0 ].IsConcrete (), conjuncts [1 ].IsConcrete ()
847
+ var cr cue.Value
848
+ if aref {
849
+ cr , lit = conjuncts [0 ], & (conjuncts [1 ])
850
+ } else {
851
+ cr , lit = conjuncts [1 ], & (conjuncts [0 ])
852
+ }
853
+
854
+ if aref == bref || aconc == bconc || cr .Subsume (* lit ) != nil {
855
+ return nil , errors .New (fmt .Sprintf ("may only unify a referenced enum with a concrete literal member of that enum. Path: %s" , conjuncts [0 ].Path ()))
856
+ }
857
+
858
+ return lit , nil
859
+ }
860
+
824
861
// typeRef is a pair of expressions for referring to another type - the reference
825
862
// to the type, and the default value for the referrer. The default value
826
863
// may be the one provided by either the referent, or by the field doing the referring
0 commit comments