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