2
0
mirror of synced 2025-02-24 07:18:15 +00:00

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>
This commit is contained in:
Elias Naur 2016-12-31 16:33:26 +01:00
parent fa10d8888b
commit f5d8ba6777
2 changed files with 52 additions and 6 deletions

View File

@ -13,7 +13,22 @@ import (
type goGen struct { type goGen struct {
*Generator *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 ( const (
@ -497,15 +512,16 @@ func (g *goGen) genPreamble() {
g.Printf("import (\n") g.Printf("import (\n")
g.Indent() g.Indent()
g.Printf("_seq \"golang.org/x/mobile/bind/seq\"\n") g.Printf("_seq \"golang.org/x/mobile/bind/seq\"\n")
for path := range g.imports { for _, imp := range g.imports {
g.Printf("%q\n", path) g.Printf("%s\n", imp)
} }
g.Outdent() g.Outdent()
g.Printf(")\n\n") g.Printf(")\n\n")
} }
func (g *goGen) gen() error { 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 // Switch to a temporary buffer so the preamble can be
// written last. // written last.
@ -545,6 +561,28 @@ func (g *goGen) pkgName(pkg *types.Package) string {
if pkg == nil { if pkg == nil {
return "" return ""
} }
g.imports[pkg.Path()] = struct{}{} if name, exists := g.importMap[pkg]; exists {
return pkg.Name() + "." 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 + "."
} }

View File

@ -15,8 +15,10 @@ import (
"Java/java/lang/Integer" "Java/java/lang/Integer"
"Java/java/lang/Object" "Java/java/lang/Object"
"Java/java/lang/Runnable" "Java/java/lang/Runnable"
"Java/java/net"
"Java/java/util" "Java/java/util"
"Java/java/util/concurrent" "Java/java/util/concurrent"
xnet "Java/javax/net"
) )
const ( const (
@ -189,3 +191,9 @@ func CastRunnable(o lang.Object) lang.Runnable {
r.Run() r.Run()
return r 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) {
}