Skip to content

Commit

Permalink
Support sourcing from packages
Browse files Browse the repository at this point in the history
  • Loading branch information
csueiras committed Apr 6, 2021
1 parent 55bbdc1 commit 6c8bbe1
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 11 deletions.
8 changes: 7 additions & 1 deletion cmd/reinforcer/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,11 @@ such as circuit breaker, retries, timeouts, etc.
if err != nil {
return err
}
if len(sources) == 0 {
sourcePackages, err := flags.GetStringSlice("srcpkg")
if err != nil {
return err
}
if len(sources)+len(sourcePackages) == 0 {
goFile := os.Getenv("GOFILE")
if goFile == "" {
return fmt.Errorf("no source provided")
Expand Down Expand Up @@ -132,6 +136,7 @@ such as circuit breaker, retries, timeouts, etc.

gen, err := exec.Execute(&executor.Parameters{
Sources: sources,
SourcePackages: sourcePackages,
Targets: targets,
TargetsAll: targetAll,
OutPkg: outPkg,
Expand All @@ -155,6 +160,7 @@ such as circuit breaker, retries, timeouts, etc.
flags.BoolP("debug", "d", false, "enables debug logs")
flags.BoolP("silent", "q", false, "disables logging. Mutually exclusive with the debug flag.")
flags.StringSliceP("src", "s", nil, "source files to scan for the target interface or struct. If unspecified the file pointed by the env variable GOFILE will be used.")
flags.StringSliceP("srcpkg", "k", nil, "source packages to scan for the target interface or struct.")
flags.StringSliceP("target", "t", []string{}, "name of target type or regex to match interface or struct names with")
flags.BoolP("targetall", "a", false, "codegen for all exported interfaces/structs discovered. This option is mutually exclusive with the target option.")
flags.StringP("outputdir", "o", "./reinforced", "directory to write the generated code to")
Expand Down
24 changes: 24 additions & 0 deletions cmd/reinforcer/cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func TestRootCommand(t *testing.T) {
exec := &mocks.Executor{}
exec.On("Execute", &executor.Parameters{
Sources: []string{"/path/to/target.go"},
SourcePackages: []string{},
Targets: []string{"Client", "SomeOtherClient"},
TargetsAll: false,
OutPkg: "reinforced",
Expand All @@ -32,10 +33,31 @@ func TestRootCommand(t *testing.T) {
require.NoError(t, c.Execute())
})

t.Run("Source packages", func(t *testing.T) {
exec := &mocks.Executor{}
exec.On("Execute", &executor.Parameters{
Sources: []string{},
SourcePackages: []string{"github.com/csueiras/somelib"},
Targets: []string{"Client", "SomeOtherClient"},
TargetsAll: false,
OutPkg: "reinforced",
IgnoreNoReturnMethods: false,
}).Return(gen, nil)
writ := &mocks.Writer{}
writ.On("Write", "./reinforced", gen).Return(nil)

b := bytes.NewBufferString("")
c := cmd.NewRootCmd(exec, writ)
c.SetOut(b)
c.SetArgs([]string{"--srcpkg=github.com/csueiras/somelib", "--target=Client", "--target=SomeOtherClient", "--outputdir=./reinforced"})
require.NoError(t, c.Execute())
})

t.Run("Target All", func(t *testing.T) {
exec := &mocks.Executor{}
exec.On("Execute", &executor.Parameters{
Sources: []string{"/path/to/target.go"},
SourcePackages: []string{},
Targets: []string{},
TargetsAll: true,
OutPkg: "reinforced",
Expand All @@ -55,6 +77,7 @@ func TestRootCommand(t *testing.T) {
exec := &mocks.Executor{}
exec.On("Execute", &executor.Parameters{
Sources: []string{"/path/to/target.go"},
SourcePackages: []string{},
Targets: []string{"Client", "SomeOtherClient"},
TargetsAll: false,
OutPkg: "reinforced",
Expand All @@ -74,6 +97,7 @@ func TestRootCommand(t *testing.T) {
exec := &mocks.Executor{}
exec.On("Execute", &executor.Parameters{
Sources: []string{"/path/to/target.go"},
SourcePackages: []string{},
Targets: []string{},
TargetsAll: true,
OutPkg: "reinforced",
Expand Down
52 changes: 42 additions & 10 deletions internal/generator/executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"github.com/csueiras/reinforcer/internal/generator"
"github.com/csueiras/reinforcer/internal/loader"
"github.com/pkg/errors"
)

// ErrNoTargetableTypesFound indicates that no types that could be targeted for code generation were discovered
Expand All @@ -19,8 +20,10 @@ type Loader interface {

// Parameters are the input parameters for the executor
type Parameters struct {
// Sources are the paths to the packages that are eligible for targetting
// Sources are the paths to the packages that are eligible for targeting
Sources []string
// SourcePackages are the packages that are eligible for targeting (e.g. github.com/csueiras/somelib)
SourcePackages []string
// Targets contains the target types to search for, these are expressions that may contain RegEx
Targets []string
// TargetsAll enables targeting of every exported interface type
Expand All @@ -47,6 +50,26 @@ func (e *Executor) Execute(settings *Parameters) (*generator.Generated, error) {

var cfg []*generator.FileConfig
var err error

for _, sourcePkg := range settings.SourcePackages {
var match map[string]*loader.Result
if settings.TargetsAll {
match, err = e.loader.LoadAll(sourcePkg, loader.PackageLoadMode)
} else {
match, err = e.loader.LoadMatched(sourcePkg, settings.Targets, loader.PackageLoadMode)
}
if err != nil {
return nil, errors.Wrapf(err, "failed to load from pkg=%s", sourcePkg)
}

configs, err := createFileConfigs(discoveredTypes, match)
if err != nil {
return nil, err
}

cfg = append(cfg, configs...)
}

for _, source := range settings.Sources {
var match map[string]*loader.Result
if settings.TargetsAll {
Expand All @@ -55,17 +78,13 @@ func (e *Executor) Execute(settings *Parameters) (*generator.Generated, error) {
match, err = e.loader.LoadMatched(source, settings.Targets, loader.FileLoadMode)
}
if err != nil {
return nil, err
return nil, errors.Wrapf(err, "failed to load from file=%s", source)
}

// Check types aren't repeated before adding them to the generator's config
for typName, res := range match {
if _, ok := discoveredTypes[typName]; ok {
return nil, fmt.Errorf("multiple types with same name discovered with name %s", typName)
}
discoveredTypes[typName] = struct{}{}
cfg = append(cfg, generator.NewFileConfig(typName, typName, res.Methods))
configs, err := createFileConfigs(discoveredTypes, match)
if err != nil {
return nil, err
}
cfg = append(cfg, configs...)
}

if len(cfg) == 0 {
Expand All @@ -82,3 +101,16 @@ func (e *Executor) Execute(settings *Parameters) (*generator.Generated, error) {
}
return code, nil
}

func createFileConfigs(discoveredSet map[string]struct{}, match map[string]*loader.Result) ([]*generator.FileConfig, error) {
var cfg []*generator.FileConfig
for typName, res := range match {
// Check types aren't repeated before adding them to the generator's config
if _, ok := discoveredSet[typName]; ok {
return nil, errors.Errorf("multiple types with same name discovered with name %s", typName)
}
discoveredSet[typName] = struct{}{}
cfg = append(cfg, generator.NewFileConfig(typName, typName, res.Methods))
}
return cfg, nil
}
24 changes: 24 additions & 0 deletions internal/generator/executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,30 @@ func TestExecutor_Execute(t *testing.T) {
require.Equal(t, "LockService", got.Files[0].TypeName)
})

t.Run("Loads types from packages", func(t *testing.T) {
l := &mocks.Loader{}
l.On("LoadMatched", "github.com/csueiras/somelib", []string{"MyService"}, loader.PackageLoadMode).Return(
map[string]*loader.Result{
"LockService": {
Name: "LockService",
Methods: createTestServiceMethods(),
},
}, nil,
)

exec := executor.New(l)
got, err := exec.Execute(&executor.Parameters{
SourcePackages: []string{"github.com/csueiras/somelib"},
Targets: []string{"MyService"},
OutPkg: "testpkg",
IgnoreNoReturnMethods: false,
})
require.NoError(t, err)
require.NotNil(t, got)
require.Equal(t, 1, len(got.Files))
require.Equal(t, "LockService", got.Files[0].TypeName)
})

t.Run("No types found", func(t *testing.T) {
l := &mocks.Loader{}
l.On("LoadMatched", "./testpkg.go", []string{"MyService"}, loader.FileLoadMode).
Expand Down

0 comments on commit 6c8bbe1

Please sign in to comment.