in internal/importers/java/java.go [727:849]
func (j *Importer) scanClass(s *bufio.Scanner, name string) (*Class, error) {
if !s.Scan() {
return nil, fmt.Errorf("%s: missing javap header", name)
}
head := s.Text()
if errPref := "Error: "; strings.HasPrefix(head, errPref) {
msg := head[len(errPref):]
if strings.HasPrefix(msg, "class not found: "+name) {
return nil, &errClsNotFound{name}
}
return nil, errors.New(msg)
}
if !strings.HasPrefix(head, "Compiled from ") {
return nil, fmt.Errorf("%s: unexpected header: %s", name, head)
}
if !s.Scan() {
return nil, fmt.Errorf("%s: missing javap class declaration", name)
}
clsDecl := s.Text()
cls, err := j.scanClassDecl(name, clsDecl)
if err != nil {
return nil, err
}
cls.JNIName = JNIMangle(cls.Name)
clsElems := strings.Split(cls.Name, ".")
cls.PkgName = clsElems[len(clsElems)-1]
var funcs []*Func
for s.Scan() {
decl := strings.TrimSpace(s.Text())
if decl == "}" {
break
} else if decl == "" {
continue
}
if !s.Scan() {
return nil, fmt.Errorf("%s: missing descriptor for member %q", name, decl)
}
desc := strings.TrimSpace(s.Text())
desc = strings.TrimPrefix(desc, "descriptor: ")
var static, final, abstract, public bool
// Trim modifiders from the declaration.
loop:
for {
idx := strings.Index(decl, " ")
if idx == -1 {
break
}
keyword := decl[:idx]
switch keyword {
case "public":
public = true
case "protected", "native":
// ignore
case "static":
static = true
case "final":
final = true
case "abstract":
abstract = true
default:
// Hopefully we reached the declaration now.
break loop
}
decl = decl[idx+1:]
}
// Trim ending ;
decl = decl[:len(decl)-1]
if idx := strings.Index(decl, "("); idx != -1 {
f, err := j.scanMethod(decl, desc, idx)
if err != nil {
return nil, fmt.Errorf("%s: %v", name, err)
}
if f != nil {
f.Static = static
f.Abstract = abstract
f.Public = public || cls.Interface
f.Final = final
f.Constructor = f.Name == cls.FindName
if f.Constructor {
cls.HasNoArgCon = cls.HasNoArgCon || len(f.Params) == 0
f.Public = f.Public && !cls.Abstract
f.Name = "new"
f.Ret = &Type{Class: name, Kind: Object}
}
funcs = append(funcs, f)
}
} else {
// Member is a variable
v, err := j.scanVar(decl, desc)
if err != nil {
return nil, fmt.Errorf("%s: %v", name, err)
}
if v != nil && public {
v.Static = static
v.Final = final
cls.Vars = append(cls.Vars, v)
}
}
}
for _, f := range funcs {
var m map[string]*FuncSet
var l *[]*FuncSet
goName := initialUpper(f.Name)
if f.Static || f.Constructor {
m = cls.funcMap
l = &cls.Funcs
} else {
m = cls.methodMap
l = &cls.Methods
}
fs, exists := m[goName]
if !exists {
fs = &FuncSet{
Name: f.Name,
GoName: goName,
}
m[goName] = fs
*l = append(*l, fs)
}
fs.Funcs = append(fs.Funcs, f)
}
return cls, nil
}