diff --git a/xsdgen/testdata/redundant-union.go.golden b/xsdgen/testdata/redundant-union.go.golden new file mode 100644 index 0000000..33a37b4 --- /dev/null +++ b/xsdgen/testdata/redundant-union.go.golden @@ -0,0 +1,18 @@ +// Code generated by xsdgen.test. DO NOT EDIT. + +package ws + +import "encoding/xml" + +// May be one of A, B, C +type EnumType string + +const ( + EnumType_A EnumType = "A" + EnumType_B EnumType = "B" + EnumType_C EnumType = "C" +) + +type Type1 struct { + Elem []EnumType `xml:"Elem,omitempty"` +} diff --git a/xsdgen/testdata/redundant-union.xsd b/xsdgen/testdata/redundant-union.xsd new file mode 100644 index 0000000..cd28300 --- /dev/null +++ b/xsdgen/testdata/redundant-union.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xsdgen/xsdgen.go b/xsdgen/xsdgen.go index 0604c4d..af41607 100644 --- a/xsdgen/xsdgen.go +++ b/xsdgen/xsdgen.go @@ -402,6 +402,54 @@ func dedup(types []xsd.Type) (unique []xsd.Type) { return unique } +// for now, bustUnion only resolves simple cases like a union of a builtin and an enum of the same builtin, e.g. in +// this case redundantUnionType will be replaced with enumType +// +// +// +// +// +// +// +// +// +// +// +func (cfg *Config) bustUnion(t *xsd.SimpleType) xsd.Type { + var underlying xsd.Type + var actual xsd.Type + for _, member := range t.Union { + switch ut := member.(type) { + case xsd.Builtin: + if underlying != nil && underlying != ut { + // can't simplify + return t + } + underlying = ut + case *xsd.SimpleType: + base := xsd.Base(ut) + if underlying != nil && underlying != ut { + // can't simplify + return t + } + if actual != nil && actual != ut { + // TODO: can we simplify this case? + return t + } + underlying = base + actual = ut + default: + // TODO: handle more union member types + return t + } + } + + if actual != nil { + return actual + } + return underlying +} + func (cfg *Config) flatten1(t xsd.Type, push func(xsd.Type), depth int) xsd.Type { const maxDepth = 1000 if depth > maxDepth { @@ -414,7 +462,12 @@ func (cfg *Config) flatten1(t xsd.Type, push func(xsd.Type), depth int) xsd.Type base, builtin xsd.Type ok bool ) - // TODO: handle list/union types + // TODO: handle list types + + if len(t.Union) > 0 { + return cfg.bustUnion(t) + } + for base = xsd.Base(t); base != nil; base = xsd.Base(base) { if builtin, ok = base.(xsd.Builtin); ok { break