in mockgen/parse.go [250:353]
func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*model.Interface, error) {
iface := &model.Interface{Name: name}
for _, field := range it.Methods.List {
switch v := field.Type.(type) {
case *ast.FuncType:
if nn := len(field.Names); nn != 1 {
return nil, fmt.Errorf("expected one name for interface %v, got %d", iface.Name, nn)
}
m := &model.Method{
Name: field.Names[0].String(),
}
var err error
m.In, m.Variadic, m.Out, err = p.parseFunc(pkg, v)
if err != nil {
return nil, err
}
iface.AddMethod(m)
case *ast.Ident:
// Embedded interface in this package.
embeddedIfaceType := p.auxInterfaces[pkg][v.String()]
if embeddedIfaceType == nil {
embeddedIfaceType = p.importedInterfaces[pkg][v.String()]
}
var embeddedIface *model.Interface
if embeddedIfaceType != nil {
var err error
embeddedIface, err = p.parseInterface(v.String(), pkg, embeddedIfaceType)
if err != nil {
return nil, err
}
} else {
// This is built-in error interface.
if v.String() == model.ErrorInterface.Name {
embeddedIface = &model.ErrorInterface
} else {
ip, err := p.parsePackage(pkg)
if err != nil {
return nil, p.errorf(v.Pos(), "could not parse package %s: %v", pkg, err)
}
if embeddedIfaceType = ip.importedInterfaces[pkg][v.String()]; embeddedIfaceType == nil {
return nil, p.errorf(v.Pos(), "unknown embedded interface %s.%s", pkg, v.String())
}
embeddedIface, err = ip.parseInterface(v.String(), pkg, embeddedIfaceType)
if err != nil {
return nil, err
}
}
}
// Copy the methods.
for _, m := range embeddedIface.Methods {
iface.AddMethod(m)
}
case *ast.SelectorExpr:
// Embedded interface in another package.
filePkg, sel := v.X.(*ast.Ident).String(), v.Sel.String()
embeddedPkg, ok := p.imports[filePkg]
if !ok {
return nil, p.errorf(v.X.Pos(), "unknown package %s", filePkg)
}
var embeddedIface *model.Interface
var err error
embeddedIfaceType := p.auxInterfaces[filePkg][sel]
if embeddedIfaceType != nil {
embeddedIface, err = p.parseInterface(sel, filePkg, embeddedIfaceType)
if err != nil {
return nil, err
}
} else {
path := embeddedPkg.Path()
parser := embeddedPkg.Parser()
if parser == nil {
ip, err := p.parsePackage(path)
if err != nil {
return nil, p.errorf(v.Pos(), "could not parse package %s: %v", path, err)
}
parser = ip
p.imports[filePkg] = importedPkg{
path: embeddedPkg.Path(),
parser: parser,
}
}
if embeddedIfaceType = parser.importedInterfaces[path][sel]; embeddedIfaceType == nil {
return nil, p.errorf(v.Pos(), "unknown embedded interface %s.%s", path, sel)
}
embeddedIface, err = parser.parseInterface(sel, path, embeddedIfaceType)
if err != nil {
return nil, err
}
}
// Copy the methods.
// TODO: apply shadowing rules.
for _, m := range embeddedIface.Methods {
iface.AddMethod(m)
}
default:
return nil, fmt.Errorf("don't know how to mock method of type %T", field.Type)
}
}
return iface, nil
}