Source file
src/go/types/exprstring.go
1
2
3
4
5
6
7 package types
8
9 import (
10 "bytes"
11 "fmt"
12 "go/ast"
13 "go/internal/typeparams"
14 )
15
16
17
18
19 func ExprString(x ast.Expr) string {
20 var buf bytes.Buffer
21 WriteExpr(&buf, x)
22 return buf.String()
23 }
24
25
26
27
28 func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
29
30
31
32
33
34 switch x := x.(type) {
35 default:
36 buf.WriteString(fmt.Sprintf("(ast: %T)", x))
37
38 case *ast.Ident:
39 buf.WriteString(x.Name)
40
41 case *ast.Ellipsis:
42 buf.WriteString("...")
43 if x.Elt != nil {
44 WriteExpr(buf, x.Elt)
45 }
46
47 case *ast.BasicLit:
48 buf.WriteString(x.Value)
49
50 case *ast.FuncLit:
51 buf.WriteByte('(')
52 WriteExpr(buf, x.Type)
53 buf.WriteString(" literal)")
54
55 case *ast.CompositeLit:
56 buf.WriteByte('(')
57 WriteExpr(buf, x.Type)
58 buf.WriteString(" literal)")
59
60 case *ast.ParenExpr:
61 buf.WriteByte('(')
62 WriteExpr(buf, x.X)
63 buf.WriteByte(')')
64
65 case *ast.SelectorExpr:
66 WriteExpr(buf, x.X)
67 buf.WriteByte('.')
68 buf.WriteString(x.Sel.Name)
69
70 case *ast.IndexExpr:
71 WriteExpr(buf, x.X)
72 buf.WriteByte('[')
73 exprs := typeparams.UnpackExpr(x.Index)
74 for i, e := range exprs {
75 if i > 0 {
76 buf.WriteString(", ")
77 }
78 WriteExpr(buf, e)
79 }
80 buf.WriteByte(']')
81
82 case *ast.SliceExpr:
83 WriteExpr(buf, x.X)
84 buf.WriteByte('[')
85 if x.Low != nil {
86 WriteExpr(buf, x.Low)
87 }
88 buf.WriteByte(':')
89 if x.High != nil {
90 WriteExpr(buf, x.High)
91 }
92 if x.Slice3 {
93 buf.WriteByte(':')
94 if x.Max != nil {
95 WriteExpr(buf, x.Max)
96 }
97 }
98 buf.WriteByte(']')
99
100 case *ast.TypeAssertExpr:
101 WriteExpr(buf, x.X)
102 buf.WriteString(".(")
103 WriteExpr(buf, x.Type)
104 buf.WriteByte(')')
105
106 case *ast.CallExpr:
107 WriteExpr(buf, x.Fun)
108 buf.WriteByte('(')
109 writeExprList(buf, x.Args)
110 if x.Ellipsis.IsValid() {
111 buf.WriteString("...")
112 }
113 buf.WriteByte(')')
114
115 case *ast.StarExpr:
116 buf.WriteByte('*')
117 WriteExpr(buf, x.X)
118
119 case *ast.UnaryExpr:
120 buf.WriteString(x.Op.String())
121 WriteExpr(buf, x.X)
122
123 case *ast.BinaryExpr:
124 WriteExpr(buf, x.X)
125 buf.WriteByte(' ')
126 buf.WriteString(x.Op.String())
127 buf.WriteByte(' ')
128 WriteExpr(buf, x.Y)
129
130 case *ast.ArrayType:
131 buf.WriteByte('[')
132 if x.Len != nil {
133 WriteExpr(buf, x.Len)
134 }
135 buf.WriteByte(']')
136 WriteExpr(buf, x.Elt)
137
138 case *ast.StructType:
139 buf.WriteString("struct{")
140 writeFieldList(buf, x.Fields.List, "; ", false)
141 buf.WriteByte('}')
142
143 case *ast.FuncType:
144 buf.WriteString("func")
145 writeSigExpr(buf, x)
146
147 case *ast.InterfaceType:
148
149
150 var types []ast.Expr
151 var methods []*ast.Field
152 for _, f := range x.Methods.List {
153 if len(f.Names) > 1 && f.Names[0].Name == "type" {
154
155 types = append(types, f.Type)
156 } else {
157
158 methods = append(methods, f)
159 }
160 }
161
162 buf.WriteString("interface{")
163 writeFieldList(buf, methods, "; ", true)
164 if len(types) > 0 {
165 if len(methods) > 0 {
166 buf.WriteString("; ")
167 }
168 buf.WriteString("type ")
169 writeExprList(buf, types)
170 }
171 buf.WriteByte('}')
172
173 case *ast.MapType:
174 buf.WriteString("map[")
175 WriteExpr(buf, x.Key)
176 buf.WriteByte(']')
177 WriteExpr(buf, x.Value)
178
179 case *ast.ChanType:
180 var s string
181 switch x.Dir {
182 case ast.SEND:
183 s = "chan<- "
184 case ast.RECV:
185 s = "<-chan "
186 default:
187 s = "chan "
188 }
189 buf.WriteString(s)
190 WriteExpr(buf, x.Value)
191 }
192 }
193
194 func writeSigExpr(buf *bytes.Buffer, sig *ast.FuncType) {
195 buf.WriteByte('(')
196 writeFieldList(buf, sig.Params.List, ", ", false)
197 buf.WriteByte(')')
198
199 res := sig.Results
200 n := res.NumFields()
201 if n == 0 {
202
203 return
204 }
205
206 buf.WriteByte(' ')
207 if n == 1 && len(res.List[0].Names) == 0 {
208
209 WriteExpr(buf, res.List[0].Type)
210 return
211 }
212
213
214 buf.WriteByte('(')
215 writeFieldList(buf, res.List, ", ", false)
216 buf.WriteByte(')')
217 }
218
219 func writeFieldList(buf *bytes.Buffer, list []*ast.Field, sep string, iface bool) {
220 for i, f := range list {
221 if i > 0 {
222 buf.WriteString(sep)
223 }
224
225
226 writeIdentList(buf, f.Names)
227
228
229 if sig, _ := f.Type.(*ast.FuncType); sig != nil && iface {
230 writeSigExpr(buf, sig)
231 continue
232 }
233
234
235 if len(f.Names) > 0 {
236 buf.WriteByte(' ')
237 }
238
239 WriteExpr(buf, f.Type)
240
241
242 }
243 }
244
245 func writeIdentList(buf *bytes.Buffer, list []*ast.Ident) {
246 for i, x := range list {
247 if i > 0 {
248 buf.WriteString(", ")
249 }
250 buf.WriteString(x.Name)
251 }
252 }
253
254 func writeExprList(buf *bytes.Buffer, list []ast.Expr) {
255 for i, x := range list {
256 if i > 0 {
257 buf.WriteString(", ")
258 }
259 WriteExpr(buf, x)
260 }
261 }
262
View as plain text