bind: allow implicit `this` argument on every exported method
Before this CL, the implicit `this` arguments to methods on Java classes
implemented in Go was only supported on overriding methods, because
their parameter count are known. This CL expands support for the `this`
parameter to every exported method. It only recognizes parameters named
`this` declared with a Java wrapper type.
Change-Id: I8a9d3417d259bdfcc28512a72f07d6a05f483adc
Reviewed-on: https://go-review.googlesource.com/30276
Reviewed-by: David Crawshaw <crawshaw@golang.org>
diff --git a/bind/genjava.go b/bind/genjava.go
index dadcf8a..3fb71e0 100644
--- a/bind/genjava.go
+++ b/bind/genjava.go
@@ -214,46 +214,40 @@
continue
}
var jm *java.Func
+ hasThis := false
if jinf != nil {
jm = jinf.methods[m.Name()]
if jm != nil {
- // Check the implicit this argument, if any
- sig := m.Type().(*types.Signature)
- params := sig.Params()
- excess := params.Len() - len(jm.Params)
- switch {
- case excess < 0:
- g.errorf("method %s.%s has fewer arguments than the method it overrides", n, m.Name())
- continue
- case excess > 1:
- g.errorf("overriding method %s.%s has more arguments than the method it overrides", n, m.Name())
- continue
- case excess == 1:
- v := params.At(0)
+ g.Printf("@Override ")
+ }
+ // Check the implicit this argument, if any
+ sig := m.Type().(*types.Signature)
+ params := sig.Params()
+ if params.Len() > 0 {
+ v := params.At(0)
+ if v.Name() == "this" {
t := v.Type()
- if !isJavaType(t) {
- g.errorf("the `this` argument to method %s.%s is not a Java type", n, m.Name())
- continue
- }
- clsName := classNameFor(t)
- cls := g.clsMap[clsName]
- found := false
- for _, sup := range jinf.supers {
- if cls == sup {
- found = true
- break
+ if isJavaType(t) {
+ clsName := classNameFor(t)
+ cls := g.clsMap[clsName]
+ found := false
+ for _, sup := range jinf.supers {
+ if cls == sup {
+ found = true
+ break
+ }
}
- }
- if !found {
- g.errorf("the type %s of the `this` argument to method %s.%s is not a super class to %s", cls.Name, n, m.Name(), n)
- continue
+ if !found {
+ g.errorf("the type %s of the `this` argument to method %s.%s is not a super class to %s", cls.Name, n, m.Name(), n)
+ continue
+ }
+ hasThis = true
}
}
- g.Printf("@Override ")
}
}
g.Printf("public native ")
- g.genFuncSignature(m, jm)
+ g.genFuncSignature(m, jm, hasThis)
t := m.Type().(*types.Signature)
isStringer = isStringer || (m.Name() == "String" && t.Params().Len() == 0 && t.Results().Len() == 1 &&
types.Identical(t.Results().At(0).Type(), types.Typ[types.String]))
@@ -269,7 +263,7 @@
func (g *JavaGen) genConstructor(f *types.Func, n string, jcls bool) {
g.Printf("public %s(", n)
- g.genFuncArgs(f, nil)
+ g.genFuncArgs(f, nil, false)
g.Printf(") {\n")
g.Indent()
sig := f.Type().(*types.Signature)
@@ -296,20 +290,20 @@
g.Outdent()
g.Printf("}\n\n")
g.Printf("private static native Seq.Ref __%s(", f.Name())
- g.genFuncArgs(f, nil)
+ g.genFuncArgs(f, nil, false)
g.Printf(");\n\n")
}
// genFuncArgs generated Java function arguments declaration for the function f.
// If the supplied overridden java function is supplied, genFuncArgs omits the implicit
// this argument.
-func (g *JavaGen) genFuncArgs(f *types.Func, jm *java.Func) {
+func (g *JavaGen) genFuncArgs(f *types.Func, jm *java.Func, hasThis bool) {
sig := f.Type().(*types.Signature)
params := sig.Params()
first := 0
- if jm != nil {
+ if hasThis {
// Skip the implicit this argument to the Go method
- first = params.Len() - len(jm.Params)
+ first = 1
}
for i := first; i < params.Len(); i++ {
if i > first {
@@ -420,7 +414,7 @@
continue
}
g.Printf("public ")
- g.genFuncSignature(m, nil)
+ g.genFuncSignature(m, nil, false)
}
g.Printf("\n")
@@ -562,7 +556,7 @@
return "TODO"
}
-func (g *JavaGen) genJNIFuncSignature(o *types.Func, sName string, jm *java.Func, proxy bool) {
+func (g *JavaGen) genJNIFuncSignature(o *types.Func, sName string, jm *java.Func, proxy, isjava bool) {
sig := o.Type().(*types.Signature)
res := sig.Results()
@@ -614,9 +608,9 @@
}
params := sig.Params()
i := 0
- if jm != nil {
+ if isjava && params.Len() > 0 && params.At(0).Name() == "this" {
// Skip the implicit this argument, if any.
- i = params.Len() - len(jm.Params)
+ i = 1
}
for ; i < params.Len(); i++ {
g.Printf(", ")
@@ -632,7 +626,7 @@
return strings.Replace(g.javaPkgName(g.Pkg), ".", "_", -1)
}
-func (g *JavaGen) genFuncSignature(o *types.Func, jm *java.Func) {
+func (g *JavaGen) genFuncSignature(o *types.Func, jm *java.Func, hasThis bool) {
sig := o.Type().(*types.Signature)
res := sig.Results()
@@ -667,7 +661,7 @@
g.Printf(javaNameReplacer(lowerFirst(o.Name())))
}
g.Printf("(")
- g.genFuncArgs(o, jm)
+ g.genFuncArgs(o, jm, hasThis)
g.Printf(")")
if returnsError {
if jm != nil {
@@ -969,7 +963,7 @@
g.Printf("// skipped function %s with unsupported parameter or return types\n\n", n)
return
}
- g.genJNIFuncSignature(o, sName, jm, proxy)
+ g.genJNIFuncSignature(o, sName, jm, proxy, isjava)
g.Printf(" {\n")
g.Indent()
@@ -992,12 +986,10 @@
}
params := sig.Params()
first := 0
- if jm != nil {
+ if isjava && params.Len() > 0 && params.At(0).Name() == "this" {
// Start after the implicit this argument.
- first = params.Len() - len(jm.Params)
- if first >= 1 {
- g.Printf("int32_t _%s = go_seq_to_refnum(env, __this__);\n", paramName(params, 0))
- }
+ first = 1
+ g.Printf("int32_t _%s = go_seq_to_refnum(env, __this__);\n", paramName(params, 0))
}
for i := first; i < params.Len(); i++ {
name := paramName(params, i)
@@ -1423,7 +1415,7 @@
continue
}
g.Printf("public native ")
- g.genFuncSignature(m, nil)
+ g.genFuncSignature(m, nil, false)
}
g.Outdent()
@@ -1445,7 +1437,7 @@
continue
}
g.Printf("public static native ")
- g.genFuncSignature(f, nil)
+ g.genFuncSignature(f, nil, false)
}
g.Outdent()
diff --git a/bind/testpkg/javapkg/classes.go b/bind/testpkg/javapkg/classes.go
index 834dce7..c492c62 100644
--- a/bind/testpkg/javapkg/classes.go
+++ b/bind/testpkg/javapkg/classes.go
@@ -27,16 +27,15 @@
this lang.Runnable
}
-func (r *GoRunnable) ToString(_ lang.Runnable) string {
+func (r *GoRunnable) ToString(this lang.Runnable) string {
return ToStringPrefix
}
func (r *GoRunnable) Run(this lang.Runnable) {
- r.this = this // Careful: This creates a reference cycle
}
-func (r *GoRunnable) GetThis() lang.Runnable {
- return r.this
+func (r *GoRunnable) GetThis(this lang.Runnable) lang.Runnable {
+ return this
}
type GoInputStream struct {