From cfa99c97a8197a3899aa6c322f7adc2f6b3a8e9d Mon Sep 17 00:00:00 2001 From: Zhongpeng Lin Date: Sun, 24 Sep 2023 17:32:44 -0700 Subject: [PATCH 1/8] Porting golang/mock#633 --- README.md | 20 +++- mockgen/archive.go | 55 +++++++++++ mockgen/mockgen.go | 23 ++++- mockgen/model/model_gotypes.go | 164 +++++++++++++++++++++++++++++++++ 4 files changed, 257 insertions(+), 5 deletions(-) create mode 100644 mockgen/archive.go create mode 100644 mockgen/model/model_gotypes.go diff --git a/README.md b/README.md index eba715b..b7ce6a6 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,23 @@ go install go.uber.org/mock/mockgen@latest ## Running mockgen -`mockgen` has two modes of operation: source and reflect. +`mockgen` has three modes of operation: archive, source and reflect. + +### Archive mode + +Archive mode generates mock interfaces from a package archive +file (.a). It is enabled by using the -archive flag, the import +path is also needed as a non-flag argument. No other flags are +required. + +Example: + +```bash +# Build the package to a archive. +go build -o pkg.a database/sql/driver + +mockgen -archive=pkg.a database/sql/driver +``` ### Source mode @@ -66,6 +82,8 @@ The `mockgen` command is used to generate source code for a mock class given a Go source file containing interfaces to be mocked. It supports the following flags: +- `-archive`: A package archive file containing interfaces to be mocked. + - `-source`: A file containing interfaces to be mocked. - `-destination`: A file to which to write the resulting source code. If you diff --git a/mockgen/archive.go b/mockgen/archive.go new file mode 100644 index 0000000..11b2f1f --- /dev/null +++ b/mockgen/archive.go @@ -0,0 +1,55 @@ +package main + +import ( + "fmt" + "go/token" + "go/types" + "log" + "os" + + "go.uber.org/mock/mockgen/model" + + "golang.org/x/tools/go/gcexportdata" +) + +func archiveMode(importpath, archive string) (*model.Package, error) { + f, err := os.Open(archive) + if err != nil { + return nil, err + } + defer f.Close() + r, err := gcexportdata.NewReader(f) + if err != nil { + return nil, fmt.Errorf("read export data %q: %v", archive, err) + } + + fset := token.NewFileSet() + imports := make(map[string]*types.Package) + tp, err := gcexportdata.Read(r, fset, imports, importpath) + if err != nil { + return nil, err + } + + pkg := &model.Package{ + Name: tp.Name(), + PkgPath: tp.Path(), + } + for _, name := range tp.Scope().Names() { + m := tp.Scope().Lookup(name) + tn, ok := m.(*types.TypeName) + if !ok { + continue + } + ti, ok := tn.Type().Underlying().(*types.Interface) + if !ok { + continue + } + it, err := model.InterfaceFromGoTypesType(ti) + if err != nil { + log.Fatal(err) + } + it.Name = m.Name() + pkg.Interfaces = append(pkg.Interfaces, it) + } + return pkg, nil +} diff --git a/mockgen/mockgen.go b/mockgen/mockgen.go index feb747f..2f5f7e3 100644 --- a/mockgen/mockgen.go +++ b/mockgen/mockgen.go @@ -53,6 +53,7 @@ var ( ) var ( + archive = flag.String("archive", "", "(archive mode) Input Go archive file; enables archive mode.") source = flag.String("source", "", "(source mode) Input Go source file; enables source mode.") destination = flag.String("destination", "", "Output file; defaults to stdout.") mockNames = flag.String("mock_names", "", "Comma-separated interfaceName=mockName pairs of explicit mock names to use. Mock names default to 'Mock'+ interfaceName suffix.") @@ -66,9 +67,8 @@ var ( imports = flag.String("imports", "", "(source mode) Comma-separated name=path pairs of explicit imports to use.") auxFiles = flag.String("aux_files", "", "(source mode) Comma-separated pkg=path pairs of auxiliary Go source files.") excludeInterfaces = flag.String("exclude_interfaces", "", "Comma-separated names of interfaces to be excluded") - - debugParser = flag.Bool("debug_parser", false, "Print out parser results only.") - showVersion = flag.Bool("version", false, "Print version.") + debugParser = flag.Bool("debug_parser", false, "Print out parser results only.") + showVersion = flag.Bool("version", false, "Print version.") ) func main() { @@ -85,6 +85,12 @@ func main() { var packageName string if *source != "" { pkg, err = sourceMode(*source) + } else if *archive != "" { + if flag.NArg() != 1 { + usage() + log.Fatal("Expected exactly one argument") + } + pkg, err = archiveMode(flag.Arg(0), *archive) } else { if flag.NArg() != 2 { usage() @@ -144,6 +150,8 @@ func main() { g := new(generator) if *source != "" { g.filename = *source + } else if *archive != "" { + g.filename = *archive } else { g.srcPackage = packageName g.srcInterfaces = flag.Arg(1) @@ -224,7 +232,14 @@ func usage() { flag.PrintDefaults() } -const usageText = `mockgen has two modes of operation: source and reflect. +const usageText = `mockgen has three modes of operation: archive, source and reflect. + +Archive mode generates mock interfaces from a package archive +file (.a). It is enabled by using the -archive flag, the import +path is also needed as a non-flag argument. No other flags are +required. +Example: + mockgen -archive=pkg.a importpath Source mode generates mock interfaces from a source file. It is enabled by using the -source flag. Other flags that diff --git a/mockgen/model/model_gotypes.go b/mockgen/model/model_gotypes.go new file mode 100644 index 0000000..2b1a976 --- /dev/null +++ b/mockgen/model/model_gotypes.go @@ -0,0 +1,164 @@ +package model + +import ( + "fmt" + "go/types" +) + +// InterfaceFromGoTypesType returns a pointer to an interface for the +// given reflection interface type. +func InterfaceFromGoTypesType(it *types.Interface) (*Interface, error) { + intf := &Interface{} + + for i := 0; i < it.NumMethods(); i++ { + mt := it.Method(i) + // TODO: need to skip unexported methods? or just raise an error? + m := &Method{ + Name: mt.Name(), + } + + var err error + m.In, m.Variadic, m.Out, err = funcArgsFromGoTypesType(mt.Type().(*types.Signature)) + if err != nil { + return nil, err + } + + intf.AddMethod(m) + } + + return intf, nil +} + +func funcArgsFromGoTypesType(t *types.Signature) (in []*Parameter, variadic *Parameter, out []*Parameter, err error) { + nin := t.Params().Len() + if t.Variadic() { + nin-- + } + var p *Parameter + for i := 0; i < nin; i++ { + p, err = parameterFromGoTypesType(t.Params().At(i), false) + if err != nil { + return + } + in = append(in, p) + } + if t.Variadic() { + p, err = parameterFromGoTypesType(t.Params().At(nin), true) + if err != nil { + return + } + variadic = p + } + for i := 0; i < t.Results().Len(); i++ { + p, err = parameterFromGoTypesType(t.Results().At(i), false) + if err != nil { + return + } + out = append(out, p) + } + return +} + +func parameterFromGoTypesType(v *types.Var, variadic bool) (*Parameter, error) { + t := v.Type() + if variadic { + t = t.(*types.Slice).Elem() + } + tt, err := typeFromGoTypesType(t) + if err != nil { + return nil, err + } + return &Parameter{Name: v.Name(), Type: tt}, nil +} + +func typeFromGoTypesType(t types.Type) (Type, error) { + // Hack workaround for https://golang.org/issue/3853. + // This explicit check should not be necessary. + // if t == byteType { + // return PredeclaredType("byte"), nil + // } + + if t, ok := t.(*types.Named); ok { + tn := t.Obj() + if tn.Pkg() == nil { + return PredeclaredType(tn.Name()), nil + } + return &NamedType{ + Package: tn.Pkg().Path(), + Type: tn.Name(), + }, nil + } + + // only unnamed or predeclared types after here + + // Lots of types have element types. Let's do the parsing and error checking for all of them. + var elemType Type + if t, ok := t.(interface{ Elem() types.Type }); ok { + var err error + elemType, err = typeFromGoTypesType(t.Elem()) + if err != nil { + return nil, err + } + } + + switch t := t.(type) { + case *types.Array: + return &ArrayType{ + Len: int(t.Len()), + Type: elemType, + }, nil + case *types.Basic: + return PredeclaredType(t.String()), nil + case *types.Chan: + var dir ChanDir + switch t.Dir() { + case types.RecvOnly: + dir = RecvDir + case types.SendOnly: + dir = SendDir + } + return &ChanType{ + Dir: dir, + Type: elemType, + }, nil + case *types.Signature: + in, variadic, out, err := funcArgsFromGoTypesType(t) + if err != nil { + return nil, err + } + return &FuncType{ + In: in, + Out: out, + Variadic: variadic, + }, nil + case *types.Interface: + if t.NumMethods() == 0 { + return PredeclaredType("interface{}"), nil + } + case *types.Map: + kt, err := typeFromGoTypesType(t.Key()) + if err != nil { + return nil, err + } + return &MapType{ + Key: kt, + Value: elemType, + }, nil + case *types.Pointer: + return &PointerType{ + Type: elemType, + }, nil + case *types.Slice: + return &ArrayType{ + Len: -1, + Type: elemType, + }, nil + case *types.Struct: + if t.NumFields() == 0 { + return PredeclaredType("struct{}"), nil + } + } + + // TODO: Struct, UnsafePointer + return nil, fmt.Errorf("can't yet turn %v (%T) into a model.Type", t.String(), t) +} From efa95d95a0ccef342dccbfd6c08db040bb950bc8 Mon Sep 17 00:00:00 2001 From: Zhongpeng Lin Date: Tue, 10 Oct 2023 20:51:31 -0700 Subject: [PATCH 2/8] passing a list of interfaces --- mockgen/archive.go | 6 +++--- mockgen/mockgen.go | 42 ++++++++++++++++++++---------------------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/mockgen/archive.go b/mockgen/archive.go index 11b2f1f..1f79e4d 100644 --- a/mockgen/archive.go +++ b/mockgen/archive.go @@ -12,7 +12,7 @@ import ( "golang.org/x/tools/go/gcexportdata" ) -func archiveMode(importpath, archive string) (*model.Package, error) { +func archiveMode(importPath string, symbols []string, archive string) (*model.Package, error) { f, err := os.Open(archive) if err != nil { return nil, err @@ -25,7 +25,7 @@ func archiveMode(importpath, archive string) (*model.Package, error) { fset := token.NewFileSet() imports := make(map[string]*types.Package) - tp, err := gcexportdata.Read(r, fset, imports, importpath) + tp, err := gcexportdata.Read(r, fset, imports, importPath) if err != nil { return nil, err } @@ -34,7 +34,7 @@ func archiveMode(importpath, archive string) (*model.Package, error) { Name: tp.Name(), PkgPath: tp.Path(), } - for _, name := range tp.Scope().Names() { + for _, name := range symbols { m := tp.Scope().Lookup(name) tn, ok := m.(*types.TypeName) if !ok { diff --git a/mockgen/mockgen.go b/mockgen/mockgen.go index 2f5f7e3..13c8028 100644 --- a/mockgen/mockgen.go +++ b/mockgen/mockgen.go @@ -85,12 +85,6 @@ func main() { var packageName string if *source != "" { pkg, err = sourceMode(*source) - } else if *archive != "" { - if flag.NArg() != 1 { - usage() - log.Fatal("Expected exactly one argument") - } - pkg, err = archiveMode(flag.Arg(0), *archive) } else { if flag.NArg() != 2 { usage() @@ -98,17 +92,21 @@ func main() { } packageName = flag.Arg(0) interfaces := strings.Split(flag.Arg(1), ",") - if packageName == "." { - dir, err := os.Getwd() - if err != nil { - log.Fatalf("Get current directory failed: %v", err) - } - packageName, err = packageNameOfDir(dir) - if err != nil { - log.Fatalf("Parse package name failed: %v", err) + if *archive != "" { + pkg, err = archiveMode(packageName, interfaces, *archive) + } else { + if packageName == "." { + dir, err := os.Getwd() + if err != nil { + log.Fatalf("Get current directory failed: %v", err) + } + packageName, err = packageNameOfDir(dir) + if err != nil { + log.Fatalf("Parse package name failed: %v", err) + } } + pkg, err = reflectMode(packageName, interfaces) } - pkg, err = reflectMode(packageName, interfaces) } if err != nil { log.Fatalf("Loading input failed: %v", err) @@ -234,13 +232,6 @@ func usage() { const usageText = `mockgen has three modes of operation: archive, source and reflect. -Archive mode generates mock interfaces from a package archive -file (.a). It is enabled by using the -archive flag, the import -path is also needed as a non-flag argument. No other flags are -required. -Example: - mockgen -archive=pkg.a importpath - Source mode generates mock interfaces from a source file. It is enabled by using the -source flag. Other flags that may be useful in this mode are -imports and -aux_files. @@ -254,6 +245,13 @@ comma-separated list of symbols. Example: mockgen database/sql/driver Conn,Driver +Archive mode generates mock interfaces from a package archive +file (.a). It is enabled by using the -archive flag and two +two non-flag arguments: an import path, and a comma-separated +list of symbols. +Example: + mockgen -archive=pkg.a database/sql/driver Conn,Driver + ` type generator struct { From e50e7bbe7eafcf1dbd074d7514c75260f34ebbab Mon Sep 17 00:00:00 2001 From: Zhongpeng Lin Date: Wed, 11 Oct 2023 07:22:17 -0700 Subject: [PATCH 3/8] comments --- README.md | 6 +++--- mockgen/mockgen.go | 2 +- mockgen/model/model_gotypes.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b7ce6a6..6f05a12 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,9 @@ go install go.uber.org/mock/mockgen@latest ### Archive mode Archive mode generates mock interfaces from a package archive -file (.a). It is enabled by using the -archive flag, the import -path is also needed as a non-flag argument. No other flags are -required. +file (.a). It is enabled by using the -archive flag and two +non-flag arguments: an import path, and a comma-separated +list of symbols. Example: diff --git a/mockgen/mockgen.go b/mockgen/mockgen.go index 13c8028..93db24b 100644 --- a/mockgen/mockgen.go +++ b/mockgen/mockgen.go @@ -247,7 +247,7 @@ Example: Archive mode generates mock interfaces from a package archive file (.a). It is enabled by using the -archive flag and two -two non-flag arguments: an import path, and a comma-separated +non-flag arguments: an import path, and a comma-separated list of symbols. Example: mockgen -archive=pkg.a database/sql/driver Conn,Driver diff --git a/mockgen/model/model_gotypes.go b/mockgen/model/model_gotypes.go index 2b1a976..37e5e38 100644 --- a/mockgen/model/model_gotypes.go +++ b/mockgen/model/model_gotypes.go @@ -157,8 +157,8 @@ func typeFromGoTypesType(t types.Type) (Type, error) { if t.NumFields() == 0 { return PredeclaredType("struct{}"), nil } + // TODO: UnsafePointer } - // TODO: Struct, UnsafePointer return nil, fmt.Errorf("can't yet turn %v (%T) into a model.Type", t.String(), t) } From b0a8c11753717f368d747d22e8fec3eb6a1a8c65 Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Mon, 23 Oct 2023 09:13:01 -0700 Subject: [PATCH 4/8] Update mockgen/model/model_gotypes.go --- mockgen/model/model_gotypes.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mockgen/model/model_gotypes.go b/mockgen/model/model_gotypes.go index 37e5e38..14970b2 100644 --- a/mockgen/model/model_gotypes.go +++ b/mockgen/model/model_gotypes.go @@ -36,8 +36,7 @@ func funcArgsFromGoTypesType(t *types.Signature) (in []*Parameter, variadic *Par } var p *Parameter for i := 0; i < nin; i++ { - p, err = parameterFromGoTypesType(t.Params().At(i), false) - if err != nil { + if p, err = parameterFromGoTypesType(t.Params().At(i), false); err != nil { return } in = append(in, p) From c045055e1697e470ba4199053ccf3085e7ee547b Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Mon, 23 Oct 2023 09:13:08 -0700 Subject: [PATCH 5/8] Update mockgen/model/model_gotypes.go --- mockgen/model/model_gotypes.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mockgen/model/model_gotypes.go b/mockgen/model/model_gotypes.go index 14970b2..9b9a6e4 100644 --- a/mockgen/model/model_gotypes.go +++ b/mockgen/model/model_gotypes.go @@ -42,8 +42,7 @@ func funcArgsFromGoTypesType(t *types.Signature) (in []*Parameter, variadic *Par in = append(in, p) } if t.Variadic() { - p, err = parameterFromGoTypesType(t.Params().At(nin), true) - if err != nil { + if p, err = parameterFromGoTypesType(t.Params().At(nin), true); err != nil { return } variadic = p From d619fd7f6e39ed99e90868612e2c7cf0f62c4f51 Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Mon, 23 Oct 2023 09:21:12 -0700 Subject: [PATCH 6/8] skip unexported methods --- mockgen/model/model_gotypes.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/mockgen/model/model_gotypes.go b/mockgen/model/model_gotypes.go index 9b9a6e4..cbfcf41 100644 --- a/mockgen/model/model_gotypes.go +++ b/mockgen/model/model_gotypes.go @@ -12,7 +12,10 @@ func InterfaceFromGoTypesType(it *types.Interface) (*Interface, error) { for i := 0; i < it.NumMethods(); i++ { mt := it.Method(i) - // TODO: need to skip unexported methods? or just raise an error? + // Skip unexported methods. + if !mt.Exported() { + continue + } m := &Method{ Name: mt.Name(), } @@ -36,13 +39,15 @@ func funcArgsFromGoTypesType(t *types.Signature) (in []*Parameter, variadic *Par } var p *Parameter for i := 0; i < nin; i++ { - if p, err = parameterFromGoTypesType(t.Params().At(i), false); err != nil { + p, err = parameterFromGoTypesType(t.Params().At(i), false) + if err != nil { return } in = append(in, p) } if t.Variadic() { - if p, err = parameterFromGoTypesType(t.Params().At(nin), true); err != nil { + p, err = parameterFromGoTypesType(t.Params().At(nin), true) + if err != nil { return } variadic = p @@ -70,12 +75,6 @@ func parameterFromGoTypesType(v *types.Var, variadic bool) (*Parameter, error) { } func typeFromGoTypesType(t types.Type) (Type, error) { - // Hack workaround for https://golang.org/issue/3853. - // This explicit check should not be necessary. - // if t == byteType { - // return PredeclaredType("byte"), nil - // } - if t, ok := t.(*types.Named); ok { tn := t.Obj() if tn.Pkg() == nil { From 1d18764bf1a8e4f0d101d0afc1f494a286649aaf Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Tue, 21 Nov 2023 13:23:59 -0800 Subject: [PATCH 7/8] Clean up main function Use switch instead of nested if-elses to enhance readability. --- README.md | 6 +++--- mockgen/archive.go | 5 +++-- mockgen/mockgen.go | 49 ++++++++++++++++++++++++++++------------------ 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 6f05a12..422c0ca 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,9 @@ go install go.uber.org/mock/mockgen@latest ### Archive mode Archive mode generates mock interfaces from a package archive -file (.a). It is enabled by using the -archive flag and two -non-flag arguments: an import path, and a comma-separated -list of symbols. +file (.a). It is enabled by using the -archive flag. An import +path and a comma-separated list of symbols should be provided +as a non-flag argument to the command. Example: diff --git a/mockgen/archive.go b/mockgen/archive.go index 1f79e4d..54333d5 100644 --- a/mockgen/archive.go +++ b/mockgen/archive.go @@ -31,8 +31,9 @@ func archiveMode(importPath string, symbols []string, archive string) (*model.Pa } pkg := &model.Package{ - Name: tp.Name(), - PkgPath: tp.Path(), + Name: tp.Name(), + PkgPath: tp.Path(), + Interfaces: make([]*model.Interface, 0, len(symbols)), } for _, name := range symbols { m := tp.Scope().Lookup(name) diff --git a/mockgen/mockgen.go b/mockgen/mockgen.go index 93db24b..d17fea3 100644 --- a/mockgen/mockgen.go +++ b/mockgen/mockgen.go @@ -83,31 +83,35 @@ func main() { var pkg *model.Package var err error var packageName string - if *source != "" { + + // Switch between modes + switch { + case *source != "": // source mode pkg, err = sourceMode(*source) - } else { - if flag.NArg() != 2 { - usage() - log.Fatal("Expected exactly two arguments") - } + case *archive != "": // archive mode + checkArgs() packageName = flag.Arg(0) interfaces := strings.Split(flag.Arg(1), ",") - if *archive != "" { - pkg, err = archiveMode(packageName, interfaces, *archive) - } else { - if packageName == "." { - dir, err := os.Getwd() - if err != nil { - log.Fatalf("Get current directory failed: %v", err) - } - packageName, err = packageNameOfDir(dir) - if err != nil { - log.Fatalf("Parse package name failed: %v", err) - } + pkg, err = archiveMode(packageName, interfaces, *archive) + + default: // reflect mode + checkArgs() + packageName = flag.Arg(0) + interfaces := strings.Split(flag.Arg(1), ",") + + if packageName == "." { + dir, err := os.Getwd() + if err != nil { + log.Fatalf("Get current directory failed: %v", err) + } + packageName, err = packageNameOfDir(dir) + if err != nil { + log.Fatalf("Parse package name failed: %v", err) } - pkg, err = reflectMode(packageName, interfaces) } + pkg, err = reflectMode(packageName, interfaces) } + if err != nil { log.Fatalf("Loading input failed: %v", err) } @@ -225,6 +229,13 @@ func parseExcludeInterfaces(names string) map[string]struct{} { return namesSet } +func checkArgs() { + if flag.NArg() != 2 { + usage() + log.Fatal("Expected exactly two arguments") + } +} + func usage() { _, _ = io.WriteString(os.Stderr, usageText) flag.PrintDefaults() From 9251d5a6ba1b90924b907fdb3607b7d257fa77c5 Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Tue, 5 Dec 2023 12:42:18 -0800 Subject: [PATCH 8/8] code review suggestions --- README.md | 2 +- mockgen/archive.go | 3 +-- mockgen/model/model_gotypes.go | 17 ++++++++--------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 422c0ca..a680c35 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Example: # Build the package to a archive. go build -o pkg.a database/sql/driver -mockgen -archive=pkg.a database/sql/driver +mockgen -archive=pkg.a database/sql/driver Conn,Driver ``` ### Source mode diff --git a/mockgen/archive.go b/mockgen/archive.go index 54333d5..bc80ad1 100644 --- a/mockgen/archive.go +++ b/mockgen/archive.go @@ -4,7 +4,6 @@ import ( "fmt" "go/token" "go/types" - "log" "os" "go.uber.org/mock/mockgen/model" @@ -47,7 +46,7 @@ func archiveMode(importPath string, symbols []string, archive string) (*model.Pa } it, err := model.InterfaceFromGoTypesType(ti) if err != nil { - log.Fatal(err) + return nil, err } it.Name = m.Name() pkg.Interfaces = append(pkg.Interfaces, it) diff --git a/mockgen/model/model_gotypes.go b/mockgen/model/model_gotypes.go index cbfcf41..4596c3d 100644 --- a/mockgen/model/model_gotypes.go +++ b/mockgen/model/model_gotypes.go @@ -6,7 +6,7 @@ import ( ) // InterfaceFromGoTypesType returns a pointer to an interface for the -// given reflection interface type. +// given interface type loaded from archive. func InterfaceFromGoTypesType(it *types.Interface) (*Interface, error) { intf := &Interface{} @@ -23,7 +23,7 @@ func InterfaceFromGoTypesType(it *types.Interface) (*Interface, error) { var err error m.In, m.Variadic, m.Out, err = funcArgsFromGoTypesType(mt.Type().(*types.Signature)) if err != nil { - return nil, err + return nil, fmt.Errorf("method %q: %w", mt.Name(), err) } intf.AddMethod(m) @@ -37,25 +37,24 @@ func funcArgsFromGoTypesType(t *types.Signature) (in []*Parameter, variadic *Par if t.Variadic() { nin-- } - var p *Parameter for i := 0; i < nin; i++ { - p, err = parameterFromGoTypesType(t.Params().At(i), false) + p, err := parameterFromGoTypesType(t.Params().At(i), false) if err != nil { - return + return nil, nil, nil, err } in = append(in, p) } if t.Variadic() { - p, err = parameterFromGoTypesType(t.Params().At(nin), true) + p, err := parameterFromGoTypesType(t.Params().At(nin), true) if err != nil { - return + return nil, nil, nil, err } variadic = p } for i := 0; i < t.Results().Len(); i++ { - p, err = parameterFromGoTypesType(t.Results().At(i), false) + p, err := parameterFromGoTypesType(t.Results().At(i), false) if err != nil { - return + return nil, nil, nil, err } out = append(out, p) }