github.com/aloncn/graphics-go@v0.0.1/src/go/types/exprstring.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file implements printing of expressions. 6 7 package types 8 9 import ( 10 "bytes" 11 "go/ast" 12 ) 13 14 // ExprString returns the (possibly simplified) string representation for x. 15 func ExprString(x ast.Expr) string { 16 var buf bytes.Buffer 17 WriteExpr(&buf, x) 18 return buf.String() 19 } 20 21 // WriteExpr writes the (possibly simplified) string representation for x to buf. 22 func WriteExpr(buf *bytes.Buffer, x ast.Expr) { 23 // The AST preserves source-level parentheses so there is 24 // no need to introduce them here to correct for different 25 // operator precedences. (This assumes that the AST was 26 // generated by a Go parser.) 27 28 switch x := x.(type) { 29 default: 30 buf.WriteString("(bad expr)") // nil, ast.BadExpr, ast.KeyValueExpr 31 32 case *ast.Ident: 33 buf.WriteString(x.Name) 34 35 case *ast.Ellipsis: 36 buf.WriteString("...") 37 if x.Elt != nil { 38 WriteExpr(buf, x.Elt) 39 } 40 41 case *ast.BasicLit: 42 buf.WriteString(x.Value) 43 44 case *ast.FuncLit: 45 buf.WriteByte('(') 46 WriteExpr(buf, x.Type) 47 buf.WriteString(" literal)") // simplified 48 49 case *ast.CompositeLit: 50 buf.WriteByte('(') 51 WriteExpr(buf, x.Type) 52 buf.WriteString(" literal)") // simplified 53 54 case *ast.ParenExpr: 55 buf.WriteByte('(') 56 WriteExpr(buf, x.X) 57 buf.WriteByte(')') 58 59 case *ast.SelectorExpr: 60 WriteExpr(buf, x.X) 61 buf.WriteByte('.') 62 buf.WriteString(x.Sel.Name) 63 64 case *ast.IndexExpr: 65 WriteExpr(buf, x.X) 66 buf.WriteByte('[') 67 WriteExpr(buf, x.Index) 68 buf.WriteByte(']') 69 70 case *ast.SliceExpr: 71 WriteExpr(buf, x.X) 72 buf.WriteByte('[') 73 if x.Low != nil { 74 WriteExpr(buf, x.Low) 75 } 76 buf.WriteByte(':') 77 if x.High != nil { 78 WriteExpr(buf, x.High) 79 } 80 if x.Slice3 { 81 buf.WriteByte(':') 82 if x.Max != nil { 83 WriteExpr(buf, x.Max) 84 } 85 } 86 buf.WriteByte(']') 87 88 case *ast.TypeAssertExpr: 89 WriteExpr(buf, x.X) 90 buf.WriteString(".(") 91 WriteExpr(buf, x.Type) 92 buf.WriteByte(')') 93 94 case *ast.CallExpr: 95 WriteExpr(buf, x.Fun) 96 buf.WriteByte('(') 97 for i, arg := range x.Args { 98 if i > 0 { 99 buf.WriteString(", ") 100 } 101 WriteExpr(buf, arg) 102 } 103 if x.Ellipsis.IsValid() { 104 buf.WriteString("...") 105 } 106 buf.WriteByte(')') 107 108 case *ast.StarExpr: 109 buf.WriteByte('*') 110 WriteExpr(buf, x.X) 111 112 case *ast.UnaryExpr: 113 buf.WriteString(x.Op.String()) 114 WriteExpr(buf, x.X) 115 116 case *ast.BinaryExpr: 117 WriteExpr(buf, x.X) 118 buf.WriteByte(' ') 119 buf.WriteString(x.Op.String()) 120 buf.WriteByte(' ') 121 WriteExpr(buf, x.Y) 122 123 case *ast.ArrayType: 124 buf.WriteByte('[') 125 if x.Len != nil { 126 WriteExpr(buf, x.Len) 127 } 128 buf.WriteByte(']') 129 WriteExpr(buf, x.Elt) 130 131 case *ast.StructType: 132 buf.WriteString("struct{") 133 writeFieldList(buf, x.Fields, "; ", false) 134 buf.WriteByte('}') 135 136 case *ast.FuncType: 137 buf.WriteString("func") 138 writeSigExpr(buf, x) 139 140 case *ast.InterfaceType: 141 buf.WriteString("interface{") 142 writeFieldList(buf, x.Methods, "; ", true) 143 buf.WriteByte('}') 144 145 case *ast.MapType: 146 buf.WriteString("map[") 147 WriteExpr(buf, x.Key) 148 buf.WriteByte(']') 149 WriteExpr(buf, x.Value) 150 151 case *ast.ChanType: 152 var s string 153 switch x.Dir { 154 case ast.SEND: 155 s = "chan<- " 156 case ast.RECV: 157 s = "<-chan " 158 default: 159 s = "chan " 160 } 161 buf.WriteString(s) 162 WriteExpr(buf, x.Value) 163 } 164 } 165 166 func writeSigExpr(buf *bytes.Buffer, sig *ast.FuncType) { 167 buf.WriteByte('(') 168 writeFieldList(buf, sig.Params, ", ", false) 169 buf.WriteByte(')') 170 171 res := sig.Results 172 n := res.NumFields() 173 if n == 0 { 174 // no result 175 return 176 } 177 178 buf.WriteByte(' ') 179 if n == 1 && len(res.List[0].Names) == 0 { 180 // single unnamed result 181 WriteExpr(buf, res.List[0].Type) 182 return 183 } 184 185 // multiple or named result(s) 186 buf.WriteByte('(') 187 writeFieldList(buf, res, ", ", false) 188 buf.WriteByte(')') 189 } 190 191 func writeFieldList(buf *bytes.Buffer, fields *ast.FieldList, sep string, iface bool) { 192 for i, f := range fields.List { 193 if i > 0 { 194 buf.WriteString(sep) 195 } 196 197 // field list names 198 for i, name := range f.Names { 199 if i > 0 { 200 buf.WriteString(", ") 201 } 202 buf.WriteString(name.Name) 203 } 204 205 // types of interface methods consist of signatures only 206 if sig, _ := f.Type.(*ast.FuncType); sig != nil && iface { 207 writeSigExpr(buf, sig) 208 continue 209 } 210 211 // named fields are separated with a blank from the field type 212 if len(f.Names) > 0 { 213 buf.WriteByte(' ') 214 } 215 216 WriteExpr(buf, f.Type) 217 218 // ignore tag 219 } 220 }