github.com/F4RD1N/gomobile@v1.0.1/bind/genjava.go (about)

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package bind
     6  
     7  import (
     8  	"fmt"
     9  	"go/constant"
    10  	"go/types"
    11  	"html"
    12  	"math"
    13  	"reflect"
    14  	"regexp"
    15  	"strings"
    16  
    17  	"github.com/F4RD1N/gomobile/internal/importers/java"
    18  )
    19  
    20  // TODO(crawshaw): disallow basic android java type names in exported symbols.
    21  // TODO(crawshaw): consider introducing Java functions for casting to and from interfaces at runtime.
    22  
    23  type JavaGen struct {
    24  	// JavaPkg is the Java package prefix for the generated classes. The prefix is prepended to the Go
    25  	// package name to create the full Java package name.
    26  	JavaPkg string
    27  
    28  	*Generator
    29  
    30  	jstructs map[*types.TypeName]*javaClassInfo
    31  	clsMap   map[string]*java.Class
    32  	// Constructors is a map from Go struct types to a list
    33  	// of exported constructor functions for the type, on the form
    34  	// func New<Type>(...) *Type
    35  	constructors map[*types.TypeName][]*types.Func
    36  }
    37  
    38  type javaClassInfo struct {
    39  	// The Java class this class extends.
    40  	extends *java.Class
    41  	// All Java classes and interfaces this class extends and implements.
    42  	supers  []*java.Class
    43  	methods map[string]*java.FuncSet
    44  	// Does the class need a default no-arg constructor
    45  	genNoargCon bool
    46  }
    47  
    48  // Init intializes the embedded Generator and initializes the Java class information
    49  // needed to generate structs that extend Java classes and interfaces.
    50  func (g *JavaGen) Init(classes []*java.Class) {
    51  	g.Generator.Init()
    52  	g.clsMap = make(map[string]*java.Class)
    53  	for _, cls := range classes {
    54  		g.clsMap[cls.Name] = cls
    55  	}
    56  	g.jstructs = make(map[*types.TypeName]*javaClassInfo)
    57  	g.constructors = make(map[*types.TypeName][]*types.Func)
    58  	for _, s := range g.structs {
    59  		classes := embeddedJavaClasses(s.t)
    60  		if len(classes) == 0 {
    61  			continue
    62  		}
    63  		inf := &javaClassInfo{
    64  			methods:     make(map[string]*java.FuncSet),
    65  			genNoargCon: true, // java.lang.Object has a no-arg constructor
    66  		}
    67  		for _, n := range classes {
    68  			cls := g.clsMap[n]
    69  			for _, fs := range cls.AllMethods {
    70  				hasMeth := false
    71  				for _, f := range fs.Funcs {
    72  					if !f.Final {
    73  						hasMeth = true
    74  					}
    75  				}
    76  				if hasMeth {
    77  					inf.methods[fs.GoName] = fs
    78  				}
    79  			}
    80  			inf.supers = append(inf.supers, cls)
    81  			if !cls.Interface {
    82  				if inf.extends != nil {
    83  					g.errorf("%s embeds more than one Java class; only one is allowed.", s.obj)
    84  				}
    85  				if cls.Final {
    86  					g.errorf("%s embeds final Java class %s", s.obj, cls.Name)
    87  				}
    88  				inf.extends = cls
    89  				inf.genNoargCon = cls.HasNoArgCon
    90  			}
    91  		}
    92  		g.jstructs[s.obj] = inf
    93  	}
    94  	for _, f := range g.funcs {
    95  		if t := g.constructorType(f); t != nil {
    96  			jinf := g.jstructs[t]
    97  			if jinf != nil {
    98  				sig := f.Type().(*types.Signature)
    99  				jinf.genNoargCon = jinf.genNoargCon && sig.Params().Len() > 0
   100  			}
   101  			g.constructors[t] = append(g.constructors[t], f)
   102  		}
   103  	}
   104  }
   105  
   106  func (j *javaClassInfo) toJavaType(T types.Type) *java.Type {
   107  	switch T := T.(type) {
   108  	case *types.Basic:
   109  		var kind java.TypeKind
   110  		switch T.Kind() {
   111  		case types.Bool, types.UntypedBool:
   112  			kind = java.Boolean
   113  		case types.Uint8:
   114  			kind = java.Byte
   115  		case types.Int16:
   116  			kind = java.Short
   117  		case types.Int32, types.UntypedRune: // types.Rune
   118  			kind = java.Int
   119  		case types.Int64, types.UntypedInt:
   120  			kind = java.Long
   121  		case types.Float32:
   122  			kind = java.Float
   123  		case types.Float64, types.UntypedFloat:
   124  			kind = java.Double
   125  		case types.String, types.UntypedString:
   126  			kind = java.String
   127  		default:
   128  			return nil
   129  		}
   130  		return &java.Type{Kind: kind}
   131  	case *types.Slice:
   132  		switch e := T.Elem().(type) {
   133  		case *types.Basic:
   134  			switch e.Kind() {
   135  			case types.Uint8: // Byte.
   136  				return &java.Type{Kind: java.Array, Elem: &java.Type{Kind: java.Byte}}
   137  			}
   138  		}
   139  		return nil
   140  	case *types.Named:
   141  		if isJavaType(T) {
   142  			return &java.Type{Kind: java.Object, Class: classNameFor(T)}
   143  		}
   144  	}
   145  	return nil
   146  }
   147  
   148  // lookupMethod searches the Java class descriptor for a method
   149  // that matches the Go method.
   150  func (j *javaClassInfo) lookupMethod(m *types.Func, hasThis bool) *java.Func {
   151  	jm := j.methods[m.Name()]
   152  	if jm == nil {
   153  		// If an exact match is not found, try the method with trailing underscores
   154  		// stripped. This way, name clashes can be avoided when overriding multiple
   155  		// overloaded methods from Go.
   156  		base := strings.TrimRight(m.Name(), "_")
   157  		jm = j.methods[base]
   158  		if jm == nil {
   159  			return nil
   160  		}
   161  	}
   162  	// A name match was found. Now use the parameter and return types to locate
   163  	// the correct variant.
   164  	sig := m.Type().(*types.Signature)
   165  	params := sig.Params()
   166  	// Convert Go parameter types to their Java counterparts, if possible.
   167  	var jparams []*java.Type
   168  	i := 0
   169  	if hasThis {
   170  		i = 1
   171  	}
   172  	for ; i < params.Len(); i++ {
   173  		jparams = append(jparams, j.toJavaType(params.At(i).Type()))
   174  	}
   175  	var ret *java.Type
   176  	var throws bool
   177  	if results := sig.Results(); results.Len() > 0 {
   178  		ret = j.toJavaType(results.At(0).Type())
   179  		if results.Len() > 1 {
   180  			throws = isErrorType(results.At(1).Type())
   181  		}
   182  	}
   183  loop:
   184  	for _, f := range jm.Funcs {
   185  		if len(f.Params) != len(jparams) {
   186  			continue
   187  		}
   188  		if throws != (f.Throws != "") {
   189  			continue
   190  		}
   191  		if !reflect.DeepEqual(ret, f.Ret) {
   192  			continue
   193  		}
   194  		for i, p := range f.Params {
   195  			if !reflect.DeepEqual(p, jparams[i]) {
   196  				continue loop
   197  			}
   198  		}
   199  		return f
   200  	}
   201  	return nil
   202  }
   203  
   204  // ClassNames returns the list of names of the generated Java classes and interfaces.
   205  func (g *JavaGen) ClassNames() []string {
   206  	var names []string
   207  	for _, s := range g.structs {
   208  		names = append(names, g.javaTypeName(s.obj.Name()))
   209  	}
   210  	for _, iface := range g.interfaces {
   211  		names = append(names, g.javaTypeName(iface.obj.Name()))
   212  	}
   213  	return names
   214  }
   215  
   216  func (g *JavaGen) GenClass(idx int) error {
   217  	ns := len(g.structs)
   218  	if idx < ns {
   219  		s := g.structs[idx]
   220  		g.genStruct(s)
   221  	} else {
   222  		iface := g.interfaces[idx-ns]
   223  		g.genInterface(iface)
   224  	}
   225  	if len(g.err) > 0 {
   226  		return g.err
   227  	}
   228  	return nil
   229  }
   230  
   231  func (g *JavaGen) genProxyImpl(name string) {
   232  	g.Printf("private final int refnum;\n\n")
   233  	g.Printf("@Override public final int incRefnum() {\n")
   234  	g.Printf("      Seq.incGoRef(refnum, this);\n")
   235  	g.Printf("      return refnum;\n")
   236  	g.Printf("}\n\n")
   237  }
   238  
   239  func (g *JavaGen) genStruct(s structInfo) {
   240  	pkgPath := ""
   241  	if g.Pkg != nil {
   242  		pkgPath = g.Pkg.Path()
   243  	}
   244  	n := g.javaTypeName(s.obj.Name())
   245  	g.Printf(javaPreamble, g.javaPkgName(g.Pkg), n, g.gobindOpts(), pkgPath)
   246  
   247  	fields := exportedFields(s.t)
   248  	methods := exportedMethodSet(types.NewPointer(s.obj.Type()))
   249  
   250  	var impls []string
   251  	jinf := g.jstructs[s.obj]
   252  	if jinf != nil {
   253  		impls = append(impls, "Seq.GoObject")
   254  		for _, cls := range jinf.supers {
   255  			if cls.Interface {
   256  				impls = append(impls, g.javaTypeName(cls.Name))
   257  			}
   258  		}
   259  	} else {
   260  		impls = append(impls, "Seq.Proxy")
   261  	}
   262  
   263  	pT := types.NewPointer(s.obj.Type())
   264  	for _, iface := range g.allIntf {
   265  		if types.AssignableTo(pT, iface.obj.Type()) {
   266  			n := iface.obj.Name()
   267  			if p := iface.obj.Pkg(); p != g.Pkg {
   268  				if n == JavaClassName(p) {
   269  					n = n + "_"
   270  				}
   271  				n = fmt.Sprintf("%s.%s", g.javaPkgName(p), n)
   272  			} else {
   273  				n = g.javaTypeName(n)
   274  			}
   275  			impls = append(impls, n)
   276  		}
   277  	}
   278  
   279  	doc := g.docs[n]
   280  	g.javadoc(doc.Doc())
   281  	g.Printf("public final class %s", n)
   282  	if jinf != nil {
   283  		if jinf.extends != nil {
   284  			g.Printf(" extends %s", g.javaTypeName(jinf.extends.Name))
   285  		}
   286  	}
   287  	if len(impls) > 0 {
   288  		g.Printf(" implements %s", strings.Join(impls, ", "))
   289  	}
   290  	g.Printf(" {\n")
   291  	g.Indent()
   292  
   293  	g.Printf("static { %s.touch(); }\n\n", g.className())
   294  	g.genProxyImpl(n)
   295  	cons := g.constructors[s.obj]
   296  	for _, f := range cons {
   297  		if !g.isConsSigSupported(f.Type()) {
   298  			g.Printf("// skipped constructor %s.%s with unsupported parameter or return types\n\n", n, f.Name())
   299  			continue
   300  		}
   301  		g.genConstructor(f, n, jinf != nil)
   302  	}
   303  	if jinf == nil || jinf.genNoargCon {
   304  		// constructor for Go instantiated instances.
   305  		g.Printf("%s(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }\n\n", n)
   306  		if len(cons) == 0 {
   307  			// Generate default no-arg constructor
   308  			g.Printf("public %s() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }\n\n", n)
   309  			g.Printf("private static native int __New();\n\n")
   310  		}
   311  	}
   312  
   313  	for _, f := range fields {
   314  		if t := f.Type(); !g.isSupported(t) {
   315  			g.Printf("// skipped field %s.%s with unsupported type: %s\n\n", n, f.Name(), t)
   316  			continue
   317  		}
   318  
   319  		fdoc := doc.Member(f.Name())
   320  		g.javadoc(fdoc)
   321  		g.Printf("public final native %s get%s();\n", g.javaType(f.Type()), f.Name())
   322  		g.javadoc(fdoc)
   323  		g.Printf("public final native void set%s(%s v);\n\n", f.Name(), g.javaType(f.Type()))
   324  	}
   325  
   326  	var isStringer bool
   327  	for _, m := range methods {
   328  		if !g.isSigSupported(m.Type()) {
   329  			g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", n, m.Name())
   330  			continue
   331  		}
   332  		g.javadoc(doc.Member(m.Name()))
   333  		var jm *java.Func
   334  		hasThis := false
   335  		if jinf != nil {
   336  			hasThis = g.hasThis(n, m)
   337  			jm = jinf.lookupMethod(m, hasThis)
   338  			if jm != nil {
   339  				g.Printf("@Override ")
   340  			}
   341  		}
   342  		g.Printf("public native ")
   343  		g.genFuncSignature(m, jm, hasThis)
   344  		t := m.Type().(*types.Signature)
   345  		isStringer = isStringer || (m.Name() == "String" && t.Params().Len() == 0 && t.Results().Len() == 1 &&
   346  			types.Identical(t.Results().At(0).Type(), types.Typ[types.String]))
   347  	}
   348  
   349  	if jinf == nil {
   350  		g.genObjectMethods(n, fields, isStringer)
   351  	}
   352  
   353  	g.Outdent()
   354  	g.Printf("}\n\n")
   355  }
   356  
   357  // isConsSigSupported reports whether the generators can handle a given
   358  // constructor signature.
   359  func (g *JavaGen) isConsSigSupported(t types.Type) bool {
   360  	if !g.isSigSupported(t) {
   361  		return false
   362  	}
   363  	// Skip constructors taking a single int32 argument
   364  	// since they clash with the proxy constructors that
   365  	// take a refnum.
   366  	params := t.(*types.Signature).Params()
   367  	if params.Len() != 1 {
   368  		return true
   369  	}
   370  	if t, ok := params.At(0).Type().(*types.Basic); ok {
   371  		switch t.Kind() {
   372  		case types.Int32, types.Uint32:
   373  			return false
   374  		}
   375  	}
   376  	return true
   377  }
   378  
   379  // javaTypeName returns the class name of a given Go type name. If
   380  // the type name clashes with the package class name, an underscore is
   381  // appended.
   382  func (g *JavaGen) javaTypeName(n string) string {
   383  	if n == JavaClassName(g.Pkg) {
   384  		return n + "_"
   385  	}
   386  	return n
   387  }
   388  
   389  func (g *JavaGen) javadoc(doc string) {
   390  	if doc == "" {
   391  		return
   392  	}
   393  	// JavaDoc expects HTML-escaped documentation.
   394  	g.Printf("/**\n * %s */\n", html.EscapeString(doc))
   395  }
   396  
   397  // hasThis reports whether a method has an implicit "this" parameter.
   398  func (g *JavaGen) hasThis(sName string, m *types.Func) bool {
   399  	sig := m.Type().(*types.Signature)
   400  	params := sig.Params()
   401  	if params.Len() == 0 {
   402  		return false
   403  	}
   404  	v := params.At(0)
   405  	if v.Name() != "this" {
   406  		return false
   407  	}
   408  	t, ok := v.Type().(*types.Named)
   409  	if !ok {
   410  		return false
   411  	}
   412  	obj := t.Obj()
   413  	pkg := obj.Pkg()
   414  	if pkgFirstElem(pkg) != "Java" {
   415  		return false
   416  	}
   417  	clsName := classNameFor(t)
   418  	exp := g.javaPkgName(g.Pkg) + "." + sName
   419  	if clsName != exp {
   420  		g.errorf("the type %s of the `this` argument to method %s.%s is not %s", clsName, sName, m.Name(), exp)
   421  		return false
   422  	}
   423  	return true
   424  }
   425  
   426  func (g *JavaGen) genConstructor(f *types.Func, n string, jcls bool) {
   427  	g.javadoc(g.docs[f.Name()].Doc())
   428  	g.Printf("public %s(", n)
   429  	g.genFuncArgs(f, nil, false)
   430  	g.Printf(") {\n")
   431  	g.Indent()
   432  	sig := f.Type().(*types.Signature)
   433  	params := sig.Params()
   434  	if jcls {
   435  		g.Printf("super(")
   436  		for i := 0; i < params.Len(); i++ {
   437  			if i > 0 {
   438  				g.Printf(", ")
   439  			}
   440  			g.Printf(g.paramName(params, i))
   441  		}
   442  		g.Printf(");\n")
   443  	}
   444  	g.Printf("this.refnum = ")
   445  	g.Printf("__%s(", f.Name())
   446  	for i := 0; i < params.Len(); i++ {
   447  		if i > 0 {
   448  			g.Printf(", ")
   449  		}
   450  		g.Printf(g.paramName(params, i))
   451  	}
   452  	g.Printf(");\n")
   453  	g.Printf("Seq.trackGoRef(refnum, this);\n")
   454  	g.Outdent()
   455  	g.Printf("}\n\n")
   456  	g.Printf("private static native int __%s(", f.Name())
   457  	g.genFuncArgs(f, nil, false)
   458  	g.Printf(");\n\n")
   459  }
   460  
   461  // genFuncArgs generated Java function arguments declaration for the function f.
   462  // If the supplied overridden java function is supplied, genFuncArgs omits the implicit
   463  // this argument.
   464  func (g *JavaGen) genFuncArgs(f *types.Func, jm *java.Func, hasThis bool) {
   465  	sig := f.Type().(*types.Signature)
   466  	params := sig.Params()
   467  	first := 0
   468  	if hasThis {
   469  		// Skip the implicit this argument to the Go method
   470  		first = 1
   471  	}
   472  	for i := first; i < params.Len(); i++ {
   473  		if i > first {
   474  			g.Printf(", ")
   475  		}
   476  		v := params.At(i)
   477  		name := g.paramName(params, i)
   478  		jt := g.javaType(v.Type())
   479  		g.Printf("%s %s", jt, name)
   480  	}
   481  }
   482  
   483  func (g *JavaGen) genObjectMethods(n string, fields []*types.Var, isStringer bool) {
   484  	g.Printf("@Override public boolean equals(Object o) {\n")
   485  	g.Indent()
   486  	g.Printf("if (o == null || !(o instanceof %s)) {\n    return false;\n}\n", n)
   487  	g.Printf("%s that = (%s)o;\n", n, n)
   488  	for _, f := range fields {
   489  		if t := f.Type(); !g.isSupported(t) {
   490  			g.Printf("// skipped field %s.%s with unsupported type: %s\n\n", n, f.Name(), t)
   491  			continue
   492  		}
   493  		nf := f.Name()
   494  		g.Printf("%s this%s = get%s();\n", g.javaType(f.Type()), nf, nf)
   495  		g.Printf("%s that%s = that.get%s();\n", g.javaType(f.Type()), nf, nf)
   496  		if isJavaPrimitive(f.Type()) {
   497  			g.Printf("if (this%s != that%s) {\n    return false;\n}\n", nf, nf)
   498  		} else {
   499  			g.Printf("if (this%s == null) {\n", nf)
   500  			g.Indent()
   501  			g.Printf("if (that%s != null) {\n    return false;\n}\n", nf)
   502  			g.Outdent()
   503  			g.Printf("} else if (!this%s.equals(that%s)) {\n    return false;\n}\n", nf, nf)
   504  		}
   505  	}
   506  	g.Printf("return true;\n")
   507  	g.Outdent()
   508  	g.Printf("}\n\n")
   509  
   510  	g.Printf("@Override public int hashCode() {\n")
   511  	g.Printf("    return java.util.Arrays.hashCode(new Object[] {")
   512  	idx := 0
   513  	for _, f := range fields {
   514  		if t := f.Type(); !g.isSupported(t) {
   515  			continue
   516  		}
   517  		if idx > 0 {
   518  			g.Printf(", ")
   519  		}
   520  		idx++
   521  		g.Printf("get%s()", f.Name())
   522  	}
   523  	g.Printf("});\n")
   524  	g.Printf("}\n\n")
   525  
   526  	g.Printf("@Override public String toString() {\n")
   527  	g.Indent()
   528  	if isStringer {
   529  		g.Printf("return string();\n")
   530  	} else {
   531  		g.Printf("StringBuilder b = new StringBuilder();\n")
   532  		g.Printf(`b.append("%s").append("{");`, n)
   533  		g.Printf("\n")
   534  		for _, f := range fields {
   535  			if t := f.Type(); !g.isSupported(t) {
   536  				continue
   537  			}
   538  			n := f.Name()
   539  			g.Printf(`b.append("%s:").append(get%s()).append(",");`, n, n)
   540  			g.Printf("\n")
   541  		}
   542  		g.Printf(`return b.append("}").toString();`)
   543  		g.Printf("\n")
   544  	}
   545  	g.Outdent()
   546  	g.Printf("}\n")
   547  }
   548  
   549  func (g *JavaGen) genInterface(iface interfaceInfo) {
   550  	pkgPath := ""
   551  	if g.Pkg != nil {
   552  		pkgPath = g.Pkg.Path()
   553  	}
   554  	g.Printf(javaPreamble, g.javaPkgName(g.Pkg), g.javaTypeName(iface.obj.Name()), g.gobindOpts(), pkgPath)
   555  
   556  	var exts []string
   557  	numM := iface.t.NumMethods()
   558  	for _, other := range g.allIntf {
   559  		// Only extend interfaces with fewer methods to avoid circular references
   560  		if other.t.NumMethods() < numM && types.AssignableTo(iface.t, other.t) {
   561  			n := other.obj.Name()
   562  			if p := other.obj.Pkg(); p != g.Pkg {
   563  				if n == JavaClassName(p) {
   564  					n = n + "_"
   565  				}
   566  				n = fmt.Sprintf("%s.%s", g.javaPkgName(p), n)
   567  			} else {
   568  				n = g.javaTypeName(n)
   569  			}
   570  			exts = append(exts, n)
   571  		}
   572  	}
   573  	doc := g.docs[iface.obj.Name()]
   574  	g.javadoc(doc.Doc())
   575  	g.Printf("public interface %s", g.javaTypeName(iface.obj.Name()))
   576  	if len(exts) > 0 {
   577  		g.Printf(" extends %s", strings.Join(exts, ", "))
   578  	}
   579  	g.Printf(" {\n")
   580  	g.Indent()
   581  
   582  	for _, m := range iface.summary.callable {
   583  		if !g.isSigSupported(m.Type()) {
   584  			g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", iface.obj.Name(), m.Name())
   585  			continue
   586  		}
   587  		g.javadoc(doc.Member(m.Name()))
   588  		g.Printf("public ")
   589  		g.genFuncSignature(m, nil, false)
   590  	}
   591  
   592  	g.Printf("\n")
   593  
   594  	g.Outdent()
   595  	g.Printf("}\n\n")
   596  }
   597  
   598  func isJavaPrimitive(T types.Type) bool {
   599  	b, ok := T.(*types.Basic)
   600  	if !ok {
   601  		return false
   602  	}
   603  	switch b.Kind() {
   604  	case types.Bool, types.Uint8, types.Float32, types.Float64,
   605  		types.Int, types.Int8, types.Int16, types.Int32, types.Int64:
   606  		return true
   607  	}
   608  	return false
   609  }
   610  
   611  // jniType returns a string that can be used as a JNI type.
   612  func (g *JavaGen) jniType(T types.Type) string {
   613  	switch T := T.(type) {
   614  	case *types.Basic:
   615  		switch T.Kind() {
   616  		case types.Bool, types.UntypedBool:
   617  			return "jboolean"
   618  		case types.Int:
   619  			return "jlong"
   620  		case types.Int8:
   621  			return "jbyte"
   622  		case types.Int16:
   623  			return "jshort"
   624  		case types.Int32, types.UntypedRune: // types.Rune
   625  			return "jint"
   626  		case types.Int64, types.UntypedInt:
   627  			return "jlong"
   628  		case types.Uint8: // types.Byte
   629  			// TODO(crawshaw): Java bytes are signed, so this is
   630  			// questionable, but vital.
   631  			return "jbyte"
   632  		// TODO(crawshaw): case types.Uint, types.Uint16, types.Uint32, types.Uint64:
   633  		case types.Float32:
   634  			return "jfloat"
   635  		case types.Float64, types.UntypedFloat:
   636  			return "jdouble"
   637  		case types.String, types.UntypedString:
   638  			return "jstring"
   639  		default:
   640  			g.errorf("unsupported basic type: %s", T)
   641  			return "TODO"
   642  		}
   643  	case *types.Slice:
   644  		return "jbyteArray"
   645  
   646  	case *types.Pointer:
   647  		if _, ok := T.Elem().(*types.Named); ok {
   648  			return g.jniType(T.Elem())
   649  		}
   650  		g.errorf("unsupported pointer to type: %s", T)
   651  	case *types.Named:
   652  		return "jobject"
   653  	default:
   654  		g.errorf("unsupported jniType: %#+v, %s\n", T, T)
   655  	}
   656  	return "TODO"
   657  }
   658  
   659  func (g *JavaGen) javaBasicType(T *types.Basic) string {
   660  	switch T.Kind() {
   661  	case types.Bool, types.UntypedBool:
   662  		return "boolean"
   663  	case types.Int:
   664  		return "long"
   665  	case types.Int8:
   666  		return "byte"
   667  	case types.Int16:
   668  		return "short"
   669  	case types.Int32, types.UntypedRune: // types.Rune
   670  		return "int"
   671  	case types.Int64, types.UntypedInt:
   672  		return "long"
   673  	case types.Uint8: // types.Byte
   674  		// TODO(crawshaw): Java bytes are signed, so this is
   675  		// questionable, but vital.
   676  		return "byte"
   677  	// TODO(crawshaw): case types.Uint, types.Uint16, types.Uint32, types.Uint64:
   678  	case types.Float32:
   679  		return "float"
   680  	case types.Float64, types.UntypedFloat:
   681  		return "double"
   682  	case types.String, types.UntypedString:
   683  		return "String"
   684  	default:
   685  		g.errorf("unsupported basic type: %s", T)
   686  		return "TODO"
   687  	}
   688  }
   689  
   690  // javaType returns a string that can be used as a Java type.
   691  func (g *JavaGen) javaType(T types.Type) string {
   692  	if isErrorType(T) {
   693  		// The error type is usually translated into an exception in
   694  		// Java, however the type can be exposed in other ways, such
   695  		// as an exported field.
   696  		return "java.lang.Exception"
   697  	} else if isJavaType(T) {
   698  		return classNameFor(T)
   699  	}
   700  	switch T := T.(type) {
   701  	case *types.Basic:
   702  		return g.javaBasicType(T)
   703  	case *types.Slice:
   704  		elem := g.javaType(T.Elem())
   705  		return elem + "[]"
   706  
   707  	case *types.Pointer:
   708  		if _, ok := T.Elem().(*types.Named); ok {
   709  			return g.javaType(T.Elem())
   710  		}
   711  		g.errorf("unsupported pointer to type: %s", T)
   712  	case *types.Named:
   713  		n := T.Obj()
   714  		nPkg := n.Pkg()
   715  		if !isErrorType(T) && !g.validPkg(nPkg) {
   716  			g.errorf("type %s is in %s, which is not bound", n.Name(), nPkg)
   717  			break
   718  		}
   719  		// TODO(crawshaw): more checking here
   720  		clsName := n.Name()
   721  		if nPkg != g.Pkg {
   722  			if clsName == JavaClassName(nPkg) {
   723  				clsName += "_"
   724  			}
   725  			return fmt.Sprintf("%s.%s", g.javaPkgName(nPkg), clsName)
   726  		} else {
   727  			return g.javaTypeName(clsName)
   728  		}
   729  	default:
   730  		g.errorf("unsupported javaType: %#+v, %s\n", T, T)
   731  	}
   732  	return "TODO"
   733  }
   734  
   735  func (g *JavaGen) genJNIFuncSignature(o *types.Func, sName string, jm *java.Func, proxy, isjava bool) {
   736  	sig := o.Type().(*types.Signature)
   737  	res := sig.Results()
   738  
   739  	var ret string
   740  	switch res.Len() {
   741  	case 2:
   742  		ret = g.jniType(res.At(0).Type())
   743  	case 1:
   744  		if isErrorType(res.At(0).Type()) {
   745  			ret = "void"
   746  		} else {
   747  			ret = g.jniType(res.At(0).Type())
   748  		}
   749  	case 0:
   750  		ret = "void"
   751  	default:
   752  		g.errorf("too many result values: %s", o)
   753  		return
   754  	}
   755  
   756  	g.Printf("JNIEXPORT %s JNICALL\n", ret)
   757  	g.Printf("Java_%s_", g.jniPkgName())
   758  	if sName != "" {
   759  		if proxy {
   760  			g.Printf(java.JNIMangle(g.className()))
   761  			// 0024 is the mangled form of $, for naming inner classes.
   762  			g.Printf("_00024proxy%s", sName)
   763  		} else {
   764  			g.Printf(java.JNIMangle(g.javaTypeName(sName)))
   765  		}
   766  	} else {
   767  		g.Printf(java.JNIMangle(g.className()))
   768  	}
   769  	g.Printf("_")
   770  	if jm != nil {
   771  		g.Printf(jm.JNIName)
   772  	} else {
   773  		oName := javaNameReplacer(lowerFirst(o.Name()))
   774  		g.Printf(java.JNIMangle(oName))
   775  	}
   776  	g.Printf("(JNIEnv* env, ")
   777  	if sName != "" {
   778  		g.Printf("jobject __this__")
   779  	} else {
   780  		g.Printf("jclass _clazz")
   781  	}
   782  	params := sig.Params()
   783  	i := 0
   784  	if isjava && params.Len() > 0 && params.At(0).Name() == "this" {
   785  		// Skip the implicit this argument, if any.
   786  		i = 1
   787  	}
   788  	for ; i < params.Len(); i++ {
   789  		g.Printf(", ")
   790  		v := sig.Params().At(i)
   791  		name := g.paramName(params, i)
   792  		jt := g.jniType(v.Type())
   793  		g.Printf("%s %s", jt, name)
   794  	}
   795  	g.Printf(")")
   796  }
   797  
   798  func (g *JavaGen) jniPkgName() string {
   799  	return strings.Replace(java.JNIMangle(g.javaPkgName(g.Pkg)), ".", "_", -1)
   800  }
   801  
   802  var javaLetterDigitRE = regexp.MustCompile(`[0-9a-zA-Z$_]`)
   803  
   804  func (g *JavaGen) paramName(params *types.Tuple, pos int) string {
   805  	name := basicParamName(params, pos)
   806  	if !javaLetterDigitRE.MatchString(name) {
   807  		name = fmt.Sprintf("p%d", pos)
   808  	}
   809  	return javaNameReplacer(name)
   810  }
   811  
   812  func (g *JavaGen) genFuncSignature(o *types.Func, jm *java.Func, hasThis bool) {
   813  	sig := o.Type().(*types.Signature)
   814  	res := sig.Results()
   815  
   816  	var returnsError bool
   817  	var ret string
   818  	switch res.Len() {
   819  	case 2:
   820  		if !isErrorType(res.At(1).Type()) {
   821  			g.errorf("second result value must be of type error: %s", o)
   822  			return
   823  		}
   824  		returnsError = true
   825  		ret = g.javaType(res.At(0).Type())
   826  	case 1:
   827  		if isErrorType(res.At(0).Type()) {
   828  			returnsError = true
   829  			ret = "void"
   830  		} else {
   831  			ret = g.javaType(res.At(0).Type())
   832  		}
   833  	case 0:
   834  		ret = "void"
   835  	default:
   836  		g.errorf("too many result values: %s", o)
   837  		return
   838  	}
   839  
   840  	g.Printf("%s ", ret)
   841  	if jm != nil {
   842  		g.Printf(jm.Name)
   843  	} else {
   844  		g.Printf(javaNameReplacer(lowerFirst(o.Name())))
   845  	}
   846  	g.Printf("(")
   847  	g.genFuncArgs(o, jm, hasThis)
   848  	g.Printf(")")
   849  	if returnsError {
   850  		if jm != nil {
   851  			if jm.Throws == "" {
   852  				g.errorf("%s declares an error return value but the overriden method does not throw", o)
   853  				return
   854  			}
   855  			g.Printf(" throws %s", jm.Throws)
   856  		} else {
   857  			g.Printf(" throws Exception")
   858  		}
   859  	}
   860  	g.Printf(";\n")
   861  }
   862  
   863  func (g *JavaGen) genVar(o *types.Var) {
   864  	if t := o.Type(); !g.isSupported(t) {
   865  		g.Printf("// skipped variable %s with unsupported type: %s\n\n", o.Name(), t)
   866  		return
   867  	}
   868  	jType := g.javaType(o.Type())
   869  
   870  	doc := g.docs[o.Name()].Doc()
   871  	// setter
   872  	g.javadoc(doc)
   873  	g.Printf("public static native void set%s(%s v);\n", o.Name(), jType)
   874  
   875  	// getter
   876  	g.javadoc(doc)
   877  	g.Printf("public static native %s get%s();\n\n", jType, o.Name())
   878  }
   879  
   880  // genCRetClear clears the result value from a JNI call if an exception was
   881  // raised.
   882  func (g *JavaGen) genCRetClear(varName string, t types.Type, exc string) {
   883  	g.Printf("if (%s != NULL) {\n", exc)
   884  	g.Indent()
   885  	switch t := t.(type) {
   886  	case *types.Basic:
   887  		switch t.Kind() {
   888  		case types.String:
   889  			g.Printf("%s = NULL;\n", varName)
   890  		default:
   891  			g.Printf("%s = 0;\n", varName)
   892  		}
   893  	case *types.Slice, *types.Named, *types.Pointer:
   894  		g.Printf("%s = NULL;\n", varName)
   895  	}
   896  	g.Outdent()
   897  	g.Printf("}\n")
   898  }
   899  
   900  func (g *JavaGen) genJavaToC(varName string, t types.Type, mode varMode) {
   901  	switch t := t.(type) {
   902  	case *types.Basic:
   903  		switch t.Kind() {
   904  		case types.String:
   905  			g.Printf("nstring _%s = go_seq_from_java_string(env, %s);\n", varName, varName)
   906  		default:
   907  			g.Printf("%s _%s = (%s)%s;\n", g.cgoType(t), varName, g.cgoType(t), varName)
   908  		}
   909  	case *types.Slice:
   910  		switch e := t.Elem().(type) {
   911  		case *types.Basic:
   912  			switch e.Kind() {
   913  			case types.Uint8: // Byte.
   914  				g.Printf("nbyteslice _%s = go_seq_from_java_bytearray(env, %s, %d);\n", varName, varName, toCFlag(mode == modeRetained))
   915  			default:
   916  				g.errorf("unsupported type: %s", t)
   917  			}
   918  		default:
   919  			g.errorf("unsupported type: %s", t)
   920  		}
   921  	case *types.Named:
   922  		switch u := t.Underlying().(type) {
   923  		case *types.Interface:
   924  			g.Printf("int32_t _%s = go_seq_to_refnum(env, %s);\n", varName, varName)
   925  		default:
   926  			g.errorf("unsupported named type: %s / %T", u, u)
   927  		}
   928  	case *types.Pointer:
   929  		g.Printf("int32_t _%s = go_seq_to_refnum(env, %s);\n", varName, varName)
   930  	default:
   931  		g.Printf("%s _%s = (%s)%s;\n", g.cgoType(t), varName, g.cgoType(t), varName)
   932  	}
   933  }
   934  
   935  func (g *JavaGen) genCToJava(toName, fromName string, t types.Type, mode varMode) {
   936  	switch t := t.(type) {
   937  	case *types.Basic:
   938  		switch t.Kind() {
   939  		case types.String:
   940  			g.Printf("jstring %s = go_seq_to_java_string(env, %s);\n", toName, fromName)
   941  		case types.Bool:
   942  			g.Printf("jboolean %s = %s ? JNI_TRUE : JNI_FALSE;\n", toName, fromName)
   943  		default:
   944  			g.Printf("%s %s = (%s)%s;\n", g.jniType(t), toName, g.jniType(t), fromName)
   945  		}
   946  	case *types.Slice:
   947  		switch e := t.Elem().(type) {
   948  		case *types.Basic:
   949  			switch e.Kind() {
   950  			case types.Uint8: // Byte.
   951  				g.Printf("jbyteArray %s = go_seq_to_java_bytearray(env, %s, %d);\n", toName, fromName, toCFlag(mode == modeRetained))
   952  			default:
   953  				g.errorf("unsupported type: %s", t)
   954  			}
   955  		default:
   956  			g.errorf("unsupported type: %s", t)
   957  		}
   958  	case *types.Pointer:
   959  		// TODO(crawshaw): test *int
   960  		// TODO(crawshaw): test **Generator
   961  		switch t := t.Elem().(type) {
   962  		case *types.Named:
   963  			g.genFromRefnum(toName, fromName, t, t.Obj())
   964  		default:
   965  			g.errorf("unsupported type %s", t)
   966  		}
   967  	case *types.Named:
   968  		switch t.Underlying().(type) {
   969  		case *types.Interface, *types.Pointer:
   970  			g.genFromRefnum(toName, fromName, t, t.Obj())
   971  		default:
   972  			g.errorf("unsupported, direct named type %s", t)
   973  		}
   974  	default:
   975  		g.Printf("%s %s = (%s)%s;\n", g.jniType(t), toName, g.jniType(t), fromName)
   976  	}
   977  }
   978  
   979  func (g *JavaGen) genFromRefnum(toName, fromName string, t types.Type, o *types.TypeName) {
   980  	oPkg := o.Pkg()
   981  	isJava := isJavaType(o.Type())
   982  	if !isErrorType(o.Type()) && !g.validPkg(oPkg) && !isJava {
   983  		g.errorf("type %s is defined in package %s, which is not bound", t, oPkg)
   984  		return
   985  	}
   986  	p := pkgPrefix(oPkg)
   987  	g.Printf("jobject %s = go_seq_from_refnum(env, %s, ", toName, fromName)
   988  	if isJava {
   989  		g.Printf("NULL, NULL")
   990  	} else {
   991  		g.Printf("proxy_class_%s_%s, proxy_class_%s_%s_cons", p, o.Name(), p, o.Name())
   992  	}
   993  	g.Printf(");\n")
   994  }
   995  
   996  func (g *JavaGen) gobindOpts() string {
   997  	opts := []string{"-lang=java"}
   998  	if g.JavaPkg != "" {
   999  		opts = append(opts, "-javapkg="+g.JavaPkg)
  1000  	}
  1001  	return strings.Join(opts, " ")
  1002  }
  1003  
  1004  var javaNameReplacer = newNameSanitizer([]string{
  1005  	"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char",
  1006  	"class", "const", "continue", "default", "do", "double", "else", "enum",
  1007  	"extends", "final", "finally", "float", "for", "goto", "if", "implements",
  1008  	"import", "instanceof", "int", "interface", "long", "native", "new", "package",
  1009  	"private", "protected", "public", "return", "short", "static", "strictfp",
  1010  	"super", "switch", "synchronized", "this", "throw", "throws", "transient",
  1011  	"try", "void", "volatile", "while", "false", "null", "true"})
  1012  
  1013  func (g *JavaGen) javaPkgName(pkg *types.Package) string {
  1014  	return JavaPkgName(g.JavaPkg, pkg)
  1015  }
  1016  
  1017  // JavaPkgName returns the Java package name for a Go package
  1018  // given a pkg prefix. If the prefix is empty, "go" is used
  1019  // instead.
  1020  func JavaPkgName(pkgPrefix string, pkg *types.Package) string {
  1021  	if pkg == nil {
  1022  		return "go"
  1023  	}
  1024  	s := javaNameReplacer(pkg.Name())
  1025  	if pkgPrefix == "" {
  1026  		return s
  1027  	}
  1028  	return pkgPrefix + "." + s
  1029  }
  1030  
  1031  func (g *JavaGen) className() string {
  1032  	return JavaClassName(g.Pkg)
  1033  }
  1034  
  1035  // JavaClassName returns the name of the Java class that
  1036  // contains Go package level identifiers.
  1037  func JavaClassName(pkg *types.Package) string {
  1038  	if pkg == nil {
  1039  		return "Universe"
  1040  	}
  1041  	return javaNameReplacer(strings.Title(pkg.Name()))
  1042  }
  1043  
  1044  func (g *JavaGen) genConst(o *types.Const) {
  1045  	if _, ok := o.Type().(*types.Basic); !ok || !g.isSupported(o.Type()) {
  1046  		g.Printf("// skipped const %s with unsupported type: %s\n\n", o.Name(), o.Type())
  1047  		return
  1048  	}
  1049  	// TODO(hyangah): should const names use upper cases + "_"?
  1050  	// TODO(hyangah): check invalid names.
  1051  	jType := g.javaType(o.Type())
  1052  	val := o.Val().ExactString()
  1053  	switch b := o.Type().(*types.Basic); b.Kind() {
  1054  	case types.Int64, types.UntypedInt:
  1055  		i, exact := constant.Int64Val(o.Val())
  1056  		if !exact {
  1057  			g.errorf("const value %s for %s cannot be represented as %s", val, o.Name(), jType)
  1058  			return
  1059  		}
  1060  		val = fmt.Sprintf("%dL", i)
  1061  
  1062  	case types.Float32:
  1063  		f, _ := constant.Float32Val(o.Val())
  1064  		val = fmt.Sprintf("%gf", f)
  1065  
  1066  	case types.Float64, types.UntypedFloat:
  1067  		f, _ := constant.Float64Val(o.Val())
  1068  		if math.IsInf(f, 0) || math.Abs(f) > math.MaxFloat64 {
  1069  			g.errorf("const value %s for %s cannot be represented as %s", val, o.Name(), jType)
  1070  			return
  1071  		}
  1072  		val = fmt.Sprintf("%g", f)
  1073  	}
  1074  	g.javadoc(g.docs[o.Name()].Doc())
  1075  	g.Printf("public static final %s %s = %s;\n", g.javaType(o.Type()), o.Name(), val)
  1076  }
  1077  
  1078  func (g *JavaGen) genJNIField(o *types.TypeName, f *types.Var) {
  1079  	if t := f.Type(); !g.isSupported(t) {
  1080  		g.Printf("// skipped field %s with unsupported type: %s\n\n", o.Name(), t)
  1081  		return
  1082  	}
  1083  	n := java.JNIMangle(g.javaTypeName(o.Name()))
  1084  	// setter
  1085  	g.Printf("JNIEXPORT void JNICALL\n")
  1086  	g.Printf("Java_%s_%s_set%s(JNIEnv *env, jobject this, %s v) {\n", g.jniPkgName(), n, java.JNIMangle(f.Name()), g.jniType(f.Type()))
  1087  	g.Indent()
  1088  	g.Printf("int32_t o = go_seq_to_refnum_go(env, this);\n")
  1089  	g.genJavaToC("v", f.Type(), modeRetained)
  1090  	g.Printf("proxy%s_%s_%s_Set(o, _v);\n", g.pkgPrefix, o.Name(), f.Name())
  1091  	g.genRelease("v", f.Type(), modeRetained)
  1092  	g.Outdent()
  1093  	g.Printf("}\n\n")
  1094  
  1095  	// getter
  1096  	g.Printf("JNIEXPORT %s JNICALL\n", g.jniType(f.Type()))
  1097  	g.Printf("Java_%s_%s_get%s(JNIEnv *env, jobject this) {\n", g.jniPkgName(), n, java.JNIMangle(f.Name()))
  1098  	g.Indent()
  1099  	g.Printf("int32_t o = go_seq_to_refnum_go(env, this);\n")
  1100  	g.Printf("%s r0 = ", g.cgoType(f.Type()))
  1101  	g.Printf("proxy%s_%s_%s_Get(o);\n", g.pkgPrefix, o.Name(), f.Name())
  1102  	g.genCToJava("_r0", "r0", f.Type(), modeRetained)
  1103  	g.Printf("return _r0;\n")
  1104  	g.Outdent()
  1105  	g.Printf("}\n\n")
  1106  }
  1107  
  1108  func (g *JavaGen) genJNIVar(o *types.Var) {
  1109  	if t := o.Type(); !g.isSupported(t) {
  1110  		g.Printf("// skipped variable %s with unsupported type: %s\n\n", o.Name(), t)
  1111  		return
  1112  	}
  1113  	n := java.JNIMangle(g.javaTypeName(o.Name()))
  1114  	// setter
  1115  	g.Printf("JNIEXPORT void JNICALL\n")
  1116  	g.Printf("Java_%s_%s_set%s(JNIEnv *env, jclass clazz, %s v) {\n", g.jniPkgName(), java.JNIMangle(g.className()), n, g.jniType(o.Type()))
  1117  	g.Indent()
  1118  	g.genJavaToC("v", o.Type(), modeRetained)
  1119  	g.Printf("var_set%s_%s(_v);\n", g.pkgPrefix, o.Name())
  1120  	g.genRelease("v", o.Type(), modeRetained)
  1121  	g.Outdent()
  1122  	g.Printf("}\n\n")
  1123  
  1124  	// getter
  1125  	g.Printf("JNIEXPORT %s JNICALL\n", g.jniType(o.Type()))
  1126  	g.Printf("Java_%s_%s_get%s(JNIEnv *env, jclass clazz) {\n", g.jniPkgName(), java.JNIMangle(g.className()), n)
  1127  	g.Indent()
  1128  	g.Printf("%s r0 = ", g.cgoType(o.Type()))
  1129  	g.Printf("var_get%s_%s();\n", g.pkgPrefix, o.Name())
  1130  	g.genCToJava("_r0", "r0", o.Type(), modeRetained)
  1131  	g.Printf("return _r0;\n")
  1132  	g.Outdent()
  1133  	g.Printf("}\n\n")
  1134  }
  1135  
  1136  func (g *JavaGen) genJNIConstructor(f *types.Func, sName string) {
  1137  	if !g.isConsSigSupported(f.Type()) {
  1138  		return
  1139  	}
  1140  	sig := f.Type().(*types.Signature)
  1141  	res := sig.Results()
  1142  
  1143  	g.Printf("JNIEXPORT jint JNICALL\n")
  1144  	g.Printf("Java_%s_%s_%s(JNIEnv *env, jclass clazz", g.jniPkgName(), java.JNIMangle(g.javaTypeName(sName)), java.JNIMangle("__"+f.Name()))
  1145  	params := sig.Params()
  1146  	for i := 0; i < params.Len(); i++ {
  1147  		v := params.At(i)
  1148  		jt := g.jniType(v.Type())
  1149  		g.Printf(", %s %s", jt, g.paramName(params, i))
  1150  	}
  1151  	g.Printf(") {\n")
  1152  	g.Indent()
  1153  	for i := 0; i < params.Len(); i++ {
  1154  		name := g.paramName(params, i)
  1155  		g.genJavaToC(name, params.At(i).Type(), modeTransient)
  1156  	}
  1157  	// Constructors always return a mandatory *T and an optional error
  1158  	if res.Len() == 1 {
  1159  		g.Printf("int32_t refnum = proxy%s__%s(", g.pkgPrefix, f.Name())
  1160  	} else {
  1161  		g.Printf("struct proxy%s__%s_return res = proxy%s__%s(", g.pkgPrefix, f.Name(), g.pkgPrefix, f.Name())
  1162  	}
  1163  	for i := 0; i < params.Len(); i++ {
  1164  		if i > 0 {
  1165  			g.Printf(", ")
  1166  		}
  1167  		g.Printf("_%s", g.paramName(params, i))
  1168  	}
  1169  	g.Printf(");\n")
  1170  	for i := 0; i < params.Len(); i++ {
  1171  		g.genRelease(g.paramName(params, i), params.At(i).Type(), modeTransient)
  1172  	}
  1173  	// Extract multi returns and handle errors
  1174  	if res.Len() == 2 {
  1175  		g.Printf("int32_t refnum = res.r0;\n")
  1176  		g.genCToJava("_err", "res.r1", res.At(1).Type(), modeRetained)
  1177  		g.Printf("go_seq_maybe_throw_exception(env, _err);\n")
  1178  	}
  1179  	g.Printf("return refnum;\n")
  1180  	g.Outdent()
  1181  	g.Printf("}\n\n")
  1182  }
  1183  
  1184  func (g *JavaGen) genJNIFunc(o *types.Func, sName string, jm *java.Func, proxy, isjava bool) {
  1185  	if !g.isSigSupported(o.Type()) {
  1186  		n := o.Name()
  1187  		if sName != "" {
  1188  			n = sName + "." + n
  1189  		}
  1190  		g.Printf("// skipped function %s with unsupported parameter or return types\n\n", n)
  1191  		return
  1192  	}
  1193  	g.genJNIFuncSignature(o, sName, jm, proxy, isjava)
  1194  
  1195  	g.Printf(" {\n")
  1196  	g.Indent()
  1197  	g.genJNIFuncBody(o, sName, jm, isjava)
  1198  	g.Outdent()
  1199  	g.Printf("}\n\n")
  1200  }
  1201  
  1202  func (g *JavaGen) genJNIFuncBody(o *types.Func, sName string, jm *java.Func, isjava bool) {
  1203  	sig := o.Type().(*types.Signature)
  1204  	res := sig.Results()
  1205  	if sName != "" {
  1206  		g.Printf("int32_t o = go_seq_to_refnum_go(env, __this__);\n")
  1207  	}
  1208  	params := sig.Params()
  1209  	first := 0
  1210  	if isjava && params.Len() > 0 && params.At(0).Name() == "this" {
  1211  		// Start after the implicit this argument.
  1212  		first = 1
  1213  		g.Printf("int32_t _%s = go_seq_to_refnum(env, __this__);\n", g.paramName(params, 0))
  1214  	}
  1215  	for i := first; i < params.Len(); i++ {
  1216  		name := g.paramName(params, i)
  1217  		g.genJavaToC(name, params.At(i).Type(), modeTransient)
  1218  	}
  1219  	resPrefix := ""
  1220  	if res.Len() > 0 {
  1221  		if res.Len() == 1 {
  1222  			g.Printf("%s r0 = ", g.cgoType(res.At(0).Type()))
  1223  		} else {
  1224  			resPrefix = "res."
  1225  			g.Printf("struct proxy%s_%s_%s_return res = ", g.pkgPrefix, sName, o.Name())
  1226  		}
  1227  	}
  1228  	g.Printf("proxy%s_%s_%s(", g.pkgPrefix, sName, o.Name())
  1229  	if sName != "" {
  1230  		g.Printf("o")
  1231  	}
  1232  	// Pass all arguments, including the implicit this argument.
  1233  	for i := 0; i < params.Len(); i++ {
  1234  		if i > 0 || sName != "" {
  1235  			g.Printf(", ")
  1236  		}
  1237  		g.Printf("_%s", g.paramName(params, i))
  1238  	}
  1239  	g.Printf(");\n")
  1240  	for i := first; i < params.Len(); i++ {
  1241  		g.genRelease(g.paramName(params, i), params.At(i).Type(), modeTransient)
  1242  	}
  1243  	for i := 0; i < res.Len(); i++ {
  1244  		tn := fmt.Sprintf("_r%d", i)
  1245  		t := res.At(i).Type()
  1246  		g.genCToJava(tn, fmt.Sprintf("%sr%d", resPrefix, i), t, modeRetained)
  1247  	}
  1248  	// Go backwards so that any exception is thrown before
  1249  	// the return.
  1250  	for i := res.Len() - 1; i >= 0; i-- {
  1251  		t := res.At(i).Type()
  1252  		if !isErrorType(t) {
  1253  			g.Printf("return _r%d;\n", i)
  1254  		} else {
  1255  			g.Printf("go_seq_maybe_throw_exception(env, _r%d);\n", i)
  1256  		}
  1257  	}
  1258  }
  1259  
  1260  // genRelease cleans up arguments that weren't copied in genJavaToC.
  1261  func (g *JavaGen) genRelease(varName string, t types.Type, mode varMode) {
  1262  	switch t := t.(type) {
  1263  	case *types.Basic:
  1264  	case *types.Slice:
  1265  		switch e := t.Elem().(type) {
  1266  		case *types.Basic:
  1267  			switch e.Kind() {
  1268  			case types.Uint8: // Byte.
  1269  				if mode == modeTransient {
  1270  					g.Printf("go_seq_release_byte_array(env, %s, _%s.ptr);\n", varName, varName)
  1271  				}
  1272  			}
  1273  		}
  1274  	}
  1275  }
  1276  
  1277  func (g *JavaGen) genMethodInterfaceProxy(oName string, m *types.Func) {
  1278  	if !g.isSigSupported(m.Type()) {
  1279  		g.Printf("// skipped method %s with unsupported parameter or return types\n\n", oName)
  1280  		return
  1281  	}
  1282  	sig := m.Type().(*types.Signature)
  1283  	params := sig.Params()
  1284  	res := sig.Results()
  1285  	g.genInterfaceMethodSignature(m, oName, false, g.paramName)
  1286  	g.Indent()
  1287  	g.Printf("JNIEnv *env = go_seq_push_local_frame(%d);\n", params.Len())
  1288  	g.Printf("jobject o = go_seq_from_refnum(env, refnum, proxy_class_%s_%s, proxy_class_%s_%s_cons);\n", g.pkgPrefix, oName, g.pkgPrefix, oName)
  1289  	for i := 0; i < params.Len(); i++ {
  1290  		pn := g.paramName(params, i)
  1291  		g.genCToJava("_"+pn, pn, params.At(i).Type(), modeTransient)
  1292  	}
  1293  	if res.Len() > 0 && !isErrorType(res.At(0).Type()) {
  1294  		t := res.At(0).Type()
  1295  		g.Printf("%s res = (*env)->Call%sMethod(env, o, ", g.jniType(t), g.jniCallType(t))
  1296  	} else {
  1297  		g.Printf("(*env)->CallVoidMethod(env, o, ")
  1298  	}
  1299  	g.Printf("mid_%s_%s", oName, m.Name())
  1300  	for i := 0; i < params.Len(); i++ {
  1301  		g.Printf(", _%s", g.paramName(params, i))
  1302  	}
  1303  	g.Printf(");\n")
  1304  	var retName string
  1305  	if res.Len() > 0 {
  1306  		t := res.At(0).Type()
  1307  		if res.Len() == 2 || isErrorType(t) {
  1308  			g.Printf("jobject exc = go_seq_get_exception(env);\n")
  1309  			errType := types.Universe.Lookup("error").Type()
  1310  			g.genJavaToC("exc", errType, modeRetained)
  1311  			retName = "_exc"
  1312  		}
  1313  		if !isErrorType(t) {
  1314  			if res.Len() == 2 {
  1315  				g.genCRetClear("res", t, "exc")
  1316  			}
  1317  			g.genJavaToC("res", t, modeRetained)
  1318  			retName = "_res"
  1319  		}
  1320  
  1321  		if res.Len() > 1 {
  1322  			g.Printf("cproxy%s_%s_%s_return sres = {\n", g.pkgPrefix, oName, m.Name())
  1323  			g.Printf("	_res, _exc\n")
  1324  			g.Printf("};\n")
  1325  			retName = "sres"
  1326  		}
  1327  	}
  1328  	g.Printf("go_seq_pop_local_frame(env);\n")
  1329  	if retName != "" {
  1330  		g.Printf("return %s;\n", retName)
  1331  	}
  1332  	g.Outdent()
  1333  	g.Printf("}\n\n")
  1334  }
  1335  
  1336  func (g *JavaGen) GenH() error {
  1337  	pkgPath := ""
  1338  	if g.Pkg != nil {
  1339  		pkgPath = g.Pkg.Path()
  1340  	}
  1341  	g.Printf(hPreamble, g.gobindOpts(), pkgPath, g.className())
  1342  	for _, iface := range g.interfaces {
  1343  		g.Printf("extern jclass proxy_class_%s_%s;\n", g.pkgPrefix, iface.obj.Name())
  1344  		g.Printf("extern jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, iface.obj.Name())
  1345  		g.Printf("\n")
  1346  		for _, m := range iface.summary.callable {
  1347  			if !g.isSigSupported(m.Type()) {
  1348  				g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", iface.obj.Name(), m.Name())
  1349  				continue
  1350  			}
  1351  			g.genInterfaceMethodSignature(m, iface.obj.Name(), true, g.paramName)
  1352  			g.Printf("\n")
  1353  		}
  1354  	}
  1355  	for _, s := range g.structs {
  1356  		g.Printf("extern jclass proxy_class_%s_%s;\n", g.pkgPrefix, s.obj.Name())
  1357  		g.Printf("extern jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, s.obj.Name())
  1358  	}
  1359  	g.Printf("#endif\n")
  1360  	if len(g.err) > 0 {
  1361  		return g.err
  1362  	}
  1363  	return nil
  1364  }
  1365  
  1366  func (g *JavaGen) jniCallType(t types.Type) string {
  1367  	switch t := t.(type) {
  1368  	case *types.Basic:
  1369  		switch t.Kind() {
  1370  		case types.Bool, types.UntypedBool:
  1371  			return "Boolean"
  1372  		case types.Int:
  1373  			return "Long"
  1374  		case types.Int8, types.Uint8: // types.Byte
  1375  			return "Byte"
  1376  		case types.Int16:
  1377  			return "Short"
  1378  		case types.Int32, types.UntypedRune: // types.Rune
  1379  			return "Int"
  1380  		case types.Int64, types.UntypedInt:
  1381  			return "Long"
  1382  		case types.Float32:
  1383  			return "Float"
  1384  		case types.Float64, types.UntypedFloat:
  1385  			return "Double"
  1386  		case types.String, types.UntypedString:
  1387  			return "Object"
  1388  		default:
  1389  			g.errorf("unsupported basic type: %s", t)
  1390  		}
  1391  	case *types.Slice:
  1392  		return "Object"
  1393  	case *types.Pointer:
  1394  		if _, ok := t.Elem().(*types.Named); ok {
  1395  			return g.jniCallType(t.Elem())
  1396  		}
  1397  		g.errorf("unsupported pointer to type: %s", t)
  1398  	case *types.Named:
  1399  		return "Object"
  1400  	default:
  1401  		return "Object"
  1402  	}
  1403  	return "TODO"
  1404  }
  1405  
  1406  func (g *JavaGen) jniClassSigPrefix(pkg *types.Package) string {
  1407  	return strings.Replace(g.javaPkgName(pkg), ".", "/", -1) + "/"
  1408  }
  1409  
  1410  func (g *JavaGen) jniSigType(T types.Type) string {
  1411  	if isErrorType(T) {
  1412  		return "Ljava/lang/Exception;"
  1413  	}
  1414  	switch T := T.(type) {
  1415  	case *types.Basic:
  1416  		switch T.Kind() {
  1417  		case types.Bool, types.UntypedBool:
  1418  			return "Z"
  1419  		case types.Int:
  1420  			return "J"
  1421  		case types.Int8:
  1422  			return "B"
  1423  		case types.Int16:
  1424  			return "S"
  1425  		case types.Int32, types.UntypedRune: // types.Rune
  1426  			return "I"
  1427  		case types.Int64, types.UntypedInt:
  1428  			return "J"
  1429  		case types.Uint8: // types.Byte
  1430  			return "B"
  1431  		case types.Float32:
  1432  			return "F"
  1433  		case types.Float64, types.UntypedFloat:
  1434  			return "D"
  1435  		case types.String, types.UntypedString:
  1436  			return "Ljava/lang/String;"
  1437  		default:
  1438  			g.errorf("unsupported basic type: %s", T)
  1439  			return "TODO"
  1440  		}
  1441  	case *types.Slice:
  1442  		return "[" + g.jniSigType(T.Elem())
  1443  	case *types.Pointer:
  1444  		if _, ok := T.Elem().(*types.Named); ok {
  1445  			return g.jniSigType(T.Elem())
  1446  		}
  1447  		g.errorf("unsupported pointer to type: %s", T)
  1448  	case *types.Named:
  1449  		return "L" + g.jniClassSigPrefix(T.Obj().Pkg()) + g.javaTypeName(T.Obj().Name()) + ";"
  1450  	default:
  1451  		g.errorf("unsupported jniType: %#+v, %s\n", T, T)
  1452  	}
  1453  	return "TODO"
  1454  }
  1455  
  1456  func (g *JavaGen) GenC() error {
  1457  	var pkgName, pkgPath string
  1458  	if g.Pkg != nil {
  1459  		pkgName = g.Pkg.Name()
  1460  		pkgPath = g.Pkg.Path()
  1461  	} else {
  1462  		pkgName = "universe"
  1463  	}
  1464  	g.Printf(cPreamble, g.gobindOpts(), pkgPath)
  1465  	g.Printf("#include %q\n", pkgName+".h")
  1466  	if g.Pkg != nil {
  1467  		for _, pkg := range g.Pkg.Imports() {
  1468  			if g.validPkg(pkg) {
  1469  				g.Printf("#include \"%s.h\"\n", pkg.Name())
  1470  			}
  1471  		}
  1472  	}
  1473  	g.Printf("\n")
  1474  
  1475  	for _, iface := range g.interfaces {
  1476  		g.Printf("jclass proxy_class_%s_%s;\n", g.pkgPrefix, iface.obj.Name())
  1477  		g.Printf("jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, iface.obj.Name())
  1478  		for _, m := range iface.summary.callable {
  1479  			if !g.isSigSupported(m.Type()) {
  1480  				g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", iface.obj.Name(), m.Name())
  1481  				continue
  1482  			}
  1483  			g.Printf("static jmethodID mid_%s_%s;\n", iface.obj.Name(), m.Name())
  1484  		}
  1485  	}
  1486  	for _, s := range g.structs {
  1487  		g.Printf("jclass proxy_class_%s_%s;\n", g.pkgPrefix, s.obj.Name())
  1488  		g.Printf("jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, s.obj.Name())
  1489  	}
  1490  	g.Printf("\n")
  1491  	g.Printf("JNIEXPORT void JNICALL\n")
  1492  	g.Printf("Java_%s_%s__1init(JNIEnv *env, jclass _unused) {\n", g.jniPkgName(), java.JNIMangle(g.className()))
  1493  	g.Indent()
  1494  	g.Printf("jclass clazz;\n")
  1495  	for _, s := range g.structs {
  1496  		if jinf, ok := g.jstructs[s.obj]; ok {
  1497  			// Leave the class and constructor NULL for Java classes with no
  1498  			// default constructor.
  1499  			if !jinf.genNoargCon {
  1500  				continue
  1501  			}
  1502  		}
  1503  		g.Printf("clazz = (*env)->FindClass(env, %q);\n", g.jniClassSigPrefix(s.obj.Pkg())+g.javaTypeName(s.obj.Name()))
  1504  		g.Printf("proxy_class_%s_%s = (*env)->NewGlobalRef(env, clazz);\n", g.pkgPrefix, s.obj.Name())
  1505  		g.Printf("proxy_class_%s_%s_cons = (*env)->GetMethodID(env, clazz, \"<init>\", \"(I)V\");\n", g.pkgPrefix, s.obj.Name())
  1506  	}
  1507  	for _, iface := range g.interfaces {
  1508  		pkg := iface.obj.Pkg()
  1509  		g.Printf("clazz = (*env)->FindClass(env, %q);\n", g.jniClassSigPrefix(pkg)+JavaClassName(pkg)+"$proxy"+iface.obj.Name())
  1510  		g.Printf("proxy_class_%s_%s = (*env)->NewGlobalRef(env, clazz);\n", g.pkgPrefix, iface.obj.Name())
  1511  		g.Printf("proxy_class_%s_%s_cons = (*env)->GetMethodID(env, clazz, \"<init>\", \"(I)V\");\n", g.pkgPrefix, iface.obj.Name())
  1512  		if isErrorType(iface.obj.Type()) {
  1513  			// As a special case, Java Exceptions are passed to Go pretending to implement the Go error interface.
  1514  			// To complete the illusion, use the Throwable.getMessage method for proxied calls to the error.Error method.
  1515  			g.Printf("clazz = (*env)->FindClass(env, \"java/lang/Throwable\");\n")
  1516  			g.Printf("mid_error_Error = (*env)->GetMethodID(env, clazz, \"getMessage\", \"()Ljava/lang/String;\");\n")
  1517  			continue
  1518  		}
  1519  		g.Printf("clazz = (*env)->FindClass(env, %q);\n", g.jniClassSigPrefix(pkg)+g.javaTypeName(iface.obj.Name()))
  1520  		for _, m := range iface.summary.callable {
  1521  			if !g.isSigSupported(m.Type()) {
  1522  				g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", iface.obj.Name(), m.Name())
  1523  				continue
  1524  			}
  1525  			sig := m.Type().(*types.Signature)
  1526  			res := sig.Results()
  1527  			retSig := "V"
  1528  			if res.Len() > 0 {
  1529  				if t := res.At(0).Type(); !isErrorType(t) {
  1530  					retSig = g.jniSigType(t)
  1531  				}
  1532  			}
  1533  			var jniParams string
  1534  			params := sig.Params()
  1535  			for i := 0; i < params.Len(); i++ {
  1536  				jniParams += g.jniSigType(params.At(i).Type())
  1537  			}
  1538  			g.Printf("mid_%s_%s = (*env)->GetMethodID(env, clazz, %q, \"(%s)%s\");\n",
  1539  				iface.obj.Name(), m.Name(), javaNameReplacer(lowerFirst(m.Name())), jniParams, retSig)
  1540  		}
  1541  		g.Printf("\n")
  1542  	}
  1543  	g.Outdent()
  1544  	g.Printf("}\n\n")
  1545  	for _, f := range g.funcs {
  1546  		g.genJNIFunc(f, "", nil, false, false)
  1547  	}
  1548  	for _, s := range g.structs {
  1549  		sName := s.obj.Name()
  1550  		cons := g.constructors[s.obj]
  1551  		jinf := g.jstructs[s.obj]
  1552  		for _, f := range cons {
  1553  			g.genJNIConstructor(f, sName)
  1554  		}
  1555  		if len(cons) == 0 && (jinf == nil || jinf.genNoargCon) {
  1556  			g.Printf("JNIEXPORT jint JNICALL\n")
  1557  			g.Printf("Java_%s_%s_%s(JNIEnv *env, jclass clazz) {\n", g.jniPkgName(), java.JNIMangle(g.javaTypeName(sName)), java.JNIMangle("__New"))
  1558  			g.Indent()
  1559  			g.Printf("return new_%s_%s();\n", g.pkgPrefix, sName)
  1560  			g.Outdent()
  1561  			g.Printf("}\n\n")
  1562  		}
  1563  
  1564  		for _, m := range exportedMethodSet(types.NewPointer(s.obj.Type())) {
  1565  			var jm *java.Func
  1566  			if jinf != nil {
  1567  				jm = jinf.lookupMethod(m, g.hasThis(s.obj.Name(), m))
  1568  			}
  1569  			g.genJNIFunc(m, sName, jm, false, jinf != nil)
  1570  		}
  1571  		for _, f := range exportedFields(s.t) {
  1572  			g.genJNIField(s.obj, f)
  1573  		}
  1574  	}
  1575  	for _, iface := range g.interfaces {
  1576  		for _, m := range iface.summary.callable {
  1577  			g.genJNIFunc(m, iface.obj.Name(), nil, true, false)
  1578  			g.genMethodInterfaceProxy(iface.obj.Name(), m)
  1579  		}
  1580  	}
  1581  	for _, v := range g.vars {
  1582  		g.genJNIVar(v)
  1583  	}
  1584  	if len(g.err) > 0 {
  1585  		return g.err
  1586  	}
  1587  	return nil
  1588  }
  1589  
  1590  func (g *JavaGen) GenJava() error {
  1591  	pkgPath := ""
  1592  	if g.Pkg != nil {
  1593  		pkgPath = g.Pkg.Path()
  1594  	}
  1595  	g.Printf(javaPreamble, g.javaPkgName(g.Pkg), g.className(), g.gobindOpts(), pkgPath)
  1596  
  1597  	g.Printf("public abstract class %s {\n", g.className())
  1598  	g.Indent()
  1599  	g.Printf("static {\n")
  1600  	g.Indent()
  1601  	g.Printf("Seq.touch(); // for loading the native library\n")
  1602  	if g.Pkg != nil {
  1603  		for _, p := range g.Pkg.Imports() {
  1604  			if g.validPkg(p) {
  1605  				g.Printf("%s.%s.touch();\n", g.javaPkgName(p), JavaClassName(p))
  1606  			}
  1607  		}
  1608  	}
  1609  	g.Printf("_init();\n")
  1610  	g.Outdent()
  1611  	g.Printf("}\n\n")
  1612  	g.Printf("private %s() {} // uninstantiable\n\n", g.className())
  1613  	g.Printf("// touch is called from other bound packages to initialize this package\n")
  1614  	g.Printf("public static void touch() {}\n\n")
  1615  	g.Printf("private static native void _init();\n\n")
  1616  
  1617  	for _, iface := range g.interfaces {
  1618  		n := iface.obj.Name()
  1619  		g.Printf("private static final class proxy%s", n)
  1620  		if isErrorType(iface.obj.Type()) {
  1621  			g.Printf(" extends Exception")
  1622  		}
  1623  		g.Printf(" implements Seq.Proxy, %s {\n", g.javaTypeName(n))
  1624  		g.Indent()
  1625  		g.genProxyImpl("proxy" + n)
  1626  		g.Printf("proxy%s(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }\n\n", n)
  1627  
  1628  		if isErrorType(iface.obj.Type()) {
  1629  			g.Printf("@Override public String getMessage() { return error(); }\n\n")
  1630  		}
  1631  		for _, m := range iface.summary.callable {
  1632  			if !g.isSigSupported(m.Type()) {
  1633  				g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", n, m.Name())
  1634  				continue
  1635  			}
  1636  			g.Printf("public native ")
  1637  			g.genFuncSignature(m, nil, false)
  1638  		}
  1639  
  1640  		g.Outdent()
  1641  		g.Printf("}\n")
  1642  	}
  1643  
  1644  	g.Printf("\n")
  1645  
  1646  	for _, c := range g.constants {
  1647  		g.genConst(c)
  1648  	}
  1649  	g.Printf("\n")
  1650  	for _, v := range g.vars {
  1651  		g.genVar(v)
  1652  	}
  1653  	for _, f := range g.funcs {
  1654  		if !g.isSigSupported(f.Type()) {
  1655  			g.Printf("// skipped function %s with unsupported parameter or return types\n\n", f.Name())
  1656  			continue
  1657  		}
  1658  		g.javadoc(g.docs[f.Name()].Doc())
  1659  		g.Printf("public static native ")
  1660  		g.genFuncSignature(f, nil, false)
  1661  	}
  1662  
  1663  	g.Outdent()
  1664  	g.Printf("}\n")
  1665  
  1666  	if len(g.err) > 0 {
  1667  		return g.err
  1668  	}
  1669  	return nil
  1670  }
  1671  
  1672  // embeddedJavaClasses returns the possible empty list of Java types embedded
  1673  // in the given struct type.
  1674  func embeddedJavaClasses(t *types.Struct) []string {
  1675  	clsSet := make(map[string]struct{})
  1676  	var classes []string
  1677  	for i := 0; i < t.NumFields(); i++ {
  1678  		f := t.Field(i)
  1679  		if !f.Exported() {
  1680  			continue
  1681  		}
  1682  		if t := f.Type(); isJavaType(t) {
  1683  			cls := classNameFor(t)
  1684  			if _, exists := clsSet[cls]; !exists {
  1685  				clsSet[cls] = struct{}{}
  1686  				classes = append(classes, cls)
  1687  			}
  1688  		}
  1689  	}
  1690  	return classes
  1691  }
  1692  
  1693  func classNameFor(t types.Type) string {
  1694  	obj := t.(*types.Named).Obj()
  1695  	pkg := obj.Pkg()
  1696  	return strings.Replace(pkg.Path()[len("Java/"):], "/", ".", -1) + "." + obj.Name()
  1697  }
  1698  
  1699  func isJavaType(t types.Type) bool {
  1700  	return typePkgFirstElem(t) == "Java"
  1701  }
  1702  
  1703  const (
  1704  	javaPreamble = gobindPreamble + `// Java class %[1]s.%[2]s is a proxy for talking to a Go program.
  1705  //
  1706  //   autogenerated by gobind %[3]s %[4]s
  1707  package %[1]s;
  1708  
  1709  import go.Seq;
  1710  
  1711  `
  1712  	cPreamble = gobindPreamble + `// JNI functions for the Go <=> Java bridge.
  1713  //
  1714  //   autogenerated by gobind %[1]s %[2]s
  1715  
  1716  #include <android/log.h>
  1717  #include <stdint.h>
  1718  #include "seq.h"
  1719  #include "_cgo_export.h"
  1720  `
  1721  
  1722  	hPreamble = gobindPreamble + `// JNI function headers for the Go <=> Java bridge.
  1723  //
  1724  //   autogenerated by gobind %[1]s %[2]s
  1725  
  1726  #ifndef __%[3]s_H__
  1727  #define __%[3]s_H__
  1728  
  1729  #include <jni.h>
  1730  
  1731  `
  1732  )