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