From e7d14dfe5b9e4ef4f0e4844492d1db499e8c9f5f Mon Sep 17 00:00:00 2001 From: "David R. Jenni" Date: Sun, 9 Aug 2015 19:07:02 +0200 Subject: [PATCH] refactor/rename: fix crash when renaming type embedded in another package. Fixes golang/go#12038. Change-Id: I9026edef7f8769b451f2b1502c107d6b2bb45096 Reviewed-on: https://go-review.googlesource.com/13451 Reviewed-by: Alan Donovan --- refactor/rename/rename_test.go | 51 ++++++++++++++++++++++++++++++++++ refactor/rename/spec.go | 9 ++++++ 2 files changed, 60 insertions(+) diff --git a/refactor/rename/rename_test.go b/refactor/rename/rename_test.go index 778fa78b..92959a96 100644 --- a/refactor/rename/rename_test.go +++ b/refactor/rename/rename_test.go @@ -720,6 +720,57 @@ type _ struct{ *foo.U } }, }, + // Renaming of embedded field that is a qualified reference with the '-from' flag. + // (Regression test for bug 12038.) + { + ctxt: fakeContext(map[string][]string{ + "foo": {`package foo; type T int`}, + "main": {`package main + +import "foo" + +type V struct{ *foo.T } +`}, + }), + from: "(main.V).T", 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 V struct{ *foo.U } +`, + }, + }, + { + ctxt: fakeContext(map[string][]string{ + "foo": {`package foo; type T int`}, + "main": {`package main + +import "foo" + +type V struct{ foo.T } +`}, + }), + from: "(main.V).T", 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 V struct{ foo.U } +`, + }, + }, + // Interface method renaming. { ctxt: fakeContext(map[string][]string{ diff --git a/refactor/rename/spec.go b/refactor/rename/spec.go index f37c3280..6e70e3f6 100644 --- a/refactor/rename/spec.go +++ b/refactor/rename/spec.go @@ -452,6 +452,15 @@ func findObjects(info *loader.PackageInfo, spec *spec) ([]types.Object, error) { } if spec.searchFor == "" { + // If it is an embedded field, return the type of the field. + if v, ok := obj.(*types.Var); ok && v.Anonymous() { + switch t := v.Type().(type) { + case *types.Pointer: + return []types.Object{t.Elem().(*types.Named).Obj()}, nil + case *types.Named: + return []types.Object{t.Obj()}, nil + } + } return []types.Object{obj}, nil }