fakereflect.go raw
1 package fakereflect
2
3 import (
4 "fmt"
5 "go/types"
6 "reflect"
7 )
8
9 type TypeAndCanAddr struct {
10 Type types.Type
11 canAddr bool
12 }
13
14 type StructField struct {
15 Index []int
16 Name string
17 Anonymous bool
18 Tag reflect.StructTag
19 f *types.Var
20 Type TypeAndCanAddr
21 }
22
23 func (sf StructField) IsExported() bool { return sf.f.Exported() }
24
25 func (t TypeAndCanAddr) Field(i int) StructField {
26 st := t.Type.Underlying().(*types.Struct)
27 f := st.Field(i)
28 return StructField{
29 f: f,
30 Index: []int{i},
31 Name: f.Name(),
32 Anonymous: f.Anonymous(),
33 Tag: reflect.StructTag(st.Tag(i)),
34 Type: TypeAndCanAddr{
35 Type: f.Type(),
36 canAddr: t.canAddr,
37 },
38 }
39 }
40
41 func (t TypeAndCanAddr) FieldByIndex(index []int) StructField {
42 f := t.Field(index[0])
43 for _, idx := range index[1:] {
44 f = f.Type.Field(idx)
45 }
46 f.Index = index
47 return f
48 }
49
50 func PtrTo(t TypeAndCanAddr) TypeAndCanAddr {
51 // Note that we don't care about canAddr here because it's irrelevant to all uses of PtrTo
52 return TypeAndCanAddr{Type: types.NewPointer(t.Type)}
53 }
54
55 func (t TypeAndCanAddr) CanAddr() bool { return t.canAddr }
56
57 func (t TypeAndCanAddr) Implements(ityp *types.Interface) bool {
58 return types.Implements(t.Type, ityp)
59 }
60
61 func (t TypeAndCanAddr) IsSlice() bool {
62 _, ok := t.Type.Underlying().(*types.Slice)
63 return ok
64 }
65
66 func (t TypeAndCanAddr) IsArray() bool {
67 _, ok := t.Type.Underlying().(*types.Array)
68 return ok
69 }
70
71 func (t TypeAndCanAddr) IsPtr() bool {
72 _, ok := t.Type.Underlying().(*types.Pointer)
73 return ok
74 }
75
76 func (t TypeAndCanAddr) IsInterface() bool {
77 _, ok := t.Type.Underlying().(*types.Interface)
78 return ok
79 }
80
81 func (t TypeAndCanAddr) IsStruct() bool {
82 _, ok := t.Type.Underlying().(*types.Struct)
83 return ok
84 }
85
86 func (t TypeAndCanAddr) Name() string {
87 named, ok := types.Unalias(t.Type).(*types.Named)
88 if !ok {
89 return ""
90 }
91 return named.Obj().Name()
92 }
93
94 func (t TypeAndCanAddr) NumField() int {
95 return t.Type.Underlying().(*types.Struct).NumFields()
96 }
97
98 func (t TypeAndCanAddr) String() string {
99 return t.Type.String()
100 }
101
102 func (t TypeAndCanAddr) Key() TypeAndCanAddr {
103 return TypeAndCanAddr{Type: t.Type.Underlying().(*types.Map).Key()}
104 }
105
106 func (t TypeAndCanAddr) Elem() TypeAndCanAddr {
107 switch typ := t.Type.Underlying().(type) {
108 case *types.Pointer:
109 return TypeAndCanAddr{
110 Type: typ.Elem(),
111 canAddr: true,
112 }
113 case *types.Slice:
114 return TypeAndCanAddr{
115 Type: typ.Elem(),
116 canAddr: true,
117 }
118 case *types.Array:
119 return TypeAndCanAddr{
120 Type: typ.Elem(),
121 canAddr: t.canAddr,
122 }
123 case *types.Map:
124 return TypeAndCanAddr{
125 Type: typ.Elem(),
126 canAddr: false,
127 }
128 default:
129 panic(fmt.Sprintf("unhandled type %T", typ))
130 }
131 }
132