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:
parent
ab43333964
commit
fb44a24d4c
@ -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",
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user