1 package main 2 3 import ( 4 "go/types" 5 ) 6 7 type Type interface{} 8 9 type Struct struct { 10 Fields []Field 11 } 12 13 type Field struct { 14 Name string 15 Type Type 16 Tag string 17 } 18 19 type Array struct { 20 Length int64 21 Element Type 22 } 23 24 type Slice struct { 25 Element Type 26 } 27 28 type Map struct { 29 Key, Value Type 30 } 31 32 type Pointer struct { 33 Element Type 34 } 35 36 type Int uint8 37 38 type Uint uint8 39 40 type Float uint8 41 42 type Complex uint8 43 44 type String struct{} 45 46 type Bool struct{} 47 48 type Interface struct{} 49 50 type NamedType struct { 51 Package string 52 Name string 53 Type Type 54 55 Implements []bool 56 } 57 58 type processor struct { 59 pkg string 60 methods []method 61 named map[string]*NamedType 62 } 63 64 type method struct { 65 name string 66 args []string 67 returns []string 68 } 69 70 func (p *processor) processType(typ types.Type) Type { 71 var nt NamedType 72 73 if named, ok := typ.(*types.Named); ok { 74 id := named.Obj().Id() 75 76 if exist, ok := p.named[id]; ok { 77 return exist 78 } 79 80 p.named[id] = &nt 81 82 nt = NamedType{ 83 Package: named.Obj().Pkg().Path(), 84 Name: named.Obj().Name(), 85 Implements: make([]bool, len(p.methods)), 86 } 87 88 for method := range named.Methods() { 89 name := method.Name() 90 91 Loop: 92 for i, req := range p.methods { 93 if req.name != name { 94 continue 95 } 96 97 sig := method.Signature() 98 params := sig.Params() 99 results := sig.Results() 100 101 if params.Len() != len(req.args) || results.Len() != len(req.returns) { 102 break 103 } 104 105 for n, arg := range req.args { 106 if params.At(n).Type().String() != arg { 107 break Loop 108 } 109 } 110 111 for n, ret := range req.returns { 112 if results.At(n).Type().String() != ret { 113 break Loop 114 } 115 } 116 117 nt.Implements[i] = true 118 119 break 120 } 121 } 122 } 123 124 switch t := typ.Underlying().(type) { 125 case *types.Struct: 126 nt.Type = p.toStruct(t) 127 case *types.Array: 128 nt.Type = p.toArray(t) 129 case *types.Slice: 130 nt.Type = p.toSlice(t) 131 case *types.Map: 132 nt.Type = p.toMap(t) 133 case *types.Pointer: 134 nt.Type = p.toPointer(t) 135 case *types.Basic: 136 nt.Type = toBasic(t) 137 } 138 139 if nt.Name == "" { 140 return nt.Type 141 } 142 143 return nt 144 } 145 146 func (p *processor) toStruct(t *types.Struct) Type { 147 var s Struct 148 149 for field := range t.NumFields() { 150 s.Fields = append(s.Fields, Field{ 151 Name: t.Field(field).Name(), 152 Type: p.processType(t.Field(field).Type()), 153 Tag: t.Tag(field), 154 }) 155 } 156 157 return s 158 } 159 160 func (p *processor) toArray(t *types.Array) Type { 161 return Array{ 162 Length: t.Len(), 163 Element: p.processType(t.Elem()), 164 } 165 } 166 167 func (p *processor) toSlice(t *types.Slice) Type { 168 return Slice{ 169 Element: p.processType(t.Elem()), 170 } 171 } 172 173 func (p *processor) toMap(t *types.Map) Type { 174 return Map{ 175 Key: p.processType(t.Key()), 176 Value: p.processType(t.Elem()), 177 } 178 } 179 180 func (p *processor) toPointer(t *types.Pointer) Type { 181 return Pointer{ 182 Element: p.processType(t.Elem()), 183 } 184 } 185 186 func toBasic(t *types.Basic) Type { 187 switch t.Kind() { 188 case types.Bool: 189 return Bool{} 190 case types.Int: 191 return Int(0) 192 case types.Int8: 193 return Int(8) 194 case types.Int16: 195 return Int(16) 196 case types.Int32: 197 return Int(32) 198 case types.Int64: 199 return Int(64) 200 case types.Uint: 201 return Uint(0) 202 case types.Uint8: 203 return Uint(8) 204 case types.Uint16: 205 return Uint(16) 206 case types.Uint32: 207 return Uint(32) 208 case types.Uint64, types.Uintptr: 209 return Uint(64) 210 case types.Float32: 211 return Float(32) 212 case types.Float64: 213 return Float(64) 214 case types.Complex64: 215 return Complex(64) 216 case types.Complex128: 217 return Complex(128) 218 case types.String: 219 return String{} 220 } 221 222 return nil 223 } 224