github.com/myhau/pulumi/pkg/v3@v3.70.2-0.20221116134521-f2775972e587/codegen/utilities_types.go (about) 1 package codegen 2 3 import ( 4 "github.com/pulumi/pulumi/pkg/v3/codegen/schema" 5 ) 6 7 func visitTypeClosure(t schema.Type, visitor func(t schema.Type), seen Set) { 8 if seen.Has(t) { 9 return 10 } 11 seen.Add(t) 12 13 visitor(t) 14 15 switch st := t.(type) { 16 case *schema.ArrayType: 17 visitTypeClosure(st.ElementType, visitor, seen) 18 case *schema.MapType: 19 visitTypeClosure(st.ElementType, visitor, seen) 20 case *schema.ObjectType: 21 for _, p := range st.Properties { 22 visitTypeClosure(p.Type, visitor, seen) 23 } 24 case *schema.UnionType: 25 for _, e := range st.ElementTypes { 26 visitTypeClosure(e, visitor, seen) 27 } 28 case *schema.InputType: 29 visitTypeClosure(st.ElementType, visitor, seen) 30 case *schema.OptionalType: 31 visitTypeClosure(st.ElementType, visitor, seen) 32 } 33 } 34 35 func VisitTypeClosure(properties []*schema.Property, visitor func(t schema.Type)) { 36 seen := Set{} 37 for _, p := range properties { 38 visitTypeClosure(p.Type, visitor, seen) 39 } 40 } 41 42 func SimplifyInputUnion(t schema.Type) schema.Type { 43 union, ok := t.(*schema.UnionType) 44 if !ok { 45 return t 46 } 47 48 elements := make([]schema.Type, len(union.ElementTypes)) 49 for i, et := range union.ElementTypes { 50 if input, ok := et.(*schema.InputType); ok { 51 elements[i] = input.ElementType 52 } else { 53 elements[i] = et 54 } 55 } 56 return &schema.UnionType{ 57 ElementTypes: elements, 58 DefaultType: union.DefaultType, 59 Discriminator: union.Discriminator, 60 Mapping: union.Mapping, 61 } 62 } 63 64 // RequiredType unwraps the OptionalType enclosing the Property's type, if any. 65 func RequiredType(p *schema.Property) schema.Type { 66 if optional, ok := p.Type.(*schema.OptionalType); ok { 67 return optional.ElementType 68 } 69 return p.Type 70 } 71 72 // OptionalType wraps the Property's type in an OptionalType if it is not already optional. 73 func OptionalType(p *schema.Property) schema.Type { 74 if optional, ok := p.Type.(*schema.OptionalType); ok { 75 return optional 76 } 77 return &schema.OptionalType{ElementType: p.Type} 78 } 79 80 // UnwrapType removes any outer OptionalTypes and InputTypes from t. 81 func UnwrapType(t schema.Type) schema.Type { 82 for { 83 switch typ := t.(type) { 84 case *schema.InputType: 85 t = typ.ElementType 86 case *schema.OptionalType: 87 t = typ.ElementType 88 default: 89 return t 90 } 91 } 92 } 93 94 // MapInnerType applies f to the first non-wrapper type in t. 95 // MapInnerType does not mutate it's input, and t should not either. 96 func MapInnerType(t schema.Type, f func(schema.Type) schema.Type) schema.Type { 97 switch t := t.(type) { 98 case *schema.InputType: 99 return &schema.InputType{ElementType: MapInnerType(t.ElementType, f)} 100 case *schema.OptionalType: 101 return &schema.OptionalType{ElementType: MapInnerType(t.ElementType, f)} 102 case *schema.ArrayType: 103 return &schema.ArrayType{ElementType: MapInnerType(t.ElementType, f)} 104 case *schema.MapType: 105 return &schema.MapType{ElementType: MapInnerType(t.ElementType, f)} 106 default: 107 return f(t) 108 } 109 } 110 111 // Applies f to the first non-optional type in t. 112 // If t is Optional{v} then returns Optional{f(v)}, otherwise f(t) is returned 113 func MapOptionalType(t schema.Type, f func(schema.Type) schema.Type) schema.Type { 114 if opt, ok := t.(*schema.OptionalType); ok { 115 return &schema.OptionalType{ElementType: f(opt.ElementType)} 116 } 117 return f(t) 118 } 119 120 func IsNOptionalInput(t schema.Type) bool { 121 for { 122 switch typ := t.(type) { 123 case *schema.InputType: 124 return true 125 case *schema.OptionalType: 126 t = typ.ElementType 127 default: 128 return false 129 } 130 } 131 } 132 133 func resolvedType(t schema.Type, plainObjects bool) schema.Type { 134 switch typ := t.(type) { 135 case *schema.InputType: 136 return resolvedType(typ.ElementType, plainObjects) 137 case *schema.OptionalType: 138 e := resolvedType(typ.ElementType, plainObjects) 139 if e == typ.ElementType { 140 return typ 141 } 142 return &schema.OptionalType{ElementType: e} 143 case *schema.ArrayType: 144 e := resolvedType(typ.ElementType, plainObjects) 145 if e == typ.ElementType { 146 return typ 147 } 148 return &schema.ArrayType{ElementType: e} 149 case *schema.MapType: 150 e := resolvedType(typ.ElementType, plainObjects) 151 if e == typ.ElementType { 152 return typ 153 } 154 return &schema.MapType{ElementType: e} 155 case *schema.ObjectType: 156 if !plainObjects || !typ.IsInputShape() { 157 return typ 158 } 159 return typ.PlainShape 160 case *schema.UnionType: 161 elems, changed := make([]schema.Type, len(typ.ElementTypes)), false 162 for i, e := range typ.ElementTypes { 163 elems[i] = resolvedType(e, plainObjects) 164 changed = changed || elems[i] != e 165 } 166 if !changed { 167 return typ 168 } 169 return &schema.UnionType{ 170 ElementTypes: elems, 171 DefaultType: typ.DefaultType, 172 Discriminator: typ.Discriminator, 173 Mapping: typ.Mapping, 174 } 175 default: 176 return t 177 } 178 } 179 180 // PlainType deeply removes any InputTypes from t, with the exception of argument structs. Use ResolvedType to 181 // unwrap argument structs as well. 182 func PlainType(t schema.Type) schema.Type { 183 return resolvedType(t, false) 184 } 185 186 // ResolvedType deeply removes any InputTypes from t. 187 func ResolvedType(t schema.Type) schema.Type { 188 return resolvedType(t, true) 189 } 190 191 // If a helper function needs to be invoked to provide default values for a 192 // plain type. The provided map cannot be reused. 193 func IsProvideDefaultsFuncRequired(t schema.Type) bool { 194 return isProvideDefaultsFuncRequiredHelper(t, map[string]bool{}) 195 } 196 197 func isProvideDefaultsFuncRequiredHelper(t schema.Type, seen map[string]bool) bool { 198 if seen[t.String()] { 199 return false 200 } 201 seen[t.String()] = true 202 t = UnwrapType(t) 203 object, ok := t.(*schema.ObjectType) 204 if !ok { 205 return false 206 } 207 for _, p := range object.Properties { 208 if p.DefaultValue != nil || isProvideDefaultsFuncRequiredHelper(p.Type, seen) { 209 return true 210 } 211 } 212 return false 213 }