1
0
mirror of https://github.com/golang/go synced 2024-11-18 09:04:49 -07:00

refactor/rename: fix crash when renaming anonymous struct field that's a qualified reference

(or a pointer, or both).

+ test

Fixes bug 8924

LGTM=sameer
R=dominik.honnef, sameer
CC=<dominik.honnef, golang-codereviews
https://golang.org/cl/158920043
This commit is contained in:
Alan Donovan 2014-11-10 16:03:40 -05:00
parent ab43333964
commit fb44a24d4c
2 changed files with 41 additions and 3 deletions

View File

@ -293,10 +293,21 @@ func (r *renamer) checkStructField(from *types.Var) {
// method) to its declaring struct (or interface), so we must
// ascend the AST.
info, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos())
// path is [Ident Field FieldList StructType ... File]. Can't fail.
// path matches this pattern:
// [Ident SelectorExpr? StarExpr? Field FieldList StructType ParenExpr* ... File]
// Ascend to FieldList.
var i int
for {
if _, ok := path[i].(*ast.FieldList); ok {
break
}
i++
}
i++
tStruct := path[i].(*ast.StructType)
i++
// Ascend past parens (unlikely).
i := 4
for {
_, ok := path[i].(*ast.ParenExpr)
if !ok {
@ -320,7 +331,7 @@ func (r *renamer) checkStructField(from *types.Var) {
} else {
// This struct is not a named type.
// We need only check for direct (non-promoted) field/field conflicts.
T := info.Types[path[3].(*ast.StructType)].Type.Underlying().(*types.Struct)
T := info.Types[tStruct].Type.Underlying().(*types.Struct)
for i := 0; i < T.NumFields(); i++ {
if prev := T.Field(i); prev.Name() == r.to {
r.errorf(from.Pos(), "renaming this field %q to %q",

View File

@ -648,6 +648,33 @@ func f(z interface{}) {
}
`},
},
// Renaming of embedded field that is a qualified reference.
// (Regression test for bug 8924.)
{
ctxt: fakeContext(map[string][]string{
"foo": {`package foo; type T int`},
"main": {`package main
import "foo"
type _ struct{ *foo.T }
`},
}),
offset: "/go/src/main/0.go:#48", to: "U", // the "T" in *foo.T
want: map[string]string{
"/go/src/foo/0.go": `package foo
type U int
`,
"/go/src/main/0.go": `package main
import "foo"
type _ struct{ *foo.U }
`,
},
},
} {
if test.ctxt != nil {
ctxt = test.ctxt