Skip to content

Commit

Permalink
go/types, types2: move go/types-only Scope methods into scopes2.go
Browse files Browse the repository at this point in the history
Remove them them from types2.

Updates #69673.

Change-Id: I7843f6da1edf3a19f85c61706104d173e04088d3
Reviewed-on: https://go-review.googlesource.com/c/go/+/616261
Reviewed-by: Alan Donovan <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
Auto-Submit: Robert Griesemer <[email protected]>
Reviewed-by: Robert Griesemer <[email protected]>
  • Loading branch information
griesemer authored and gopherbot committed Sep 27, 2024
1 parent 62452be commit 6ad3933
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 430 deletions.
158 changes: 0 additions & 158 deletions src/cmd/compile/internal/types2/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import (
"fmt"
"internal/goversion"
"internal/testenv"
"reflect"
"regexp"
"sort"
"strings"
"sync"
Expand Down Expand Up @@ -1993,162 +1991,6 @@ func sameSlice(a, b []int) bool {
return true
}

// TestScopeLookupParent ensures that (*Scope).LookupParent returns
// the correct result at various positions within the source.
func TestScopeLookupParent(t *testing.T) {
imports := make(testImporter)
conf := Config{
Importer: imports,
EnableAlias: true, // must match default Universe.Lookup behavior
}
var info Info
makePkg := func(path, src string) {
var err error
imports[path], err = conf.Check(path, []*syntax.File{mustParse(src)}, &info)
if err != nil {
t.Fatal(err)
}
}

makePkg("lib", "package lib; var X int")
// Each /*name=kind:line*/ comment makes the test look up the
// name at that point and checks that it resolves to a decl of
// the specified kind and line number. "undef" means undefined.
// Note that type switch case clauses with an empty body (but for
// comments) need the ";" to ensure that the recorded scope extends
// past the comments.
mainSrc := `
/*lib=pkgname:5*/ /*X=var:1*/ /*Pi=const:8*/ /*T=typename:9*/ /*Y=var:10*/ /*F=func:12*/
package main
import "lib"
import . "lib"
const Pi = 3.1415
type T struct{}
var Y, _ = lib.X, X
func F[T *U, U any](param1, param2 int) /*param1=undef*/ (res1 /*res1=undef*/, res2 int) /*param1=var:12*/ /*res1=var:12*/ /*U=typename:12*/ {
const pi, e = 3.1415, /*pi=undef*/ 2.71828 /*pi=const:13*/ /*e=const:13*/
type /*t=undef*/ t /*t=typename:14*/ *t
print(Y) /*Y=var:10*/
x, Y := Y, /*x=undef*/ /*Y=var:10*/ Pi /*x=var:16*/ /*Y=var:16*/ ; _ = x; _ = Y
var F = /*F=func:12*/ F[*int, int] /*F=var:17*/ ; _ = F
var a []int
for i, x := range a /*i=undef*/ /*x=var:16*/ { _ = i; _ = x }
var i interface{}
switch y := i.(type) { /*y=undef*/
case /*y=undef*/ int /*y=undef*/ : /*y=var:23*/ ;
case float32, /*y=undef*/ float64 /*y=undef*/ : /*y=var:23*/ ;
default /*y=undef*/ : /*y=var:23*/
println(y)
}
/*y=undef*/
switch int := i.(type) {
case /*int=typename:0*/ int /*int=typename:0*/ : /*int=var:31*/
println(int)
default /*int=typename:0*/ : /*int=var:31*/ ;
}
_ = param1
_ = res1
return
}
/*main=undef*/
`

info.Uses = make(map[*syntax.Name]Object)
makePkg("main", mainSrc)
mainScope := imports["main"].Scope()

rx := regexp.MustCompile(`^/\*(\w*)=([\w:]*)\*/$`)

base := syntax.NewFileBase("main")
syntax.CommentsDo(strings.NewReader(mainSrc), func(line, col uint, text string) {
pos := syntax.MakePos(base, line, col)

// Syntax errors are not comments.
if text[0] != '/' {
t.Errorf("%s: %s", pos, text)
return
}

// Parse the assertion in the comment.
m := rx.FindStringSubmatch(text)
if m == nil {
t.Errorf("%s: bad comment: %s", pos, text)
return
}
name, want := m[1], m[2]

// Look up the name in the innermost enclosing scope.
inner := mainScope.Innermost(pos)
if inner == nil {
t.Errorf("%s: at %s: can't find innermost scope", pos, text)
return
}
got := "undef"
if _, obj := inner.LookupParent(name, pos); obj != nil {
kind := strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types2."))
got = fmt.Sprintf("%s:%d", kind, obj.Pos().Line())
}
if got != want {
t.Errorf("%s: at %s: %s resolved to %s, want %s", pos, text, name, got, want)
}
})

// Check that for each referring identifier,
// a lookup of its name on the innermost
// enclosing scope returns the correct object.

for id, wantObj := range info.Uses {
inner := mainScope.Innermost(id.Pos())
if inner == nil {
t.Errorf("%s: can't find innermost scope enclosing %q", id.Pos(), id.Value)
continue
}

// Exclude selectors and qualified identifiers---lexical
// refs only. (Ideally, we'd see if the AST parent is a
// SelectorExpr, but that requires PathEnclosingInterval
// from golang.org/x/tools/go/ast/astutil.)
if id.Value == "X" {
continue
}

_, gotObj := inner.LookupParent(id.Value, id.Pos())
if gotObj != wantObj {
// Print the scope tree of mainScope in case of error.
var printScopeTree func(indent string, s *Scope)
printScopeTree = func(indent string, s *Scope) {
t.Logf("%sscope %s %v-%v = %v",
indent,
ScopeComment(s),
s.Pos(),
s.End(),
s.Names())
for i := range s.NumChildren() {
printScopeTree(indent+" ", s.Child(i))
}
}
printScopeTree("", mainScope)

t.Errorf("%s: Scope(%s).LookupParent(%s@%v) got %v, want %v [scopePos=%v]",
id.Pos(),
ScopeComment(inner),
id.Value,
id.Pos(),
gotObj,
wantObj,
ObjectScopePos(wantObj))
continue
}
}
}

// newDefined creates a new defined type named T with the given underlying type.
func newDefined(underlying Type) *Named {
tname := NewTypeName(nopos, nil, "T", nil)
Expand Down
60 changes: 0 additions & 60 deletions src/cmd/compile/internal/types2/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,25 +83,6 @@ func (s *Scope) Lookup(name string) Object {
return obj
}

// LookupParent follows the parent chain of scopes starting with s until
// it finds a scope where Lookup(name) returns a non-nil object, and then
// returns that scope and object. If a valid position pos is provided,
// only objects that were declared at or before pos are considered.
// If no such scope and object exists, the result is (nil, nil).
//
// Note that obj.Parent() may be different from the returned scope if the
// object was inserted into the scope and already had a parent at that
// time (see Insert). This can only happen for dot-imported objects
// whose parent is the scope of the package that exported them.
func (s *Scope) LookupParent(name string, pos syntax.Pos) (*Scope, Object) {
for ; s != nil; s = s.parent {
if obj := s.Lookup(name); obj != nil && (!pos.IsKnown() || cmpPos(obj.scopePos(), pos) <= 0) {
return s, obj
}
}
return nil, nil
}

// Insert attempts to insert an object obj into scope s.
// If s already contains an alternative object alt with
// the same name, Insert leaves s unchanged and returns alt.
Expand Down Expand Up @@ -146,47 +127,6 @@ func (s *Scope) insert(name string, obj Object) {
s.elems[name] = obj
}

// Pos and End describe the scope's source code extent [pos, end).
// The results are guaranteed to be valid only if the type-checked
// AST has complete position information. The extent is undefined
// for Universe and package scopes.
func (s *Scope) Pos() syntax.Pos { return s.pos }
func (s *Scope) End() syntax.Pos { return s.end }

// Contains reports whether pos is within the scope's extent.
// The result is guaranteed to be valid only if the type-checked
// AST has complete position information.
func (s *Scope) Contains(pos syntax.Pos) bool {
return cmpPos(s.pos, pos) <= 0 && cmpPos(pos, s.end) < 0
}

// Innermost returns the innermost (child) scope containing
// pos. If pos is not within any scope, the result is nil.
// The result is also nil for the Universe scope.
// The result is guaranteed to be valid only if the type-checked
// AST has complete position information.
func (s *Scope) Innermost(pos syntax.Pos) *Scope {
// Package scopes do not have extents since they may be
// discontiguous, so iterate over the package's files.
if s.parent == Universe {
for _, s := range s.children {
if inner := s.Innermost(pos); inner != nil {
return inner
}
}
}

if s.Contains(pos) {
for _, s := range s.children {
if s.Contains(pos) {
return s.Innermost(pos)
}
}
return s
}
return nil
}

// WriteTo writes a string representation of the scope to w,
// with the scope elements sorted by name.
// The level of indentation is controlled by n >= 0, with
Expand Down
Loading

0 comments on commit 6ad3933

Please sign in to comment.