PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/third_party/gofrontend/libgo/go/go/types/api_test.go

http://github.com/axw/llgo
Go | 1044 lines | 879 code | 94 blank | 71 comment | 131 complexity | 4dce6cb1f7fa549f5718ed4dfbf2b70e MD5 | raw file
Possible License(s): BSD-3-Clause, MIT
  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. package types_test
  5. import (
  6. "bytes"
  7. "fmt"
  8. "go/ast"
  9. "go/importer"
  10. "go/parser"
  11. "go/token"
  12. "internal/testenv"
  13. "reflect"
  14. "regexp"
  15. "strings"
  16. "testing"
  17. . "go/types"
  18. )
  19. func pkgFor(path, source string, info *Info) (*Package, error) {
  20. fset := token.NewFileSet()
  21. f, err := parser.ParseFile(fset, path, source, 0)
  22. if err != nil {
  23. return nil, err
  24. }
  25. conf := Config{Importer: importer.Default()}
  26. return conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
  27. }
  28. func mustTypecheck(t *testing.T, path, source string, info *Info) string {
  29. pkg, err := pkgFor(path, source, info)
  30. if err != nil {
  31. name := path
  32. if pkg != nil {
  33. name = "package " + pkg.Name()
  34. }
  35. t.Fatalf("%s: didn't type-check (%s)", name, err)
  36. }
  37. return pkg.Name()
  38. }
  39. func TestValuesInfo(t *testing.T) {
  40. var tests = []struct {
  41. src string
  42. expr string // constant expression
  43. typ string // constant type
  44. val string // constant value
  45. }{
  46. {`package a0; const _ = false`, `false`, `untyped bool`, `false`},
  47. {`package a1; const _ = 0`, `0`, `untyped int`, `0`},
  48. {`package a2; const _ = 'A'`, `'A'`, `untyped rune`, `65`},
  49. {`package a3; const _ = 0.`, `0.`, `untyped float`, `0`},
  50. {`package a4; const _ = 0i`, `0i`, `untyped complex`, `0`},
  51. {`package a5; const _ = "foo"`, `"foo"`, `untyped string`, `"foo"`},
  52. {`package b0; var _ = false`, `false`, `bool`, `false`},
  53. {`package b1; var _ = 0`, `0`, `int`, `0`},
  54. {`package b2; var _ = 'A'`, `'A'`, `rune`, `65`},
  55. {`package b3; var _ = 0.`, `0.`, `float64`, `0`},
  56. {`package b4; var _ = 0i`, `0i`, `complex128`, `0`},
  57. {`package b5; var _ = "foo"`, `"foo"`, `string`, `"foo"`},
  58. {`package c0a; var _ = bool(false)`, `false`, `bool`, `false`},
  59. {`package c0b; var _ = bool(false)`, `bool(false)`, `bool`, `false`},
  60. {`package c0c; type T bool; var _ = T(false)`, `T(false)`, `c0c.T`, `false`},
  61. {`package c1a; var _ = int(0)`, `0`, `int`, `0`},
  62. {`package c1b; var _ = int(0)`, `int(0)`, `int`, `0`},
  63. {`package c1c; type T int; var _ = T(0)`, `T(0)`, `c1c.T`, `0`},
  64. {`package c2a; var _ = rune('A')`, `'A'`, `rune`, `65`},
  65. {`package c2b; var _ = rune('A')`, `rune('A')`, `rune`, `65`},
  66. {`package c2c; type T rune; var _ = T('A')`, `T('A')`, `c2c.T`, `65`},
  67. {`package c3a; var _ = float32(0.)`, `0.`, `float32`, `0`},
  68. {`package c3b; var _ = float32(0.)`, `float32(0.)`, `float32`, `0`},
  69. {`package c3c; type T float32; var _ = T(0.)`, `T(0.)`, `c3c.T`, `0`},
  70. {`package c4a; var _ = complex64(0i)`, `0i`, `complex64`, `0`},
  71. {`package c4b; var _ = complex64(0i)`, `complex64(0i)`, `complex64`, `0`},
  72. {`package c4c; type T complex64; var _ = T(0i)`, `T(0i)`, `c4c.T`, `0`},
  73. {`package c5a; var _ = string("foo")`, `"foo"`, `string`, `"foo"`},
  74. {`package c5b; var _ = string("foo")`, `string("foo")`, `string`, `"foo"`},
  75. {`package c5c; type T string; var _ = T("foo")`, `T("foo")`, `c5c.T`, `"foo"`},
  76. {`package d0; var _ = []byte("foo")`, `"foo"`, `string`, `"foo"`},
  77. {`package d1; var _ = []byte(string("foo"))`, `"foo"`, `string`, `"foo"`},
  78. {`package d2; var _ = []byte(string("foo"))`, `string("foo")`, `string`, `"foo"`},
  79. {`package d3; type T []byte; var _ = T("foo")`, `"foo"`, `string`, `"foo"`},
  80. {`package e0; const _ = float32( 1e-200)`, `float32(1e-200)`, `float32`, `0`},
  81. {`package e1; const _ = float32(-1e-200)`, `float32(-1e-200)`, `float32`, `0`},
  82. {`package e2; const _ = float64( 1e-2000)`, `float64(1e-2000)`, `float64`, `0`},
  83. {`package e3; const _ = float64(-1e-2000)`, `float64(-1e-2000)`, `float64`, `0`},
  84. {`package e4; const _ = complex64( 1e-200)`, `complex64(1e-200)`, `complex64`, `0`},
  85. {`package e5; const _ = complex64(-1e-200)`, `complex64(-1e-200)`, `complex64`, `0`},
  86. {`package e6; const _ = complex128( 1e-2000)`, `complex128(1e-2000)`, `complex128`, `0`},
  87. {`package e7; const _ = complex128(-1e-2000)`, `complex128(-1e-2000)`, `complex128`, `0`},
  88. {`package f0 ; var _ float32 = 1e-200`, `1e-200`, `float32`, `0`},
  89. {`package f1 ; var _ float32 = -1e-200`, `-1e-200`, `float32`, `0`},
  90. {`package f2a; var _ float64 = 1e-2000`, `1e-2000`, `float64`, `0`},
  91. {`package f3a; var _ float64 = -1e-2000`, `-1e-2000`, `float64`, `0`},
  92. {`package f2b; var _ = 1e-2000`, `1e-2000`, `float64`, `0`},
  93. {`package f3b; var _ = -1e-2000`, `-1e-2000`, `float64`, `0`},
  94. {`package f4 ; var _ complex64 = 1e-200 `, `1e-200`, `complex64`, `0`},
  95. {`package f5 ; var _ complex64 = -1e-200 `, `-1e-200`, `complex64`, `0`},
  96. {`package f6a; var _ complex128 = 1e-2000i`, `1e-2000i`, `complex128`, `0`},
  97. {`package f7a; var _ complex128 = -1e-2000i`, `-1e-2000i`, `complex128`, `0`},
  98. {`package f6b; var _ = 1e-2000i`, `1e-2000i`, `complex128`, `0`},
  99. {`package f7b; var _ = -1e-2000i`, `-1e-2000i`, `complex128`, `0`},
  100. }
  101. for _, test := range tests {
  102. info := Info{
  103. Types: make(map[ast.Expr]TypeAndValue),
  104. }
  105. name := mustTypecheck(t, "ValuesInfo", test.src, &info)
  106. // look for constant expression
  107. var expr ast.Expr
  108. for e := range info.Types {
  109. if ExprString(e) == test.expr {
  110. expr = e
  111. break
  112. }
  113. }
  114. if expr == nil {
  115. t.Errorf("package %s: no expression found for %s", name, test.expr)
  116. continue
  117. }
  118. tv := info.Types[expr]
  119. // check that type is correct
  120. if got := tv.Type.String(); got != test.typ {
  121. t.Errorf("package %s: got type %s; want %s", name, got, test.typ)
  122. continue
  123. }
  124. // check that value is correct
  125. if got := tv.Value.String(); got != test.val {
  126. t.Errorf("package %s: got value %s; want %s", name, got, test.val)
  127. }
  128. }
  129. }
  130. func TestTypesInfo(t *testing.T) {
  131. var tests = []struct {
  132. src string
  133. expr string // expression
  134. typ string // value type
  135. }{
  136. // single-valued expressions of untyped constants
  137. {`package b0; var x interface{} = false`, `false`, `bool`},
  138. {`package b1; var x interface{} = 0`, `0`, `int`},
  139. {`package b2; var x interface{} = 0.`, `0.`, `float64`},
  140. {`package b3; var x interface{} = 0i`, `0i`, `complex128`},
  141. {`package b4; var x interface{} = "foo"`, `"foo"`, `string`},
  142. // comma-ok expressions
  143. {`package p0; var x interface{}; var _, _ = x.(int)`,
  144. `x.(int)`,
  145. `(int, bool)`,
  146. },
  147. {`package p1; var x interface{}; func _() { _, _ = x.(int) }`,
  148. `x.(int)`,
  149. `(int, bool)`,
  150. },
  151. // TODO(gri): uncomment if we accept issue 8189.
  152. // {`package p2; type mybool bool; var m map[string]complex128; var b mybool; func _() { _, b = m["foo"] }`,
  153. // `m["foo"]`,
  154. // `(complex128, p2.mybool)`,
  155. // },
  156. // TODO(gri): remove if we accept issue 8189.
  157. {`package p2; var m map[string]complex128; var b bool; func _() { _, b = m["foo"] }`,
  158. `m["foo"]`,
  159. `(complex128, bool)`,
  160. },
  161. {`package p3; var c chan string; var _, _ = <-c`,
  162. `<-c`,
  163. `(string, bool)`,
  164. },
  165. // issue 6796
  166. {`package issue6796_a; var x interface{}; var _, _ = (x.(int))`,
  167. `x.(int)`,
  168. `(int, bool)`,
  169. },
  170. {`package issue6796_b; var c chan string; var _, _ = (<-c)`,
  171. `(<-c)`,
  172. `(string, bool)`,
  173. },
  174. {`package issue6796_c; var c chan string; var _, _ = (<-c)`,
  175. `<-c`,
  176. `(string, bool)`,
  177. },
  178. {`package issue6796_d; var c chan string; var _, _ = ((<-c))`,
  179. `(<-c)`,
  180. `(string, bool)`,
  181. },
  182. {`package issue6796_e; func f(c chan string) { _, _ = ((<-c)) }`,
  183. `(<-c)`,
  184. `(string, bool)`,
  185. },
  186. // issue 7060
  187. {`package issue7060_a; var ( m map[int]string; x, ok = m[0] )`,
  188. `m[0]`,
  189. `(string, bool)`,
  190. },
  191. {`package issue7060_b; var ( m map[int]string; x, ok interface{} = m[0] )`,
  192. `m[0]`,
  193. `(string, bool)`,
  194. },
  195. {`package issue7060_c; func f(x interface{}, ok bool, m map[int]string) { x, ok = m[0] }`,
  196. `m[0]`,
  197. `(string, bool)`,
  198. },
  199. {`package issue7060_d; var ( ch chan string; x, ok = <-ch )`,
  200. `<-ch`,
  201. `(string, bool)`,
  202. },
  203. {`package issue7060_e; var ( ch chan string; x, ok interface{} = <-ch )`,
  204. `<-ch`,
  205. `(string, bool)`,
  206. },
  207. {`package issue7060_f; func f(x interface{}, ok bool, ch chan string) { x, ok = <-ch }`,
  208. `<-ch`,
  209. `(string, bool)`,
  210. },
  211. }
  212. for _, test := range tests {
  213. info := Info{Types: make(map[ast.Expr]TypeAndValue)}
  214. name := mustTypecheck(t, "TypesInfo", test.src, &info)
  215. // look for expression type
  216. var typ Type
  217. for e, tv := range info.Types {
  218. if ExprString(e) == test.expr {
  219. typ = tv.Type
  220. break
  221. }
  222. }
  223. if typ == nil {
  224. t.Errorf("package %s: no type found for %s", name, test.expr)
  225. continue
  226. }
  227. // check that type is correct
  228. if got := typ.String(); got != test.typ {
  229. t.Errorf("package %s: got %s; want %s", name, got, test.typ)
  230. }
  231. }
  232. }
  233. func predString(tv TypeAndValue) string {
  234. var buf bytes.Buffer
  235. pred := func(b bool, s string) {
  236. if b {
  237. if buf.Len() > 0 {
  238. buf.WriteString(", ")
  239. }
  240. buf.WriteString(s)
  241. }
  242. }
  243. pred(tv.IsVoid(), "void")
  244. pred(tv.IsType(), "type")
  245. pred(tv.IsBuiltin(), "builtin")
  246. pred(tv.IsValue() && tv.Value != nil, "const")
  247. pred(tv.IsValue() && tv.Value == nil, "value")
  248. pred(tv.IsNil(), "nil")
  249. pred(tv.Addressable(), "addressable")
  250. pred(tv.Assignable(), "assignable")
  251. pred(tv.HasOk(), "hasOk")
  252. if buf.Len() == 0 {
  253. return "invalid"
  254. }
  255. return buf.String()
  256. }
  257. func TestPredicatesInfo(t *testing.T) {
  258. testenv.MustHaveGoBuild(t)
  259. var tests = []struct {
  260. src string
  261. expr string
  262. pred string
  263. }{
  264. // void
  265. {`package n0; func f() { f() }`, `f()`, `void`},
  266. // types
  267. {`package t0; type _ int`, `int`, `type`},
  268. {`package t1; type _ []int`, `[]int`, `type`},
  269. {`package t2; type _ func()`, `func()`, `type`},
  270. // built-ins
  271. {`package b0; var _ = len("")`, `len`, `builtin`},
  272. {`package b1; var _ = (len)("")`, `(len)`, `builtin`},
  273. // constants
  274. {`package c0; var _ = 42`, `42`, `const`},
  275. {`package c1; var _ = "foo" + "bar"`, `"foo" + "bar"`, `const`},
  276. {`package c2; const (i = 1i; _ = i)`, `i`, `const`},
  277. // values
  278. {`package v0; var (a, b int; _ = a + b)`, `a + b`, `value`},
  279. {`package v1; var _ = &[]int{1}`, `([]int literal)`, `value`},
  280. {`package v2; var _ = func(){}`, `(func() literal)`, `value`},
  281. {`package v4; func f() { _ = f }`, `f`, `value`},
  282. {`package v3; var _ *int = nil`, `nil`, `value, nil`},
  283. {`package v3; var _ *int = (nil)`, `(nil)`, `value, nil`},
  284. // addressable (and thus assignable) operands
  285. {`package a0; var (x int; _ = x)`, `x`, `value, addressable, assignable`},
  286. {`package a1; var (p *int; _ = *p)`, `*p`, `value, addressable, assignable`},
  287. {`package a2; var (s []int; _ = s[0])`, `s[0]`, `value, addressable, assignable`},
  288. {`package a3; var (s struct{f int}; _ = s.f)`, `s.f`, `value, addressable, assignable`},
  289. {`package a4; var (a [10]int; _ = a[0])`, `a[0]`, `value, addressable, assignable`},
  290. {`package a5; func _(x int) { _ = x }`, `x`, `value, addressable, assignable`},
  291. {`package a6; func _()(x int) { _ = x; return }`, `x`, `value, addressable, assignable`},
  292. {`package a7; type T int; func (x T) _() { _ = x }`, `x`, `value, addressable, assignable`},
  293. // composite literals are not addressable
  294. // assignable but not addressable values
  295. {`package s0; var (m map[int]int; _ = m[0])`, `m[0]`, `value, assignable, hasOk`},
  296. {`package s1; var (m map[int]int; _, _ = m[0])`, `m[0]`, `value, assignable, hasOk`},
  297. // hasOk expressions
  298. {`package k0; var (ch chan int; _ = <-ch)`, `<-ch`, `value, hasOk`},
  299. {`package k1; var (ch chan int; _, _ = <-ch)`, `<-ch`, `value, hasOk`},
  300. // missing entries
  301. // - package names are collected in the Uses map
  302. // - identifiers being declared are collected in the Defs map
  303. {`package m0; import "os"; func _() { _ = os.Stdout }`, `os`, `<missing>`},
  304. {`package m1; import p "os"; func _() { _ = p.Stdout }`, `p`, `<missing>`},
  305. {`package m2; const c = 0`, `c`, `<missing>`},
  306. {`package m3; type T int`, `T`, `<missing>`},
  307. {`package m4; var v int`, `v`, `<missing>`},
  308. {`package m5; func f() {}`, `f`, `<missing>`},
  309. {`package m6; func _(x int) {}`, `x`, `<missing>`},
  310. {`package m6; func _()(x int) { return }`, `x`, `<missing>`},
  311. {`package m6; type T int; func (x T) _() {}`, `x`, `<missing>`},
  312. }
  313. for _, test := range tests {
  314. info := Info{Types: make(map[ast.Expr]TypeAndValue)}
  315. name := mustTypecheck(t, "PredicatesInfo", test.src, &info)
  316. // look for expression predicates
  317. got := "<missing>"
  318. for e, tv := range info.Types {
  319. //println(name, ExprString(e))
  320. if ExprString(e) == test.expr {
  321. got = predString(tv)
  322. break
  323. }
  324. }
  325. if got != test.pred {
  326. t.Errorf("package %s: got %s; want %s", name, got, test.pred)
  327. }
  328. }
  329. }
  330. func TestScopesInfo(t *testing.T) {
  331. testenv.MustHaveGoBuild(t)
  332. var tests = []struct {
  333. src string
  334. scopes []string // list of scope descriptors of the form kind:varlist
  335. }{
  336. {`package p0`, []string{
  337. "file:",
  338. }},
  339. {`package p1; import ( "fmt"; m "math"; _ "os" ); var ( _ = fmt.Println; _ = m.Pi )`, []string{
  340. "file:fmt m",
  341. }},
  342. {`package p2; func _() {}`, []string{
  343. "file:", "func:",
  344. }},
  345. {`package p3; func _(x, y int) {}`, []string{
  346. "file:", "func:x y",
  347. }},
  348. {`package p4; func _(x, y int) { x, z := 1, 2; _ = z }`, []string{
  349. "file:", "func:x y z", // redeclaration of x
  350. }},
  351. {`package p5; func _(x, y int) (u, _ int) { return }`, []string{
  352. "file:", "func:u x y",
  353. }},
  354. {`package p6; func _() { { var x int; _ = x } }`, []string{
  355. "file:", "func:", "block:x",
  356. }},
  357. {`package p7; func _() { if true {} }`, []string{
  358. "file:", "func:", "if:", "block:",
  359. }},
  360. {`package p8; func _() { if x := 0; x < 0 { y := x; _ = y } }`, []string{
  361. "file:", "func:", "if:x", "block:y",
  362. }},
  363. {`package p9; func _() { switch x := 0; x {} }`, []string{
  364. "file:", "func:", "switch:x",
  365. }},
  366. {`package p10; func _() { switch x := 0; x { case 1: y := x; _ = y; default: }}`, []string{
  367. "file:", "func:", "switch:x", "case:y", "case:",
  368. }},
  369. {`package p11; func _(t interface{}) { switch t.(type) {} }`, []string{
  370. "file:", "func:t", "type switch:",
  371. }},
  372. {`package p12; func _(t interface{}) { switch t := t; t.(type) {} }`, []string{
  373. "file:", "func:t", "type switch:t",
  374. }},
  375. {`package p13; func _(t interface{}) { switch x := t.(type) { case int: _ = x } }`, []string{
  376. "file:", "func:t", "type switch:", "case:x", // x implicitly declared
  377. }},
  378. {`package p14; func _() { select{} }`, []string{
  379. "file:", "func:",
  380. }},
  381. {`package p15; func _(c chan int) { select{ case <-c: } }`, []string{
  382. "file:", "func:c", "comm:",
  383. }},
  384. {`package p16; func _(c chan int) { select{ case i := <-c: x := i; _ = x} }`, []string{
  385. "file:", "func:c", "comm:i x",
  386. }},
  387. {`package p17; func _() { for{} }`, []string{
  388. "file:", "func:", "for:", "block:",
  389. }},
  390. {`package p18; func _(n int) { for i := 0; i < n; i++ { _ = i } }`, []string{
  391. "file:", "func:n", "for:i", "block:",
  392. }},
  393. {`package p19; func _(a []int) { for i := range a { _ = i} }`, []string{
  394. "file:", "func:a", "range:i", "block:",
  395. }},
  396. {`package p20; var s int; func _(a []int) { for i, x := range a { s += x; _ = i } }`, []string{
  397. "file:", "func:a", "range:i x", "block:",
  398. }},
  399. }
  400. for _, test := range tests {
  401. info := Info{Scopes: make(map[ast.Node]*Scope)}
  402. name := mustTypecheck(t, "ScopesInfo", test.src, &info)
  403. // number of scopes must match
  404. if len(info.Scopes) != len(test.scopes) {
  405. t.Errorf("package %s: got %d scopes; want %d", name, len(info.Scopes), len(test.scopes))
  406. }
  407. // scope descriptions must match
  408. for node, scope := range info.Scopes {
  409. kind := "<unknown node kind>"
  410. switch node.(type) {
  411. case *ast.File:
  412. kind = "file"
  413. case *ast.FuncType:
  414. kind = "func"
  415. case *ast.BlockStmt:
  416. kind = "block"
  417. case *ast.IfStmt:
  418. kind = "if"
  419. case *ast.SwitchStmt:
  420. kind = "switch"
  421. case *ast.TypeSwitchStmt:
  422. kind = "type switch"
  423. case *ast.CaseClause:
  424. kind = "case"
  425. case *ast.CommClause:
  426. kind = "comm"
  427. case *ast.ForStmt:
  428. kind = "for"
  429. case *ast.RangeStmt:
  430. kind = "range"
  431. }
  432. // look for matching scope description
  433. desc := kind + ":" + strings.Join(scope.Names(), " ")
  434. found := false
  435. for _, d := range test.scopes {
  436. if desc == d {
  437. found = true
  438. break
  439. }
  440. }
  441. if !found {
  442. t.Errorf("package %s: no matching scope found for %s", name, desc)
  443. }
  444. }
  445. }
  446. }
  447. func TestInitOrderInfo(t *testing.T) {
  448. var tests = []struct {
  449. src string
  450. inits []string
  451. }{
  452. {`package p0; var (x = 1; y = x)`, []string{
  453. "x = 1", "y = x",
  454. }},
  455. {`package p1; var (a = 1; b = 2; c = 3)`, []string{
  456. "a = 1", "b = 2", "c = 3",
  457. }},
  458. {`package p2; var (a, b, c = 1, 2, 3)`, []string{
  459. "a = 1", "b = 2", "c = 3",
  460. }},
  461. {`package p3; var _ = f(); func f() int { return 1 }`, []string{
  462. "_ = f()", // blank var
  463. }},
  464. {`package p4; var (a = 0; x = y; y = z; z = 0)`, []string{
  465. "a = 0", "z = 0", "y = z", "x = y",
  466. }},
  467. {`package p5; var (a, _ = m[0]; m map[int]string)`, []string{
  468. "a, _ = m[0]", // blank var
  469. }},
  470. {`package p6; var a, b = f(); func f() (_, _ int) { return z, z }; var z = 0`, []string{
  471. "z = 0", "a, b = f()",
  472. }},
  473. {`package p7; var (a = func() int { return b }(); b = 1)`, []string{
  474. "b = 1", "a = (func() int literal)()",
  475. }},
  476. {`package p8; var (a, b = func() (_, _ int) { return c, c }(); c = 1)`, []string{
  477. "c = 1", "a, b = (func() (_, _ int) literal)()",
  478. }},
  479. {`package p9; type T struct{}; func (T) m() int { _ = y; return 0 }; var x, y = T.m, 1`, []string{
  480. "y = 1", "x = T.m",
  481. }},
  482. {`package p10; var (d = c + b; a = 0; b = 0; c = 0)`, []string{
  483. "a = 0", "b = 0", "c = 0", "d = c + b",
  484. }},
  485. {`package p11; var (a = e + c; b = d + c; c = 0; d = 0; e = 0)`, []string{
  486. "c = 0", "d = 0", "b = d + c", "e = 0", "a = e + c",
  487. }},
  488. // emit an initializer for n:1 initializations only once (not for each node
  489. // on the lhs which may appear in different order in the dependency graph)
  490. {`package p12; var (a = x; b = 0; x, y = m[0]; m map[int]int)`, []string{
  491. "b = 0", "x, y = m[0]", "a = x",
  492. }},
  493. // test case from spec section on package initialization
  494. {`package p12
  495. var (
  496. a = c + b
  497. b = f()
  498. c = f()
  499. d = 3
  500. )
  501. func f() int {
  502. d++
  503. return d
  504. }`, []string{
  505. "d = 3", "b = f()", "c = f()", "a = c + b",
  506. }},
  507. // test case for issue 7131
  508. {`package main
  509. var counter int
  510. func next() int { counter++; return counter }
  511. var _ = makeOrder()
  512. func makeOrder() []int { return []int{f, b, d, e, c, a} }
  513. var a = next()
  514. var b, c = next(), next()
  515. var d, e, f = next(), next(), next()
  516. `, []string{
  517. "a = next()", "b = next()", "c = next()", "d = next()", "e = next()", "f = next()", "_ = makeOrder()",
  518. }},
  519. }
  520. for _, test := range tests {
  521. info := Info{}
  522. name := mustTypecheck(t, "InitOrderInfo", test.src, &info)
  523. // number of initializers must match
  524. if len(info.InitOrder) != len(test.inits) {
  525. t.Errorf("package %s: got %d initializers; want %d", name, len(info.InitOrder), len(test.inits))
  526. continue
  527. }
  528. // initializers must match
  529. for i, want := range test.inits {
  530. got := info.InitOrder[i].String()
  531. if got != want {
  532. t.Errorf("package %s, init %d: got %s; want %s", name, i, got, want)
  533. continue
  534. }
  535. }
  536. }
  537. }
  538. func TestMultiFileInitOrder(t *testing.T) {
  539. fset := token.NewFileSet()
  540. mustParse := func(src string) *ast.File {
  541. f, err := parser.ParseFile(fset, "main", src, 0)
  542. if err != nil {
  543. t.Fatal(err)
  544. }
  545. return f
  546. }
  547. fileA := mustParse(`package main; var a = 1`)
  548. fileB := mustParse(`package main; var b = 2`)
  549. // The initialization order must not depend on the parse
  550. // order of the files, only on the presentation order to
  551. // the type-checker.
  552. for _, test := range []struct {
  553. files []*ast.File
  554. want string
  555. }{
  556. {[]*ast.File{fileA, fileB}, "[a = 1 b = 2]"},
  557. {[]*ast.File{fileB, fileA}, "[b = 2 a = 1]"},
  558. } {
  559. var info Info
  560. if _, err := new(Config).Check("main", fset, test.files, &info); err != nil {
  561. t.Fatal(err)
  562. }
  563. if got := fmt.Sprint(info.InitOrder); got != test.want {
  564. t.Fatalf("got %s; want %s", got, test.want)
  565. }
  566. }
  567. }
  568. func TestFiles(t *testing.T) {
  569. var sources = []string{
  570. "package p; type T struct{}; func (T) m1() {}",
  571. "package p; func (T) m2() {}; var x interface{ m1(); m2() } = T{}",
  572. "package p; func (T) m3() {}; var y interface{ m1(); m2(); m3() } = T{}",
  573. "package p",
  574. }
  575. var conf Config
  576. fset := token.NewFileSet()
  577. pkg := NewPackage("p", "p")
  578. var info Info
  579. check := NewChecker(&conf, fset, pkg, &info)
  580. for i, src := range sources {
  581. filename := fmt.Sprintf("sources%d", i)
  582. f, err := parser.ParseFile(fset, filename, src, 0)
  583. if err != nil {
  584. t.Fatal(err)
  585. }
  586. if err := check.Files([]*ast.File{f}); err != nil {
  587. t.Error(err)
  588. }
  589. }
  590. // check InitOrder is [x y]
  591. var vars []string
  592. for _, init := range info.InitOrder {
  593. for _, v := range init.Lhs {
  594. vars = append(vars, v.Name())
  595. }
  596. }
  597. if got, want := fmt.Sprint(vars), "[x y]"; got != want {
  598. t.Errorf("InitOrder == %s, want %s", got, want)
  599. }
  600. }
  601. type testImporter map[string]*Package
  602. func (m testImporter) Import(path string) (*Package, error) {
  603. if pkg := m[path]; pkg != nil {
  604. return pkg, nil
  605. }
  606. return nil, fmt.Errorf("package %q not found", path)
  607. }
  608. func TestSelection(t *testing.T) {
  609. selections := make(map[*ast.SelectorExpr]*Selection)
  610. fset := token.NewFileSet()
  611. imports := make(testImporter)
  612. conf := Config{Importer: imports}
  613. makePkg := func(path, src string) {
  614. f, err := parser.ParseFile(fset, path+".go", src, 0)
  615. if err != nil {
  616. t.Fatal(err)
  617. }
  618. pkg, err := conf.Check(path, fset, []*ast.File{f}, &Info{Selections: selections})
  619. if err != nil {
  620. t.Fatal(err)
  621. }
  622. imports[path] = pkg
  623. }
  624. const libSrc = `
  625. package lib
  626. type T float64
  627. const C T = 3
  628. var V T
  629. func F() {}
  630. func (T) M() {}
  631. `
  632. const mainSrc = `
  633. package main
  634. import "lib"
  635. type A struct {
  636. *B
  637. C
  638. }
  639. type B struct {
  640. b int
  641. }
  642. func (B) f(int)
  643. type C struct {
  644. c int
  645. }
  646. func (C) g()
  647. func (*C) h()
  648. func main() {
  649. // qualified identifiers
  650. var _ lib.T
  651. _ = lib.C
  652. _ = lib.F
  653. _ = lib.V
  654. _ = lib.T.M
  655. // fields
  656. _ = A{}.B
  657. _ = new(A).B
  658. _ = A{}.C
  659. _ = new(A).C
  660. _ = A{}.b
  661. _ = new(A).b
  662. _ = A{}.c
  663. _ = new(A).c
  664. // methods
  665. _ = A{}.f
  666. _ = new(A).f
  667. _ = A{}.g
  668. _ = new(A).g
  669. _ = new(A).h
  670. _ = B{}.f
  671. _ = new(B).f
  672. _ = C{}.g
  673. _ = new(C).g
  674. _ = new(C).h
  675. // method expressions
  676. _ = A.f
  677. _ = (*A).f
  678. _ = B.f
  679. _ = (*B).f
  680. }`
  681. wantOut := map[string][2]string{
  682. "lib.T.M": {"method expr (lib.T) M(lib.T)", ".[0]"},
  683. "A{}.B": {"field (main.A) B *main.B", ".[0]"},
  684. "new(A).B": {"field (*main.A) B *main.B", "->[0]"},
  685. "A{}.C": {"field (main.A) C main.C", ".[1]"},
  686. "new(A).C": {"field (*main.A) C main.C", "->[1]"},
  687. "A{}.b": {"field (main.A) b int", "->[0 0]"},
  688. "new(A).b": {"field (*main.A) b int", "->[0 0]"},
  689. "A{}.c": {"field (main.A) c int", ".[1 0]"},
  690. "new(A).c": {"field (*main.A) c int", "->[1 0]"},
  691. "A{}.f": {"method (main.A) f(int)", "->[0 0]"},
  692. "new(A).f": {"method (*main.A) f(int)", "->[0 0]"},
  693. "A{}.g": {"method (main.A) g()", ".[1 0]"},
  694. "new(A).g": {"method (*main.A) g()", "->[1 0]"},
  695. "new(A).h": {"method (*main.A) h()", "->[1 1]"}, // TODO(gri) should this report .[1 1] ?
  696. "B{}.f": {"method (main.B) f(int)", ".[0]"},
  697. "new(B).f": {"method (*main.B) f(int)", "->[0]"},
  698. "C{}.g": {"method (main.C) g()", ".[0]"},
  699. "new(C).g": {"method (*main.C) g()", "->[0]"},
  700. "new(C).h": {"method (*main.C) h()", "->[1]"}, // TODO(gri) should this report .[1] ?
  701. "A.f": {"method expr (main.A) f(main.A, int)", "->[0 0]"},
  702. "(*A).f": {"method expr (*main.A) f(*main.A, int)", "->[0 0]"},
  703. "B.f": {"method expr (main.B) f(main.B, int)", ".[0]"},
  704. "(*B).f": {"method expr (*main.B) f(*main.B, int)", "->[0]"},
  705. }
  706. makePkg("lib", libSrc)
  707. makePkg("main", mainSrc)
  708. for e, sel := range selections {
  709. sel.String() // assertion: must not panic
  710. start := fset.Position(e.Pos()).Offset
  711. end := fset.Position(e.End()).Offset
  712. syntax := mainSrc[start:end] // (all SelectorExprs are in main, not lib)
  713. direct := "."
  714. if sel.Indirect() {
  715. direct = "->"
  716. }
  717. got := [2]string{
  718. sel.String(),
  719. fmt.Sprintf("%s%v", direct, sel.Index()),
  720. }
  721. want := wantOut[syntax]
  722. if want != got {
  723. t.Errorf("%s: got %q; want %q", syntax, got, want)
  724. }
  725. delete(wantOut, syntax)
  726. // We must explicitly assert properties of the
  727. // Signature's receiver since it doesn't participate
  728. // in Identical() or String().
  729. sig, _ := sel.Type().(*Signature)
  730. if sel.Kind() == MethodVal {
  731. got := sig.Recv().Type()
  732. want := sel.Recv()
  733. if !Identical(got, want) {
  734. t.Errorf("%s: Recv() = %s, want %s", syntax, got, want)
  735. }
  736. } else if sig != nil && sig.Recv() != nil {
  737. t.Errorf("%s: signature has receiver %s", sig, sig.Recv().Type())
  738. }
  739. }
  740. // Assert that all wantOut entries were used exactly once.
  741. for syntax := range wantOut {
  742. t.Errorf("no ast.Selection found with syntax %q", syntax)
  743. }
  744. }
  745. func TestIssue8518(t *testing.T) {
  746. fset := token.NewFileSet()
  747. imports := make(testImporter)
  748. conf := Config{
  749. Error: func(err error) { t.Log(err) }, // don't exit after first error
  750. Importer: imports,
  751. }
  752. makePkg := func(path, src string) {
  753. f, err := parser.ParseFile(fset, path, src, 0)
  754. if err != nil {
  755. t.Fatal(err)
  756. }
  757. pkg, _ := conf.Check(path, fset, []*ast.File{f}, nil) // errors logged via conf.Error
  758. imports[path] = pkg
  759. }
  760. const libSrc = `
  761. package a
  762. import "missing"
  763. const C1 = foo
  764. const C2 = missing.C
  765. `
  766. const mainSrc = `
  767. package main
  768. import "a"
  769. var _ = a.C1
  770. var _ = a.C2
  771. `
  772. makePkg("a", libSrc)
  773. makePkg("main", mainSrc) // don't crash when type-checking this package
  774. }
  775. func TestLookupFieldOrMethod(t *testing.T) {
  776. // Test cases assume a lookup of the form a.f or x.f, where a stands for an
  777. // addressable value, and x for a non-addressable value (even though a variable
  778. // for ease of test case writing).
  779. var tests = []struct {
  780. src string
  781. found bool
  782. index []int
  783. indirect bool
  784. }{
  785. // field lookups
  786. {"var x T; type T struct{}", false, nil, false},
  787. {"var x T; type T struct{ f int }", true, []int{0}, false},
  788. {"var x T; type T struct{ a, b, f, c int }", true, []int{2}, false},
  789. // method lookups
  790. {"var a T; type T struct{}; func (T) f() {}", true, []int{0}, false},
  791. {"var a *T; type T struct{}; func (T) f() {}", true, []int{0}, true},
  792. {"var a T; type T struct{}; func (*T) f() {}", true, []int{0}, false},
  793. {"var a *T; type T struct{}; func (*T) f() {}", true, []int{0}, true}, // TODO(gri) should this report indirect = false?
  794. // collisions
  795. {"type ( E1 struct{ f int }; E2 struct{ f int }; x struct{ E1; *E2 })", false, []int{1, 0}, false},
  796. {"type ( E1 struct{ f int }; E2 struct{}; x struct{ E1; *E2 }); func (E2) f() {}", false, []int{1, 0}, false},
  797. // outside methodset
  798. // (*T).f method exists, but value of type T is not addressable
  799. {"var x T; type T struct{}; func (*T) f() {}", false, nil, true},
  800. }
  801. for _, test := range tests {
  802. pkg, err := pkgFor("test", "package p;"+test.src, nil)
  803. if err != nil {
  804. t.Errorf("%s: incorrect test case: %s", test.src, err)
  805. continue
  806. }
  807. obj := pkg.Scope().Lookup("a")
  808. if obj == nil {
  809. if obj = pkg.Scope().Lookup("x"); obj == nil {
  810. t.Errorf("%s: incorrect test case - no object a or x", test.src)
  811. continue
  812. }
  813. }
  814. f, index, indirect := LookupFieldOrMethod(obj.Type(), obj.Name() == "a", pkg, "f")
  815. if (f != nil) != test.found {
  816. if f == nil {
  817. t.Errorf("%s: got no object; want one", test.src)
  818. } else {
  819. t.Errorf("%s: got object = %v; want none", test.src, f)
  820. }
  821. }
  822. if !sameSlice(index, test.index) {
  823. t.Errorf("%s: got index = %v; want %v", test.src, index, test.index)
  824. }
  825. if indirect != test.indirect {
  826. t.Errorf("%s: got indirect = %v; want %v", test.src, indirect, test.indirect)
  827. }
  828. }
  829. }
  830. func sameSlice(a, b []int) bool {
  831. if len(a) != len(b) {
  832. return false
  833. }
  834. for i, x := range a {
  835. if x != b[i] {
  836. return false
  837. }
  838. }
  839. return true
  840. }
  841. // TestScopeLookupParent ensures that (*Scope).LookupParent returns
  842. // the correct result at various positions with the source.
  843. func TestScopeLookupParent(t *testing.T) {
  844. fset := token.NewFileSet()
  845. imports := make(testImporter)
  846. conf := Config{Importer: imports}
  847. mustParse := func(src string) *ast.File {
  848. f, err := parser.ParseFile(fset, "dummy.go", src, parser.ParseComments)
  849. if err != nil {
  850. t.Fatal(err)
  851. }
  852. return f
  853. }
  854. var info Info
  855. makePkg := func(path string, files ...*ast.File) {
  856. imports[path], _ = conf.Check(path, fset, files, &info)
  857. }
  858. makePkg("lib", mustParse("package lib; var X int"))
  859. // Each /*name=kind:line*/ comment makes the test look up the
  860. // name at that point and checks that it resolves to a decl of
  861. // the specified kind and line number. "undef" means undefined.
  862. mainSrc := `
  863. package main
  864. import "lib"
  865. var Y = lib.X
  866. func f() {
  867. print(Y) /*Y=var:4*/
  868. z /*z=undef*/ := /*z=undef*/ 1 /*z=var:7*/
  869. print(z)
  870. /*f=func:5*/ /*lib=pkgname:3*/
  871. type /*T=undef*/ T /*T=typename:10*/ *T
  872. }
  873. `
  874. info.Uses = make(map[*ast.Ident]Object)
  875. f := mustParse(mainSrc)
  876. makePkg("main", f)
  877. mainScope := imports["main"].Scope()
  878. rx := regexp.MustCompile(`^/\*(\w*)=([\w:]*)\*/$`)
  879. for _, group := range f.Comments {
  880. for _, comment := range group.List {
  881. // Parse the assertion in the comment.
  882. m := rx.FindStringSubmatch(comment.Text)
  883. if m == nil {
  884. t.Errorf("%s: bad comment: %s",
  885. fset.Position(comment.Pos()), comment.Text)
  886. continue
  887. }
  888. name, want := m[1], m[2]
  889. // Look up the name in the innermost enclosing scope.
  890. inner := mainScope.Innermost(comment.Pos())
  891. if inner == nil {
  892. t.Errorf("%s: at %s: can't find innermost scope",
  893. fset.Position(comment.Pos()), comment.Text)
  894. continue
  895. }
  896. got := "undef"
  897. if _, obj := inner.LookupParent(name, comment.Pos()); obj != nil {
  898. kind := strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types."))
  899. got = fmt.Sprintf("%s:%d", kind, fset.Position(obj.Pos()).Line)
  900. }
  901. if got != want {
  902. t.Errorf("%s: at %s: %s resolved to %s, want %s",
  903. fset.Position(comment.Pos()), comment.Text, name, got, want)
  904. }
  905. }
  906. }
  907. // Check that for each referring identifier,
  908. // a lookup of its name on the innermost
  909. // enclosing scope returns the correct object.
  910. for id, wantObj := range info.Uses {
  911. inner := mainScope.Innermost(id.Pos())
  912. if inner == nil {
  913. t.Errorf("%s: can't find innermost scope enclosing %q",
  914. fset.Position(id.Pos()), id.Name)
  915. continue
  916. }
  917. // Exclude selectors and qualified identifiers---lexical
  918. // refs only. (Ideally, we'd see if the AST parent is a
  919. // SelectorExpr, but that requires PathEnclosingInterval
  920. // from golang.org/x/tools/go/ast/astutil.)
  921. if id.Name == "X" {
  922. continue
  923. }
  924. _, gotObj := inner.LookupParent(id.Name, id.Pos())
  925. if gotObj != wantObj {
  926. t.Errorf("%s: got %v, want %v",
  927. fset.Position(id.Pos()), gotObj, wantObj)
  928. continue
  929. }
  930. }
  931. }