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:
parent
305a363bdd
commit
4f7b2f8882
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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])
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue