Skip to content

Commit

Permalink
x/typesutil: TestScopesInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
visualfc committed Feb 21, 2024
1 parent d78d079 commit e8e9c3e
Showing 1 changed file with 131 additions and 2 deletions.
133 changes: 131 additions & 2 deletions x/typesutil/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func parseSource(fset *token.FileSet, filename string, src interface{}, mode par
return nil, nil, err
}

pkg := types.NewPackage("main", f.Name.Name)
pkg := types.NewPackage("", f.Name.Name)
conf := &types.Config{}
conf.Importer = importer.Default()
chkOpts := &typesutil.Config{
Expand Down Expand Up @@ -150,7 +150,7 @@ func parseGoSource(fset *token.FileSet, filename string, src interface{}, mode g
Selections: make(map[*goast.SelectorExpr]*types.Selection),
Scopes: make(map[goast.Node]*types.Scope),
}
pkg := types.NewPackage("main", f.Name.Name)
pkg := types.NewPackage("", f.Name.Name)
check := types.NewChecker(conf, fset, pkg, info)
err = check.Files([]*goast.File{f})
return pkg, info, err
Expand Down Expand Up @@ -1671,3 +1671,132 @@ func onCloned() {
009: 15: 9 | info | type main.info struct{x int; y int}
010: 19: 2 | say | func (*github.com/goplus/gop/cl/internal/spx.Sprite).Say(msg string, secs ...float64)`)
}

func TestScopesInfo(t *testing.T) {
var tests = []struct {
src string
scopes []string // list of scope descriptors of the form kind:varlist
}{
{`package p0`, []string{
"file:",
}},
{`package p1; import ( "fmt"; m "math"; _ "os" ); var ( _ = fmt.Println; _ = m.Pi )`, []string{
"file:fmt m",
}},
{`package p2; func _() {}`, []string{
"file:", "func:",
}},
{`package p3; func _(x, y int) {}`, []string{
"file:", "func:x y",
}},
{`package p4; func _(x, y int) { x, z := 1, 2; _ = z }`, []string{
"file:", "func:x y z", // redeclaration of x
}},
{`package p5; func _(x, y int) (u, _ int) { return }`, []string{
"file:", "func:u x y",
}},
{`package p6; func _() { { var x int; _ = x } }`, []string{
"file:", "func:", "block:x",
}},
{`package p7; func _() { if true {} }`, []string{
"file:", "func:", "if:", "block:",
}},
{`package p8; func _() { if x := 0; x < 0 { y := x; _ = y } }`, []string{
"file:", "func:", "if:x", "block:y",
}},
{`package p9; func _() { switch x := 0; x {} }`, []string{
"file:", "func:", "switch:x",
}},
{`package p10; func _() { switch x := 0; x { case 1: y := x; _ = y; default: }}`, []string{
"file:", "func:", "switch:x", "case:y", "case:",
}},
{`package p11; func _(t interface{}) { switch t.(type) {} }`, []string{
"file:", "func:t", "type switch:",
}},
{`package p12; func _(t interface{}) { switch t := t; t.(type) {} }`, []string{
"file:", "func:t", "type switch:t",
}},
{`package p13; func _(t interface{}) { switch x := t.(type) { case int: _ = x } }`, []string{
"file:", "func:t", "type switch:", "case:x", // x implicitly declared
}},
{`package p14; func _() { select{} }`, []string{
"file:", "func:",
}},
{`package p15; func _(c chan int) { select{ case <-c: } }`, []string{
"file:", "func:c", "comm:",
}},
{`package p16; func _(c chan int) { select{ case i := <-c: x := i; _ = x} }`, []string{
"file:", "func:c", "comm:i x",
}},
{`package p17; func _() { for{} }`, []string{
"file:", "func:", "for:", "block:",
}},
{`package p18; func _(n int) { for i := 0; i < n; i++ { _ = i } }`, []string{
"file:", "func:n", "for:i", "block:",
}},
{`package p19; func _(a []int) { for i := range a { _ = i} }`, []string{
"file:", "func:a", "range:i", "block:",
}},
{`package p20; var s int; func _(a []int) { for i, x := range a { s += x; _ = i } }`, []string{
"file:", "func:a", "range:i x", "block:",
}},
{`package p21; var s int; func _(a []int) { for i, x := range a { c := i; println(c) } }`, []string{
"file:", "func:a", "range:i x", "block:c",
}},
}

for _, test := range tests {
pkg, info, err := parseSource(token.NewFileSet(), "src.gop", test.src, 0)
if err != nil {
t.Fatalf("parse source failed: %v", test.src)
}
name := pkg.Name()
// number of scopes must match
if len(info.Scopes) != len(test.scopes) {
t.Errorf("package %s: got %d scopes; want %d\n%v\n%v", name, len(info.Scopes), len(test.scopes),
test.scopes, info.Scopes)
}

// scope descriptions must match
for node, scope := range info.Scopes {
kind := "<unknown node kind>"
switch node.(type) {
case *ast.File:
kind = "file"
case *ast.FuncType:
kind = "func"
case *ast.BlockStmt:
kind = "block"
case *ast.IfStmt:
kind = "if"
case *ast.SwitchStmt:
kind = "switch"
case *ast.TypeSwitchStmt:
kind = "type switch"
case *ast.CaseClause:
kind = "case"
case *ast.CommClause:
kind = "comm"
case *ast.ForStmt:
kind = "for"
case *ast.RangeStmt:
kind = "range"
default:
kind = fmt.Sprintf("<unknown node kind> %T", node)
}

// look for matching scope description
desc := kind + ":" + strings.Join(scope.Names(), " ")
found := false
for _, d := range test.scopes {
if desc == d {
found = true
break
}
}
if !found {
t.Errorf("package %s: no matching scope found for %s", name, desc)
}
}
}
}

0 comments on commit e8e9c3e

Please sign in to comment.