PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/src/pkg/go/types/errors.go

https://bitbucket.org/nightsnaker/go
Go | 318 lines | 254 code | 49 blank | 15 comment | 40 complexity | 475f57b11c0a7dd3af969fa8972a1a43 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Copyright 2012 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. // This file implements various error reporters.
  5. package types
  6. import (
  7. "bytes"
  8. "fmt"
  9. "go/ast"
  10. "go/token"
  11. )
  12. // TODO(gri) eventually assert and unimplemented should disappear.
  13. func assert(p bool) {
  14. if !p {
  15. panic("assertion failed")
  16. }
  17. }
  18. func unreachable() {
  19. panic("unreachable")
  20. }
  21. func (check *checker) printTrace(format string, args []interface{}) {
  22. const dots = ". . . . . . . . . . . . . . . . . . . . "
  23. n := len(check.pos) - 1
  24. i := 3 * n
  25. for i > len(dots) {
  26. fmt.Print(dots)
  27. i -= len(dots)
  28. }
  29. // i <= len(dots)
  30. fmt.Printf("%s:\t", check.fset.Position(check.pos[n]))
  31. fmt.Print(dots[0:i])
  32. fmt.Println(check.formatMsg(format, args))
  33. }
  34. func (check *checker) trace(pos token.Pos, format string, args ...interface{}) {
  35. check.pos = append(check.pos, pos)
  36. check.printTrace(format, args)
  37. }
  38. func (check *checker) untrace(format string, args ...interface{}) {
  39. if len(format) > 0 {
  40. check.printTrace(format, args)
  41. }
  42. check.pos = check.pos[:len(check.pos)-1]
  43. }
  44. func (check *checker) formatMsg(format string, args []interface{}) string {
  45. for i, arg := range args {
  46. switch a := arg.(type) {
  47. case token.Pos:
  48. args[i] = check.fset.Position(a)
  49. case ast.Expr:
  50. args[i] = exprString(a)
  51. case Type:
  52. args[i] = typeString(a)
  53. case operand:
  54. panic("internal error: should always pass *operand")
  55. }
  56. }
  57. return fmt.Sprintf(format, args...)
  58. }
  59. // dump is only needed for debugging
  60. func (check *checker) dump(format string, args ...interface{}) {
  61. fmt.Println(check.formatMsg(format, args))
  62. }
  63. func (check *checker) err(err error) {
  64. if check.firsterr == nil {
  65. check.firsterr = err
  66. }
  67. f := check.ctxt.Error
  68. if f == nil {
  69. panic(bailout{}) // report only first error
  70. }
  71. f(err)
  72. }
  73. func (check *checker) errorf(pos token.Pos, format string, args ...interface{}) {
  74. check.err(fmt.Errorf("%s: %s", check.fset.Position(pos), check.formatMsg(format, args)))
  75. }
  76. func (check *checker) invalidAST(pos token.Pos, format string, args ...interface{}) {
  77. check.errorf(pos, "invalid AST: "+format, args...)
  78. }
  79. func (check *checker) invalidArg(pos token.Pos, format string, args ...interface{}) {
  80. check.errorf(pos, "invalid argument: "+format, args...)
  81. }
  82. func (check *checker) invalidOp(pos token.Pos, format string, args ...interface{}) {
  83. check.errorf(pos, "invalid operation: "+format, args...)
  84. }
  85. // exprString returns a (simplified) string representation for an expression.
  86. func exprString(expr ast.Expr) string {
  87. var buf bytes.Buffer
  88. writeExpr(&buf, expr)
  89. return buf.String()
  90. }
  91. // TODO(gri) Need to merge with typeString since some expressions are types (try: ([]int)(a))
  92. func writeExpr(buf *bytes.Buffer, expr ast.Expr) {
  93. switch x := expr.(type) {
  94. case *ast.Ident:
  95. buf.WriteString(x.Name)
  96. case *ast.BasicLit:
  97. buf.WriteString(x.Value)
  98. case *ast.FuncLit:
  99. buf.WriteString("(func literal)")
  100. case *ast.CompositeLit:
  101. buf.WriteString("(composite literal)")
  102. case *ast.ParenExpr:
  103. buf.WriteByte('(')
  104. writeExpr(buf, x.X)
  105. buf.WriteByte(')')
  106. case *ast.SelectorExpr:
  107. writeExpr(buf, x.X)
  108. buf.WriteByte('.')
  109. buf.WriteString(x.Sel.Name)
  110. case *ast.IndexExpr:
  111. writeExpr(buf, x.X)
  112. buf.WriteByte('[')
  113. writeExpr(buf, x.Index)
  114. buf.WriteByte(']')
  115. case *ast.SliceExpr:
  116. writeExpr(buf, x.X)
  117. buf.WriteByte('[')
  118. if x.Low != nil {
  119. writeExpr(buf, x.Low)
  120. }
  121. buf.WriteByte(':')
  122. if x.High != nil {
  123. writeExpr(buf, x.High)
  124. }
  125. buf.WriteByte(']')
  126. case *ast.TypeAssertExpr:
  127. writeExpr(buf, x.X)
  128. buf.WriteString(".(...)")
  129. case *ast.CallExpr:
  130. writeExpr(buf, x.Fun)
  131. buf.WriteByte('(')
  132. for i, arg := range x.Args {
  133. if i > 0 {
  134. buf.WriteString(", ")
  135. }
  136. writeExpr(buf, arg)
  137. }
  138. buf.WriteByte(')')
  139. case *ast.StarExpr:
  140. buf.WriteByte('*')
  141. writeExpr(buf, x.X)
  142. case *ast.UnaryExpr:
  143. buf.WriteString(x.Op.String())
  144. writeExpr(buf, x.X)
  145. case *ast.BinaryExpr:
  146. // The AST preserves source-level parentheses so there is
  147. // no need to introduce parentheses here for correctness.
  148. writeExpr(buf, x.X)
  149. buf.WriteByte(' ')
  150. buf.WriteString(x.Op.String())
  151. buf.WriteByte(' ')
  152. writeExpr(buf, x.Y)
  153. default:
  154. fmt.Fprintf(buf, "<expr %T>", x)
  155. }
  156. }
  157. // typeString returns a string representation for typ.
  158. func typeString(typ Type) string {
  159. var buf bytes.Buffer
  160. writeType(&buf, typ)
  161. return buf.String()
  162. }
  163. func writeParams(buf *bytes.Buffer, params []*Var, isVariadic bool) {
  164. buf.WriteByte('(')
  165. for i, par := range params {
  166. if i > 0 {
  167. buf.WriteString(", ")
  168. }
  169. if par.Name != "" {
  170. buf.WriteString(par.Name)
  171. buf.WriteByte(' ')
  172. }
  173. if isVariadic && i == len(params)-1 {
  174. buf.WriteString("...")
  175. }
  176. writeType(buf, par.Type)
  177. }
  178. buf.WriteByte(')')
  179. }
  180. func writeSignature(buf *bytes.Buffer, sig *Signature) {
  181. writeParams(buf, sig.Params, sig.IsVariadic)
  182. if len(sig.Results) == 0 {
  183. // no result
  184. return
  185. }
  186. buf.WriteByte(' ')
  187. if len(sig.Results) == 1 && sig.Results[0].Name == "" {
  188. // single unnamed result
  189. writeType(buf, sig.Results[0].Type.(Type))
  190. return
  191. }
  192. // multiple or named result(s)
  193. writeParams(buf, sig.Results, false)
  194. }
  195. func writeType(buf *bytes.Buffer, typ Type) {
  196. switch t := typ.(type) {
  197. case nil:
  198. buf.WriteString("<nil>")
  199. case *Basic:
  200. buf.WriteString(t.Name)
  201. case *Array:
  202. fmt.Fprintf(buf, "[%d]", t.Len)
  203. writeType(buf, t.Elt)
  204. case *Slice:
  205. buf.WriteString("[]")
  206. writeType(buf, t.Elt)
  207. case *Struct:
  208. buf.WriteString("struct{")
  209. for i, f := range t.Fields {
  210. if i > 0 {
  211. buf.WriteString("; ")
  212. }
  213. if !f.IsAnonymous {
  214. buf.WriteString(f.Name)
  215. buf.WriteByte(' ')
  216. }
  217. writeType(buf, f.Type)
  218. if f.Tag != "" {
  219. fmt.Fprintf(buf, " %q", f.Tag)
  220. }
  221. }
  222. buf.WriteByte('}')
  223. case *Pointer:
  224. buf.WriteByte('*')
  225. writeType(buf, t.Base)
  226. case *Result:
  227. writeParams(buf, t.Values, false)
  228. case *Signature:
  229. buf.WriteString("func")
  230. writeSignature(buf, t)
  231. case *builtin:
  232. fmt.Fprintf(buf, "<type of %s>", t.name)
  233. case *Interface:
  234. buf.WriteString("interface{")
  235. for i, m := range t.Methods {
  236. if i > 0 {
  237. buf.WriteString("; ")
  238. }
  239. buf.WriteString(m.Name)
  240. writeSignature(buf, m.Type)
  241. }
  242. buf.WriteByte('}')
  243. case *Map:
  244. buf.WriteString("map[")
  245. writeType(buf, t.Key)
  246. buf.WriteByte(']')
  247. writeType(buf, t.Elt)
  248. case *Chan:
  249. var s string
  250. switch t.Dir {
  251. case ast.SEND:
  252. s = "chan<- "
  253. case ast.RECV:
  254. s = "<-chan "
  255. default:
  256. s = "chan "
  257. }
  258. buf.WriteString(s)
  259. writeType(buf, t.Elt)
  260. case *NamedType:
  261. s := "<NamedType w/o object>"
  262. if t.Obj != nil {
  263. s = t.Obj.GetName()
  264. }
  265. buf.WriteString(s)
  266. default:
  267. fmt.Fprintf(buf, "<type %T>", t)
  268. }
  269. }