github.com/acrespo/mobile@v0.0.0-20190107162257-dc0771356504/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  	"golang.org/x/mobile/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.isSigSupported(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  // javaTypeName returns the class name of a given Go type name. If
   358  // the type name clashes with the package class name, an underscore is
   359  // appended.
   360  func (g *JavaGen) javaTypeName(n string) string {
   361  	if n == JavaClassName(g.Pkg) {
   362  		return n + "_"
   363  	}
   364  	return n
   365  }
   366  
   367  func (g *JavaGen) javadoc(doc string) {
   368  	if doc == "" {
   369  		return
   370  	}
   371  	// JavaDoc expects HTML-escaped documentation.
   372  	g.Printf("/**\n * %s */\n", html.EscapeString(doc))
   373  }
   374  
   375  // hasThis reports whether a method has an implicit "this" parameter.
   376  func (g *JavaGen) hasThis(sName string, m *types.Func) bool {
   377  	sig := m.Type().(*types.Signature)
   378  	params := sig.Params()
   379  	if params.Len() == 0 {
   380  		return false
   381  	}
   382  	v := params.At(0)
   383  	if v.Name() != "this" {
   384  		return false
   385  	}
   386  	t, ok := v.Type().(*types.Named)
   387  	if !ok {
   388  		return false
   389  	}
   390  	obj := t.Obj()
   391  	pkg := obj.Pkg()
   392  	if pkgFirstElem(pkg) != "Java" {
   393  		return false
   394  	}
   395  	clsName := classNameFor(t)
   396  	exp := g.javaPkgName(g.Pkg) + "." + sName
   397  	if clsName != exp {
   398  		g.errorf("the type %s of the `this` argument to method %s.%s is not %s", clsName, sName, m.Name(), exp)
   399  		return false
   400  	}
   401  	return true
   402  }
   403  
   404  func (g *JavaGen) genConstructor(f *types.Func, n string, jcls bool) {
   405  	g.javadoc(g.docs[f.Name()].Doc())
   406  	g.Printf("public %s(", n)
   407  	g.genFuncArgs(f, nil, false)
   408  	g.Printf(") {\n")
   409  	g.Indent()
   410  	sig := f.Type().(*types.Signature)
   411  	params := sig.Params()
   412  	if jcls {
   413  		g.Printf("super(")
   414  		for i := 0; i < params.Len(); i++ {
   415  			if i > 0 {
   416  				g.Printf(", ")
   417  			}
   418  			g.Printf(g.paramName(params, i))
   419  		}
   420  		g.Printf(");\n")
   421  	}
   422  	g.Printf("this.refnum = ")
   423  	g.Printf("__%s(", f.Name())
   424  	for i := 0; i < params.Len(); i++ {
   425  		if i > 0 {
   426  			g.Printf(", ")
   427  		}
   428  		g.Printf(g.paramName(params, i))
   429  	}
   430  	g.Printf(");\n")
   431  	g.Printf("Seq.trackGoRef(refnum, this);\n")
   432  	g.Outdent()
   433  	g.Printf("}\n\n")
   434  	g.Printf("private static native int __%s(", f.Name())
   435  	g.genFuncArgs(f, nil, false)
   436  	g.Printf(");\n\n")
   437  }
   438  
   439  // genFuncArgs generated Java function arguments declaration for the function f.
   440  // If the supplied overridden java function is supplied, genFuncArgs omits the implicit
   441  // this argument.
   442  func (g *JavaGen) genFuncArgs(f *types.Func, jm *java.Func, hasThis bool) {
   443  	sig := f.Type().(*types.Signature)
   444  	params := sig.Params()
   445  	first := 0
   446  	if hasThis {
   447  		// Skip the implicit this argument to the Go method
   448  		first = 1
   449  	}
   450  	for i := first; i < params.Len(); i++ {
   451  		if i > first {
   452  			g.Printf(", ")
   453  		}
   454  		v := params.At(i)
   455  		name := g.paramName(params, i)
   456  		jt := g.javaType(v.Type())
   457  		g.Printf("%s %s", jt, name)
   458  	}
   459  }
   460  
   461  func (g *JavaGen) genObjectMethods(n string, fields []*types.Var, isStringer bool) {
   462  	g.Printf("@Override public boolean equals(Object o) {\n")
   463  	g.Indent()
   464  	g.Printf("if (o == null || !(o instanceof %s)) {\n    return false;\n}\n", n)
   465  	g.Printf("%s that = (%s)o;\n", n, n)
   466  	for _, f := range fields {
   467  		if t := f.Type(); !g.isSupported(t) {
   468  			g.Printf("// skipped field %s.%s with unsupported type: %s\n\n", n, f.Name(), t)
   469  			continue
   470  		}
   471  		nf := f.Name()
   472  		g.Printf("%s this%s = get%s();\n", g.javaType(f.Type()), nf, nf)
   473  		g.Printf("%s that%s = that.get%s();\n", g.javaType(f.Type()), nf, nf)
   474  		if isJavaPrimitive(f.Type()) {
   475  			g.Printf("if (this%s != that%s) {\n    return false;\n}\n", nf, nf)
   476  		} else {
   477  			g.Printf("if (this%s == null) {\n", nf)
   478  			g.Indent()
   479  			g.Printf("if (that%s != null) {\n    return false;\n}\n", nf)
   480  			g.Outdent()
   481  			g.Printf("} else if (!this%s.equals(that%s)) {\n    return false;\n}\n", nf, nf)
   482  		}
   483  	}
   484  	g.Printf("return true;\n")
   485  	g.Outdent()
   486  	g.Printf("}\n\n")
   487  
   488  	g.Printf("@Override public int hashCode() {\n")
   489  	g.Printf("    return java.util.Arrays.hashCode(new Object[] {")
   490  	idx := 0
   491  	for _, f := range fields {
   492  		if t := f.Type(); !g.isSupported(t) {
   493  			continue
   494  		}
   495  		if idx > 0 {
   496  			g.Printf(", ")
   497  		}
   498  		idx++
   499  		g.Printf("get%s()", f.Name())
   500  	}
   501  	g.Printf("});\n")
   502  	g.Printf("}\n\n")
   503  
   504  	g.Printf("@Override public String toString() {\n")
   505  	g.Indent()
   506  	if isStringer {
   507  		g.Printf("return string();\n")
   508  	} else {
   509  		g.Printf("StringBuilder b = new StringBuilder();\n")
   510  		g.Printf(`b.append("%s").append("{");`, n)
   511  		g.Printf("\n")
   512  		for _, f := range fields {
   513  			if t := f.Type(); !g.isSupported(t) {
   514  				continue
   515  			}
   516  			n := f.Name()
   517  			g.Printf(`b.append("%s:").append(get%s()).append(",");`, n, n)
   518  			g.Printf("\n")
   519  		}
   520  		g.Printf(`return b.append("}").toString();`)
   521  		g.Printf("\n")
   522  	}
   523  	g.Outdent()
   524  	g.Printf("}\n")
   525  }
   526  
   527  func (g *JavaGen) genInterface(iface interfaceInfo) {
   528  	pkgPath := ""
   529  	if g.Pkg != nil {
   530  		pkgPath = g.Pkg.Path()
   531  	}
   532  	g.Printf(javaPreamble, g.javaPkgName(g.Pkg), g.javaTypeName(iface.obj.Name()), g.gobindOpts(), pkgPath)
   533  
   534  	var exts []string
   535  	numM := iface.t.NumMethods()
   536  	for _, other := range g.allIntf {
   537  		// Only extend interfaces with fewer methods to avoid circular references
   538  		if other.t.NumMethods() < numM && types.AssignableTo(iface.t, other.t) {
   539  			n := other.obj.Name()
   540  			if p := other.obj.Pkg(); p != g.Pkg {
   541  				if n == JavaClassName(p) {
   542  					n = n + "_"
   543  				}
   544  				n = fmt.Sprintf("%s.%s", g.javaPkgName(p), n)
   545  			} else {
   546  				n = g.javaTypeName(n)
   547  			}
   548  			exts = append(exts, n)
   549  		}
   550  	}
   551  	doc := g.docs[iface.obj.Name()]
   552  	g.javadoc(doc.Doc())
   553  	g.Printf("public interface %s", g.javaTypeName(iface.obj.Name()))
   554  	if len(exts) > 0 {
   555  		g.Printf(" extends %s", strings.Join(exts, ", "))
   556  	}
   557  	g.Printf(" {\n")
   558  	g.Indent()
   559  
   560  	for _, m := range iface.summary.callable {
   561  		if !g.isSigSupported(m.Type()) {
   562  			g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", iface.obj.Name(), m.Name())
   563  			continue
   564  		}
   565  		g.javadoc(doc.Member(m.Name()))
   566  		g.Printf("public ")
   567  		g.genFuncSignature(m, nil, false)
   568  	}
   569  
   570  	g.Printf("\n")
   571  
   572  	g.Outdent()
   573  	g.Printf("}\n\n")
   574  }
   575  
   576  func isJavaPrimitive(T types.Type) bool {
   577  	b, ok := T.(*types.Basic)
   578  	if !ok {
   579  		return false
   580  	}
   581  	switch b.Kind() {
   582  	case types.Bool, types.Uint8, types.Float32, types.Float64,
   583  		types.Int, types.Int8, types.Int16, types.Int32, types.Int64:
   584  		return true
   585  	}
   586  	return false
   587  }
   588  
   589  // jniType returns a string that can be used as a JNI type.
   590  func (g *JavaGen) jniType(T types.Type) string {
   591  	switch T := T.(type) {
   592  	case *types.Basic:
   593  		switch T.Kind() {
   594  		case types.Bool, types.UntypedBool:
   595  			return "jboolean"
   596  		case types.Int:
   597  			return "jlong"
   598  		case types.Int8:
   599  			return "jbyte"
   600  		case types.Int16:
   601  			return "jshort"
   602  		case types.Int32, types.UntypedRune: // types.Rune
   603  			return "jint"
   604  		case types.Int64, types.UntypedInt:
   605  			return "jlong"
   606  		case types.Uint8: // types.Byte
   607  			// TODO(crawshaw): Java bytes are signed, so this is
   608  			// questionable, but vital.
   609  			return "jbyte"
   610  		// TODO(crawshaw): case types.Uint, types.Uint16, types.Uint32, types.Uint64:
   611  		case types.Float32:
   612  			return "jfloat"
   613  		case types.Float64, types.UntypedFloat:
   614  			return "jdouble"
   615  		case types.String, types.UntypedString:
   616  			return "jstring"
   617  		default:
   618  			g.errorf("unsupported basic type: %s", T)
   619  			return "TODO"
   620  		}
   621  	case *types.Slice:
   622  		return "jbyteArray"
   623  
   624  	case *types.Pointer:
   625  		if _, ok := T.Elem().(*types.Named); ok {
   626  			return g.jniType(T.Elem())
   627  		}
   628  		g.errorf("unsupported pointer to type: %s", T)
   629  	case *types.Named:
   630  		return "jobject"
   631  	default:
   632  		g.errorf("unsupported jniType: %#+v, %s\n", T, T)
   633  	}
   634  	return "TODO"
   635  }
   636  
   637  func (g *JavaGen) javaBasicType(T *types.Basic) string {
   638  	switch T.Kind() {
   639  	case types.Bool, types.UntypedBool:
   640  		return "boolean"
   641  	case types.Int:
   642  		return "long"
   643  	case types.Int8:
   644  		return "byte"
   645  	case types.Int16:
   646  		return "short"
   647  	case types.Int32, types.UntypedRune: // types.Rune
   648  		return "int"
   649  	case types.Int64, types.UntypedInt:
   650  		return "long"
   651  	case types.Uint8: // types.Byte
   652  		// TODO(crawshaw): Java bytes are signed, so this is
   653  		// questionable, but vital.
   654  		return "byte"
   655  	// TODO(crawshaw): case types.Uint, types.Uint16, types.Uint32, types.Uint64:
   656  	case types.Float32:
   657  		return "float"
   658  	case types.Float64, types.UntypedFloat:
   659  		return "double"
   660  	case types.String, types.UntypedString:
   661  		return "String"
   662  	default:
   663  		g.errorf("unsupported basic type: %s", T)
   664  		return "TODO"
   665  	}
   666  }
   667  
   668  // javaType returns a string that can be used as a Java type.
   669  func (g *JavaGen) javaType(T types.Type) string {
   670  	if isErrorType(T) {
   671  		// The error type is usually translated into an exception in
   672  		// Java, however the type can be exposed in other ways, such
   673  		// as an exported field.
   674  		return "java.lang.Exception"
   675  	} else if isJavaType(T) {
   676  		return classNameFor(T)
   677  	}
   678  	switch T := T.(type) {
   679  	case *types.Basic:
   680  		return g.javaBasicType(T)
   681  	case *types.Slice:
   682  		elem := g.javaType(T.Elem())
   683  		return elem + "[]"
   684  
   685  	case *types.Pointer:
   686  		if _, ok := T.Elem().(*types.Named); ok {
   687  			return g.javaType(T.Elem())
   688  		}
   689  		g.errorf("unsupported pointer to type: %s", T)
   690  	case *types.Named:
   691  		n := T.Obj()
   692  		nPkg := n.Pkg()
   693  		if !isErrorType(T) && !g.validPkg(nPkg) {
   694  			g.errorf("type %s is in %s, which is not bound", n.Name(), nPkg)
   695  			break
   696  		}
   697  		// TODO(crawshaw): more checking here
   698  		clsName := n.Name()
   699  		if nPkg != g.Pkg {
   700  			if clsName == JavaClassName(nPkg) {
   701  				clsName += "_"
   702  			}
   703  			return fmt.Sprintf("%s.%s", g.javaPkgName(nPkg), clsName)
   704  		} else {
   705  			return g.javaTypeName(clsName)
   706  		}
   707  	default:
   708  		g.errorf("unsupported javaType: %#+v, %s\n", T, T)
   709  	}
   710  	return "TODO"
   711  }
   712  
   713  func (g *JavaGen) genJNIFuncSignature(o *types.Func, sName string, jm *java.Func, proxy, isjava bool) {
   714  	sig := o.Type().(*types.Signature)
   715  	res := sig.Results()
   716  
   717  	var ret string
   718  	switch res.Len() {
   719  	case 2:
   720  		ret = g.jniType(res.At(0).Type())
   721  	case 1:
   722  		if isErrorType(res.At(0).Type()) {
   723  			ret = "void"
   724  		} else {
   725  			ret = g.jniType(res.At(0).Type())
   726  		}
   727  	case 0:
   728  		ret = "void"
   729  	default:
   730  		g.errorf("too many result values: %s", o)
   731  		return
   732  	}
   733  
   734  	g.Printf("JNIEXPORT %s JNICALL\n", ret)
   735  	g.Printf("Java_%s_", g.jniPkgName())
   736  	if sName != "" {
   737  		if proxy {
   738  			g.Printf(java.JNIMangle(g.className()))
   739  			// 0024 is the mangled form of $, for naming inner classes.
   740  			g.Printf("_00024proxy%s", sName)
   741  		} else {
   742  			g.Printf(java.JNIMangle(g.javaTypeName(sName)))
   743  		}
   744  	} else {
   745  		g.Printf(java.JNIMangle(g.className()))
   746  	}
   747  	g.Printf("_")
   748  	if jm != nil {
   749  		g.Printf(jm.JNIName)
   750  	} else {
   751  		oName := javaNameReplacer(lowerFirst(o.Name()))
   752  		g.Printf(java.JNIMangle(oName))
   753  	}
   754  	g.Printf("(JNIEnv* env, ")
   755  	if sName != "" {
   756  		g.Printf("jobject __this__")
   757  	} else {
   758  		g.Printf("jclass _clazz")
   759  	}
   760  	params := sig.Params()
   761  	i := 0
   762  	if isjava && params.Len() > 0 && params.At(0).Name() == "this" {
   763  		// Skip the implicit this argument, if any.
   764  		i = 1
   765  	}
   766  	for ; i < params.Len(); i++ {
   767  		g.Printf(", ")
   768  		v := sig.Params().At(i)
   769  		name := g.paramName(params, i)
   770  		jt := g.jniType(v.Type())
   771  		g.Printf("%s %s", jt, name)
   772  	}
   773  	g.Printf(")")
   774  }
   775  
   776  func (g *JavaGen) jniPkgName() string {
   777  	return strings.Replace(java.JNIMangle(g.javaPkgName(g.Pkg)), ".", "_", -1)
   778  }
   779  
   780  var javaLetterDigitRE = regexp.MustCompile(`[0-9a-zA-Z$_]`)
   781  
   782  func (g *JavaGen) paramName(params *types.Tuple, pos int) string {
   783  	name := basicParamName(params, pos)
   784  	if !javaLetterDigitRE.MatchString(name) {
   785  		name = fmt.Sprintf("p%d", pos)
   786  	}
   787  	return javaNameReplacer(name)
   788  }
   789  
   790  func (g *JavaGen) genFuncSignature(o *types.Func, jm *java.Func, hasThis bool) {
   791  	sig := o.Type().(*types.Signature)
   792  	res := sig.Results()
   793  
   794  	var returnsError bool
   795  	var ret string
   796  	switch res.Len() {
   797  	case 2:
   798  		if !isErrorType(res.At(1).Type()) {
   799  			g.errorf("second result value must be of type error: %s", o)
   800  			return
   801  		}
   802  		returnsError = true
   803  		ret = g.javaType(res.At(0).Type())
   804  	case 1:
   805  		if isErrorType(res.At(0).Type()) {
   806  			returnsError = true
   807  			ret = "void"
   808  		} else {
   809  			ret = g.javaType(res.At(0).Type())
   810  		}
   811  	case 0:
   812  		ret = "void"
   813  	default:
   814  		g.errorf("too many result values: %s", o)
   815  		return
   816  	}
   817  
   818  	g.Printf("%s ", ret)
   819  	if jm != nil {
   820  		g.Printf(jm.Name)
   821  	} else {
   822  		g.Printf(javaNameReplacer(lowerFirst(o.Name())))
   823  	}
   824  	g.Printf("(")
   825  	g.genFuncArgs(o, jm, hasThis)
   826  	g.Printf(")")
   827  	if returnsError {
   828  		if jm != nil {
   829  			if jm.Throws == "" {
   830  				g.errorf("%s declares an error return value but the overriden method does not throw", o)
   831  				return
   832  			}
   833  			g.Printf(" throws %s", jm.Throws)
   834  		} else {
   835  			g.Printf(" throws Exception")
   836  		}
   837  	}
   838  	g.Printf(";\n")
   839  }
   840  
   841  func (g *JavaGen) genVar(o *types.Var) {
   842  	if t := o.Type(); !g.isSupported(t) {
   843  		g.Printf("// skipped variable %s with unsupported type: %s\n\n", o.Name(), t)
   844  		return
   845  	}
   846  	jType := g.javaType(o.Type())
   847  
   848  	doc := g.docs[o.Name()].Doc()
   849  	// setter
   850  	g.javadoc(doc)
   851  	g.Printf("public static native void set%s(%s v);\n", o.Name(), jType)
   852  
   853  	// getter
   854  	g.javadoc(doc)
   855  	g.Printf("public static native %s get%s();\n\n", jType, o.Name())
   856  }
   857  
   858  // genCRetClear clears the result value from a JNI call if an exception was
   859  // raised.
   860  func (g *JavaGen) genCRetClear(varName string, t types.Type, exc string) {
   861  	g.Printf("if (%s != NULL) {\n", exc)
   862  	g.Indent()
   863  	switch t := t.(type) {
   864  	case *types.Basic:
   865  		switch t.Kind() {
   866  		case types.String:
   867  			g.Printf("%s = NULL;\n", varName)
   868  		default:
   869  			g.Printf("%s = 0;\n", varName)
   870  		}
   871  	case *types.Slice, *types.Named, *types.Pointer:
   872  		g.Printf("%s = NULL;\n", varName)
   873  	}
   874  	g.Outdent()
   875  	g.Printf("}\n")
   876  }
   877  
   878  func (g *JavaGen) genJavaToC(varName string, t types.Type, mode varMode) {
   879  	switch t := t.(type) {
   880  	case *types.Basic:
   881  		switch t.Kind() {
   882  		case types.String:
   883  			g.Printf("nstring _%s = go_seq_from_java_string(env, %s);\n", varName, varName)
   884  		default:
   885  			g.Printf("%s _%s = (%s)%s;\n", g.cgoType(t), varName, g.cgoType(t), varName)
   886  		}
   887  	case *types.Slice:
   888  		switch e := t.Elem().(type) {
   889  		case *types.Basic:
   890  			switch e.Kind() {
   891  			case types.Uint8: // Byte.
   892  				g.Printf("nbyteslice _%s = go_seq_from_java_bytearray(env, %s, %d);\n", varName, varName, toCFlag(mode == modeRetained))
   893  			default:
   894  				g.errorf("unsupported type: %s", t)
   895  			}
   896  		default:
   897  			g.errorf("unsupported type: %s", t)
   898  		}
   899  	case *types.Named:
   900  		switch u := t.Underlying().(type) {
   901  		case *types.Interface:
   902  			g.Printf("int32_t _%s = go_seq_to_refnum(env, %s);\n", varName, varName)
   903  		default:
   904  			g.errorf("unsupported named type: %s / %T", u, u)
   905  		}
   906  	case *types.Pointer:
   907  		g.Printf("int32_t _%s = go_seq_to_refnum(env, %s);\n", varName, varName)
   908  	default:
   909  		g.Printf("%s _%s = (%s)%s;\n", g.cgoType(t), varName, g.cgoType(t), varName)
   910  	}
   911  }
   912  
   913  func (g *JavaGen) genCToJava(toName, fromName string, t types.Type, mode varMode) {
   914  	switch t := t.(type) {
   915  	case *types.Basic:
   916  		switch t.Kind() {
   917  		case types.String:
   918  			g.Printf("jstring %s = go_seq_to_java_string(env, %s);\n", toName, fromName)
   919  		case types.Bool:
   920  			g.Printf("jboolean %s = %s ? JNI_TRUE : JNI_FALSE;\n", toName, fromName)
   921  		default:
   922  			g.Printf("%s %s = (%s)%s;\n", g.jniType(t), toName, g.jniType(t), fromName)
   923  		}
   924  	case *types.Slice:
   925  		switch e := t.Elem().(type) {
   926  		case *types.Basic:
   927  			switch e.Kind() {
   928  			case types.Uint8: // Byte.
   929  				g.Printf("jbyteArray %s = go_seq_to_java_bytearray(env, %s, %d);\n", toName, fromName, toCFlag(mode == modeRetained))
   930  			default:
   931  				g.errorf("unsupported type: %s", t)
   932  			}
   933  		default:
   934  			g.errorf("unsupported type: %s", t)
   935  		}
   936  	case *types.Pointer:
   937  		// TODO(crawshaw): test *int
   938  		// TODO(crawshaw): test **Generator
   939  		switch t := t.Elem().(type) {
   940  		case *types.Named:
   941  			g.genFromRefnum(toName, fromName, t, t.Obj())
   942  		default:
   943  			g.errorf("unsupported type %s", t)
   944  		}
   945  	case *types.Named:
   946  		switch t.Underlying().(type) {
   947  		case *types.Interface, *types.Pointer:
   948  			g.genFromRefnum(toName, fromName, t, t.Obj())
   949  		default:
   950  			g.errorf("unsupported, direct named type %s", t)
   951  		}
   952  	default:
   953  		g.Printf("%s %s = (%s)%s;\n", g.jniType(t), toName, g.jniType(t), fromName)
   954  	}
   955  }
   956  
   957  func (g *JavaGen) genFromRefnum(toName, fromName string, t types.Type, o *types.TypeName) {
   958  	oPkg := o.Pkg()
   959  	isJava := isJavaType(o.Type())
   960  	if !isErrorType(o.Type()) && !g.validPkg(oPkg) && !isJava {
   961  		g.errorf("type %s is defined in package %s, which is not bound", t, oPkg)
   962  		return
   963  	}
   964  	p := pkgPrefix(oPkg)
   965  	g.Printf("jobject %s = go_seq_from_refnum(env, %s, ", toName, fromName)
   966  	if isJava {
   967  		g.Printf("NULL, NULL")
   968  	} else {
   969  		g.Printf("proxy_class_%s_%s, proxy_class_%s_%s_cons", p, o.Name(), p, o.Name())
   970  	}
   971  	g.Printf(");\n")
   972  }
   973  
   974  func (g *JavaGen) gobindOpts() string {
   975  	opts := []string{"-lang=java"}
   976  	if g.JavaPkg != "" {
   977  		opts = append(opts, "-javapkg="+g.JavaPkg)
   978  	}
   979  	return strings.Join(opts, " ")
   980  }
   981  
   982  var javaNameReplacer = newNameSanitizer([]string{
   983  	"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char",
   984  	"class", "const", "continue", "default", "do", "double", "else", "enum",
   985  	"extends", "final", "finally", "float", "for", "goto", "if", "implements",
   986  	"import", "instanceof", "int", "interface", "long", "native", "new", "package",
   987  	"private", "protected", "public", "return", "short", "static", "strictfp",
   988  	"super", "switch", "synchronized", "this", "throw", "throws", "transient",
   989  	"try", "void", "volatile", "while", "false", "null", "true"})
   990  
   991  func (g *JavaGen) javaPkgName(pkg *types.Package) string {
   992  	return JavaPkgName(g.JavaPkg, pkg)
   993  }
   994  
   995  // JavaPkgName returns the Java package name for a Go package
   996  // given a pkg prefix. If the prefix is empty, "go" is used
   997  // instead.
   998  func JavaPkgName(pkgPrefix string, pkg *types.Package) string {
   999  	if pkg == nil {
  1000  		return "go"
  1001  	}
  1002  	s := javaNameReplacer(pkg.Name())
  1003  	if pkgPrefix == "" {
  1004  		return s
  1005  	}
  1006  	return pkgPrefix + "." + s
  1007  }
  1008  
  1009  func (g *JavaGen) className() string {
  1010  	return JavaClassName(g.Pkg)
  1011  }
  1012  
  1013  // JavaClassName returns the name of the Java class that
  1014  // contains Go package level identifiers.
  1015  func JavaClassName(pkg *types.Package) string {
  1016  	if pkg == nil {
  1017  		return "Universe"
  1018  	}
  1019  	return javaNameReplacer(strings.Title(pkg.Name()))
  1020  }
  1021  
  1022  func (g *JavaGen) genConst(o *types.Const) {
  1023  	if _, ok := o.Type().(*types.Basic); !ok || !g.isSupported(o.Type()) {
  1024  		g.Printf("// skipped const %s with unsupported type: %s\n\n", o.Name(), o.Type())
  1025  		return
  1026  	}
  1027  	// TODO(hyangah): should const names use upper cases + "_"?
  1028  	// TODO(hyangah): check invalid names.
  1029  	jType := g.javaType(o.Type())
  1030  	val := o.Val().ExactString()
  1031  	switch b := o.Type().(*types.Basic); b.Kind() {
  1032  	case types.Int64, types.UntypedInt:
  1033  		i, exact := constant.Int64Val(o.Val())
  1034  		if !exact {
  1035  			g.errorf("const value %s for %s cannot be represented as %s", val, o.Name(), jType)
  1036  			return
  1037  		}
  1038  		val = fmt.Sprintf("%dL", i)
  1039  
  1040  	case types.Float32:
  1041  		f, _ := constant.Float32Val(o.Val())
  1042  		val = fmt.Sprintf("%gf", f)
  1043  
  1044  	case types.Float64, types.UntypedFloat:
  1045  		f, _ := constant.Float64Val(o.Val())
  1046  		if math.IsInf(f, 0) || math.Abs(f) > math.MaxFloat64 {
  1047  			g.errorf("const value %s for %s cannot be represented as %s", val, o.Name(), jType)
  1048  			return
  1049  		}
  1050  		val = fmt.Sprintf("%g", f)
  1051  	}
  1052  	g.javadoc(g.docs[o.Name()].Doc())
  1053  	g.Printf("public static final %s %s = %s;\n", g.javaType(o.Type()), o.Name(), val)
  1054  }
  1055  
  1056  func (g *JavaGen) genJNIField(o *types.TypeName, f *types.Var) {
  1057  	if t := f.Type(); !g.isSupported(t) {
  1058  		g.Printf("// skipped field %s with unsupported type: %s\n\n", o.Name(), t)
  1059  		return
  1060  	}
  1061  	n := java.JNIMangle(g.javaTypeName(o.Name()))
  1062  	// setter
  1063  	g.Printf("JNIEXPORT void JNICALL\n")
  1064  	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()))
  1065  	g.Indent()
  1066  	g.Printf("int32_t o = go_seq_to_refnum_go(env, this);\n")
  1067  	g.genJavaToC("v", f.Type(), modeRetained)
  1068  	g.Printf("proxy%s_%s_%s_Set(o, _v);\n", g.pkgPrefix, o.Name(), f.Name())
  1069  	g.genRelease("v", f.Type(), modeRetained)
  1070  	g.Outdent()
  1071  	g.Printf("}\n\n")
  1072  
  1073  	// getter
  1074  	g.Printf("JNIEXPORT %s JNICALL\n", g.jniType(f.Type()))
  1075  	g.Printf("Java_%s_%s_get%s(JNIEnv *env, jobject this) {\n", g.jniPkgName(), n, java.JNIMangle(f.Name()))
  1076  	g.Indent()
  1077  	g.Printf("int32_t o = go_seq_to_refnum_go(env, this);\n")
  1078  	g.Printf("%s r0 = ", g.cgoType(f.Type()))
  1079  	g.Printf("proxy%s_%s_%s_Get(o);\n", g.pkgPrefix, o.Name(), f.Name())
  1080  	g.genCToJava("_r0", "r0", f.Type(), modeRetained)
  1081  	g.Printf("return _r0;\n")
  1082  	g.Outdent()
  1083  	g.Printf("}\n\n")
  1084  }
  1085  
  1086  func (g *JavaGen) genJNIVar(o *types.Var) {
  1087  	if t := o.Type(); !g.isSupported(t) {
  1088  		g.Printf("// skipped variable %s with unsupported type: %s\n\n", o.Name(), t)
  1089  		return
  1090  	}
  1091  	n := java.JNIMangle(g.javaTypeName(o.Name()))
  1092  	// setter
  1093  	g.Printf("JNIEXPORT void JNICALL\n")
  1094  	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()))
  1095  	g.Indent()
  1096  	g.genJavaToC("v", o.Type(), modeRetained)
  1097  	g.Printf("var_set%s_%s(_v);\n", g.pkgPrefix, o.Name())
  1098  	g.genRelease("v", o.Type(), modeRetained)
  1099  	g.Outdent()
  1100  	g.Printf("}\n\n")
  1101  
  1102  	// getter
  1103  	g.Printf("JNIEXPORT %s JNICALL\n", g.jniType(o.Type()))
  1104  	g.Printf("Java_%s_%s_get%s(JNIEnv *env, jclass clazz) {\n", g.jniPkgName(), java.JNIMangle(g.className()), n)
  1105  	g.Indent()
  1106  	g.Printf("%s r0 = ", g.cgoType(o.Type()))
  1107  	g.Printf("var_get%s_%s();\n", g.pkgPrefix, o.Name())
  1108  	g.genCToJava("_r0", "r0", o.Type(), modeRetained)
  1109  	g.Printf("return _r0;\n")
  1110  	g.Outdent()
  1111  	g.Printf("}\n\n")
  1112  }
  1113  
  1114  func (g *JavaGen) genJNIConstructor(f *types.Func, sName string) {
  1115  	if !g.isSigSupported(f.Type()) {
  1116  		return
  1117  	}
  1118  	sig := f.Type().(*types.Signature)
  1119  	res := sig.Results()
  1120  
  1121  	g.Printf("JNIEXPORT jint JNICALL\n")
  1122  	g.Printf("Java_%s_%s_%s(JNIEnv *env, jclass clazz", g.jniPkgName(), java.JNIMangle(g.javaTypeName(sName)), java.JNIMangle("__"+f.Name()))
  1123  	params := sig.Params()
  1124  	for i := 0; i < params.Len(); i++ {
  1125  		v := params.At(i)
  1126  		jt := g.jniType(v.Type())
  1127  		g.Printf(", %s %s", jt, g.paramName(params, i))
  1128  	}
  1129  	g.Printf(") {\n")
  1130  	g.Indent()
  1131  	for i := 0; i < params.Len(); i++ {
  1132  		name := g.paramName(params, i)
  1133  		g.genJavaToC(name, params.At(i).Type(), modeTransient)
  1134  	}
  1135  	// Constructors always return a mandatory *T and an optional error
  1136  	if res.Len() == 1 {
  1137  		g.Printf("int32_t refnum = proxy%s__%s(", g.pkgPrefix, f.Name())
  1138  	} else {
  1139  		g.Printf("struct proxy%s__%s_return res = proxy%s__%s(", g.pkgPrefix, f.Name(), g.pkgPrefix, f.Name())
  1140  	}
  1141  	for i := 0; i < params.Len(); i++ {
  1142  		if i > 0 {
  1143  			g.Printf(", ")
  1144  		}
  1145  		g.Printf("_%s", g.paramName(params, i))
  1146  	}
  1147  	g.Printf(");\n")
  1148  	for i := 0; i < params.Len(); i++ {
  1149  		g.genRelease(g.paramName(params, i), params.At(i).Type(), modeTransient)
  1150  	}
  1151  	// Extract multi returns and handle errors
  1152  	if res.Len() == 2 {
  1153  		g.Printf("int32_t refnum = res.r0;\n")
  1154  		g.genCToJava("_err", "res.r1", res.At(1).Type(), modeRetained)
  1155  		g.Printf("go_seq_maybe_throw_exception(env, _err);\n")
  1156  	}
  1157  	g.Printf("return refnum;\n")
  1158  	g.Outdent()
  1159  	g.Printf("}\n\n")
  1160  }
  1161  
  1162  func (g *JavaGen) genJNIFunc(o *types.Func, sName string, jm *java.Func, proxy, isjava bool) {
  1163  	if !g.isSigSupported(o.Type()) {
  1164  		n := o.Name()
  1165  		if sName != "" {
  1166  			n = sName + "." + n
  1167  		}
  1168  		g.Printf("// skipped function %s with unsupported parameter or return types\n\n", n)
  1169  		return
  1170  	}
  1171  	g.genJNIFuncSignature(o, sName, jm, proxy, isjava)
  1172  
  1173  	g.Printf(" {\n")
  1174  	g.Indent()
  1175  	g.genJNIFuncBody(o, sName, jm, isjava)
  1176  	g.Outdent()
  1177  	g.Printf("}\n\n")
  1178  }
  1179  
  1180  func (g *JavaGen) genJNIFuncBody(o *types.Func, sName string, jm *java.Func, isjava bool) {
  1181  	sig := o.Type().(*types.Signature)
  1182  	res := sig.Results()
  1183  	if sName != "" {
  1184  		g.Printf("int32_t o = go_seq_to_refnum_go(env, __this__);\n")
  1185  	}
  1186  	params := sig.Params()
  1187  	first := 0
  1188  	if isjava && params.Len() > 0 && params.At(0).Name() == "this" {
  1189  		// Start after the implicit this argument.
  1190  		first = 1
  1191  		g.Printf("int32_t _%s = go_seq_to_refnum(env, __this__);\n", g.paramName(params, 0))
  1192  	}
  1193  	for i := first; i < params.Len(); i++ {
  1194  		name := g.paramName(params, i)
  1195  		g.genJavaToC(name, params.At(i).Type(), modeTransient)
  1196  	}
  1197  	resPrefix := ""
  1198  	if res.Len() > 0 {
  1199  		if res.Len() == 1 {
  1200  			g.Printf("%s r0 = ", g.cgoType(res.At(0).Type()))
  1201  		} else {
  1202  			resPrefix = "res."
  1203  			g.Printf("struct proxy%s_%s_%s_return res = ", g.pkgPrefix, sName, o.Name())
  1204  		}
  1205  	}
  1206  	g.Printf("proxy%s_%s_%s(", g.pkgPrefix, sName, o.Name())
  1207  	if sName != "" {
  1208  		g.Printf("o")
  1209  	}
  1210  	// Pass all arguments, including the implicit this argument.
  1211  	for i := 0; i < params.Len(); i++ {
  1212  		if i > 0 || sName != "" {
  1213  			g.Printf(", ")
  1214  		}
  1215  		g.Printf("_%s", g.paramName(params, i))
  1216  	}
  1217  	g.Printf(");\n")
  1218  	for i := first; i < params.Len(); i++ {
  1219  		g.genRelease(g.paramName(params, i), params.At(i).Type(), modeTransient)
  1220  	}
  1221  	for i := 0; i < res.Len(); i++ {
  1222  		tn := fmt.Sprintf("_r%d", i)
  1223  		t := res.At(i).Type()
  1224  		g.genCToJava(tn, fmt.Sprintf("%sr%d", resPrefix, i), t, modeRetained)
  1225  	}
  1226  	// Go backwards so that any exception is thrown before
  1227  	// the return.
  1228  	for i := res.Len() - 1; i >= 0; i-- {
  1229  		t := res.At(i).Type()
  1230  		if !isErrorType(t) {
  1231  			g.Printf("return _r%d;\n", i)
  1232  		} else {
  1233  			g.Printf("go_seq_maybe_throw_exception(env, _r%d);\n", i)
  1234  		}
  1235  	}
  1236  }
  1237  
  1238  // genRelease cleans up arguments that weren't copied in genJavaToC.
  1239  func (g *JavaGen) genRelease(varName string, t types.Type, mode varMode) {
  1240  	switch t := t.(type) {
  1241  	case *types.Basic:
  1242  	case *types.Slice:
  1243  		switch e := t.Elem().(type) {
  1244  		case *types.Basic:
  1245  			switch e.Kind() {
  1246  			case types.Uint8: // Byte.
  1247  				if mode == modeTransient {
  1248  					g.Printf("go_seq_release_byte_array(env, %s, _%s.ptr);\n", varName, varName)
  1249  				}
  1250  			}
  1251  		}
  1252  	}
  1253  }
  1254  
  1255  func (g *JavaGen) genMethodInterfaceProxy(oName string, m *types.Func) {
  1256  	if !g.isSigSupported(m.Type()) {
  1257  		g.Printf("// skipped method %s with unsupported parameter or return types\n\n", oName)
  1258  		return
  1259  	}
  1260  	sig := m.Type().(*types.Signature)
  1261  	params := sig.Params()
  1262  	res := sig.Results()
  1263  	g.genInterfaceMethodSignature(m, oName, false, g.paramName)
  1264  	g.Indent()
  1265  	g.Printf("JNIEnv *env = go_seq_push_local_frame(%d);\n", params.Len())
  1266  	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)
  1267  	for i := 0; i < params.Len(); i++ {
  1268  		pn := g.paramName(params, i)
  1269  		g.genCToJava("_"+pn, pn, params.At(i).Type(), modeTransient)
  1270  	}
  1271  	if res.Len() > 0 && !isErrorType(res.At(0).Type()) {
  1272  		t := res.At(0).Type()
  1273  		g.Printf("%s res = (*env)->Call%sMethod(env, o, ", g.jniType(t), g.jniCallType(t))
  1274  	} else {
  1275  		g.Printf("(*env)->CallVoidMethod(env, o, ")
  1276  	}
  1277  	g.Printf("mid_%s_%s", oName, m.Name())
  1278  	for i := 0; i < params.Len(); i++ {
  1279  		g.Printf(", _%s", g.paramName(params, i))
  1280  	}
  1281  	g.Printf(");\n")
  1282  	var retName string
  1283  	if res.Len() > 0 {
  1284  		t := res.At(0).Type()
  1285  		if res.Len() == 2 || isErrorType(t) {
  1286  			g.Printf("jobject exc = go_seq_get_exception(env);\n")
  1287  			errType := types.Universe.Lookup("error").Type()
  1288  			g.genJavaToC("exc", errType, modeRetained)
  1289  			retName = "_exc"
  1290  		}
  1291  		if !isErrorType(t) {
  1292  			if res.Len() == 2 {
  1293  				g.genCRetClear("res", t, "exc")
  1294  			}
  1295  			g.genJavaToC("res", t, modeRetained)
  1296  			retName = "_res"
  1297  		}
  1298  
  1299  		if res.Len() > 1 {
  1300  			g.Printf("cproxy%s_%s_%s_return sres = {\n", g.pkgPrefix, oName, m.Name())
  1301  			g.Printf("	_res, _exc\n")
  1302  			g.Printf("};\n")
  1303  			retName = "sres"
  1304  		}
  1305  	}
  1306  	g.Printf("go_seq_pop_local_frame(env);\n")
  1307  	if retName != "" {
  1308  		g.Printf("return %s;\n", retName)
  1309  	}
  1310  	g.Outdent()
  1311  	g.Printf("}\n\n")
  1312  }
  1313  
  1314  func (g *JavaGen) GenH() error {
  1315  	pkgPath := ""
  1316  	if g.Pkg != nil {
  1317  		pkgPath = g.Pkg.Path()
  1318  	}
  1319  	g.Printf(hPreamble, g.gobindOpts(), pkgPath, g.className())
  1320  	for _, iface := range g.interfaces {
  1321  		g.Printf("extern jclass proxy_class_%s_%s;\n", g.pkgPrefix, iface.obj.Name())
  1322  		g.Printf("extern jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, iface.obj.Name())
  1323  		g.Printf("\n")
  1324  		for _, m := range iface.summary.callable {
  1325  			if !g.isSigSupported(m.Type()) {
  1326  				g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", iface.obj.Name(), m.Name())
  1327  				continue
  1328  			}
  1329  			g.genInterfaceMethodSignature(m, iface.obj.Name(), true, g.paramName)
  1330  			g.Printf("\n")
  1331  		}
  1332  	}
  1333  	for _, s := range g.structs {
  1334  		g.Printf("extern jclass proxy_class_%s_%s;\n", g.pkgPrefix, s.obj.Name())
  1335  		g.Printf("extern jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, s.obj.Name())
  1336  	}
  1337  	g.Printf("#endif\n")
  1338  	if len(g.err) > 0 {
  1339  		return g.err
  1340  	}
  1341  	return nil
  1342  }
  1343  
  1344  func (g *JavaGen) jniCallType(t types.Type) string {
  1345  	switch t := t.(type) {
  1346  	case *types.Basic:
  1347  		switch t.Kind() {
  1348  		case types.Bool, types.UntypedBool:
  1349  			return "Boolean"
  1350  		case types.Int:
  1351  			return "Long"
  1352  		case types.Int8, types.Uint8: // types.Byte
  1353  			return "Byte"
  1354  		case types.Int16:
  1355  			return "Short"
  1356  		case types.Int32, types.UntypedRune: // types.Rune
  1357  			return "Int"
  1358  		case types.Int64, types.UntypedInt:
  1359  			return "Long"
  1360  		case types.Float32:
  1361  			return "Float"
  1362  		case types.Float64, types.UntypedFloat:
  1363  			return "Double"
  1364  		case types.String, types.UntypedString:
  1365  			return "Object"
  1366  		default:
  1367  			g.errorf("unsupported basic type: %s", t)
  1368  		}
  1369  	case *types.Slice:
  1370  		return "Object"
  1371  	case *types.Pointer:
  1372  		if _, ok := t.Elem().(*types.Named); ok {
  1373  			return g.jniCallType(t.Elem())
  1374  		}
  1375  		g.errorf("unsupported pointer to type: %s", t)
  1376  	case *types.Named:
  1377  		return "Object"
  1378  	default:
  1379  		return "Object"
  1380  	}
  1381  	return "TODO"
  1382  }
  1383  
  1384  func (g *JavaGen) jniClassSigPrefix(pkg *types.Package) string {
  1385  	return strings.Replace(g.javaPkgName(pkg), ".", "/", -1) + "/"
  1386  }
  1387  
  1388  func (g *JavaGen) jniSigType(T types.Type) string {
  1389  	if isErrorType(T) {
  1390  		return "Ljava/lang/Exception;"
  1391  	}
  1392  	switch T := T.(type) {
  1393  	case *types.Basic:
  1394  		switch T.Kind() {
  1395  		case types.Bool, types.UntypedBool:
  1396  			return "Z"
  1397  		case types.Int:
  1398  			return "J"
  1399  		case types.Int8:
  1400  			return "B"
  1401  		case types.Int16:
  1402  			return "S"
  1403  		case types.Int32, types.UntypedRune: // types.Rune
  1404  			return "I"
  1405  		case types.Int64, types.UntypedInt:
  1406  			return "J"
  1407  		case types.Uint8: // types.Byte
  1408  			return "B"
  1409  		case types.Float32:
  1410  			return "F"
  1411  		case types.Float64, types.UntypedFloat:
  1412  			return "D"
  1413  		case types.String, types.UntypedString:
  1414  			return "Ljava/lang/String;"
  1415  		default:
  1416  			g.errorf("unsupported basic type: %s", T)
  1417  			return "TODO"
  1418  		}
  1419  	case *types.Slice:
  1420  		return "[" + g.jniSigType(T.Elem())
  1421  	case *types.Pointer:
  1422  		if _, ok := T.Elem().(*types.Named); ok {
  1423  			return g.jniSigType(T.Elem())
  1424  		}
  1425  		g.errorf("unsupported pointer to type: %s", T)
  1426  	case *types.Named:
  1427  		return "L" + g.jniClassSigPrefix(T.Obj().Pkg()) + g.javaTypeName(T.Obj().Name()) + ";"
  1428  	default:
  1429  		g.errorf("unsupported jniType: %#+v, %s\n", T, T)
  1430  	}
  1431  	return "TODO"
  1432  }
  1433  
  1434  func (g *JavaGen) GenC() error {
  1435  	var pkgName, pkgPath string
  1436  	if g.Pkg != nil {
  1437  		pkgName = g.Pkg.Name()
  1438  		pkgPath = g.Pkg.Path()
  1439  	} else {
  1440  		pkgName = "universe"
  1441  	}
  1442  	g.Printf(cPreamble, g.gobindOpts(), pkgPath)
  1443  	g.Printf("#include %q\n", pkgName+".h")
  1444  	if g.Pkg != nil {
  1445  		for _, pkg := range g.Pkg.Imports() {
  1446  			if g.validPkg(pkg) {
  1447  				g.Printf("#include \"%s.h\"\n", pkg.Name())
  1448  			}
  1449  		}
  1450  	}
  1451  	g.Printf("\n")
  1452  
  1453  	for _, iface := range g.interfaces {
  1454  		g.Printf("jclass proxy_class_%s_%s;\n", g.pkgPrefix, iface.obj.Name())
  1455  		g.Printf("jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, iface.obj.Name())
  1456  		for _, m := range iface.summary.callable {
  1457  			if !g.isSigSupported(m.Type()) {
  1458  				g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", iface.obj.Name(), m.Name())
  1459  				continue
  1460  			}
  1461  			g.Printf("static jmethodID mid_%s_%s;\n", iface.obj.Name(), m.Name())
  1462  		}
  1463  	}
  1464  	for _, s := range g.structs {
  1465  		g.Printf("jclass proxy_class_%s_%s;\n", g.pkgPrefix, s.obj.Name())
  1466  		g.Printf("jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, s.obj.Name())
  1467  	}
  1468  	g.Printf("\n")
  1469  	g.Printf("JNIEXPORT void JNICALL\n")
  1470  	g.Printf("Java_%s_%s__1init(JNIEnv *env, jclass _unused) {\n", g.jniPkgName(), java.JNIMangle(g.className()))
  1471  	g.Indent()
  1472  	g.Printf("jclass clazz;\n")
  1473  	for _, s := range g.structs {
  1474  		if jinf, ok := g.jstructs[s.obj]; ok {
  1475  			// Leave the class and constructor NULL for Java classes with no
  1476  			// default constructor.
  1477  			if !jinf.genNoargCon {
  1478  				continue
  1479  			}
  1480  		}
  1481  		g.Printf("clazz = (*env)->FindClass(env, %q);\n", g.jniClassSigPrefix(s.obj.Pkg())+g.javaTypeName(s.obj.Name()))
  1482  		g.Printf("proxy_class_%s_%s = (*env)->NewGlobalRef(env, clazz);\n", g.pkgPrefix, s.obj.Name())
  1483  		g.Printf("proxy_class_%s_%s_cons = (*env)->GetMethodID(env, clazz, \"<init>\", \"(I)V\");\n", g.pkgPrefix, s.obj.Name())
  1484  	}
  1485  	for _, iface := range g.interfaces {
  1486  		pkg := iface.obj.Pkg()
  1487  		g.Printf("clazz = (*env)->FindClass(env, %q);\n", g.jniClassSigPrefix(pkg)+JavaClassName(pkg)+"$proxy"+iface.obj.Name())
  1488  		g.Printf("proxy_class_%s_%s = (*env)->NewGlobalRef(env, clazz);\n", g.pkgPrefix, iface.obj.Name())
  1489  		g.Printf("proxy_class_%s_%s_cons = (*env)->GetMethodID(env, clazz, \"<init>\", \"(I)V\");\n", g.pkgPrefix, iface.obj.Name())
  1490  		if isErrorType(iface.obj.Type()) {
  1491  			// As a special case, Java Exceptions are passed to Go pretending to implement the Go error interface.
  1492  			// To complete the illusion, use the Throwable.getMessage method for proxied calls to the error.Error method.
  1493  			g.Printf("clazz = (*env)->FindClass(env, \"java/lang/Throwable\");\n")
  1494  			g.Printf("mid_error_Error = (*env)->GetMethodID(env, clazz, \"getMessage\", \"()Ljava/lang/String;\");\n")
  1495  			continue
  1496  		}
  1497  		g.Printf("clazz = (*env)->FindClass(env, %q);\n", g.jniClassSigPrefix(pkg)+g.javaTypeName(iface.obj.Name()))
  1498  		for _, m := range iface.summary.callable {
  1499  			if !g.isSigSupported(m.Type()) {
  1500  				g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", iface.obj.Name(), m.Name())
  1501  				continue
  1502  			}
  1503  			sig := m.Type().(*types.Signature)
  1504  			res := sig.Results()
  1505  			retSig := "V"
  1506  			if res.Len() > 0 {
  1507  				if t := res.At(0).Type(); !isErrorType(t) {
  1508  					retSig = g.jniSigType(t)
  1509  				}
  1510  			}
  1511  			var jniParams string
  1512  			params := sig.Params()
  1513  			for i := 0; i < params.Len(); i++ {
  1514  				jniParams += g.jniSigType(params.At(i).Type())
  1515  			}
  1516  			g.Printf("mid_%s_%s = (*env)->GetMethodID(env, clazz, %q, \"(%s)%s\");\n",
  1517  				iface.obj.Name(), m.Name(), javaNameReplacer(lowerFirst(m.Name())), jniParams, retSig)
  1518  		}
  1519  		g.Printf("\n")
  1520  	}
  1521  	g.Outdent()
  1522  	g.Printf("}\n\n")
  1523  	for _, f := range g.funcs {
  1524  		g.genJNIFunc(f, "", nil, false, false)
  1525  	}
  1526  	for _, s := range g.structs {
  1527  		sName := s.obj.Name()
  1528  		cons := g.constructors[s.obj]
  1529  		jinf := g.jstructs[s.obj]
  1530  		for _, f := range cons {
  1531  			g.genJNIConstructor(f, sName)
  1532  		}
  1533  		if len(cons) == 0 && (jinf == nil || jinf.genNoargCon) {
  1534  			g.Printf("JNIEXPORT jint JNICALL\n")
  1535  			g.Printf("Java_%s_%s_%s(JNIEnv *env, jclass clazz) {\n", g.jniPkgName(), java.JNIMangle(g.javaTypeName(sName)), java.JNIMangle("__New"))
  1536  			g.Indent()
  1537  			g.Printf("return new_%s_%s();\n", g.pkgPrefix, sName)
  1538  			g.Outdent()
  1539  			g.Printf("}\n\n")
  1540  		}
  1541  
  1542  		for _, m := range exportedMethodSet(types.NewPointer(s.obj.Type())) {
  1543  			var jm *java.Func
  1544  			if jinf != nil {
  1545  				jm = jinf.lookupMethod(m, g.hasThis(s.obj.Name(), m))
  1546  			}
  1547  			g.genJNIFunc(m, sName, jm, false, jinf != nil)
  1548  		}
  1549  		for _, f := range exportedFields(s.t) {
  1550  			g.genJNIField(s.obj, f)
  1551  		}
  1552  	}
  1553  	for _, iface := range g.interfaces {
  1554  		for _, m := range iface.summary.callable {
  1555  			g.genJNIFunc(m, iface.obj.Name(), nil, true, false)
  1556  			g.genMethodInterfaceProxy(iface.obj.Name(), m)
  1557  		}
  1558  	}
  1559  	for _, v := range g.vars {
  1560  		g.genJNIVar(v)
  1561  	}
  1562  	if len(g.err) > 0 {
  1563  		return g.err
  1564  	}
  1565  	return nil
  1566  }
  1567  
  1568  func (g *JavaGen) GenJava() error {
  1569  	pkgPath := ""
  1570  	if g.Pkg != nil {
  1571  		pkgPath = g.Pkg.Path()
  1572  	}
  1573  	g.Printf(javaPreamble, g.javaPkgName(g.Pkg), g.className(), g.gobindOpts(), pkgPath)
  1574  
  1575  	g.Printf("public abstract class %s {\n", g.className())
  1576  	g.Indent()
  1577  	g.Printf("static {\n")
  1578  	g.Indent()
  1579  	g.Printf("Seq.touch(); // for loading the native library\n")
  1580  	if g.Pkg != nil {
  1581  		for _, p := range g.Pkg.Imports() {
  1582  			if g.validPkg(p) {
  1583  				g.Printf("%s.%s.touch();\n", g.javaPkgName(p), JavaClassName(p))
  1584  			}
  1585  		}
  1586  	}
  1587  	g.Printf("_init();\n")
  1588  	g.Outdent()
  1589  	g.Printf("}\n\n")
  1590  	g.Printf("private %s() {} // uninstantiable\n\n", g.className())
  1591  	g.Printf("// touch is called from other bound packages to initialize this package\n")
  1592  	g.Printf("public static void touch() {}\n\n")
  1593  	g.Printf("private static native void _init();\n\n")
  1594  
  1595  	for _, iface := range g.interfaces {
  1596  		n := iface.obj.Name()
  1597  		g.Printf("private static final class proxy%s", n)
  1598  		if isErrorType(iface.obj.Type()) {
  1599  			g.Printf(" extends Exception")
  1600  		}
  1601  		g.Printf(" implements Seq.Proxy, %s {\n", g.javaTypeName(n))
  1602  		g.Indent()
  1603  		g.genProxyImpl("proxy" + n)
  1604  		g.Printf("proxy%s(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }\n\n", n)
  1605  
  1606  		if isErrorType(iface.obj.Type()) {
  1607  			g.Printf("@Override public String getMessage() { return error(); }\n\n")
  1608  		}
  1609  		for _, m := range iface.summary.callable {
  1610  			if !g.isSigSupported(m.Type()) {
  1611  				g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", n, m.Name())
  1612  				continue
  1613  			}
  1614  			g.Printf("public native ")
  1615  			g.genFuncSignature(m, nil, false)
  1616  		}
  1617  
  1618  		g.Outdent()
  1619  		g.Printf("}\n")
  1620  	}
  1621  
  1622  	g.Printf("\n")
  1623  
  1624  	for _, c := range g.constants {
  1625  		g.genConst(c)
  1626  	}
  1627  	g.Printf("\n")
  1628  	for _, v := range g.vars {
  1629  		g.genVar(v)
  1630  	}
  1631  	for _, f := range g.funcs {
  1632  		if !g.isSigSupported(f.Type()) {
  1633  			g.Printf("// skipped function %s with unsupported parameter or return types\n\n", f.Name())
  1634  			continue
  1635  		}
  1636  		g.Printf("public static native ")
  1637  		g.genFuncSignature(f, nil, false)
  1638  	}
  1639  
  1640  	g.Outdent()
  1641  	g.Printf("}\n")
  1642  
  1643  	if len(g.err) > 0 {
  1644  		return g.err
  1645  	}
  1646  	return nil
  1647  }
  1648  
  1649  // embeddedJavaClasses returns the possible empty list of Java types embedded
  1650  // in the given struct type.
  1651  func embeddedJavaClasses(t *types.Struct) []string {
  1652  	clsSet := make(map[string]struct{})
  1653  	var classes []string
  1654  	for i := 0; i < t.NumFields(); i++ {
  1655  		f := t.Field(i)
  1656  		if !f.Exported() {
  1657  			continue
  1658  		}
  1659  		if t := f.Type(); isJavaType(t) {
  1660  			cls := classNameFor(t)
  1661  			if _, exists := clsSet[cls]; !exists {
  1662  				clsSet[cls] = struct{}{}
  1663  				classes = append(classes, cls)
  1664  			}
  1665  		}
  1666  	}
  1667  	return classes
  1668  }
  1669  
  1670  func classNameFor(t types.Type) string {
  1671  	obj := t.(*types.Named).Obj()
  1672  	pkg := obj.Pkg()
  1673  	return strings.Replace(pkg.Path()[len("Java/"):], "/", ".", -1) + "." + obj.Name()
  1674  }
  1675  
  1676  func isJavaType(t types.Type) bool {
  1677  	return typePkgFirstElem(t) == "Java"
  1678  }
  1679  
  1680  const (
  1681  	javaPreamble = `// Java class %[1]s.%[2]s is a proxy for talking to a Go program.
  1682  //   gobind %[3]s %[4]s
  1683  //
  1684  // File is generated by gobind. Do not edit.
  1685  package %[1]s;
  1686  
  1687  import go.Seq;
  1688  
  1689  `
  1690  	cPreamble = `// JNI functions for the Go <=> Java bridge.
  1691  //   gobind %[1]s %[2]s
  1692  //
  1693  // File is generated by gobind. Do not edit.
  1694  
  1695  #include <android/log.h>
  1696  #include <stdint.h>
  1697  #include "seq.h"
  1698  #include "_cgo_export.h"
  1699  `
  1700  
  1701  	hPreamble = `// JNI function headers for the Go <=> Java bridge.
  1702  //   gobind %[1]s %[2]s
  1703  //
  1704  // File is generated by gobind. Do not edit.
  1705  
  1706  #ifndef __%[3]s_H__
  1707  #define __%[3]s_H__
  1708  
  1709  #include <jni.h>
  1710  
  1711  `
  1712  )