func()

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
}