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