Skip to content

Commit

Permalink
Merge pull request #145 from codeactual/build_tags
Browse files Browse the repository at this point in the history
Add build tag support
  • Loading branch information
evanphx authored May 20, 2017
2 parents 4df6d1b + 996fc08 commit 0b3b3df
Show file tree
Hide file tree
Showing 12 changed files with 149 additions and 20 deletions.
7 changes: 7 additions & 0 deletions mockery/fixtures/buildtag/comment/darwin_iface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// +build darwin

package comment

type IfaceWithBuildTagInComment interface {
Sprintf(format string, a ...interface{}) string
}
7 changes: 7 additions & 0 deletions mockery/fixtures/buildtag/comment/freebsd_iface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// +build freebsd

package comment

type IfaceWithBuildTagInComment interface {
Sprintf(format string, a ...interface{}) string
}
7 changes: 7 additions & 0 deletions mockery/fixtures/buildtag/comment/linux_iface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// +build linux

package comment

type IfaceWithBuildTagInComment interface {
Sprintf(format string, a ...interface{}) string
}
7 changes: 7 additions & 0 deletions mockery/fixtures/buildtag/comment/windows_iface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// +build windows

package comment

type IfaceWithBuildTagInComment interface {
Sprintf(format string, a ...interface{}) string
}
5 changes: 5 additions & 0 deletions mockery/fixtures/buildtag/filename/iface_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package filename

type IfaceWithBuildTagInFilename interface {
Sprintf(format string, a ...interface{}) string
}
5 changes: 5 additions & 0 deletions mockery/fixtures/buildtag/filename/iface_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package filename

type IfaceWithBuildTagInFilename interface {
Sprintf(format string, a ...interface{}) string
}
5 changes: 5 additions & 0 deletions mockery/fixtures/buildtag/filename/iface_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package filename

type IfaceWithBuildTagInFilename interface {
Sprintf(format string, a ...interface{}) string
}
5 changes: 5 additions & 0 deletions mockery/fixtures/buildtag/filename/iface_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package filename

type IfaceWithBuildTagInFilename interface {
Sprintf(format string, a ...interface{}) string
}
24 changes: 24 additions & 0 deletions mockery/mockery_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package mockery

import (
"os"
"path/filepath"
)

var fixturePath string

func init() {
dir, err := os.Getwd()
if err != nil {
panic(err)
}
fixturePath = filepath.Join(dir, "fixtures")
}

// getFixturePath returns an absolute path to a fixture sub-directory or file.
//
// getFixturePath("src.go") returns "/path/to/fixtures/src.go"
// getFixturePath("a", "b", "c", "src.go") returns "/path/to/fixtures/a/b/c/src.go"
func getFixturePath(subdirOrBasename ...string) string {
return filepath.Join(append([]string{fixturePath}, subdirOrBasename...)...)
}
34 changes: 29 additions & 5 deletions mockery/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ package mockery

import (
"go/ast"
"go/build"
"go/importer"
"go/types"
"io/ioutil"
"path/filepath"
"strings"

"golang.org/x/tools/go/loader"
"sort"
"sync"

"golang.org/x/tools/go/loader"
)

type Parser struct {
Expand All @@ -27,6 +29,12 @@ func NewParser() *Parser {
conf.TypeCheckFuncBodies = func(_ string) bool { return false }
conf.TypeChecker.DisableUnusedImportCheck = true
conf.TypeChecker.Importer = importer.Default()

// Initialize the build context (e.g. GOARCH/GOOS fields) so we can use it for respecting
// build tags during Parse.
defaultBuildCtx := build.Default
conf.Build = &defaultBuildCtx

return &Parser{
parserPackages: make([]*types.Package, 0),
configMapping: make(map[string][]*ast.File),
Expand All @@ -37,6 +45,7 @@ func NewParser() *Parser {
}

func (p *Parser) Parse(path string) error {

// To support relative paths to mock targets w/ vendor deps, we need to provide eventual
// calls to build.Context.Import with an absolute path. It needs to be absolute because
// Import will only find the vendor directory if our target path for parsing is under
Expand All @@ -61,10 +70,25 @@ func (p *Parser) Parse(path string) error {
continue
}

fpath := filepath.Join(dir, fi.Name())
f, err := p.conf.ParseFile(fpath, nil)
if err != nil {
return err
fname := fi.Name()
fpath := filepath.Join(dir, fname)

// If go/build would ignore this file, e.g. based on build tags, also ignore it here.
//
// (Further coupling with go internals and x/tools may of course bear a cost eventually
// e.g. https://github.com/vektra/mockery/pull/117#issue-199337071, but should add
// worthwhile consistency in this tool's behavior in the meantime.)
match, matchErr := p.conf.Build.MatchFile(dir, fname)
if matchErr != nil {
return matchErr
}
if !match {
continue
}

f, parseErr := p.conf.ParseFile(fpath, nil)
if parseErr != nil {
return parseErr
}

p.configMapping[path] = append(p.configMapping[path], f)
Expand Down
58 changes: 46 additions & 12 deletions mockery/parse_test.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,17 @@
package mockery

import (
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
)

var fixturePath string
var testFile string
var testFile2 string

func init() {
dir, err := os.Getwd()
if err != nil {
panic(err)
}

fixturePath = filepath.Join(dir, "fixtures")

testFile = filepath.Join(dir, "fixtures", "requester.go")
testFile2 = filepath.Join(dir, "fixtures", "requester2.go")
testFile = getFixturePath("requester.go")
testFile2 = getFixturePath("requester2.go")
}

func TestFileParse(t *testing.T) {
Expand Down Expand Up @@ -51,3 +41,47 @@ func noTestFileInterfaces(t *testing.T) {
assert.Equal(t, 1, len(nodes))
assert.Equal(t, "Requester", nodes[0].Name)
}

func TestBuildTagInFilename(t *testing.T) {
parser := NewParser()

// Include the major OS values found on https://golang.org/dl/ so we're likely to match
// anywhere the test is executed.
err := parser.Parse(getFixturePath("buildtag", "filename", "iface_windows.go"))
assert.NoError(t, err)
err = parser.Parse(getFixturePath("buildtag", "filename", "iface_linux.go"))
assert.NoError(t, err)
err = parser.Parse(getFixturePath("buildtag", "filename", "iface_darwin.go"))
assert.NoError(t, err)
err = parser.Parse(getFixturePath("buildtag", "filename", "iface_freebsd.go"))
assert.NoError(t, err)

err = parser.Load()
assert.NoError(t, err) // Expect "redeclared in this block" if tags aren't respected

nodes := parser.Interfaces()
assert.Equal(t, 1, len(nodes))
assert.Equal(t, "IfaceWithBuildTagInFilename", nodes[0].Name)
}

func TestBuildTagInComment(t *testing.T) {
parser := NewParser()

// Include the major OS values found on https://golang.org/dl/ so we're likely to match
// anywhere the test is executed.
err := parser.Parse(getFixturePath("buildtag", "comment", "windows_iface.go"))
assert.NoError(t, err)
err = parser.Parse(getFixturePath("buildtag", "comment", "linux_iface.go"))
assert.NoError(t, err)
err = parser.Parse(getFixturePath("buildtag", "comment", "darwin_iface.go"))
assert.NoError(t, err)
err = parser.Parse(getFixturePath("buildtag", "comment", "freebsd_iface.go"))
assert.NoError(t, err)

err = parser.Load()
assert.NoError(t, err) // Expect "redeclared in this block" if tags aren't respected

nodes := parser.Interfaces()
assert.Equal(t, 1, len(nodes))
assert.Equal(t, "IfaceWithBuildTagInComment", nodes[0].Name)
}
5 changes: 2 additions & 3 deletions mockery/walker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package mockery

import (
"os"
"path/filepath"
"regexp"
"testing"

Expand Down Expand Up @@ -45,7 +44,7 @@ func TestWalkerHere(t *testing.T) {
assert.True(t, len(gv.Interfaces) > 10)
first := gv.Interfaces[0]
assert.Equal(t, "AsyncProducer", first.Name)
assert.Equal(t, filepath.Join(wd, "fixtures", "async.go"), first.Path)
assert.Equal(t, getFixturePath("async.go"), first.Path)
}

func TestWalkerRegexp(t *testing.T) {
Expand All @@ -69,5 +68,5 @@ func TestWalkerRegexp(t *testing.T) {
assert.True(t, len(gv.Interfaces) >= 1)
first := gv.Interfaces[0]
assert.Equal(t, "AsyncProducer", first.Name)
assert.Equal(t, filepath.Join(wd, "fixtures", "async.go"), first.Path)
assert.Equal(t, getFixturePath("async.go"), first.Path)
}

0 comments on commit 0b3b3df

Please sign in to comment.