github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/mobile/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  	"bytes"
     9  	"fmt"
    10  	"go/constant"
    11  	"go/token"
    12  	"go/types"
    13  	"io"
    14  	"math"
    15  	"regexp"
    16  	"strings"
    17  )
    18  
    19  // TODO(crawshaw): disallow basic android java type names in exported symbols.
    20  // TODO(crawshaw): generate all relevant "implements" relationships for interfaces.
    21  // TODO(crawshaw): consider introducing Java functions for casting to and from interfaces at runtime.
    22  
    23  type ErrorList []error
    24  
    25  func (list ErrorList) Error() string {
    26  	buf := new(bytes.Buffer)
    27  	for i, err := range list {
    28  		if i > 0 {
    29  			buf.WriteRune('\n')
    30  		}
    31  		io.WriteString(buf, err.Error())
    32  	}
    33  	return buf.String()
    34  }
    35  
    36  type javaGen struct {
    37  	*printer
    38  	fset    *token.FileSet
    39  	pkg     *types.Package
    40  	javaPkg string
    41  	err     ErrorList
    42  }
    43  
    44  func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) {
    45  	fields := exportedFields(T)
    46  	methods := exportedMethodSet(types.NewPointer(obj.Type()))
    47  
    48  	g.Printf("public static final class %s implements go.Seq.Object {\n", obj.Name())
    49  	g.Indent()
    50  	g.Printf("private static final String DESCRIPTOR = \"go.%s.%s\";\n", g.pkg.Name(), obj.Name())
    51  	for i, f := range fields {
    52  		g.Printf("private static final int FIELD_%s_GET = 0x%x0f;\n", f.Name(), i)
    53  		g.Printf("private static final int FIELD_%s_SET = 0x%x1f;\n", f.Name(), i)
    54  	}
    55  	for i, m := range methods {
    56  		g.Printf("private static final int CALL_%s = 0x%x0c;\n", m.Name(), i)
    57  	}
    58  	g.Printf("\n")
    59  
    60  	g.Printf("private go.Seq.Ref ref;\n\n")
    61  
    62  	n := obj.Name()
    63  	g.Printf("private %s(go.Seq.Ref ref) { this.ref = ref; }\n\n", n)
    64  	g.Printf(`public go.Seq.Ref ref() { return ref; }
    65  
    66  public void call(int code, go.Seq in, go.Seq out) {
    67      throw new RuntimeException("internal error: cycle: cannot call concrete proxy");
    68  }
    69  
    70  `)
    71  
    72  	for _, f := range fields {
    73  		g.Printf("public %s get%s() {\n", g.javaType(f.Type()), f.Name())
    74  		g.Indent()
    75  		g.Printf("Seq in = new Seq();\n")
    76  		g.Printf("Seq out = new Seq();\n")
    77  		g.Printf("in.writeRef(ref);\n")
    78  		g.Printf("Seq.send(DESCRIPTOR, FIELD_%s_GET, in, out);\n", f.Name())
    79  		if seqType(f.Type()) == "Ref" {
    80  			g.Printf("return new %s(out.read%s);\n", g.javaType(f.Type()), seqRead(f.Type()))
    81  		} else {
    82  			g.Printf("return out.read%s;\n", seqRead(f.Type()))
    83  		}
    84  		g.Outdent()
    85  		g.Printf("}\n\n")
    86  
    87  		g.Printf("public void set%s(%s v) {\n", f.Name(), g.javaType(f.Type()))
    88  		g.Indent()
    89  		g.Printf("Seq in = new Seq();\n")
    90  		g.Printf("Seq out = new Seq();\n")
    91  		g.Printf("in.writeRef(ref);\n")
    92  		g.Printf("in.write%s;\n", seqWrite(f.Type(), "v"))
    93  		g.Printf("Seq.send(DESCRIPTOR, FIELD_%s_SET, in, out);\n", f.Name())
    94  		g.Outdent()
    95  		g.Printf("}\n\n")
    96  	}
    97  
    98  	for _, m := range methods {
    99  		g.genFunc(m, true)
   100  	}
   101  
   102  	g.Printf("@Override public boolean equals(Object o) {\n")
   103  	g.Indent()
   104  	g.Printf("if (o == null || !(o instanceof %s)) {\n    return false;\n}\n", n)
   105  	g.Printf("%s that = (%s)o;\n", n, n)
   106  	for _, f := range fields {
   107  		nf := f.Name()
   108  		g.Printf("%s this%s = get%s();\n", g.javaType(f.Type()), nf, nf)
   109  		g.Printf("%s that%s = that.get%s();\n", g.javaType(f.Type()), nf, nf)
   110  		if isJavaPrimitive(f.Type()) {
   111  			g.Printf("if (this%s != that%s) {\n    return false;\n}\n", nf, nf)
   112  		} else {
   113  			g.Printf("if (this%s == null) {\n", nf)
   114  			g.Indent()
   115  			g.Printf("if (that%s != null) {\n    return false;\n}\n", nf)
   116  			g.Outdent()
   117  			g.Printf("} else if (!this%s.equals(that%s)) {\n    return false;\n}\n", nf, nf)
   118  		}
   119  	}
   120  	g.Printf("return true;\n")
   121  	g.Outdent()
   122  	g.Printf("}\n\n")
   123  
   124  	g.Printf("@Override public int hashCode() {\n")
   125  	g.Printf("    return java.util.Arrays.hashCode(new Object[] {")
   126  	for i, f := range fields {
   127  		if i > 0 {
   128  			g.Printf(", ")
   129  		}
   130  		g.Printf("get%s()", f.Name())
   131  	}
   132  	g.Printf("});\n")
   133  	g.Printf("}\n\n")
   134  
   135  	// TODO(crawshaw): use String() string if it is defined.
   136  	g.Printf("@Override public String toString() {\n")
   137  	g.Indent()
   138  	g.Printf("StringBuilder b = new StringBuilder();\n")
   139  	g.Printf(`b.append("%s").append("{");`, obj.Name())
   140  	g.Printf("\n")
   141  	for _, f := range fields {
   142  		n := f.Name()
   143  		g.Printf(`b.append("%s:").append(get%s()).append(",");`, n, n)
   144  		g.Printf("\n")
   145  	}
   146  	g.Printf(`return b.append("}").toString();`)
   147  	g.Printf("\n")
   148  	g.Outdent()
   149  	g.Printf("}\n\n")
   150  
   151  	g.Outdent()
   152  	g.Printf("}\n\n")
   153  }
   154  
   155  func (g *javaGen) genInterfaceStub(o *types.TypeName, m *types.Interface) {
   156  	g.Printf("public static abstract class Stub implements %s {\n", o.Name())
   157  	g.Indent()
   158  
   159  	g.Printf("static final String DESCRIPTOR = \"go.%s.%s\";\n\n", g.pkg.Name(), o.Name())
   160  	g.Printf("private final go.Seq.Ref ref;\n")
   161  	g.Printf("public Stub() {\n    ref = go.Seq.createRef(this);\n}\n\n")
   162  	g.Printf("public go.Seq.Ref ref() { return ref; }\n\n")
   163  
   164  	g.Printf("public void call(int code, go.Seq in, go.Seq out) {\n")
   165  	g.Indent()
   166  	g.Printf("switch (code) {\n")
   167  
   168  	for i := 0; i < m.NumMethods(); i++ {
   169  		f := m.Method(i)
   170  		g.Printf("case Proxy.CALL_%s: {\n", f.Name())
   171  		g.Indent()
   172  
   173  		sig := f.Type().(*types.Signature)
   174  		params := sig.Params()
   175  		for i := 0; i < params.Len(); i++ {
   176  			p := sig.Params().At(i)
   177  			jt := g.javaType(p.Type())
   178  			g.Printf("%s param_%s;\n", jt, paramName(params, i))
   179  			g.genRead("param_"+paramName(params, i), "in", p.Type())
   180  		}
   181  
   182  		res := sig.Results()
   183  		var returnsError bool
   184  		var numRes = res.Len()
   185  		if (res.Len() == 1 && isErrorType(res.At(0).Type())) ||
   186  			(res.Len() == 2 && isErrorType(res.At(1).Type())) {
   187  			numRes -= 1
   188  			returnsError = true
   189  		}
   190  
   191  		if returnsError {
   192  			g.Printf("try {\n")
   193  			g.Indent()
   194  		}
   195  
   196  		if numRes > 0 {
   197  			g.Printf("%s result = ", g.javaType(res.At(0).Type()))
   198  		}
   199  
   200  		g.Printf("this.%s(", f.Name())
   201  		for i := 0; i < params.Len(); i++ {
   202  			if i > 0 {
   203  				g.Printf(", ")
   204  			}
   205  			g.Printf("param_%s", paramName(params, i))
   206  		}
   207  		g.Printf(");\n")
   208  
   209  		if numRes > 0 {
   210  			g.Printf("out.write%s;\n", seqWrite(res.At(0).Type(), "result"))
   211  		}
   212  		if returnsError {
   213  			g.Printf("out.writeString(null);\n")
   214  			g.Outdent()
   215  			g.Printf("} catch (Exception e) {\n")
   216  			g.Indent()
   217  			if numRes > 0 {
   218  				resTyp := res.At(0).Type()
   219  				g.Printf("%s result = %s;\n", g.javaType(resTyp), g.javaTypeDefault(resTyp))
   220  				g.Printf("out.write%s;\n", seqWrite(resTyp, "result"))
   221  			}
   222  			g.Printf("out.writeString(e.getMessage());\n")
   223  			g.Outdent()
   224  			g.Printf("}\n")
   225  		}
   226  		g.Printf("return;\n")
   227  		g.Outdent()
   228  		g.Printf("}\n")
   229  	}
   230  
   231  	g.Printf("default:\n    throw new RuntimeException(\"unknown code: \"+ code);\n")
   232  	g.Printf("}\n")
   233  	g.Outdent()
   234  	g.Printf("}\n")
   235  
   236  	g.Outdent()
   237  	g.Printf("}\n\n")
   238  }
   239  
   240  const javaProxyPreamble = `static final class Proxy implements %s {
   241      static final String DESCRIPTOR = Stub.DESCRIPTOR;
   242  
   243      private go.Seq.Ref ref;
   244  
   245      Proxy(go.Seq.Ref ref) { this.ref = ref; }
   246  
   247      public go.Seq.Ref ref() { return ref; }
   248  
   249      public void call(int code, go.Seq in, go.Seq out) {
   250          throw new RuntimeException("cycle: cannot call proxy");
   251      }
   252  
   253  `
   254  
   255  func (g *javaGen) genInterface(o *types.TypeName) {
   256  	iface := o.Type().(*types.Named).Underlying().(*types.Interface)
   257  
   258  	summary := makeIfaceSummary(iface)
   259  
   260  	g.Printf("public interface %s extends go.Seq.Object {\n", o.Name())
   261  	g.Indent()
   262  
   263  	methodSigErr := false
   264  	for _, m := range summary.callable {
   265  		if err := g.funcSignature(m, false); err != nil {
   266  			methodSigErr = true
   267  			g.errorf("%v", err)
   268  		}
   269  		g.Printf(";\n\n")
   270  	}
   271  	if methodSigErr {
   272  		return // skip stub generation, more of the same errors
   273  	}
   274  
   275  	if summary.implementable {
   276  		g.genInterfaceStub(o, iface)
   277  	}
   278  
   279  	g.Printf(javaProxyPreamble, o.Name())
   280  	g.Indent()
   281  
   282  	for _, m := range summary.callable {
   283  		g.genFunc(m, true)
   284  	}
   285  	for i, m := range summary.callable {
   286  		g.Printf("static final int CALL_%s = 0x%x0a;\n", m.Name(), i+1)
   287  	}
   288  
   289  	g.Outdent()
   290  	g.Printf("}\n")
   291  
   292  	g.Outdent()
   293  	g.Printf("}\n\n")
   294  }
   295  
   296  func isJavaPrimitive(T types.Type) bool {
   297  	b, ok := T.(*types.Basic)
   298  	if !ok {
   299  		return false
   300  	}
   301  	switch b.Kind() {
   302  	case types.Bool, types.Uint8, types.Float32, types.Float64,
   303  		types.Int, types.Int8, types.Int16, types.Int32, types.Int64:
   304  		return true
   305  	}
   306  	return false
   307  }
   308  
   309  // javaType returns a string that can be used as a Java type.
   310  func (g *javaGen) javaType(T types.Type) string {
   311  	if isErrorType(T) {
   312  		// The error type is usually translated into an exception in
   313  		// Java, however the type can be exposed in other ways, such
   314  		// as an exported field.
   315  		return "String"
   316  	}
   317  	switch T := T.(type) {
   318  	case *types.Basic:
   319  		switch T.Kind() {
   320  		case types.Bool, types.UntypedBool:
   321  			return "boolean"
   322  		case types.Int:
   323  			return "long"
   324  		case types.Int8:
   325  			return "byte"
   326  		case types.Int16:
   327  			return "short"
   328  		case types.Int32, types.UntypedRune: // types.Rune
   329  			return "int"
   330  		case types.Int64, types.UntypedInt:
   331  			return "long"
   332  		case types.Uint8: // types.Byte
   333  			// TODO(crawshaw): Java bytes are signed, so this is
   334  			// questionable, but vital.
   335  			return "byte"
   336  		// TODO(crawshaw): case types.Uint, types.Uint16, types.Uint32, types.Uint64:
   337  		case types.Float32:
   338  			return "float"
   339  		case types.Float64, types.UntypedFloat:
   340  			return "double"
   341  		case types.String, types.UntypedString:
   342  			return "String"
   343  		default:
   344  			g.errorf("unsupported basic type: %s", T)
   345  			return "TODO"
   346  		}
   347  	case *types.Slice:
   348  		elem := g.javaType(T.Elem())
   349  		return elem + "[]"
   350  
   351  	case *types.Pointer:
   352  		if _, ok := T.Elem().(*types.Named); ok {
   353  			return g.javaType(T.Elem())
   354  		}
   355  		panic(fmt.Sprintf("unsupported pointer to type: %s", T))
   356  	case *types.Named:
   357  		n := T.Obj()
   358  		if n.Pkg() != g.pkg {
   359  			nPkgName := "<nilpkg>"
   360  			if nPkg := n.Pkg(); nPkg != nil {
   361  				nPkgName = nPkg.Name()
   362  			}
   363  			panic(fmt.Sprintf("type %s is in package %s, must be defined in package %s", n.Name(), nPkgName, g.pkg.Name()))
   364  		}
   365  		// TODO(crawshaw): more checking here
   366  		return n.Name()
   367  	default:
   368  		g.errorf("unsupported javaType: %#+v, %s\n", T, T)
   369  		return "TODO"
   370  	}
   371  }
   372  
   373  // javaTypeDefault returns a string that represents the default value of the mapped java type.
   374  // TODO(hyangah): Combine javaType and javaTypeDefault?
   375  func (g *javaGen) javaTypeDefault(T types.Type) string {
   376  	switch T := T.(type) {
   377  	case *types.Basic:
   378  		switch T.Kind() {
   379  		case types.Bool:
   380  			return "false"
   381  		case types.Int, types.Int8, types.Int16, types.Int32,
   382  			types.Int64, types.Uint8:
   383  			return "0"
   384  		case types.Float32, types.Float64:
   385  			return "0.0"
   386  		case types.String:
   387  			return "null"
   388  		default:
   389  			g.errorf("unsupported return type: %s", T)
   390  			return "TODO"
   391  		}
   392  	case *types.Slice, *types.Pointer, *types.Named:
   393  		return "null"
   394  
   395  	default:
   396  		g.errorf("unsupported javaType: %#+v, %s\n", T, T)
   397  		return "TODO"
   398  	}
   399  }
   400  
   401  var paramRE = regexp.MustCompile(`^p[0-9]*$`)
   402  
   403  // paramName replaces incompatible name with a p0-pN name.
   404  // Missing names, or existing names of the form p[0-9] are incompatible.
   405  // TODO(crawshaw): Replace invalid unicode names.
   406  func paramName(params *types.Tuple, pos int) string {
   407  	name := params.At(pos).Name()
   408  	if name == "" || name == "_" || paramRE.MatchString(name) {
   409  		name = fmt.Sprintf("p%d", pos)
   410  	}
   411  	return name
   412  }
   413  
   414  func (g *javaGen) funcSignature(o *types.Func, static bool) error {
   415  	sig := o.Type().(*types.Signature)
   416  	res := sig.Results()
   417  
   418  	var returnsError bool
   419  	var ret string
   420  	switch res.Len() {
   421  	case 2:
   422  		if !isErrorType(res.At(1).Type()) {
   423  			return fmt.Errorf("second result value must be of type error: %s", o)
   424  		}
   425  		returnsError = true
   426  		ret = g.javaType(res.At(0).Type())
   427  	case 1:
   428  		if isErrorType(res.At(0).Type()) {
   429  			returnsError = true
   430  			ret = "void"
   431  		} else {
   432  			ret = g.javaType(res.At(0).Type())
   433  		}
   434  	case 0:
   435  		ret = "void"
   436  	default:
   437  		return fmt.Errorf("too many result values: %s", o)
   438  	}
   439  
   440  	g.Printf("public ")
   441  	if static {
   442  		g.Printf("static ")
   443  	}
   444  	g.Printf("%s %s(", ret, o.Name())
   445  	params := sig.Params()
   446  	for i := 0; i < params.Len(); i++ {
   447  		if i > 0 {
   448  			g.Printf(", ")
   449  		}
   450  		v := sig.Params().At(i)
   451  		name := paramName(params, i)
   452  		jt := g.javaType(v.Type())
   453  		g.Printf("%s %s", jt, name)
   454  	}
   455  	g.Printf(")")
   456  	if returnsError {
   457  		g.Printf(" throws Exception")
   458  	}
   459  	return nil
   460  }
   461  
   462  func (g *javaGen) genVar(o *types.Var) {
   463  	jType := g.javaType(o.Type())
   464  	varDesc := fmt.Sprintf("%s.%s", g.pkg.Name(), o.Name())
   465  
   466  	// setter
   467  	g.Printf("public static void set%s(%s v) {\n", o.Name(), jType)
   468  	g.Indent()
   469  	g.Printf("Seq in = new Seq();\n")
   470  	g.Printf("Seq out = new Seq();\n")
   471  	g.Printf("in.write%s;\n", seqWrite(o.Type(), "v"))
   472  	g.Printf("Seq.send(%q, 1, in, out);\n", varDesc)
   473  	g.Outdent()
   474  	g.Printf("}\n")
   475  	g.Printf("\n")
   476  
   477  	// getter
   478  	g.Printf("public static %s get%s() {\n", jType, o.Name())
   479  	g.Indent()
   480  	g.Printf("Seq in = new Seq();\n")
   481  	g.Printf("Seq out = new Seq();\n")
   482  	g.Printf("Seq.send(%q, 2, in, out);\n", varDesc)
   483  	g.Printf("%s ", jType)
   484  	g.genRead("v", "out", o.Type())
   485  	g.Printf("return v;\n")
   486  	g.Outdent()
   487  	g.Printf("}\n")
   488  	g.Printf("\n")
   489  }
   490  
   491  func (g *javaGen) genFunc(o *types.Func, method bool) {
   492  	if err := g.funcSignature(o, !method); err != nil {
   493  		g.errorf("%v", err)
   494  		return
   495  	}
   496  	sig := o.Type().(*types.Signature)
   497  	res := sig.Results()
   498  
   499  	g.Printf(" {\n")
   500  	g.Indent()
   501  	g.Printf("go.Seq _in = new go.Seq();\n")
   502  	g.Printf("go.Seq _out = new go.Seq();\n")
   503  
   504  	returnsError := false
   505  	var resultType types.Type
   506  	if res.Len() > 0 {
   507  		if !isErrorType(res.At(0).Type()) {
   508  			resultType = res.At(0).Type()
   509  		}
   510  		if res.Len() > 1 || isErrorType(res.At(0).Type()) {
   511  			returnsError = true
   512  		}
   513  	}
   514  	if resultType != nil {
   515  		t := g.javaType(resultType)
   516  		g.Printf("%s _result;\n", t)
   517  	}
   518  
   519  	if method {
   520  		g.Printf("_in.writeRef(ref);\n")
   521  	}
   522  	params := sig.Params()
   523  	for i := 0; i < params.Len(); i++ {
   524  		p := params.At(i)
   525  		g.Printf("_in.write%s;\n", seqWrite(p.Type(), paramName(params, i)))
   526  	}
   527  	g.Printf("Seq.send(DESCRIPTOR, CALL_%s, _in, _out);\n", o.Name())
   528  	if resultType != nil {
   529  		g.genRead("_result", "_out", resultType)
   530  	}
   531  	if returnsError {
   532  		g.Printf(`String _err = _out.readString();
   533  if (_err != null && !_err.isEmpty()) {
   534      throw new Exception(_err);
   535  }
   536  `)
   537  	}
   538  	if resultType != nil {
   539  		g.Printf("return _result;\n")
   540  	}
   541  	g.Outdent()
   542  	g.Printf("}\n\n")
   543  }
   544  
   545  func (g *javaGen) genRead(resName, seqName string, T types.Type) {
   546  	switch T := T.(type) {
   547  	case *types.Pointer:
   548  		// TODO(crawshaw): test *int
   549  		// TODO(crawshaw): test **Generator
   550  		switch T := T.Elem().(type) {
   551  		case *types.Named:
   552  			o := T.Obj()
   553  			if o.Pkg() != g.pkg {
   554  				g.errorf("type %s not defined in %s", T, g.pkg)
   555  				return
   556  			}
   557  			g.Printf("%s = new %s(%s.readRef());\n", resName, o.Name(), seqName)
   558  		default:
   559  			g.errorf("unsupported type %s", T)
   560  		}
   561  	case *types.Named:
   562  		switch T.Underlying().(type) {
   563  		case *types.Interface, *types.Pointer:
   564  			o := T.Obj()
   565  			if o.Pkg() != g.pkg {
   566  				g.errorf("type %s not defined in %s", T, g.pkg)
   567  				return
   568  			}
   569  			g.Printf("%s = new %s.Proxy(%s.readRef());\n", resName, o.Name(), seqName)
   570  		default:
   571  			g.errorf("unsupported, direct named type %s", T)
   572  		}
   573  	default:
   574  		g.Printf("%s = %s.read%s();\n", resName, seqName, seqType(T))
   575  	}
   576  }
   577  
   578  func (g *javaGen) errorf(format string, args ...interface{}) {
   579  	g.err = append(g.err, fmt.Errorf(format, args...))
   580  }
   581  
   582  func (g *javaGen) gobindOpts() string {
   583  	opts := []string{"-lang=java"}
   584  	if g.javaPkg != javaPkgName(g.pkg.Name()) {
   585  		opts = append(opts, "-javapkg="+g.javaPkg)
   586  	}
   587  	return strings.Join(opts, " ")
   588  }
   589  
   590  const javaPreamble = `// Java class %[1]s.%[2]s is a proxy for talking to a Go program.
   591  //   gobind %[3]s %[4]s
   592  //
   593  // File is generated by gobind. Do not edit.
   594  package %[1]s;
   595  
   596  import go.Seq;
   597  
   598  `
   599  
   600  var javaNameReplacer = strings.NewReplacer(
   601  	"-", "_",
   602  	".", "_",
   603  )
   604  
   605  func javaPkgName(pkgName string) string {
   606  	s := javaNameReplacer.Replace(pkgName)
   607  	// Look for Java keywords that are not Go keywords, and avoid using
   608  	// them as a package name.
   609  	//
   610  	// This is not a problem for normal Go identifiers as we only expose
   611  	// exported symbols. The upper case first letter saves everything
   612  	// from accidentally matching except for the package name.
   613  	//
   614  	// Note that basic type names (like int) are not keywords in Go.
   615  	switch s {
   616  	case "abstract", "assert", "boolean", "byte", "catch", "char", "class",
   617  		"do", "double", "enum", "extends", "final", "finally", "float",
   618  		"implements", "instanceof", "int", "long", "native", "private",
   619  		"protected", "public", "short", "static", "strictfp", "super",
   620  		"synchronized", "this", "throw", "throws", "transient", "try",
   621  		"void", "volatile", "while":
   622  		s += "_"
   623  	}
   624  	return "go." + s
   625  }
   626  
   627  func (g *javaGen) className() string {
   628  	return strings.Title(javaNameReplacer.Replace(g.pkg.Name()))
   629  }
   630  
   631  func (g *javaGen) genConst(o *types.Const) {
   632  	// TODO(hyangah): should const names use upper cases + "_"?
   633  	// TODO(hyangah): check invalid names.
   634  	jType := g.javaType(o.Type())
   635  	val := o.Val().String()
   636  	switch b := o.Type().(*types.Basic); b.Kind() {
   637  	case types.Int64, types.UntypedInt:
   638  		i, exact := constant.Int64Val(o.Val())
   639  		if !exact {
   640  			g.errorf("const value %s for %s cannot be represented as %s", val, o.Name(), jType)
   641  			return
   642  		}
   643  		val = fmt.Sprintf("%dL", i)
   644  
   645  	case types.Float32:
   646  		f, _ := constant.Float32Val(o.Val())
   647  		val = fmt.Sprintf("%gf", f)
   648  
   649  	case types.Float64, types.UntypedFloat:
   650  		f, _ := constant.Float64Val(o.Val())
   651  		if math.IsInf(f, 0) || math.Abs(f) > math.MaxFloat64 {
   652  			g.errorf("const value %s for %s cannot be represented as %s", val, o.Name(), jType)
   653  			return
   654  		}
   655  		val = fmt.Sprintf("%g", f)
   656  	}
   657  	g.Printf("public static final %s %s = %s;\n", g.javaType(o.Type()), o.Name(), val)
   658  }
   659  
   660  func (g *javaGen) gen() error {
   661  	g.Printf(javaPreamble, g.javaPkg, g.className(), g.gobindOpts(), g.pkg.Path())
   662  
   663  	g.Printf("public abstract class %s {\n", g.className())
   664  	g.Indent()
   665  	g.Printf("private %s() {} // uninstantiable\n\n", g.className())
   666  
   667  	var funcs []string
   668  
   669  	scope := g.pkg.Scope()
   670  	names := scope.Names()
   671  	hasExported := false
   672  	for _, name := range names {
   673  		obj := scope.Lookup(name)
   674  		if !obj.Exported() {
   675  			continue
   676  		}
   677  		hasExported = true
   678  
   679  		switch o := obj.(type) {
   680  		// TODO(crawshaw): case *types.Var:
   681  		case *types.Func:
   682  			if isCallable(o) {
   683  				g.genFunc(o, false)
   684  				funcs = append(funcs, o.Name())
   685  			}
   686  		case *types.TypeName:
   687  			named := o.Type().(*types.Named)
   688  			switch t := named.Underlying().(type) {
   689  			case *types.Struct:
   690  				g.genStruct(o, t)
   691  			case *types.Interface:
   692  				g.genInterface(o)
   693  			default:
   694  				g.errorf("%s: cannot generate binding for %s: %T", g.fset.Position(o.Pos()), o.Name(), t)
   695  				continue
   696  			}
   697  		case *types.Const:
   698  			g.genConst(o)
   699  		case *types.Var:
   700  			g.genVar(o)
   701  		default:
   702  			g.errorf("unsupported exported type: %T", obj)
   703  		}
   704  	}
   705  	if !hasExported {
   706  		g.errorf("no exported names in the package %q", g.pkg.Path())
   707  	}
   708  
   709  	for i, name := range funcs {
   710  		g.Printf("private static final int CALL_%s = %d;\n", name, i+1)
   711  	}
   712  
   713  	g.Printf("private static final String DESCRIPTOR = %q;\n", g.pkg.Name())
   714  	g.Outdent()
   715  	g.Printf("}\n")
   716  
   717  	if len(g.err) > 0 {
   718  		return g.err
   719  	}
   720  	return nil
   721  }