2
0
mirror of synced 2025-02-23 14:58:12 +00:00

mobile/bind: implement interfaces from imported bound packages

Java classes must explicitly declare implemented interfaces. Bind
already declares all such interfaces within each package. Expand
the set of interfaces to include all bound packages.

In addition, let Java interfaces extend all possible interfaces in
the same way as Java classes. To avoid circular references, only
let interfaces extend compatible interfaces with fewer methods.

Before, each package was imported in its own importer, breaking the
assumption of types.AssignableTo that identical packages have
identical *types.Package. Fix that by using one importer for all
bound packages, replacing package path equality checks with direct
equality checks.

While we're here, add missing arguments to a few error messages.

Change-Id: I5eb58972a3abe918862ca99d5a203809699a3433
Reviewed-on: https://go-review.googlesource.com/20987
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
Elias Naur 2016-03-21 20:22:15 +01:00
parent e8a257577d
commit 5b96314b59
16 changed files with 359 additions and 10 deletions

View File

@ -67,6 +67,8 @@ type generator struct {
interfaces []interfaceInfo
structs []structInfo
otherNames []*types.TypeName
// allIntf contains interfaces from all bound packages.
allIntf []interfaceInfo
}
// pkgPrefix returns a prefix that disambiguates symbol names for binding
@ -117,6 +119,21 @@ func (g *generator) init() {
if !hasExported {
g.errorf("no exported names in the package %q", g.pkg.Path())
}
for _, p := range g.allPkg {
scope := p.Scope()
for _, name := range scope.Names() {
obj := scope.Lookup(name)
if !obj.Exported() {
continue
}
if obj, ok := obj.(*types.TypeName); ok {
named := obj.Type().(*types.Named)
if t, ok := named.Underlying().(*types.Interface); ok {
g.allIntf = append(g.allIntf, interfaceInfo{obj, t, makeIfaceSummary(t)})
}
}
}
}
}
func (_ *generator) toCFlag(v bool) int {
@ -227,7 +244,7 @@ func (g *generator) genInterfaceMethodSignature(m *types.Func, iName string, hea
func (g *generator) validPkg(pkg *types.Package) bool {
for _, p := range g.allPkg {
if p.Path() == pkg.Path() {
if p == pkg {
return true
}
}

View File

@ -29,9 +29,13 @@ func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) {
impls := []string{"go.Seq.Object"}
pT := types.NewPointer(obj.Type())
for _, iface := range g.interfaces {
for _, iface := range g.allIntf {
if types.AssignableTo(pT, iface.obj.Type()) {
impls = append(impls, iface.obj.Name())
n := iface.obj.Name()
if p := iface.obj.Pkg(); p != g.pkg {
n = fmt.Sprintf("%s.%s.%s", g.javaPkgName(p), className(p), n)
}
impls = append(impls, n)
}
}
g.Printf("public static final class %s implements %s {\n", obj.Name(), strings.Join(impls, ", "))
@ -45,7 +49,7 @@ func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) {
for _, f := range fields {
if t := f.Type(); !g.isSupported(t) {
g.Printf("// skipped field %s.%s with unsupported type: %T\n\n", f.Name(), t)
g.Printf("// skipped field %s.%s with unsupported type: %T\n\n", n, f.Name(), t)
continue
}
g.Printf("public final native %s get%s();\n", g.javaType(f.Type()), f.Name())
@ -70,7 +74,7 @@ func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) {
g.Printf("%s that = (%s)o;\n", n, n)
for _, f := range fields {
if t := f.Type(); !g.isSupported(t) {
g.Printf("// skipped field %s.%s with unsupported type: %T\n\n", f.Name(), t)
g.Printf("// skipped field %s.%s with unsupported type: %T\n\n", n, f.Name(), t)
continue
}
nf := f.Name()
@ -145,7 +149,19 @@ func (g *javaGen) genInterfaceStub(o *types.TypeName, m *types.Interface) {
}
func (g *javaGen) genInterface(iface interfaceInfo) {
g.Printf("public interface %s extends go.Seq.Object {\n", iface.obj.Name())
exts := []string{"go.Seq.Object"}
numM := iface.t.NumMethods()
for _, other := range g.allIntf {
// Only extend interfaces with fewer methods to avoid circular references
if other.t.NumMethods() < numM && types.AssignableTo(iface.t, other.t) {
n := other.obj.Name()
if p := other.obj.Pkg(); p != g.pkg {
n = fmt.Sprintf("%s.%s.%s", g.javaPkgName(p), className(p), n)
}
exts = append(exts, n)
}
}
g.Printf("public interface %s extends %s {\n", iface.obj.Name(), strings.Join(exts, ", "))
g.Indent()
methodSigErr := false

View File

@ -496,6 +496,10 @@ public class SeqTest extends InstrumentationTestCase {
fields.setS(s);
Testpkg.WithImportedI(i);
Testpkg.WithImportedS(s);
Secondpkg.IF f = new AnI();
f = Testpkg.New();
Secondpkg.Ser ser = Testpkg.NewSer();
}
public void testIDup() {

View File

@ -26,7 +26,7 @@ public abstract class Ignore {
public final go.Seq.Ref ref() { return ref; }
// skipped field F.interface{} with unsupported type: %!T(MISSING)
// skipped field S.F with unsupported type: *types.Interface
// skipped method S.Argument with unsupported parameter or return types
@ -37,7 +37,7 @@ public abstract class Ignore {
return false;
}
S that = (S)o;
// skipped field F.interface{} with unsupported type: %!T(MISSING)
// skipped field S.F with unsupported type: *types.Interface
return true;
}

View File

@ -8,6 +8,15 @@ type I interface {
Rand() int32
}
type SameI interface {
Rand() int32
}
type LargerI interface {
Rand() int32
AnotherFunc()
}
func Add3(r I) int32 {
return r.Rand() + r.Rand() + r.Rand()
}

View File

@ -108,6 +108,55 @@ func (p *proxyinterfaces_I3) F() interfaces.I1 {
return _res
}
//export proxyinterfaces_LargerI_AnotherFunc
func proxyinterfaces_LargerI_AnotherFunc(refnum C.int32_t) {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(interfaces.LargerI)
v.AnotherFunc()
}
//export proxyinterfaces_LargerI_Rand
func proxyinterfaces_LargerI_Rand(refnum C.int32_t) C.int32_t {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(interfaces.LargerI)
res_0 := v.Rand()
_res_0 := C.int32_t(res_0)
return _res_0
}
type proxyinterfaces_LargerI _seq.Ref
func (p *proxyinterfaces_LargerI) Bind_proxy_refnum__() int32 { return p.Bind_Num }
func (p *proxyinterfaces_LargerI) AnotherFunc() {
C.cproxyinterfaces_LargerI_AnotherFunc(C.int32_t(p.Bind_Num))
}
func (p *proxyinterfaces_LargerI) Rand() int32 {
res := C.cproxyinterfaces_LargerI_Rand(C.int32_t(p.Bind_Num))
_res := int32(res)
return _res
}
//export proxyinterfaces_SameI_Rand
func proxyinterfaces_SameI_Rand(refnum C.int32_t) C.int32_t {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(interfaces.SameI)
res_0 := v.Rand()
_res_0 := C.int32_t(res_0)
return _res_0
}
type proxyinterfaces_SameI _seq.Ref
func (p *proxyinterfaces_SameI) Bind_proxy_refnum__() int32 { return p.Bind_Num }
func (p *proxyinterfaces_SameI) Rand() int32 {
res := C.cproxyinterfaces_SameI_Rand(C.int32_t(p.Bind_Num))
_res := int32(res)
return _res
}
//export proxyinterfaces_WithParam_HasParam
func proxyinterfaces_WithParam_HasParam(refnum C.int32_t, param_p0 C.char) {
ref := _seq.FromRefNum(int32(refnum))

View File

@ -24,6 +24,13 @@ static jmethodID mid_I2_G;
jclass proxy_class_interfaces_I3;
jmethodID proxy_class_interfaces_I3_cons;
static jmethodID mid_I3_F;
jclass proxy_class_interfaces_LargerI;
jmethodID proxy_class_interfaces_LargerI_cons;
static jmethodID mid_LargerI_AnotherFunc;
static jmethodID mid_LargerI_Rand;
jclass proxy_class_interfaces_SameI;
jmethodID proxy_class_interfaces_SameI_cons;
static jmethodID mid_SameI_Rand;
jclass proxy_class_interfaces_WithParam;
jmethodID proxy_class_interfaces_WithParam_cons;
static jmethodID mid_WithParam_HasParam;
@ -61,6 +68,19 @@ Java_go_interfaces_Interfaces_init(JNIEnv *env, jclass _unused) {
clazz = (*env)->FindClass(env, "go/interfaces/Interfaces$I3");
mid_I3_F = (*env)->GetMethodID(env, clazz, "F", "()Lgo/interfaces/Interfaces$I1;");
clazz = (*env)->FindClass(env, "go/interfaces/Interfaces$LargerI$Proxy");
proxy_class_interfaces_LargerI = (*env)->NewGlobalRef(env, clazz);
proxy_class_interfaces_LargerI_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
clazz = (*env)->FindClass(env, "go/interfaces/Interfaces$LargerI");
mid_LargerI_AnotherFunc = (*env)->GetMethodID(env, clazz, "AnotherFunc", "()V");
mid_LargerI_Rand = (*env)->GetMethodID(env, clazz, "Rand", "()I");
clazz = (*env)->FindClass(env, "go/interfaces/Interfaces$SameI$Proxy");
proxy_class_interfaces_SameI = (*env)->NewGlobalRef(env, clazz);
proxy_class_interfaces_SameI_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
clazz = (*env)->FindClass(env, "go/interfaces/Interfaces$SameI");
mid_SameI_Rand = (*env)->GetMethodID(env, clazz, "Rand", "()I");
clazz = (*env)->FindClass(env, "go/interfaces/Interfaces$WithParam$Proxy");
proxy_class_interfaces_WithParam = (*env)->NewGlobalRef(env, clazz);
proxy_class_interfaces_WithParam_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
@ -170,6 +190,53 @@ int32_t cproxyinterfaces_I3_F(int32_t refnum) {
return _res;
}
JNIEXPORT void JNICALL
Java_go_interfaces_Interfaces_00024LargerI_00024Proxy_AnotherFunc(JNIEnv* env, jobject this) {
int32_t o = go_seq_to_refnum(env, this);
proxyinterfaces_LargerI_AnotherFunc(o);
}
void cproxyinterfaces_LargerI_AnotherFunc(int32_t refnum) {
JNIEnv *env = go_seq_push_local_frame(10);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_LargerI, proxy_class_interfaces_LargerI_cons);
(*env)->CallVoidMethod(env, o, mid_LargerI_AnotherFunc);
go_seq_pop_local_frame(env);
}
JNIEXPORT jint JNICALL
Java_go_interfaces_Interfaces_00024LargerI_00024Proxy_Rand(JNIEnv* env, jobject this) {
int32_t o = go_seq_to_refnum(env, this);
int32_t r0 = proxyinterfaces_LargerI_Rand(o);
jint _r0 = (jint)r0;
return _r0;
}
int32_t cproxyinterfaces_LargerI_Rand(int32_t refnum) {
JNIEnv *env = go_seq_push_local_frame(10);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_LargerI, proxy_class_interfaces_LargerI_cons);
jint res = (*env)->CallIntMethod(env, o, mid_LargerI_Rand);
int32_t _res = (int32_t)res;
go_seq_pop_local_frame(env);
return _res;
}
JNIEXPORT jint JNICALL
Java_go_interfaces_Interfaces_00024SameI_00024Proxy_Rand(JNIEnv* env, jobject this) {
int32_t o = go_seq_to_refnum(env, this);
int32_t r0 = proxyinterfaces_SameI_Rand(o);
jint _r0 = (jint)r0;
return _r0;
}
int32_t cproxyinterfaces_SameI_Rand(int32_t refnum) {
JNIEnv *env = go_seq_push_local_frame(10);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_SameI, proxy_class_interfaces_SameI_cons);
jint res = (*env)->CallIntMethod(env, o, mid_SameI_Rand);
int32_t _res = (int32_t)res;
go_seq_pop_local_frame(env);
return _res;
}
JNIEXPORT void JNICALL
Java_go_interfaces_Interfaces_00024WithParam_00024Proxy_HasParam(JNIEnv* env, jobject this, jboolean p0) {
int32_t o = go_seq_to_refnum(env, this);

View File

@ -114,6 +114,54 @@ public abstract class Interfaces {
}
}
public interface LargerI extends go.Seq.Object, I, SameI {
public void AnotherFunc();
public int Rand();
public static abstract class Stub implements LargerI {
private final go.Seq.Ref ref;
public Stub() {
ref = go.Seq.createRef(this);
}
public final go.Seq.Ref ref() { return ref; }
}
static final class Proxy implements LargerI {
private go.Seq.Ref ref;
Proxy(go.Seq.Ref ref) { this.ref = ref; }
public final go.Seq.Ref ref() { return ref; }
public native void AnotherFunc();
public native int Rand();
}
}
public interface SameI extends go.Seq.Object {
public int Rand();
public static abstract class Stub implements SameI {
private final go.Seq.Ref ref;
public Stub() {
ref = go.Seq.createRef(this);
}
public final go.Seq.Ref ref() { return ref; }
}
static final class Proxy implements SameI {
private go.Seq.Ref ref;
Proxy(go.Seq.Ref ref) { this.ref = ref; }
public final go.Seq.Ref ref() { return ref; }
public native int Rand();
}
}
public interface WithParam extends go.Seq.Object {
public void HasParam(boolean p0);
public static abstract class Stub implements WithParam {

View File

@ -33,6 +33,18 @@ extern jmethodID proxy_class_interfaces_I3_cons;
int32_t cproxyinterfaces_I3_F(int32_t refnum);
extern jclass proxy_class_interfaces_LargerI;
extern jmethodID proxy_class_interfaces_LargerI_cons;
void cproxyinterfaces_LargerI_AnotherFunc(int32_t refnum);
int32_t cproxyinterfaces_LargerI_Rand(int32_t refnum);
extern jclass proxy_class_interfaces_SameI;
extern jmethodID proxy_class_interfaces_SameI_cons;
int32_t cproxyinterfaces_SameI_Rand(int32_t refnum);
extern jclass proxy_class_interfaces_WithParam;
extern jmethodID proxy_class_interfaces_WithParam_cons;

View File

@ -14,6 +14,12 @@ int32_t cproxyinterfaces_I_Rand(int32_t refnum);
int32_t cproxyinterfaces_I3_F(int32_t refnum);
void cproxyinterfaces_LargerI_AnotherFunc(int32_t refnum);
int32_t cproxyinterfaces_LargerI_Rand(int32_t refnum);
int32_t cproxyinterfaces_SameI_Rand(int32_t refnum);
void cproxyinterfaces_WithParam_HasParam(int32_t refnum, char p0);
#endif

View File

@ -16,6 +16,10 @@
@protocol GoInterfacesI2;
@protocol GoInterfacesI3;
@class GoInterfacesI3;
@protocol GoInterfacesLargerI;
@class GoInterfacesLargerI;
@protocol GoInterfacesSameI;
@class GoInterfacesSameI;
@protocol GoInterfacesWithParam;
@class GoInterfacesWithParam;
@ -47,6 +51,15 @@
- (GoInterfacesI1*)f;
@end
@protocol GoInterfacesLargerI
- (void)anotherFunc;
- (int32_t)rand;
@end
@protocol GoInterfacesSameI
- (int32_t)rand;
@end
@protocol GoInterfacesWithParam
- (void)hasParam:(BOOL)p0;
@end
@ -63,6 +76,10 @@ FOUNDATION_EXPORT id<GoInterfacesI> GoInterfacesSeven();
@class GoInterfacesI3;
@class GoInterfacesLargerI;
@class GoInterfacesSameI;
@class GoInterfacesWithParam;
@interface GoInterfacesError : NSObject <GoInterfacesError> {
@ -89,6 +106,23 @@ FOUNDATION_EXPORT id<GoInterfacesI> GoInterfacesSeven();
- (GoInterfacesI1*)f;
@end
@interface GoInterfacesLargerI : NSObject <GoInterfacesLargerI> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (void)anotherFunc;
- (int32_t)rand;
@end
@interface GoInterfacesSameI : NSObject <GoInterfacesSameI> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (int32_t)rand;
@end
@interface GoInterfacesWithParam : NSObject <GoInterfacesWithParam> {
}
@property(strong, readonly) id _ref;

View File

@ -113,6 +113,49 @@ static NSString* errDomain = @"go.interfaces";
@end
@implementation GoInterfacesLargerI {
}
- (id)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (void)anotherFunc {
int32_t refnum = go_seq_go_to_refnum(self._ref);
proxyinterfaces_LargerI_AnotherFunc(refnum);
}
- (int32_t)rand {
int32_t refnum = go_seq_go_to_refnum(self._ref);
int32_t r0 = proxyinterfaces_LargerI_Rand(refnum);
int32_t _ret0_ = (int32_t)r0;
return _ret0_;
}
@end
@implementation GoInterfacesSameI {
}
- (id)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (int32_t)rand {
int32_t refnum = go_seq_go_to_refnum(self._ref);
int32_t r0 = proxyinterfaces_SameI_Rand(refnum);
int32_t _ret0_ = (int32_t)r0;
return _ret0_;
}
@end
@implementation GoInterfacesWithParam {
}
@ -231,6 +274,31 @@ int32_t cproxyinterfaces_I3_F(int32_t refnum) {
}
}
void cproxyinterfaces_LargerI_AnotherFunc(int32_t refnum) {
@autoreleasepool {
id<GoInterfacesLargerI> o = go_seq_objc_from_refnum(refnum);
[o anotherFunc];
}
}
int32_t cproxyinterfaces_LargerI_Rand(int32_t refnum) {
@autoreleasepool {
id<GoInterfacesLargerI> o = go_seq_objc_from_refnum(refnum);
int32_t returnVal = [o rand];
int32_t _returnVal = (int32_t)returnVal;
return _returnVal;
}
}
int32_t cproxyinterfaces_SameI_Rand(int32_t refnum) {
@autoreleasepool {
id<GoInterfacesSameI> o = go_seq_objc_from_refnum(refnum);
int32_t returnVal = [o rand];
int32_t _returnVal = (int32_t)returnVal;
return _returnVal;
}
}
void cproxyinterfaces_WithParam_HasParam(int32_t refnum, char p0) {
@autoreleasepool {
id<GoInterfacesWithParam> o = go_seq_objc_from_refnum(refnum);

View File

@ -7,6 +7,14 @@
package secondpkg
type (
Ser interface {
S(_ *S)
}
IF interface {
F()
}
I interface {
F(i int) int
}

View File

@ -442,8 +442,13 @@ type (
ImportedI interface {
F(_ secondpkg.I)
}
AnSer struct{}
)
func (_ *AnSer) S(_ *secondpkg.S) {
}
func NewImportedFields() *ImportedFields {
return &ImportedFields{
I: NewImportedI(),
@ -471,6 +476,10 @@ func CallImportedI(i secondpkg.I) {
i.F(0)
}
func NewSer() *AnSer {
return nil
}
func NewSimpleS() *simplepkg.S {
return nil
}

View File

@ -48,8 +48,9 @@ func main() {
}
var allPkg []*types.Package
imp := importer.Default()
for _, arg := range flag.Args() {
pkg, err := importer.Default().Import(arg)
pkg, err := imp.Import(arg)
if err != nil {
fmt.Fprintf(os.Stderr, "could not import package %s: %v", arg, err)
os.Exit(1)

View File

@ -380,6 +380,7 @@ func loadExportData(pkgs []*build.Package, env []string, args ...string) ([]*typ
return nil, err
}
typePkgs := make([]*types.Package, len(pkgs))
imp := importer.Default()
for i, p := range pkgs {
importPath := p.ImportPath
src := filepath.Join(pkgdir(env), importPath+".a")
@ -395,7 +396,7 @@ func loadExportData(pkgs []*build.Package, env []string, args ...string) ([]*typ
build.Default = ctx // copy
build.Default.GOARCH = goarch
build.Default.GOPATH = fakegopath
p, err := importer.Default().Import(importPath)
p, err := imp.Import(importPath)
build.Default = oldDefault
if err != nil {
return nil, err