collectUserTypes traverses the given data type recursively and calls back the given function for each attribute using a user type.
(dt expr.DataType, cb func(expr.UserType), seen ...map[string]struct{})
| 2720 | // collectUserTypes traverses the given data type recursively and calls back the |
| 2721 | // given function for each attribute using a user type. |
| 2722 | func collectUserTypes(dt expr.DataType, cb func(expr.UserType), seen ...map[string]struct{}) { |
| 2723 | if dt == expr.Empty { |
| 2724 | return |
| 2725 | } |
| 2726 | var s map[string]struct{} |
| 2727 | if len(seen) > 0 { |
| 2728 | s = seen[0] |
| 2729 | } else { |
| 2730 | s = make(map[string]struct{}) |
| 2731 | } |
| 2732 | switch actual := dt.(type) { |
| 2733 | case *expr.Object: |
| 2734 | for _, nat := range *actual { |
| 2735 | collectUserTypes(nat.Attribute.Type, cb, seen...) |
| 2736 | } |
| 2737 | case *expr.Union: |
| 2738 | for _, nat := range actual.Values { |
| 2739 | collectUserTypes(nat.Attribute.Type, cb, seen...) |
| 2740 | } |
| 2741 | case *expr.Array: |
| 2742 | collectUserTypes(actual.ElemType.Type, cb, seen...) |
| 2743 | case *expr.Map: |
| 2744 | collectUserTypes(actual.KeyType.Type, cb, seen...) |
| 2745 | collectUserTypes(actual.ElemType.Type, cb, seen...) |
| 2746 | case expr.UserType: |
| 2747 | if _, ok := s[actual.ID()]; ok { |
| 2748 | return |
| 2749 | } |
| 2750 | s[actual.ID()] = struct{}{} |
| 2751 | cb(actual) |
| 2752 | collectUserTypes(actual.Attribute().Type, cb, s) |
| 2753 | } |
| 2754 | } |
| 2755 | |
| 2756 | func collectHTTPUnionTypes(att *expr.AttributeExpr, scope *codegen.NameScope, unions map[string]*service.UnionTypeData, seen map[string]struct{}) { |
| 2757 | if att == nil || att.Type == expr.Empty { |
no test coverage detected