Skip to content

Commit

Permalink
Fix override parent type values with defaults
Browse files Browse the repository at this point in the history
  • Loading branch information
spinillos committed Mar 21, 2023
1 parent 792ffe7 commit 40bb73f
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 49 deletions.
2 changes: 1 addition & 1 deletion analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func hasOverrideValues(v cue.Value, kinds ...TSType) bool {
}

defaultOp, _ := values[1].Expr()
if defaultOp == cue.AndOp {
if defaultOp == cue.AndOp || defaultOp == cue.OrOp {
return false
}

Expand Down
75 changes: 27 additions & 48 deletions generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,10 +506,11 @@ func (g *generator) genInterface(name string, v cue.Value) []ts.Decl {
}

sub := nolit.LookupPath(cue.MakePath(sel))
// Theoretically, lattice equality can be defined as bijective
// subsumption. In practice, Subsume() seems to ignore optional
// fields, and Equals() doesn't. So, use Equals().
if sub.Exists() && sub.Equals(iter.Value()) {
op, _ := iter.Value().Expr()
// Also we need to check if the sub operator to discard the one that have validators and if it has a default
subOp, _ := sub.Expr()
_, def := iter.Value().Default()
if sub.Exists() && sub.Equals(iter.Value()) && (subOp == cue.AndOp || op != cue.AndOp || !def) {
continue
}
}
Expand Down Expand Up @@ -656,52 +657,14 @@ func (g *generator) genInterfaceField(v cue.Value) (*typeRef, error) {
return g.genEnumReference(v)
}

// One path for when there's a ref to a cuetsy node, and a separate one otherwise
if !containsCuetsyReference(v) {
tref.T, err = tsprintField(v, true)
if err != nil {
tref.T, err = tsprintField(v, true)
if err != nil {
if !containsCuetsyReference(v) {
g.addErr(valError(v, "could not generate field: %w", err))
return nil, err
}
} else {
expr, err := tsprintField(v, true)
if err != nil {
g.addErr(err)
return nil, nil
}
tref.T = expr

// Deconstruct the field's expressions.
// conjuncts := appendSplit(nil, cue.AndOp, v)

// var expr ts.Expr
//
// for _, cv := range conjuncts {
// disjuncts := appendSplit(nil, cue.OrOp, cv)
// for i, dv := range disjuncts {
// if _, r := dv.Reference(); len(r) == 0 {
// disjuncts[i] = dv.Eval()
// }
// }
// switch len(disjuncts) {
// case 0:
// // conjunct eliminated - need more preprocessing to actually make this possible
// panic("TODO, unreachable")
// case 1:
// err := disjuncts[0].Err()
// if err != nil {
// g.addErr(valError(v, "invalid value"))
// return nil
// }
// expr, err = tsprintField(disjuncts[0])
// if err != nil {
// g.addErr(valError(v, "invalid value"))
// return nil
// }
// default:
// // TODO create disjunction handler
// }
// }
g.addErr(err)
return nil, nil
}

exists, defExpr, err := tsPrintDefault(v)
Expand Down Expand Up @@ -859,6 +822,7 @@ func tsPrintDefault(v cue.Value) (bool, ts.Expr, error) {
// }

if ok {
d = getTypeDefaultOverride(d)
expr, err := tsprintField(d, false)
if err != nil {
return false, nil, err
Expand All @@ -879,9 +843,22 @@ func tsPrintDefault(v cue.Value) (bool, ts.Expr, error) {

return true, expr, nil
}

return false, nil, nil
}

func getTypeDefaultOverride(v cue.Value) cue.Value {
op, expr := v.Expr()
if op != cue.AndOp || len(expr) < 2 {
return v
}

if def, ok := expr[1].Default(); ok {
return def
}
return v
}

// Render a string containing a Typescript semantic equivalent to the provided
// Value for placement in a single field, if possible.
func tsprintField(v cue.Value, isType bool) (ts.Expr, error) {
Expand Down Expand Up @@ -1198,7 +1175,7 @@ func refAsInterface(v cue.Value) (ts.Expr, error) {
// attribute. The variadic parameter determines which kinds will be treated as
// permissible. By default, all kinds are permitted.
//
// An nil expr indicates a reference is not allowable, including the case
// A nil expr indicates a reference is not allowable, including the case
// that the provided Value is not actually a reference. A non-nil error
// indicates a deeper problem.
func referenceValueAs(v cue.Value, kinds ...TSType) (ts.Expr, error) {
Expand Down Expand Up @@ -1269,6 +1246,8 @@ func referenceValueAs(v cue.Value, kinds ...TSType) (ts.Expr, error) {
Sel: ts.Ident(dstr),
}, nil
}

return ts.Ident(dstr), nil
default:
return nil, valError(v, "unknown selector subject type %T, cannot translate path %s", dvals[0].Source(), v.Path().String())
}
Expand Down
44 changes: 44 additions & 0 deletions testdata/fields_with_default_types.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
-- cue --

#Type: "a" | "b" | "c" @cuetsy(kind="type")

#Base: {
valueType: #Type
defaultType: #Type
} @cuetsy(kind="interface")

#StructWithDefaults: {
#Base
baseType: #Type
valueType: #Type
defaultType: #Type | (*"a" | _)
noOverrideDefaultType: #Type | (*"b" | _)
noOverrideType: #Type
defaultString: #Type | *"invalid"
defaultNumber: #Type | "something" | *34
} @cuetsy(kind="interface")

-- ts --

export type Type = ('a' | 'b' | 'c');

export interface Base {
defaultType: Type;
valueType: Type;
}

export interface StructWithDefaults extends Base {
baseType: Type;
defaultNumber: Type;
defaultString: Type;
defaultType: Type;
noOverrideDefaultType: Type;
noOverrideType: Type;
}

export const defaultStructWithDefaults: Partial<StructWithDefaults> = {
defaultNumber: 34,
defaultString: 'invalid',
defaultType: 'a',
noOverrideDefaultType: 'b',
};

0 comments on commit 40bb73f

Please sign in to comment.