1
2
3
4
5 package value
6
7 import (
8 "reflect"
9 "strconv"
10 )
11
12 var anyType = reflect.TypeOf((*interface{})(nil)).Elem()
13
14
15
16 func TypeString(t reflect.Type, qualified bool) string {
17 return string(appendTypeName(nil, t, qualified, false))
18 }
19
20 func appendTypeName(b []byte, t reflect.Type, qualified, elideFunc bool) []byte {
21
22
23
24
25
26 if t == anyType {
27 return append(b, "any"...)
28 }
29
30
31 if t.Name() != "" {
32 if qualified && t.PkgPath() != "" {
33 b = append(b, '"')
34 b = append(b, t.PkgPath()...)
35 b = append(b, '"')
36 b = append(b, '.')
37 b = append(b, t.Name()...)
38 } else {
39 b = append(b, t.String()...)
40 }
41 return b
42 }
43
44
45 switch k := t.Kind(); k {
46 case reflect.Bool, reflect.String, reflect.UnsafePointer,
47 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
48 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
49 reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
50 b = append(b, k.String()...)
51 case reflect.Chan:
52 if t.ChanDir() == reflect.RecvDir {
53 b = append(b, "<-"...)
54 }
55 b = append(b, "chan"...)
56 if t.ChanDir() == reflect.SendDir {
57 b = append(b, "<-"...)
58 }
59 b = append(b, ' ')
60 b = appendTypeName(b, t.Elem(), qualified, false)
61 case reflect.Func:
62 if !elideFunc {
63 b = append(b, "func"...)
64 }
65 b = append(b, '(')
66 for i := 0; i < t.NumIn(); i++ {
67 if i > 0 {
68 b = append(b, ", "...)
69 }
70 if i == t.NumIn()-1 && t.IsVariadic() {
71 b = append(b, "..."...)
72 b = appendTypeName(b, t.In(i).Elem(), qualified, false)
73 } else {
74 b = appendTypeName(b, t.In(i), qualified, false)
75 }
76 }
77 b = append(b, ')')
78 switch t.NumOut() {
79 case 0:
80
81 case 1:
82 b = append(b, ' ')
83 b = appendTypeName(b, t.Out(0), qualified, false)
84 default:
85 b = append(b, " ("...)
86 for i := 0; i < t.NumOut(); i++ {
87 if i > 0 {
88 b = append(b, ", "...)
89 }
90 b = appendTypeName(b, t.Out(i), qualified, false)
91 }
92 b = append(b, ')')
93 }
94 case reflect.Struct:
95 b = append(b, "struct{ "...)
96 for i := 0; i < t.NumField(); i++ {
97 if i > 0 {
98 b = append(b, "; "...)
99 }
100 sf := t.Field(i)
101 if !sf.Anonymous {
102 if qualified && sf.PkgPath != "" {
103 b = append(b, '"')
104 b = append(b, sf.PkgPath...)
105 b = append(b, '"')
106 b = append(b, '.')
107 }
108 b = append(b, sf.Name...)
109 b = append(b, ' ')
110 }
111 b = appendTypeName(b, sf.Type, qualified, false)
112 if sf.Tag != "" {
113 b = append(b, ' ')
114 b = strconv.AppendQuote(b, string(sf.Tag))
115 }
116 }
117 if b[len(b)-1] == ' ' {
118 b = b[:len(b)-1]
119 } else {
120 b = append(b, ' ')
121 }
122 b = append(b, '}')
123 case reflect.Slice, reflect.Array:
124 b = append(b, '[')
125 if k == reflect.Array {
126 b = strconv.AppendUint(b, uint64(t.Len()), 10)
127 }
128 b = append(b, ']')
129 b = appendTypeName(b, t.Elem(), qualified, false)
130 case reflect.Map:
131 b = append(b, "map["...)
132 b = appendTypeName(b, t.Key(), qualified, false)
133 b = append(b, ']')
134 b = appendTypeName(b, t.Elem(), qualified, false)
135 case reflect.Ptr:
136 b = append(b, '*')
137 b = appendTypeName(b, t.Elem(), qualified, false)
138 case reflect.Interface:
139 b = append(b, "interface{ "...)
140 for i := 0; i < t.NumMethod(); i++ {
141 if i > 0 {
142 b = append(b, "; "...)
143 }
144 m := t.Method(i)
145 if qualified && m.PkgPath != "" {
146 b = append(b, '"')
147 b = append(b, m.PkgPath...)
148 b = append(b, '"')
149 b = append(b, '.')
150 }
151 b = append(b, m.Name...)
152 b = appendTypeName(b, m.Type, qualified, true)
153 }
154 if b[len(b)-1] == ' ' {
155 b = b[:len(b)-1]
156 } else {
157 b = append(b, ' ')
158 }
159 b = append(b, '}')
160 default:
161 panic("invalid kind: " + k.String())
162 }
163 return b
164 }
165
View as plain text