github.com/TimaSlipko/gomobile@v1.0.8/internal/importers/java/java.go (about)

     1  // Copyright 2016 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  // The java package takes the result of an AST traversal by the
     6  // importers package and queries the java command for the type
     7  // information for the referenced Java classes and interfaces.
     8  //
     9  // It is the of go/types for Java types and is used by the bind
    10  // package to generate Go wrappers for Java API on Android.
    11  package java
    12  
    13  import (
    14  	"bufio"
    15  	"bytes"
    16  	"errors"
    17  	"fmt"
    18  	"os/exec"
    19  	"reflect"
    20  	"strings"
    21  	"unicode"
    22  	"unicode/utf8"
    23  
    24  	"github.com/TimaSlipko/gomobile/internal/importers"
    25  )
    26  
    27  // Class is the bind representation of a Java class or
    28  // interface.
    29  // Use Import to convert class references to Class.
    30  type Class struct {
    31  	// "java.pkg.Class.Inner"
    32  	Name string
    33  	// "java.pkg.Class$Inner"
    34  	FindName string
    35  	// JNI mangled name
    36  	JNIName string
    37  	// "Inner"
    38  	PkgName string
    39  	Funcs   []*FuncSet
    40  	Methods []*FuncSet
    41  	// funcMap maps function names.
    42  	funcMap map[string]*FuncSet
    43  	// FuncMap maps method names.
    44  	methodMap map[string]*FuncSet
    45  	// All methods, including methods from
    46  	// supers.
    47  	AllMethods []*FuncSet
    48  	Vars       []*Var
    49  	Supers     []string
    50  	Final      bool
    51  	Abstract   bool
    52  	Interface  bool
    53  	Throwable  bool
    54  	// Whether the class has a no-arg constructor
    55  	HasNoArgCon bool
    56  }
    57  
    58  // FuncSet is the set of overloaded variants of a function.
    59  // If the function is not overloaded, its FuncSet contains
    60  // one entry.
    61  type FuncSet struct {
    62  	Name   string
    63  	GoName string
    64  	Funcs  []*Func
    65  	CommonSig
    66  }
    67  
    68  // CommonSig is a signature compatible with every
    69  // overloaded variant of a FuncSet.
    70  type CommonSig struct {
    71  	// Variadic is set if the signature covers variants
    72  	// with varying number of parameters.
    73  	Variadic bool
    74  	// HasRet is true if at least one variant returns a
    75  	// value.
    76  	HasRet bool
    77  	Throws bool
    78  	Params []*Type
    79  	Ret    *Type
    80  }
    81  
    82  // Func is a Java static function or method or constructor.
    83  type Func struct {
    84  	FuncSig
    85  	ArgDesc string
    86  	// Mangled JNI name
    87  	JNIName     string
    88  	Static      bool
    89  	Abstract    bool
    90  	Final       bool
    91  	Public      bool
    92  	Constructor bool
    93  	Params      []*Type
    94  	Ret         *Type
    95  	Decl        string
    96  	Throws      string
    97  }
    98  
    99  // FuncSig uniquely identifies a Java Func.
   100  type FuncSig struct {
   101  	Name string
   102  	// The method descriptor, in JNI format.
   103  	Desc string
   104  }
   105  
   106  // Var is a Java member variable.
   107  type Var struct {
   108  	Name   string
   109  	Static bool
   110  	Final  bool
   111  	Val    string
   112  	Type   *Type
   113  }
   114  
   115  // Type is a Java type.
   116  type Type struct {
   117  	Kind  TypeKind
   118  	Class string
   119  	Elem  *Type
   120  }
   121  
   122  type TypeKind int
   123  
   124  type Importer struct {
   125  	// Bootclasspath string
   126  	Classpath string
   127  	// JavaPkg is java package name for generated classes.
   128  	JavaPkg string
   129  
   130  	clsMap map[string]*Class
   131  }
   132  
   133  // funcRef is a reference to a Java function (static method).
   134  // It is used as a key to filter unused Java functions.
   135  type funcRef struct {
   136  	clsName string
   137  	goName  string
   138  }
   139  
   140  type errClsNotFound struct {
   141  	name string
   142  }
   143  
   144  const (
   145  	Int TypeKind = iota
   146  	Boolean
   147  	Short
   148  	Char
   149  	Byte
   150  	Long
   151  	Float
   152  	Double
   153  	String
   154  	Array
   155  	Object
   156  )
   157  
   158  func (e *errClsNotFound) Error() string {
   159  	return "class not found: " + e.name
   160  }
   161  
   162  // IsAvailable reports whether the required tools are available for
   163  // Import to work. In particular, IsAvailable checks the existence
   164  // of the javap binary.
   165  func IsAvailable() bool {
   166  	_, err := javapPath()
   167  	return err == nil
   168  }
   169  
   170  func javapPath() (string, error) {
   171  	return exec.LookPath("javap")
   172  }
   173  
   174  // Import returns Java Class descriptors for a list of references.
   175  //
   176  // The javap command from the Java SDK is used to dump
   177  // class information. Its output looks like this:
   178  //
   179  // Compiled from "System.java"
   180  // public final class java.lang.System {
   181  //
   182  //	public static final java.io.InputStream in;
   183  //	  descriptor: Ljava/io/InputStream;
   184  //	public static final java.io.PrintStream out;
   185  //	  descriptor: Ljava/io/PrintStream;
   186  //	public static final java.io.PrintStream err;
   187  //	  descriptor: Ljava/io/PrintStream;
   188  //	public static void setIn(java.io.InputStream);
   189  //	  descriptor: (Ljava/io/InputStream;)V
   190  //
   191  //	...
   192  //
   193  // }
   194  func (j *Importer) Import(refs *importers.References) ([]*Class, error) {
   195  	if j.clsMap == nil {
   196  		j.clsMap = make(map[string]*Class)
   197  	}
   198  	clsSet := make(map[string]struct{})
   199  	var names []string
   200  	for _, ref := range refs.Refs {
   201  		// The reference could be to some/pkg.Class or some/pkg/Class.Identifier. Include both.
   202  		pkg := strings.Replace(ref.Pkg, "/", ".", -1)
   203  		for _, cls := range []string{pkg, pkg + "." + ref.Name} {
   204  			if _, exists := clsSet[cls]; !exists {
   205  				clsSet[cls] = struct{}{}
   206  				names = append(names, cls)
   207  			}
   208  		}
   209  	}
   210  	// Make sure toString() is included; it is called when wrapping Java exception types to Go
   211  	// errors.
   212  	refs.Names["ToString"] = struct{}{}
   213  	funcRefs := make(map[funcRef]struct{})
   214  	for _, ref := range refs.Refs {
   215  		pkgName := strings.Replace(ref.Pkg, "/", ".", -1)
   216  		funcRefs[funcRef{pkgName, ref.Name}] = struct{}{}
   217  	}
   218  	classes, err := j.importClasses(names, true)
   219  	if err != nil {
   220  		return nil, err
   221  	}
   222  	j.filterReferences(classes, refs, funcRefs)
   223  	supers, err := j.importReferencedClasses(classes)
   224  	if err != nil {
   225  		return nil, err
   226  	}
   227  	j.filterReferences(supers, refs, funcRefs)
   228  	// Embedders refer to every exported Go struct that will have its class
   229  	// generated. Allow Go code to reverse bind to those classes by synthesizing
   230  	// their class descriptors.
   231  	for _, emb := range refs.Embedders {
   232  		n := emb.Pkg + "." + emb.Name
   233  		if j.JavaPkg != "" {
   234  			n = j.JavaPkg + "." + n
   235  		}
   236  		if _, exists := j.clsMap[n]; exists {
   237  			continue
   238  		}
   239  		clsSet[n] = struct{}{}
   240  		cls := &Class{
   241  			Name:        n,
   242  			FindName:    n,
   243  			JNIName:     JNIMangle(n),
   244  			PkgName:     emb.Name,
   245  			HasNoArgCon: true,
   246  		}
   247  		for _, ref := range emb.Refs {
   248  			jpkg := strings.Replace(ref.Pkg, "/", ".", -1)
   249  			super := jpkg + "." + ref.Name
   250  			if _, exists := j.clsMap[super]; !exists {
   251  				return nil, fmt.Errorf("failed to find Java class %s, embedded by %s", super, n)
   252  			}
   253  			cls.Supers = append(cls.Supers, super)
   254  		}
   255  		classes = append(classes, cls)
   256  		j.clsMap[cls.Name] = cls
   257  	}
   258  	// Include implicit classes that are used in parameter or return values.
   259  	for _, cls := range classes {
   260  		for _, fsets := range [][]*FuncSet{cls.Funcs, cls.Methods} {
   261  			for _, fs := range fsets {
   262  				for _, f := range fs.Funcs {
   263  					names := j.implicitFuncTypes(f)
   264  					for _, name := range names {
   265  						if _, exists := clsSet[name]; exists {
   266  							continue
   267  						}
   268  						clsSet[name] = struct{}{}
   269  						classes = append(classes, j.clsMap[name])
   270  					}
   271  				}
   272  			}
   273  		}
   274  	}
   275  	for _, cls := range j.clsMap {
   276  		j.fillFuncSigs(cls.Funcs)
   277  		j.fillFuncSigs(cls.Methods)
   278  		for _, m := range cls.Methods {
   279  			j.fillSuperSigs(cls, m)
   280  		}
   281  	}
   282  	for _, cls := range j.clsMap {
   283  		j.fillAllMethods(cls)
   284  	}
   285  	// Include classes that appear as ancestor types for overloaded signatures.
   286  	for _, cls := range classes {
   287  		for _, funcs := range [][]*FuncSet{cls.Funcs, cls.AllMethods} {
   288  			for _, f := range funcs {
   289  				for _, p := range f.Params {
   290  					if p == nil || p.Kind != Object {
   291  						continue
   292  					}
   293  					if _, exists := clsSet[p.Class]; !exists {
   294  						clsSet[p.Class] = struct{}{}
   295  						classes = append(classes, j.clsMap[p.Class])
   296  					}
   297  				}
   298  				if t := f.Ret; t != nil && t.Kind == Object {
   299  					if _, exists := clsSet[t.Class]; !exists {
   300  						clsSet[t.Class] = struct{}{}
   301  						classes = append(classes, j.clsMap[t.Class])
   302  					}
   303  				}
   304  			}
   305  		}
   306  	}
   307  	for _, cls := range classes {
   308  		j.fillJNINames(cls.Funcs)
   309  		j.fillJNINames(cls.AllMethods)
   310  	}
   311  	j.fillThrowables(classes)
   312  	return classes, nil
   313  }
   314  
   315  func (j *Importer) fillJNINames(funcs []*FuncSet) {
   316  	for _, fs := range funcs {
   317  		for _, f := range fs.Funcs {
   318  			f.JNIName = JNIMangle(f.Name)
   319  			if len(fs.Funcs) > 1 {
   320  				f.JNIName += "__" + JNIMangle(f.ArgDesc)
   321  			}
   322  		}
   323  	}
   324  }
   325  
   326  // commonType finds the most specific type common to t1 and t2.
   327  // If t1 and t2 are both Java classes, the most specific ancestor
   328  // class is returned.
   329  // Else if the types are equal, their type is returned.
   330  // Finally, nil is returned, indicating no common type.
   331  func commonType(clsMap map[string]*Class, t1, t2 *Type) *Type {
   332  	if t1 == nil || t2 == nil {
   333  		return nil
   334  	}
   335  	if reflect.DeepEqual(t1, t2) {
   336  		return t1
   337  	}
   338  	if t1.Kind != Object || t2.Kind != Object {
   339  		// The types are fundamentally incompatible
   340  		return nil
   341  	}
   342  	superSet := make(map[string]struct{})
   343  	supers := []string{t1.Class}
   344  	for len(supers) > 0 {
   345  		var newSupers []string
   346  		for _, s := range supers {
   347  			cls := clsMap[s]
   348  			superSet[s] = struct{}{}
   349  			newSupers = append(newSupers, cls.Supers...)
   350  		}
   351  		supers = newSupers
   352  	}
   353  	supers = []string{t2.Class}
   354  	for len(supers) > 0 {
   355  		var newSupers []string
   356  		for _, s := range supers {
   357  			if _, exists := superSet[s]; exists {
   358  				return &Type{Kind: Object, Class: s}
   359  			}
   360  			cls := clsMap[s]
   361  			newSupers = append(newSupers, cls.Supers...)
   362  		}
   363  		supers = newSupers
   364  	}
   365  	return &Type{Kind: Object, Class: "java.lang.Object"}
   366  }
   367  
   368  // combineSigs finds the most specific function signature
   369  // that covers all its overload variants.
   370  // If a function has only one variant, its common signature
   371  // is the signature of that variant.
   372  func combineSigs(clsMap map[string]*Class, sigs ...CommonSig) CommonSig {
   373  	var common CommonSig
   374  	minp := len(sigs[0].Params)
   375  	for i := 1; i < len(sigs); i++ {
   376  		sig := sigs[i]
   377  		n := len(sig.Params)
   378  		common.Variadic = common.Variadic || sig.Variadic || n != minp
   379  		if n < minp {
   380  			minp = n
   381  		}
   382  	}
   383  	for i, sig := range sigs {
   384  		for j, p := range sig.Params {
   385  			idx := j
   386  			// If the common signature is variadic, combine all parameters in the
   387  			// last parameter type of the shortest parameter list.
   388  			if idx > minp {
   389  				idx = minp
   390  			}
   391  			if idx < len(common.Params) {
   392  				common.Params[idx] = commonType(clsMap, common.Params[idx], p)
   393  			} else {
   394  				common.Params = append(common.Params, p)
   395  			}
   396  		}
   397  		common.Throws = common.Throws || sig.Throws
   398  		common.HasRet = common.HasRet || sig.HasRet
   399  		if i > 0 {
   400  			common.Ret = commonType(clsMap, common.Ret, sig.Ret)
   401  		} else {
   402  			common.Ret = sig.Ret
   403  		}
   404  	}
   405  	return common
   406  }
   407  
   408  // fillSuperSigs combines methods signatures with super class signatures,
   409  // to preserve the assignability of classes to their super classes.
   410  //
   411  // For example, the class
   412  //
   413  //	class A {
   414  //		void f();
   415  //	}
   416  //
   417  // is by itself represented by the Go interface
   418  //
   419  //	type A interface {
   420  //		f()
   421  //	}
   422  //
   423  // However, if class
   424  //
   425  //	class B extends A {
   426  //		void f(int);
   427  //	}
   428  //
   429  // is also imported, it will be represented as
   430  //
   431  //	type B interface {
   432  //		f(...int32)
   433  //	}
   434  //
   435  // To make Go B assignable to Go A, the signature of A's f must
   436  // be updated to f(...int32) as well.
   437  func (j *Importer) fillSuperSigs(cls *Class, m *FuncSet) {
   438  	for _, s := range cls.Supers {
   439  		sup := j.clsMap[s]
   440  		if sm, exists := sup.methodMap[m.GoName]; exists {
   441  			sm.CommonSig = combineSigs(j.clsMap, sm.CommonSig, m.CommonSig)
   442  		}
   443  		j.fillSuperSigs(sup, m)
   444  	}
   445  }
   446  
   447  func (v *Var) Constant() bool {
   448  	return v.Static && v.Final && v.Val != ""
   449  }
   450  
   451  // Mangle a name according to
   452  // http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp16696
   453  //
   454  // TODO: Support unicode characters
   455  func JNIMangle(s string) string {
   456  	var m []byte
   457  	for i := 0; i < len(s); i++ {
   458  		switch c := s[i]; c {
   459  		case '.', '/':
   460  			m = append(m, '_')
   461  		case '$':
   462  			m = append(m, "_00024"...)
   463  		case '_':
   464  			m = append(m, "_1"...)
   465  		case ';':
   466  			m = append(m, "_2"...)
   467  		case '[':
   468  			m = append(m, "_3"...)
   469  		default:
   470  			m = append(m, c)
   471  		}
   472  	}
   473  	return string(m)
   474  }
   475  
   476  func (t *Type) Type() string {
   477  	switch t.Kind {
   478  	case Int:
   479  		return "int"
   480  	case Boolean:
   481  		return "boolean"
   482  	case Short:
   483  		return "short"
   484  	case Char:
   485  		return "char"
   486  	case Byte:
   487  		return "byte"
   488  	case Long:
   489  		return "long"
   490  	case Float:
   491  		return "float"
   492  	case Double:
   493  		return "double"
   494  	case String:
   495  		return "String"
   496  	case Array:
   497  		return t.Elem.Type() + "[]"
   498  	case Object:
   499  		return t.Class
   500  	default:
   501  		panic("invalid kind")
   502  	}
   503  }
   504  
   505  func (t *Type) JNIType() string {
   506  	switch t.Kind {
   507  	case Int:
   508  		return "jint"
   509  	case Boolean:
   510  		return "jboolean"
   511  	case Short:
   512  		return "jshort"
   513  	case Char:
   514  		return "jchar"
   515  	case Byte:
   516  		return "jbyte"
   517  	case Long:
   518  		return "jlong"
   519  	case Float:
   520  		return "jfloat"
   521  	case Double:
   522  		return "jdouble"
   523  	case String:
   524  		return "jstring"
   525  	case Array:
   526  		return "jarray"
   527  	case Object:
   528  		return "jobject"
   529  	default:
   530  		panic("invalid kind")
   531  	}
   532  }
   533  
   534  func (t *Type) CType() string {
   535  	switch t.Kind {
   536  	case Int, Boolean, Short, Char, Byte, Long, Float, Double:
   537  		return t.JNIType()
   538  	case String:
   539  		return "nstring"
   540  	case Array:
   541  		if t.Elem.Kind != Byte {
   542  			panic("unsupported array type")
   543  		}
   544  		return "nbyteslice"
   545  	case Object:
   546  		return "jint"
   547  	default:
   548  		panic("invalid kind")
   549  	}
   550  }
   551  
   552  func (t *Type) JNICallType() string {
   553  	switch t.Kind {
   554  	case Int:
   555  		return "Int"
   556  	case Boolean:
   557  		return "Boolean"
   558  	case Short:
   559  		return "Short"
   560  	case Char:
   561  		return "Char"
   562  	case Byte:
   563  		return "Byte"
   564  	case Long:
   565  		return "Long"
   566  	case Float:
   567  		return "Float"
   568  	case Double:
   569  		return "Double"
   570  	case String, Object, Array:
   571  		return "Object"
   572  	default:
   573  		panic("invalid kind")
   574  	}
   575  }
   576  
   577  func (j *Importer) filterReferences(classes []*Class, refs *importers.References, funcRefs map[funcRef]struct{}) {
   578  	for _, cls := range classes {
   579  		var filtered []*FuncSet
   580  		for _, f := range cls.Funcs {
   581  			if _, exists := funcRefs[funcRef{cls.Name, f.GoName}]; exists {
   582  				filtered = append(filtered, f)
   583  			}
   584  		}
   585  		cls.Funcs = filtered
   586  		filtered = nil
   587  		for _, m := range cls.Methods {
   588  			if _, exists := refs.Names[m.GoName]; exists {
   589  				filtered = append(filtered, m)
   590  			}
   591  		}
   592  		cls.Methods = filtered
   593  	}
   594  }
   595  
   596  // importClasses imports the named classes from the classpaths of the Importer.
   597  func (j *Importer) importClasses(names []string, allowMissingClasses bool) ([]*Class, error) {
   598  	if len(names) == 0 {
   599  		return nil, nil
   600  	}
   601  	args := []string{"-J-Duser.language=en", "-s", "-protected", "-constants"}
   602  	args = append(args, "-classpath", j.Classpath)
   603  	//if j.Bootclasspath != "" {
   604  	//	args = append(args, "-bootclasspath", j.Bootclasspath)
   605  	//}
   606  	args = append(args, names...)
   607  	javapPath, err := javapPath()
   608  	if err != nil {
   609  		return nil, err
   610  	}
   611  	javap := exec.Command(javapPath, args...)
   612  	out, err := javap.CombinedOutput()
   613  	if err != nil {
   614  		if _, ok := err.(*exec.ExitError); !ok {
   615  			return nil, fmt.Errorf("javap failed: %v", err)
   616  		}
   617  		// Not every name is a Java class so an exit error from javap is not
   618  		// fatal.
   619  	}
   620  	s := bufio.NewScanner(bytes.NewBuffer(out))
   621  	var classes []*Class
   622  	for _, name := range names {
   623  		cls, err := j.scanClass(s, name)
   624  		if err != nil {
   625  			_, notfound := err.(*errClsNotFound)
   626  			if notfound && allowMissingClasses {
   627  				continue
   628  			}
   629  			if notfound && name != "android.databinding.DataBindingComponent" {
   630  				return nil, err
   631  			}
   632  			// The Android Databinding library generates android.databinding.DataBindingComponent
   633  			// too late in the build process for the gobind plugin to import it. Synthesize a class
   634  			// for it instead.
   635  			cls = &Class{
   636  				Name:      name,
   637  				FindName:  name,
   638  				Interface: true,
   639  				PkgName:   "databinding",
   640  				JNIName:   JNIMangle(name),
   641  			}
   642  		}
   643  		classes = append(classes, cls)
   644  		j.clsMap[name] = cls
   645  	}
   646  	return classes, nil
   647  }
   648  
   649  // importReferencedClasses imports all implicit classes (super types, parameter and
   650  // return types) for the given classes not already imported.
   651  func (j *Importer) importReferencedClasses(classes []*Class) ([]*Class, error) {
   652  	var allCls []*Class
   653  	// Include methods from extended or implemented classes.
   654  	for {
   655  		set := make(map[string]struct{})
   656  		for _, cls := range classes {
   657  			j.unknownImplicitClasses(cls, set)
   658  		}
   659  		if len(set) == 0 {
   660  			break
   661  		}
   662  		var names []string
   663  		for n := range set {
   664  			names = append(names, n)
   665  		}
   666  		newCls, err := j.importClasses(names, false)
   667  		if err != nil {
   668  			return nil, err
   669  		}
   670  		allCls = append(allCls, newCls...)
   671  		classes = newCls
   672  	}
   673  	return allCls, nil
   674  }
   675  
   676  func (j *Importer) implicitFuncTypes(f *Func) []string {
   677  	var unk []string
   678  	if rt := f.Ret; rt != nil && rt.Kind == Object {
   679  		unk = append(unk, rt.Class)
   680  	}
   681  	for _, t := range f.Params {
   682  		if t.Kind == Object {
   683  			unk = append(unk, t.Class)
   684  		}
   685  	}
   686  	return unk
   687  }
   688  
   689  func (j *Importer) unknownImplicitClasses(cls *Class, set map[string]struct{}) {
   690  	for _, fsets := range [][]*FuncSet{cls.Funcs, cls.Methods} {
   691  		for _, fs := range fsets {
   692  			for _, f := range fs.Funcs {
   693  				names := j.implicitFuncTypes(f)
   694  				for _, name := range names {
   695  					if _, exists := j.clsMap[name]; !exists {
   696  						set[name] = struct{}{}
   697  					}
   698  				}
   699  			}
   700  		}
   701  	}
   702  	for _, n := range cls.Supers {
   703  		if s, exists := j.clsMap[n]; exists {
   704  			j.unknownImplicitClasses(s, set)
   705  		} else {
   706  			set[n] = struct{}{}
   707  		}
   708  	}
   709  }
   710  
   711  func (j *Importer) implicitFuncClasses(funcs []*FuncSet, impl []string) []string {
   712  	var l []string
   713  	for _, fs := range funcs {
   714  		for _, f := range fs.Funcs {
   715  			if rt := f.Ret; rt != nil && rt.Kind == Object {
   716  				l = append(l, rt.Class)
   717  			}
   718  			for _, t := range f.Params {
   719  				if t.Kind == Object {
   720  					l = append(l, t.Class)
   721  				}
   722  			}
   723  		}
   724  	}
   725  	return impl
   726  }
   727  
   728  func (j *Importer) scanClass(s *bufio.Scanner, name string) (*Class, error) {
   729  	if !s.Scan() {
   730  		return nil, fmt.Errorf("%s: missing javap header", name)
   731  	}
   732  	head := s.Text()
   733  	if errPref := "Error: "; strings.HasPrefix(head, errPref) {
   734  		msg := head[len(errPref):]
   735  		if strings.HasPrefix(msg, "class not found: "+name) {
   736  			return nil, &errClsNotFound{name}
   737  		}
   738  		return nil, errors.New(msg)
   739  	}
   740  	if !strings.HasPrefix(head, "Compiled from ") {
   741  		return nil, fmt.Errorf("%s: unexpected header: %s", name, head)
   742  	}
   743  	if !s.Scan() {
   744  		return nil, fmt.Errorf("%s: missing javap class declaration", name)
   745  	}
   746  	clsDecl := s.Text()
   747  	cls, err := j.scanClassDecl(name, clsDecl)
   748  	if err != nil {
   749  		return nil, err
   750  	}
   751  	cls.JNIName = JNIMangle(cls.Name)
   752  	clsElems := strings.Split(cls.Name, ".")
   753  	cls.PkgName = clsElems[len(clsElems)-1]
   754  	var funcs []*Func
   755  	for s.Scan() {
   756  		decl := strings.TrimSpace(s.Text())
   757  		if decl == "}" {
   758  			break
   759  		} else if decl == "" {
   760  			continue
   761  		}
   762  		if !s.Scan() {
   763  			return nil, fmt.Errorf("%s: missing descriptor for member %q", name, decl)
   764  		}
   765  		desc := strings.TrimSpace(s.Text())
   766  		desc = strings.TrimPrefix(desc, "descriptor: ")
   767  		var static, final, abstract, public bool
   768  		// Trim modifiders from the declaration.
   769  	loop:
   770  		for {
   771  			idx := strings.Index(decl, " ")
   772  			if idx == -1 {
   773  				break
   774  			}
   775  			keyword := decl[:idx]
   776  			switch keyword {
   777  			case "public":
   778  				public = true
   779  			case "protected", "native":
   780  				// ignore
   781  			case "static":
   782  				static = true
   783  			case "final":
   784  				final = true
   785  			case "abstract":
   786  				abstract = true
   787  			default:
   788  				// Hopefully we reached the declaration now.
   789  				break loop
   790  			}
   791  			decl = decl[idx+1:]
   792  		}
   793  		// Trim ending ;
   794  		decl = decl[:len(decl)-1]
   795  		if idx := strings.Index(decl, "("); idx != -1 {
   796  			f, err := j.scanMethod(decl, desc, idx)
   797  			if err != nil {
   798  				return nil, fmt.Errorf("%s: %v", name, err)
   799  			}
   800  			if f != nil {
   801  				f.Static = static
   802  				f.Abstract = abstract
   803  				f.Public = public || cls.Interface
   804  				f.Final = final
   805  				f.Constructor = f.Name == cls.FindName
   806  				if f.Constructor {
   807  					cls.HasNoArgCon = cls.HasNoArgCon || len(f.Params) == 0
   808  					f.Public = f.Public && !cls.Abstract
   809  					f.Name = "new"
   810  					f.Ret = &Type{Class: name, Kind: Object}
   811  				}
   812  				funcs = append(funcs, f)
   813  			}
   814  		} else {
   815  			// Member is a variable
   816  			v, err := j.scanVar(decl, desc)
   817  			if err != nil {
   818  				return nil, fmt.Errorf("%s: %v", name, err)
   819  			}
   820  			if v != nil && public {
   821  				v.Static = static
   822  				v.Final = final
   823  				cls.Vars = append(cls.Vars, v)
   824  			}
   825  		}
   826  	}
   827  	for _, f := range funcs {
   828  		var m map[string]*FuncSet
   829  		var l *[]*FuncSet
   830  		goName := initialUpper(f.Name)
   831  		if f.Static || f.Constructor {
   832  			m = cls.funcMap
   833  			l = &cls.Funcs
   834  		} else {
   835  			m = cls.methodMap
   836  			l = &cls.Methods
   837  		}
   838  		fs, exists := m[goName]
   839  		if !exists {
   840  			fs = &FuncSet{
   841  				Name:   f.Name,
   842  				GoName: goName,
   843  			}
   844  			m[goName] = fs
   845  			*l = append(*l, fs)
   846  		}
   847  		fs.Funcs = append(fs.Funcs, f)
   848  	}
   849  	return cls, nil
   850  }
   851  
   852  func (j *Importer) scanClassDecl(name string, decl string) (*Class, error) {
   853  	isRoot := name == "java.lang.Object"
   854  	cls := &Class{
   855  		Name:        name,
   856  		funcMap:     make(map[string]*FuncSet),
   857  		methodMap:   make(map[string]*FuncSet),
   858  		HasNoArgCon: isRoot,
   859  	}
   860  	const (
   861  		stMod = iota
   862  		stName
   863  		stExt
   864  		stImpl
   865  	)
   866  	superClsDecl := isRoot
   867  	st := stMod
   868  	var w []byte
   869  	// if > 0, we're inside a generics declaration
   870  	gennest := 0
   871  	for i := 0; i < len(decl); i++ {
   872  		c := decl[i]
   873  		switch c {
   874  		default:
   875  			if gennest == 0 {
   876  				w = append(w, c)
   877  			}
   878  		case '>':
   879  			gennest--
   880  		case '<':
   881  			gennest++
   882  		case '{':
   883  			if !superClsDecl && !cls.Interface {
   884  				cls.Supers = append(cls.Supers, "java.lang.Object")
   885  			}
   886  			return cls, nil
   887  		case ' ', ',':
   888  			if gennest > 0 {
   889  				break
   890  			}
   891  			switch w := string(w); w {
   892  			default:
   893  				switch st {
   894  				case stName:
   895  					if strings.Replace(w, "$", ".", -1) != strings.Replace(name, "$", ".", -1) {
   896  						return nil, fmt.Errorf("unexpected name %q in class declaration: %q", w, decl)
   897  					}
   898  					cls.FindName = w
   899  				case stExt:
   900  					superClsDecl = true
   901  					cls.Supers = append(cls.Supers, w)
   902  				case stImpl:
   903  					if !cls.Interface {
   904  						cls.Supers = append(cls.Supers, w)
   905  					}
   906  				default:
   907  					return nil, fmt.Errorf("unexpected %q in class declaration: %q", w, decl)
   908  				}
   909  			case "":
   910  				// skip
   911  			case "public":
   912  				if st != stMod {
   913  					return nil, fmt.Errorf("unexpected %q in class declaration: %q", w, decl)
   914  				}
   915  			case "abstract":
   916  				if st != stMod {
   917  					return nil, fmt.Errorf("unexpected %q in class declaration: %q", w, decl)
   918  				}
   919  				cls.Abstract = true
   920  			case "final":
   921  				if st != stMod {
   922  					return nil, fmt.Errorf("unexpected %q in class declaration: %q", w, decl)
   923  				}
   924  				cls.Final = true
   925  			case "interface":
   926  				cls.Interface = true
   927  				fallthrough
   928  			case "class":
   929  				if st != stMod {
   930  					return nil, fmt.Errorf("unexpected %q in class declaration: %q", w, decl)
   931  				}
   932  				st = stName
   933  			case "extends":
   934  				if st != stName {
   935  					return nil, fmt.Errorf("unexpected %q in class declaration: %q", w, decl)
   936  				}
   937  				st = stExt
   938  			case "implements":
   939  				if st != stName && st != stExt {
   940  					return nil, fmt.Errorf("unexpected %q in class declaration: %q", w, decl)
   941  				}
   942  				st = stImpl
   943  			}
   944  			w = w[:0]
   945  		}
   946  	}
   947  	return nil, fmt.Errorf("missing ending { in class declaration: %q", decl)
   948  }
   949  
   950  func (j *Importer) scanVar(decl, desc string) (*Var, error) {
   951  	v := new(Var)
   952  	const eq = " = "
   953  	idx := strings.Index(decl, eq)
   954  	if idx != -1 {
   955  		val, ok := j.parseJavaValue(decl[idx+len(eq):])
   956  		if !ok {
   957  			// Skip constants that cannot be represented in Go
   958  			return nil, nil
   959  		}
   960  		v.Val = val
   961  	} else {
   962  		idx = len(decl)
   963  	}
   964  	for i := idx - 1; i >= 0; i-- {
   965  		if i == 0 || decl[i-1] == ' ' {
   966  			v.Name = decl[i:idx]
   967  			break
   968  		}
   969  	}
   970  	if v.Name == "" {
   971  		return nil, fmt.Errorf("unable to parse member name from declaration: %q", decl)
   972  	}
   973  	typ, _, err := j.parseJavaType(desc)
   974  	if err != nil {
   975  		return nil, fmt.Errorf("invalid type signature for %s: %q", v.Name, desc)
   976  	}
   977  	v.Type = typ
   978  	return v, nil
   979  }
   980  
   981  func (j *Importer) scanMethod(decl, desc string, parenIdx int) (*Func, error) {
   982  	// Member is a method
   983  	f := new(Func)
   984  	f.Desc = desc
   985  	for i := parenIdx - 1; i >= 0; i-- {
   986  		if i == 0 || decl[i-1] == ' ' {
   987  			f.Name = decl[i:parenIdx]
   988  			break
   989  		}
   990  	}
   991  	if f.Name == "" {
   992  		return nil, fmt.Errorf("unable to parse method name from declaration: %q", decl)
   993  	}
   994  	if desc[0] != '(' {
   995  		return nil, fmt.Errorf("invalid descriptor for method %s: %q", f.Name, desc)
   996  	}
   997  	const throws = " throws "
   998  	if idx := strings.Index(decl, throws); idx != -1 {
   999  		f.Throws = decl[idx+len(throws):]
  1000  	}
  1001  	i := 1
  1002  	for desc[i] != ')' {
  1003  		typ, n, err := j.parseJavaType(desc[i:])
  1004  		if err != nil {
  1005  			return nil, fmt.Errorf("invalid descriptor for method %s: %v", f.Name, err)
  1006  		}
  1007  		i += n
  1008  		f.Params = append(f.Params, typ)
  1009  	}
  1010  	f.ArgDesc = desc[1:i]
  1011  	i++ // skip ending )
  1012  	if desc[i] != 'V' {
  1013  		typ, _, err := j.parseJavaType(desc[i:])
  1014  		if err != nil {
  1015  			return nil, fmt.Errorf("invalid descriptor for method %s: %v", f.Name, err)
  1016  		}
  1017  		f.Ret = typ
  1018  	}
  1019  	return f, nil
  1020  }
  1021  
  1022  func (j *Importer) fillThrowables(classes []*Class) {
  1023  	thrCls, ok := j.clsMap["java.lang.Throwable"]
  1024  	if !ok {
  1025  		// If Throwable isn't in the class map
  1026  		// no imported class inherits from Throwable
  1027  		return
  1028  	}
  1029  	for _, cls := range classes {
  1030  		j.fillThrowableFor(cls, thrCls)
  1031  	}
  1032  }
  1033  
  1034  func (j *Importer) fillThrowableFor(cls, thrCls *Class) {
  1035  	if cls.Interface || cls.Throwable {
  1036  		return
  1037  	}
  1038  	cls.Throwable = cls == thrCls
  1039  	for _, name := range cls.Supers {
  1040  		sup := j.clsMap[name]
  1041  		j.fillThrowableFor(sup, thrCls)
  1042  		cls.Throwable = cls.Throwable || sup.Throwable
  1043  	}
  1044  }
  1045  
  1046  func commonSig(f *Func) CommonSig {
  1047  	return CommonSig{
  1048  		Params: f.Params,
  1049  		Ret:    f.Ret,
  1050  		HasRet: f.Ret != nil,
  1051  		Throws: f.Throws != "",
  1052  	}
  1053  }
  1054  
  1055  func (j *Importer) fillFuncSigs(funcs []*FuncSet) {
  1056  	for _, fs := range funcs {
  1057  		var sigs []CommonSig
  1058  		for _, f := range fs.Funcs {
  1059  			sigs = append(sigs, commonSig(f))
  1060  		}
  1061  		fs.CommonSig = combineSigs(j.clsMap, sigs...)
  1062  	}
  1063  }
  1064  
  1065  func (j *Importer) fillAllMethods(cls *Class) {
  1066  	if len(cls.AllMethods) > 0 {
  1067  		return
  1068  	}
  1069  	for _, supName := range cls.Supers {
  1070  		super := j.clsMap[supName]
  1071  		j.fillAllMethods(super)
  1072  	}
  1073  	var fsets []*FuncSet
  1074  	fsets = append(fsets, cls.Methods...)
  1075  	for _, supName := range cls.Supers {
  1076  		super := j.clsMap[supName]
  1077  		fsets = append(fsets, super.AllMethods...)
  1078  	}
  1079  	sigs := make(map[FuncSig]struct{})
  1080  	methods := make(map[string]*FuncSet)
  1081  	for _, fs := range fsets {
  1082  		clsFs, exists := methods[fs.Name]
  1083  		if !exists {
  1084  			clsFs = &FuncSet{
  1085  				Name:      fs.Name,
  1086  				GoName:    fs.GoName,
  1087  				CommonSig: fs.CommonSig,
  1088  			}
  1089  			cls.AllMethods = append(cls.AllMethods, clsFs)
  1090  			methods[fs.Name] = clsFs
  1091  		} else {
  1092  			// Combine the (overloaded) signature with the other variants.
  1093  			clsFs.CommonSig = combineSigs(j.clsMap, clsFs.CommonSig, fs.CommonSig)
  1094  		}
  1095  		for _, f := range fs.Funcs {
  1096  			if _, exists := sigs[f.FuncSig]; exists {
  1097  				continue
  1098  			}
  1099  			sigs[f.FuncSig] = struct{}{}
  1100  			clsFs.Funcs = append(clsFs.Funcs, f)
  1101  		}
  1102  	}
  1103  }
  1104  
  1105  func (j *Importer) parseJavaValue(v string) (string, bool) {
  1106  	v = strings.TrimRight(v, "ldf")
  1107  	switch v {
  1108  	case "", "NaN", "Infinity", "-Infinity":
  1109  		return "", false
  1110  	default:
  1111  		if v[0] == '\'' {
  1112  			// Skip character constants, since they can contain invalid code points
  1113  			// that are unacceptable to Go.
  1114  			return "", false
  1115  		}
  1116  		return v, true
  1117  	}
  1118  }
  1119  
  1120  func (j *Importer) parseJavaType(desc string) (*Type, int, error) {
  1121  	t := new(Type)
  1122  	var n int
  1123  	if desc == "" {
  1124  		return t, n, errors.New("empty type signature")
  1125  	}
  1126  	n++
  1127  	switch desc[0] {
  1128  	case 'Z':
  1129  		t.Kind = Boolean
  1130  	case 'B':
  1131  		t.Kind = Byte
  1132  	case 'C':
  1133  		t.Kind = Char
  1134  	case 'S':
  1135  		t.Kind = Short
  1136  	case 'I':
  1137  		t.Kind = Int
  1138  	case 'J':
  1139  		t.Kind = Long
  1140  	case 'F':
  1141  		t.Kind = Float
  1142  	case 'D':
  1143  		t.Kind = Double
  1144  	case 'L':
  1145  		var clsName string
  1146  		for i := n; i < len(desc); i++ {
  1147  			if desc[i] == ';' {
  1148  				clsName = strings.Replace(desc[n:i], "/", ".", -1)
  1149  				clsName = strings.Replace(clsName, "$", ".", -1)
  1150  				n += i - n + 1
  1151  				break
  1152  			}
  1153  		}
  1154  		if clsName == "" {
  1155  			return t, n, errors.New("missing ; in class type signature")
  1156  		}
  1157  		if clsName == "java.lang.String" {
  1158  			t.Kind = String
  1159  		} else {
  1160  			t.Kind = Object
  1161  			t.Class = clsName
  1162  		}
  1163  	case '[':
  1164  		et, n2, err := j.parseJavaType(desc[n:])
  1165  		if err != nil {
  1166  			return t, n, err
  1167  		}
  1168  		n += n2
  1169  		t.Kind = Array
  1170  		t.Elem = et
  1171  	default:
  1172  		return t, n, fmt.Errorf("invalid type signature: %s", desc)
  1173  	}
  1174  	return t, n, nil
  1175  }
  1176  
  1177  func initialUpper(s string) string {
  1178  	if s == "" {
  1179  		return ""
  1180  	}
  1181  	r, n := utf8.DecodeRuneInString(s)
  1182  	return string(unicode.ToUpper(r)) + s[n:]
  1183  }