@@ -110,7 +110,7 @@ func (c *Code) NameOf(name xml.Name) string {
110110 return "NOTFOUND" + name .Local
111111 }
112112
113- switch b := c .cfg .flatten1 (t , func (xsd.Type ) {}, 0 ).(type ) {
113+ switch b := c .cfg .flatten1 (t , map [xml. Name ]xsd. Type {}, func (xsd.Type ) {}, 0 ).(type ) {
114114 case xsd.Builtin :
115115 return c .NameOf (b .Name ())
116116 }
@@ -371,6 +371,8 @@ func (cfg *Config) flatten(types map[xml.Name]xsd.Type) []xsd.Type {
371371 push := func (t xsd.Type ) {
372372 result = append (result , t )
373373 }
374+
375+ var flattenedTypes = map [xml.Name ]xsd.Type {}
374376 for _ , t := range types {
375377 if xsd .XMLName (t ).Local == "_self" {
376378 continue
@@ -384,7 +386,7 @@ func (cfg *Config) flatten(types map[xml.Name]xsd.Type) []xsd.Type {
384386 continue
385387 }
386388 }
387- if t := cfg .flatten1 (t , push , 0 ); t != nil {
389+ if t := cfg .flatten1 (t , flattenedTypes , push , 0 ); t != nil {
388390 push (t )
389391 }
390392 }
@@ -402,7 +404,12 @@ func dedup(types []xsd.Type) (unique []xsd.Type) {
402404 return unique
403405}
404406
405- func (cfg * Config ) flatten1 (t xsd.Type , push func (xsd.Type ), depth int ) xsd.Type {
407+ func (cfg * Config ) flatten1 (t xsd.Type , flattenedTypes map [xml.Name ]xsd.Type , push func (xsd.Type ), depth int ) xsd.Type {
408+ if res , ok := flattenedTypes [xsd .XMLName (t )]; ok {
409+ return res
410+ }
411+ flattenedTypes [xsd .XMLName (t )] = t
412+
406413 const maxDepth = 1000
407414 if depth > maxDepth {
408415 return t
@@ -463,6 +470,8 @@ func (cfg *Config) flatten1(t xsd.Type, push func(xsd.Type), depth int) xsd.Type
463470 t .Doc = "Must be at least " + strconv .Itoa (t .Restriction .MinLength ) + " items long"
464471 return t
465472 }
473+
474+ flattenedTypes [xsd .XMLName (t )] = t .Base
466475 return t .Base
467476 case * xsd.ComplexType :
468477 // We can "unpack" a struct if it is extending a simple
@@ -478,30 +487,33 @@ func (cfg *Config) flatten1(t xsd.Type, push func(xsd.Type), depth int) xsd.Type
478487 t .Name .Local , xsd .XMLName (t .Base ))
479488 switch b := t .Base .(type ) {
480489 case xsd.Builtin :
490+ flattenedTypes [xsd .XMLName (t )] = b
481491 return b
482492 case * xsd.SimpleType :
483- return cfg .flatten1 (t .Base , push , depth + 1 )
493+ res := cfg .flatten1 (t .Base , flattenedTypes , push , depth + 1 )
494+ flattenedTypes [xsd .XMLName (t )] = res
495+ return res
484496 }
485497 }
486498 }
487499 // We can flatten a struct field if its type does not
488500 // need additional methods for unmarshalling.
489501 for i , el := range t .Elements {
490- el .Type = cfg .flatten1 (el .Type , push , depth + 1 )
502+ el .Type = cfg .flatten1 (el .Type , flattenedTypes , push , depth + 1 )
491503 t .Elements [i ] = el
492504 push (el .Type )
493505 cfg .debugf ("element %s %T(%s): %v" , el .Name .Local , t ,
494506 xsd .XMLName (t ).Local , xsd .XMLName (el .Type ))
495507 }
496508 for i , attr := range t .Attributes {
497- attr .Type = cfg .flatten1 (attr .Type , push , depth + 1 )
509+ attr .Type = cfg .flatten1 (attr .Type , flattenedTypes , push , depth + 1 )
498510 t .Attributes [i ] = attr
499511 push (attr .Type )
500512 cfg .debugf ("attribute %s %T(%s): %v" , attr .Name .Local , t ,
501513 xsd .XMLName (t ).Local , xsd .XMLName (attr .Type ))
502514 }
503515
504- t .Base = cfg .flatten1 (t .Base , push , depth + 1 )
516+ t .Base = cfg .flatten1 (t .Base , flattenedTypes , push , depth + 1 )
505517
506518 // We expand all complexTypes to merge all of the fields from
507519 // their ancestors, so generated code has no dependencies
0 commit comments