bind: support Java packages with the same last component

Before this CL, using the reverse bindings to access two Java packages
with the same last component would fail with a duplicate package import
error. This CL renames generated import statements to use unique
aliases.

Change-Id: I94696281e58f011f45811445cf81aea02af69c4f
Reviewed-on: https://go-review.googlesource.com/34774
Reviewed-by: David Crawshaw <crawshaw@golang.org>
diff --git a/bind/gengo.go b/bind/gengo.go
index f86f6c6..c56d3e3 100644
--- a/bind/gengo.go
+++ b/bind/gengo.go
@@ -13,7 +13,22 @@
 
 type goGen struct {
 	*Generator
-	imports map[string]struct{}
+
+	// imports is the list of imports, in the form
+	// "the/package/path"
+	//
+	// or
+	//
+	// name "the/package/path"
+	//
+	// in case of duplicates.
+	imports []string
+	// The set of taken import names.
+	importNames map[string]struct{}
+	// importMap is a map from packages to their names. The name of a package is the last
+	// segment of its path, with duplicates resolved by appending a underscore and a unique
+	// number.
+	importMap map[*types.Package]string
 }
 
 const (
@@ -497,15 +512,16 @@
 	g.Printf("import (\n")
 	g.Indent()
 	g.Printf("_seq \"golang.org/x/mobile/bind/seq\"\n")
-	for path := range g.imports {
-		g.Printf("%q\n", path)
+	for _, imp := range g.imports {
+		g.Printf("%s\n", imp)
 	}
 	g.Outdent()
 	g.Printf(")\n\n")
 }
 
 func (g *goGen) gen() error {
-	g.imports = make(map[string]struct{})
+	g.importNames = make(map[string]struct{})
+	g.importMap = make(map[*types.Package]string)
 
 	// Switch to a temporary buffer so the preamble can be
 	// written last.
@@ -545,6 +561,28 @@
 	if pkg == nil {
 		return ""
 	}
-	g.imports[pkg.Path()] = struct{}{}
-	return pkg.Name() + "."
+	if name, exists := g.importMap[pkg]; exists {
+		return name + "."
+	}
+	i := 0
+	pname := pkg.Name()
+	name := pkg.Name()
+	for {
+		if _, exists := g.importNames[name]; !exists {
+			g.importNames[name] = struct{}{}
+			g.importMap[pkg] = name
+			var imp string
+			if pname != name {
+				imp = fmt.Sprintf("%s %q", name, pkg.Path())
+			} else {
+				imp = fmt.Sprintf("%q", pkg.Path())
+			}
+			g.imports = append(g.imports, imp)
+			break
+		}
+		i++
+		name = fmt.Sprintf("%s_%d", pname, i)
+	}
+	g.importMap[pkg] = name
+	return name + "."
 }
diff --git a/bind/testpkg/javapkg/classes.go b/bind/testpkg/javapkg/classes.go
index a2ac93a..7043c5f 100644
--- a/bind/testpkg/javapkg/classes.go
+++ b/bind/testpkg/javapkg/classes.go
@@ -15,8 +15,10 @@
 	"Java/java/lang/Integer"
 	"Java/java/lang/Object"
 	"Java/java/lang/Runnable"
+	"Java/java/net"
 	"Java/java/util"
 	"Java/java/util/concurrent"
+	xnet "Java/javax/net"
 )
 
 const (
@@ -189,3 +191,9 @@
 	r.Run()
 	return r
 }
+
+// Test that extending classes from Java packages
+// with the same last component (in this case "net")
+// works.
+func NameClashingPackages(_ net.Socket, _ xnet.SocketFactory) {
+}