go.tools/go/types: add Scope.comment as a debugging aid.

e.g. file foo.go scope {...}
     package math scope {...}
     function f scope {...}
     if scope {...}

LGTM=gri
R=gri
CC=golang-codereviews
https://golang.org/cl/74320043
This commit is contained in:
Alan Donovan 2014-03-12 14:12:09 -04:00
parent 305a363bdd
commit 4f7b2f8882
7 changed files with 32 additions and 22 deletions

View File

@ -7,6 +7,7 @@
package types package types
import ( import (
"fmt"
"go/ast" "go/ast"
"go/token" "go/token"
@ -164,7 +165,7 @@ func (check *checker) initFiles(files []*ast.File) {
// determine package name, files, and set up file scopes, dotImports maps // determine package name, files, and set up file scopes, dotImports maps
pkg := check.pkg pkg := check.pkg
for _, file := range files { for i, file := range files {
switch name := file.Name.Name; pkg.name { switch name := file.Name.Name; pkg.name {
case "": case "":
pkg.name = name pkg.name = name
@ -172,7 +173,13 @@ func (check *checker) initFiles(files []*ast.File) {
case name: case name:
check.files = append(check.files, file) check.files = append(check.files, file)
fileScope := NewScope(pkg.scope) var comment string
if pos := file.Pos(); pos.IsValid() {
comment = "file " + check.fset.File(pos).Name()
} else {
comment = fmt.Sprintf("file[%d]", i)
}
fileScope := NewScope(pkg.scope, comment)
check.recordScope(file, fileScope) check.recordScope(file, fileScope)
check.fileScopes = append(check.fileScopes, fileScope) check.fileScopes = append(check.fileScopes, fileScope)
check.dotImports = append(check.dotImports, nil) // element (map) is lazily allocated check.dotImports = append(check.dotImports, nil) // element (map) is lazily allocated

View File

@ -12,7 +12,7 @@ import (
// labels checks correct label use in body. // labels checks correct label use in body.
func (check *checker) labels(body *ast.BlockStmt) { func (check *checker) labels(body *ast.BlockStmt) {
// set of all labels in this body // set of all labels in this body
all := NewScope(nil) all := NewScope(nil, "label")
fwdJumps := check.blockBranches(all, nil, nil, body.List) fwdJumps := check.blockBranches(all, nil, nil, body.List)

View File

@ -19,7 +19,8 @@ type Package struct {
// NewPackage returns a new Package for the given package path and name. // NewPackage returns a new Package for the given package path and name.
// The package is not complete and contains no explicit imports. // The package is not complete and contains no explicit imports.
func NewPackage(path, name string) *Package { func NewPackage(path, name string) *Package {
return &Package{path: path, name: name, scope: NewScope(Universe)} scope := NewScope(Universe, fmt.Sprintf("package %q", path))
return &Package{path: path, name: name, scope: scope}
} }
// Path returns the package path. // Path returns the package path.

View File

@ -24,13 +24,14 @@ import (
type Scope struct { type Scope struct {
parent *Scope parent *Scope
children []*Scope children []*Scope
comment string // for debugging only
elems map[string]Object // lazily allocated elems map[string]Object // lazily allocated
} }
// NewScope returns a new, empty scope contained in the given parent // NewScope returns a new, empty scope contained in the given parent
// scope, if any. // scope, if any. The comment is for debugging only.
func NewScope(parent *Scope) *Scope { func NewScope(parent *Scope, comment string) *Scope {
s := &Scope{parent: parent} s := &Scope{parent: parent, comment: comment}
// don't add children to Universe scope! // don't add children to Universe scope!
if parent != nil && parent != Universe { if parent != nil && parent != Universe {
parent.children = append(parent.children, s) parent.children = append(parent.children, s)
@ -118,12 +119,13 @@ func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) {
const ind = ". " const ind = ". "
indn := strings.Repeat(ind, n) indn := strings.Repeat(ind, n)
fmt.Fprintf(w, "%s%s scope %p {", indn, s.comment, s)
if len(s.elems) == 0 { if len(s.elems) == 0 {
fmt.Fprintf(w, "%sscope %p {}\n", indn, s) fmt.Fprintf(w, "}\n")
return return
} }
fmt.Fprintf(w, "%sscope %p {\n", indn, s) fmt.Fprintln(w)
indn1 := indn + ind indn1 := indn + ind
for _, name := range s.Names() { for _, name := range s.Names() {
fmt.Fprintf(w, "%s%s\n", indn1, s.elems[name]) fmt.Fprintf(w, "%s%s\n", indn1, s.elems[name])

View File

@ -118,8 +118,8 @@ func (check *checker) multipleDefaults(list []ast.Stmt) {
} }
} }
func (check *checker) openScope(s ast.Stmt) { func (check *checker) openScope(s ast.Stmt, comment string) {
scope := NewScope(check.scope) scope := NewScope(check.scope, comment)
check.recordScope(s, scope) check.recordScope(s, scope)
check.scope = scope check.scope = scope
} }
@ -366,13 +366,13 @@ func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
} }
case *ast.BlockStmt: case *ast.BlockStmt:
check.openScope(s) check.openScope(s, "block")
defer check.closeScope() defer check.closeScope()
check.stmtList(inner, s.List) check.stmtList(inner, s.List)
case *ast.IfStmt: case *ast.IfStmt:
check.openScope(s) check.openScope(s, "if")
defer check.closeScope() defer check.closeScope()
check.initStmt(s.Init) check.initStmt(s.Init)
@ -388,7 +388,7 @@ func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
case *ast.SwitchStmt: case *ast.SwitchStmt:
inner |= inBreakable inner |= inBreakable
check.openScope(s) check.openScope(s, "switch")
defer check.closeScope() defer check.closeScope()
check.initStmt(s.Init) check.initStmt(s.Init)
@ -415,7 +415,7 @@ func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
if x.mode != invalid { if x.mode != invalid {
check.caseValues(x, clause.List) check.caseValues(x, clause.List)
} }
check.openScope(clause) check.openScope(clause, "case")
inner := inner inner := inner
if i+1 < len(s.Body.List) { if i+1 < len(s.Body.List) {
inner |= fallthroughOk inner |= fallthroughOk
@ -426,7 +426,7 @@ func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
case *ast.TypeSwitchStmt: case *ast.TypeSwitchStmt:
inner |= inBreakable inner |= inBreakable
check.openScope(s) check.openScope(s, "type switch")
defer check.closeScope() defer check.closeScope()
check.initStmt(s.Init) check.initStmt(s.Init)
@ -493,7 +493,7 @@ func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
} }
// Check each type in this type switch case. // Check each type in this type switch case.
T := check.caseTypes(&x, xtyp, clause.List, seen) T := check.caseTypes(&x, xtyp, clause.List, seen)
check.openScope(clause) check.openScope(clause, "case")
// If lhs exists, declare a corresponding variable in the case-local scope. // If lhs exists, declare a corresponding variable in the case-local scope.
if lhs != nil { if lhs != nil {
// spec: "The TypeSwitchGuard may include a short variable declaration. // spec: "The TypeSwitchGuard may include a short variable declaration.
@ -567,7 +567,7 @@ func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
continue continue
} }
check.openScope(s) check.openScope(s, "case")
defer check.closeScope() defer check.closeScope()
if clause.Comm != nil { if clause.Comm != nil {
check.stmt(inner, clause.Comm) check.stmt(inner, clause.Comm)
@ -577,7 +577,7 @@ func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
case *ast.ForStmt: case *ast.ForStmt:
inner |= inBreakable | inContinuable inner |= inBreakable | inContinuable
check.openScope(s) check.openScope(s, "for")
defer check.closeScope() defer check.closeScope()
check.initStmt(s.Init) check.initStmt(s.Init)
@ -593,7 +593,7 @@ func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
case *ast.RangeStmt: case *ast.RangeStmt:
inner |= inBreakable | inContinuable inner |= inBreakable | inContinuable
check.openScope(s) check.openScope(s, "for")
defer check.closeScope() defer check.closeScope()
// check expression to iterate over // check expression to iterate over

View File

@ -141,7 +141,7 @@ func (check *checker) typ(e ast.Expr) Type {
// funcType type-checks a function or method type and returns its signature. // funcType type-checks a function or method type and returns its signature.
func (check *checker) funcType(sig *Signature, recv *ast.FieldList, ftyp *ast.FuncType) *Signature { func (check *checker) funcType(sig *Signature, recv *ast.FieldList, ftyp *ast.FuncType) *Signature {
scope := NewScope(check.scope) scope := NewScope(check.scope, "function")
check.recordScope(ftyp, scope) check.recordScope(ftyp, scope)
recv_, _ := check.collectParams(scope, recv, false) recv_, _ := check.collectParams(scope, recv, false)

View File

@ -177,7 +177,7 @@ func DefPredeclaredTestFuncs() {
} }
func init() { func init() {
Universe = NewScope(nil) Universe = NewScope(nil, "universe")
Unsafe = NewPackage("unsafe", "unsafe") Unsafe = NewPackage("unsafe", "unsafe")
Unsafe.complete = true Unsafe.complete = true