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) {
+}