refactor/rename: fix spurious conflict report when renaming x/foo to y/foo

There is no need to check for import conflicts when the package name
doesn't change.  Add test.

Also, when reporting a (non-spurious) import conflict, make clear that
the error is just a warning.  Add a test for same.

Change-Id: Idde0483b502cd041fd893230fec06b8533f54f3c
Reviewed-on: https://go-review.googlesource.com/24917
Reviewed-by: Michael Matloob <matloob@golang.org>
diff --git a/refactor/rename/mvpkg_test.go b/refactor/rename/mvpkg_test.go
index e07b6b4..9476c17 100644
--- a/refactor/rename/mvpkg_test.go
+++ b/refactor/rename/mvpkg_test.go
@@ -7,8 +7,10 @@
 import (
 	"fmt"
 	"go/build"
+	"go/token"
 	"io/ioutil"
 	"path/filepath"
+	"reflect"
 	"regexp"
 	"strings"
 	"testing"
@@ -112,9 +114,10 @@
 
 func TestMoves(t *testing.T) {
 	tests := []struct {
-		ctxt     *build.Context
-		from, to string
-		want     map[string]string
+		ctxt         *build.Context
+		from, to     string
+		want         map[string]string
+		wantWarnings []string
 	}{
 		// Simple example.
 		{
@@ -267,6 +270,77 @@
 /* import " this is not an import comment */
 `},
 		},
+		// Import name conflict generates a warning, not an error.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"x": {},
+				"a": {`package a; type A int`},
+				"b": {`package b; type B int`},
+				"conflict": {`package conflict
+
+import "a"
+import "b"
+var _ a.A
+var _ b.B
+`},
+				"ok": {`package ok
+import "b"
+var _ b.B
+`},
+			}),
+			from: "b", to: "x/a",
+			want: map[string]string{
+				"/go/src/a/0.go": `package a; type A int`,
+				"/go/src/ok/0.go": `package ok
+
+import "x/a"
+
+var _ a.B
+`,
+				"/go/src/conflict/0.go": `package conflict
+
+import "a"
+import "x/a"
+
+var _ a.A
+var _ b.B
+`,
+				"/go/src/x/a/0.go": `package a
+
+type B int
+`,
+			},
+			wantWarnings: []string{
+				`/go/src/conflict/0.go:4:8: renaming this imported package name "b" to "a"`,
+				`/go/src/conflict/0.go:3:8: 	conflicts with imported package name in same block`,
+				`/go/src/conflict/0.go:3:8: skipping update of this file`,
+			},
+		},
+		// Rename with same base name.
+		{
+			ctxt: fakeContext(map[string][]string{
+				"x": {},
+				"y": {},
+				"x/foo": {`package foo
+
+type T int
+`},
+				"main": {`package main; import "x/foo"; var _ foo.T`},
+			}),
+			from: "x/foo", to: "y/foo",
+			want: map[string]string{
+				"/go/src/y/foo/0.go": `package foo
+
+type T int
+`,
+				"/go/src/main/0.go": `package main
+
+import "y/foo"
+
+var _ foo.T
+`,
+			},
+		},
 	}
 
 	for _, test := range tests {
@@ -296,6 +370,10 @@
 			}
 			got[path] = string(bytes)
 		})
+		var warnings []string
+		reportError = func(posn token.Position, message string) {
+			warnings = append(warnings, posn.String()+": "+message)
+		}
 		writeFile = func(filename string, content []byte) error {
 			got[filename] = string(content)
 			return nil
@@ -318,6 +396,13 @@
 			continue
 		}
 
+		if !reflect.DeepEqual(warnings, test.wantWarnings) {
+			t.Errorf("%s: unexpected warnings:\n%s\nwant:\n%s",
+				prefix,
+				strings.Join(warnings, "\n"),
+				strings.Join(test.wantWarnings, "\n"))
+		}
+
 		for file, wantContent := range test.want {
 			k := filepath.FromSlash(file)
 			gotContent, ok := got[k]
diff --git a/refactor/rename/rename.go b/refactor/rename/rename.go
index be47701..766bbc2 100644
--- a/refactor/rename/rename.go
+++ b/refactor/rename/rename.go
@@ -174,11 +174,13 @@
 	fmt.Fprintf(os.Stderr, "%s: %s\n", posn, message)
 }
 
-// importName renames imports of the package with the given path in
-// the given package.  If fromName is not empty, only imports as
-// fromName will be renamed.  If the renaming would lead to a conflict,
-// the file is left unchanged.
+// importName renames imports of fromPath within the package specified by info.
+// If fromName is not empty, importName renames only imports as fromName.
+// If the renaming would lead to a conflict, the file is left unchanged.
 func importName(iprog *loader.Program, info *loader.PackageInfo, fromPath, fromName, to string) error {
+	if fromName == to {
+		return nil // no-op (e.g. rename x/foo to y/foo)
+	}
 	for _, f := range info.Files {
 		var from types.Object
 		for _, imp := range f.Imports {
@@ -203,6 +205,8 @@
 		}
 		r.check(from)
 		if r.hadConflicts {
+			reportError(iprog.Fset.Position(f.Imports[0].Pos()),
+				"skipping update of this file")
 			continue // ignore errors; leave the existing name
 		}
 		if err := r.update(); err != nil {