Skip to content

Commit

Permalink
Merge pull request #31 from csueiras/fix-type-resolution
Browse files Browse the repository at this point in the history
Fix type resolution
  • Loading branch information
csueiras authored Feb 20, 2021
2 parents bd0c95f + be9b56d commit 71f6691
Show file tree
Hide file tree
Showing 16 changed files with 544 additions and 96 deletions.
11 changes: 11 additions & 0 deletions example/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@ package client
import (
"context"
"fmt"
"github.com/csueiras/reinforcer/example/client/sub"
"math/rand"
"os"
)

// File is a type defined in the same package that we are using for targetting
type File struct {
Name string
}

// Client is an example service interface that we will generate code for
type Client interface {
SayHello(ctx context.Context, name string) error
Expand All @@ -17,6 +24,10 @@ type Client interface {
// SomeOtherClient is another example service interface that can be targeted
type SomeOtherClient interface {
DoStuff() error
SaveFile(myFile *File, osFile *os.File) error
GetUser(ctx context.Context) (*sub.User, error)
MethodWithChannel(myChan <- chan bool) error
MethodWithWildcard(arg interface{})
}

// FakeClient is a Client implementation that will randomly fail
Expand Down
12 changes: 10 additions & 2 deletions example/client/reinforced/reinforcer_constants.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 68 additions & 1 deletion example/client/reinforced/some_other_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions example/client/sub/sub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package sub

// User is a test type
type User struct {
Name string
}
18 changes: 10 additions & 8 deletions internal/generator/executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ package executor
import (
"fmt"
"github.com/csueiras/reinforcer/internal/generator"
"github.com/csueiras/reinforcer/internal/loader"
"go/types"
)

// Loader describes the loader component
type Loader interface {
LoadAll(path string) (map[string]*types.Interface, error)
LoadMatched(path string, expressions []string) (map[string]*types.Interface, error)
LoadAll(path string, mode loader.LoadMode) (map[string]*loader.Result, error)
LoadMatched(path string, expressions []string, mode loader.LoadMode) (map[string]*loader.Result, error)
}

// Parameters are the input parameters for the executor
Expand Down Expand Up @@ -44,27 +45,28 @@ func (e *Executor) Execute(settings *Parameters) (*generator.Generated, error) {
var cfg []*generator.FileConfig
var err error
for _, source := range settings.Sources {
var match map[string]*types.Interface
var match map[string]*loader.Result
if settings.TargetsAll {
match, err = e.loader.LoadAll(source)
match, err = e.loader.LoadAll(source, loader.FileLoadMode)
} else {
match, err = e.loader.LoadMatched(source, settings.Targets)
match, err = e.loader.LoadMatched(source, settings.Targets, loader.FileLoadMode)
}
if err != nil {
return nil, err
}

// Check types aren't repeated before adding them to the generator's config
for typName, typ := range match {
for typName, res := range match {
if _, ok := results[typName]; ok {
return nil, fmt.Errorf("multiple types with same name discovered with name %s", typName)
}
results[typName] = typ
results[typName] = res.InterfaceType

cfg = append(cfg, &generator.FileConfig{
SrcTypeName: typName,
OutTypeName: typName,
InterfaceType: typ,
InterfaceType: res.InterfaceType,
Package: res.Package,
})
}
}
Expand Down
13 changes: 9 additions & 4 deletions internal/generator/executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package executor_test
import (
"github.com/csueiras/reinforcer/internal/generator/executor"
"github.com/csueiras/reinforcer/internal/generator/executor/mocks"
"github.com/csueiras/reinforcer/internal/loader"
"github.com/stretchr/testify/require"
"go/token"
"go/types"
Expand All @@ -11,15 +12,19 @@ import (

func TestExecutor_Execute(t *testing.T) {
l := &mocks.Loader{}
l.On("LoadMatched", "github.com/csueiras/reinforcer/pkg/testpkg", []string{"MyService"}).Return(
map[string]*types.Interface{
"LockService": createTestInterfaceType(),
l.On("LoadMatched", "./testpkg.go", []string{"MyService"}, loader.FileLoadMode).Return(
map[string]*loader.Result{
"LockService": &loader.Result{
Name: "LockService",
InterfaceType: createTestInterfaceType(),
Package: types.NewPackage("github.com/csueiras/testpkg", "testpkg"),
},
}, nil,
)

exec := executor.New(l)
got, err := exec.Execute(&executor.Parameters{
Sources: []string{"github.com/csueiras/reinforcer/pkg/testpkg"},
Sources: []string{"./testpkg.go"},
Targets: []string{"MyService"},
OutPkg: "testpkg",
IgnoreNoReturnMethods: false,
Expand Down
39 changes: 19 additions & 20 deletions internal/generator/executor/mocks/Loader.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions internal/generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type FileConfig struct {
OutTypeName string
// InterfaceType holds the type information for SrcTypeName
InterfaceType *types.Interface
// Package holds a reference to the package the interface was found in
Package *types.Package
}

func (f *FileConfig) targetName() string {
Expand Down Expand Up @@ -88,7 +90,7 @@ func Generate(cfg Config) (*Generated, error) {
var fileMethods []*fileMeta

for _, fileConfig := range cfg.Files {
methods, err := parseMethods(fileConfig.OutTypeName, fileConfig.InterfaceType)
methods, err := parseMethods(fileConfig.Package, fileConfig.OutTypeName, fileConfig.InterfaceType)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -259,11 +261,11 @@ func generateConstants(outPkg string, meta []*fileMeta) (string, error) {
return renderToString(f)
}

func parseMethods(typeName string, interfaceType *types.Interface) ([]*method.Method, error) {
func parseMethods(basePackage *types.Package, typeName string, interfaceType *types.Interface) ([]*method.Method, error) {
var methods []*method.Method
for m := 0; m < interfaceType.NumMethods(); m++ {
meth := interfaceType.Method(m)
mm, err := method.ParseMethod(typeName, meth.Name(), meth.Type().(*types.Signature))
mm, err := method.ParseMethod(basePackage, typeName, meth.Name(), meth.Type().(*types.Signature))
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit 71f6691

Please sign in to comment.