1
0
mirror of https://github.com/golang/go synced 2024-09-30 16:08:36 -06:00

go.tools/refactor/eg: Support promoted fields and methods.

As per http://golang.org/ref/spec#Struct_types enable eg tool
to wildcard match against promoted fields and methods.

LGTM=adonovan
R=adonovan, gordon.klaus
CC=golang-codereviews
https://golang.org/cl/129260043
This commit is contained in:
Paul Nasrat 2014-08-25 16:26:54 -04:00 committed by Alan Donovan
parent cd9959d796
commit 89156360f9
5 changed files with 132 additions and 5 deletions

View File

@ -62,6 +62,9 @@ func Test(t *testing.T) {
"testdata/E.template",
"testdata/E1.go",
"testdata/F.template",
"testdata/F1.go",
"testdata/bad_type.template",
"testdata/no_before.template",
"testdata/no_after_return.template",

View File

@ -35,11 +35,9 @@ func (tr *Transformer) matchExpr(x, y ast.Expr) bool {
y = unparen(y)
// Is x a wildcard? (a reference to a 'before' parameter)
if x, ok := x.(*ast.Ident); ok && x != nil && tr.allowWildcards {
if xobj, ok := tr.info.Uses[x].(*types.Var); ok && tr.wildcards[xobj] {
if xobj, ok := tr.wildcardObj(x); ok {
return tr.matchWildcard(xobj, y)
}
}
// Object identifiers (including pkg-qualified ones)
// are handled semantically, not syntactically.
@ -81,7 +79,7 @@ func (tr *Transformer) matchExpr(x, y ast.Expr) bool {
case *ast.SelectorExpr:
y := y.(*ast.SelectorExpr)
return tr.matchExpr(x.X, y.X) &&
return tr.matchSelectorExpr(x, y) &&
tr.info.Selections[x].Obj() == tr.info.Selections[y].Obj()
case *ast.IndexExpr:
@ -155,6 +153,28 @@ func (tr *Transformer) matchType(x, y ast.Expr) bool {
return types.Identical(tx, ty)
}
func (tr *Transformer) wildcardObj(x ast.Expr) (*types.Var, bool) {
if x, ok := x.(*ast.Ident); ok && x != nil && tr.allowWildcards {
if xobj, ok := tr.info.Uses[x].(*types.Var); ok && tr.wildcards[xobj] {
return xobj, true
}
}
return nil, false
}
func (tr *Transformer) matchSelectorExpr(x, y *ast.SelectorExpr) bool {
if xobj, ok := tr.wildcardObj(x.X); ok {
field := x.Sel.Name
yt := tr.info.TypeOf(y.X)
o, _, _ := types.LookupFieldOrMethod(yt, tr.currentPkg, field)
if o != nil {
tr.env[xobj.Name()] = y.X // record binding
return true
}
}
return tr.matchExpr(x.X, y.X)
}
func (tr *Transformer) matchWildcard(xobj *types.Var, y ast.Expr) bool {
name := xobj.Name()

8
refactor/eg/testdata/F.template vendored Normal file
View File

@ -0,0 +1,8 @@
package templates
// Test
import "sync"
func before(s sync.RWMutex) { s.Lock() }
func after(s sync.RWMutex) { s.RLock() }

48
refactor/eg/testdata/F1.go vendored Normal file
View File

@ -0,0 +1,48 @@
// +build ignore
package F1
import "sync"
func example(n int) {
var x struct {
mutex sync.RWMutex
}
var y struct {
sync.RWMutex
}
type l struct {
sync.RWMutex
}
var z struct {
l
}
var a struct {
*l
}
var b struct{ Lock func() }
// Match
x.mutex.Lock()
// Match
y.Lock()
// Match indirect
z.Lock()
// Should be no match however currently matches due to:
// https://code.google.com/p/go/issues/detail?id=8584
// Will start failing when this is fixed then just change golden to
// No match pointer indirect
// a.Lock()
a.Lock()
// No match
b.Lock()
}

48
refactor/eg/testdata/F1.golden vendored Normal file
View File

@ -0,0 +1,48 @@
// +build ignore
package F1
import "sync"
func example(n int) {
var x struct {
mutex sync.RWMutex
}
var y struct {
sync.RWMutex
}
type l struct {
sync.RWMutex
}
var z struct {
l
}
var a struct {
*l
}
var b struct{ Lock func() }
// Match
x.mutex.RLock()
// Match
y.RLock()
// Match indirect
z.RLock()
// Should be no match however currently matches due to:
// https://code.google.com/p/go/issues/detail?id=8584
// Will start failing when this is fixed then just change golden to
// No match pointer indirect
// a.Lock()
a.RLock()
// No match
b.Lock()
}