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