Skip to content

Commit

Permalink
Fix defaults in enums
Browse files Browse the repository at this point in the history
  • Loading branch information
spinillos committed Mar 15, 2023
1 parent 371b5a7 commit b26edcb
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 15 deletions.
47 changes: 43 additions & 4 deletions generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,15 @@ func (g *generator) genInterfaceField(v cue.Value) (*typeRef, error) {
isReference,
func(v cue.Value) bool { return targetsKind(cue.Dereference(v), TypeEnum) },
) {
return g.genEnumReference(v)
op, args := v.Expr()
if op != cue.OrOp {
return g.genEnumReference(v)
}
for _, a := range args {
if a.IncompleteKind() == cue.TopKind {
return g.genEnumReference(v)
}
}
}

// One path for when there's a ref to a cuetsy node, and a separate one otherwise
Expand Down Expand Up @@ -749,15 +757,19 @@ func (g *generator) genEnumReference(v cue.Value) (*typeRef, error) {
case 1:
case 2:
var err error
conjuncts[1] = getDefaultEnumValue(conjuncts[1])
lit, err = getEnumLiteral(conjuncts)
if err != nil {
ve := valError(v, err.Error())
g.addErr(ve)
return nil, ve
}
case 3:
// It could happen when we are setting a default value into a parent field.
if !conjuncts[0].Equals(conjuncts[1]) {
if conjuncts[1].IncompleteKind() == cue.TopKind {
conjuncts[1] = conjuncts[0]
}

if !conjuncts[0].Equals(conjuncts[1]) && conjuncts[0].Subsume(conjuncts[1]) != nil {
ve := valError(v, "complex unifications containing references to enums without overriding parent are not currently supported")
g.addErr(ve)
return nil, ve
Expand Down Expand Up @@ -822,7 +834,13 @@ func (g *generator) genEnumReference(v cue.Value) (*typeRef, error) {
return nil, err
}

if _, has := v.Default(); has {
op, args := v.Expr()
hasInnerDefault := false
if len(args) == 2 && op == cue.AndOp {
_, hasInnerDefault = args[1].Default()
}

if _, has := v.Default(); has || hasInnerDefault {
ref.D = rr
} else {
ref.T = rr
Expand Down Expand Up @@ -858,6 +876,27 @@ func getEnumLiteral(conjuncts []cue.Value) (*cue.Value, error) {
return lit, nil
}

// getDefaultEnumValue is looking for default values like #Enum & (*"default" | _) struct
func getDefaultEnumValue(v cue.Value) cue.Value {
if v.IncompleteKind() != cue.TopKind {
return v
}

op, args := v.Expr()
if op != cue.OrOp {
return v
}

for _, a := range args {
if a.IncompleteKind() == cue.TopKind {
if def, has := a.Default(); has {
return def
}
}
}
return v
}

// typeRef is a pair of expressions for referring to another type - the reference
// to the type, and the default value for the referrer. The default value
// may be the one provided by either the referent, or by the field doing the referring
Expand Down
10 changes: 8 additions & 2 deletions testdata/fields_with_default_enums.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
#Base
baseEnum: #Enum
valueEnum: #Enum & "a"
defaultEnum: #Enum | *"a"
noOverrideDefaultEnum: #Enum | *"b"
defaultEnum: #Enum | (*"a" | _)
noOverrideDefaultEnum: #Enum | (*"b" | _)
noOverrideEnum: #Enum & "b"
defaultString: #Enum | *"invalid"
defaultNumber: #Enum | "something" | *34
} @cuetsy(kind="interface")

-- ts --
Expand All @@ -32,12 +34,16 @@ export interface Base {
export interface StructWithDefaults extends Base {
baseEnum: Enum;
defaultEnum: Enum;
defaultNumber: Enum;
defaultString: Enum;
noOverrideDefaultEnum: Enum;
noOverrideEnum: Enum.B;
valueEnum: Enum.A;
}

export const defaultStructWithDefaults: Partial<StructWithDefaults> = {
defaultEnum: Enum.A,
defaultNumber: 34,
defaultString: 'invalid',
noOverrideDefaultEnum: Enum.B,
};
18 changes: 9 additions & 9 deletions testdata/imports/compose_enums.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ LocalEnumNumeric: 1 | 2 | 3 @cuetsy(kind="enum", memberNames="One|Two|Three")
LocalEnumNumericD: *1 | 2 | 3 @cuetsy(kind="enum", memberNames="One|Two|Three")

Compose: {
localstr: LocalEnum | *"baz"
localstr: LocalEnum & (*"baz" | _)
localstrd: LocalEnumD
localstrover: LocalEnumD | *"baz"
localnum: LocalEnumNumeric | *2
localstrover: LocalEnumD & (*"baz" | _)
localnum: LocalEnumNumeric & (*2 | _)
localnumd: LocalEnumNumericD
localnumover: LocalEnumNumericD | *2
impstr: dep.DepEnum | *"bar"
localnumover: LocalEnumNumericD & (*2 | _)
impstr: dep.DepEnum & (*"bar" | _)
impstrd: dep.DepEnumD
impstrover: dep.DepEnumD | *"bar"
impnum: dep.DepEnumNumeric | *3
impstrover: dep.DepEnumD & (*"bar" | _)
impnum: dep.DepEnumNumeric & (*3 | _)
impnumd: dep.DepEnumNumericD
impnumover: dep.DepEnumNumericD | *3
impnumover: dep.DepEnumNumericD & (*3 | _)
} @cuetsy(kind="interface")

-- dep/file.cue --
Expand Down Expand Up @@ -92,4 +92,4 @@ export const defaultCompose: Partial<Compose> = {
localstr: LocalEnum.Baz,
localstrd: LocalEnumD.Foo,
localstrover: LocalEnumD.Baz,
};
};

0 comments on commit b26edcb

Please sign in to comment.