in internal/importers/java/java.go [193:312]
func (j *Importer) Import(refs *importers.References) ([]*Class, error) {
if j.clsMap == nil {
j.clsMap = make(map[string]*Class)
}
clsSet := make(map[string]struct{})
var names []string
for _, ref := range refs.Refs {
// The reference could be to some/pkg.Class or some/pkg/Class.Identifier. Include both.
pkg := strings.Replace(ref.Pkg, "/", ".", -1)
for _, cls := range []string{pkg, pkg + "." + ref.Name} {
if _, exists := clsSet[cls]; !exists {
clsSet[cls] = struct{}{}
names = append(names, cls)
}
}
}
// Make sure toString() is included; it is called when wrapping Java exception types to Go
// errors.
refs.Names["ToString"] = struct{}{}
funcRefs := make(map[funcRef]struct{})
for _, ref := range refs.Refs {
pkgName := strings.Replace(ref.Pkg, "/", ".", -1)
funcRefs[funcRef{pkgName, ref.Name}] = struct{}{}
}
classes, err := j.importClasses(names, true)
if err != nil {
return nil, err
}
j.filterReferences(classes, refs, funcRefs)
supers, err := j.importReferencedClasses(classes)
if err != nil {
return nil, err
}
j.filterReferences(supers, refs, funcRefs)
// Embedders refer to every exported Go struct that will have its class
// generated. Allow Go code to reverse bind to those classes by synthesizing
// their class descriptors.
for _, emb := range refs.Embedders {
n := emb.Pkg + "." + emb.Name
if j.JavaPkg != "" {
n = j.JavaPkg + "." + n
}
if _, exists := j.clsMap[n]; exists {
continue
}
clsSet[n] = struct{}{}
cls := &Class{
Name: n,
FindName: n,
JNIName: JNIMangle(n),
PkgName: emb.Name,
HasNoArgCon: true,
}
for _, ref := range emb.Refs {
jpkg := strings.Replace(ref.Pkg, "/", ".", -1)
super := jpkg + "." + ref.Name
if _, exists := j.clsMap[super]; !exists {
return nil, fmt.Errorf("failed to find Java class %s, embedded by %s", super, n)
}
cls.Supers = append(cls.Supers, super)
}
classes = append(classes, cls)
j.clsMap[cls.Name] = cls
}
// Include implicit classes that are used in parameter or return values.
for _, cls := range classes {
for _, fsets := range [][]*FuncSet{cls.Funcs, cls.Methods} {
for _, fs := range fsets {
for _, f := range fs.Funcs {
names := j.implicitFuncTypes(f)
for _, name := range names {
if _, exists := clsSet[name]; exists {
continue
}
clsSet[name] = struct{}{}
classes = append(classes, j.clsMap[name])
}
}
}
}
}
for _, cls := range j.clsMap {
j.fillFuncSigs(cls.Funcs)
j.fillFuncSigs(cls.Methods)
for _, m := range cls.Methods {
j.fillSuperSigs(cls, m)
}
}
for _, cls := range j.clsMap {
j.fillAllMethods(cls)
}
// Include classes that appear as ancestor types for overloaded signatures.
for _, cls := range classes {
for _, funcs := range [][]*FuncSet{cls.Funcs, cls.AllMethods} {
for _, f := range funcs {
for _, p := range f.Params {
if p == nil || p.Kind != Object {
continue
}
if _, exists := clsSet[p.Class]; !exists {
clsSet[p.Class] = struct{}{}
classes = append(classes, j.clsMap[p.Class])
}
}
if t := f.Ret; t != nil && t.Kind == Object {
if _, exists := clsSet[t.Class]; !exists {
clsSet[t.Class] = struct{}{}
classes = append(classes, j.clsMap[t.Class])
}
}
}
}
}
for _, cls := range classes {
j.fillJNINames(cls.Funcs)
j.fillJNINames(cls.AllMethods)
}
j.fillThrowables(classes)
return classes, nil
}