GithubHelp home page GithubHelp logo

mvdan / interfacer Goto Github PK

View Code? Open in Web Editor NEW
694.0 12.0 17.0 556 KB

A linter that suggests interface types

License: BSD 3-Clause "New" or "Revised" License

Go 100.00%
go linter interface types

interfacer's Introduction

interfacer

GoDoc Build Status

Deprecated: A tool that suggests interfaces is prone to bad suggestions, so its usefulness in real code is limited. This tool will remain available as a proof of concept, and for others to examine and learn from.

A linter that suggests interface types. In other words, it warns about the usage of types that are more specific than necessary.

go get -u mvdan.cc/interfacer

Note that this linter's suggestions tend to be subjective, as interfaces are not always the better option. You should select the proposed changes that make sense in your codebase, instead of following all of them blindly.

Usage

func ProcessInput(f *os.File) error {
        b, err := ioutil.ReadAll(f)
        if err != nil {
                return err
        }
        return processBytes(b)
}
$ interfacer ./...
foo.go:10:19: f can be io.Reader

Basic idea

This tool inspects the parameters of your functions to see if they fit an interface type that is less specific than the current type.

The example above illustrates this point. Overly specific interfaces also trigger a warning - if f were an io.ReadCloser, the same message would appear.

It suggests interface types defined both in the func's package and the package's imports (two levels; direct imports and their direct imports).

False positives

To avoid false positives, it never does any suggestions on functions that may be implementing an interface method or a named function type.

It also skips parameters passed by value (excluding pointers and interfaces) on unexported functions, since that would introduce extra allocations where they are usually not worth the tradeoff.

Suppressing warnings

If a suggestion is technically correct but doesn't make sense, you can still suppress the warning by mentioning the type in the function name:

func ProcessInputFile(f *os.File) error {
	// use as an io.Reader
}

interfacer's People

Contributors

dmitshur avatar mvdan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

interfacer's Issues

Operators not counted towards "interface" usage

I have a type alias type units.Base2Bytes int64 that is used as a numeric value in a function:

func toBytes(b units.Base2Bytes) string {
  if b > units.GiB {
    return (b / units.GiB * units.GiB).String()
  } else if b > units.MiB {
    return (b / units.MiB * units.MiB).String()
  } else if b > units.KiB {
    return (b / units.KiB * units.KiB).String()
  }
  return b.String()
}

interfacer misreports this as saying b could be fmt.Stringer, presumably because it doesn't see the numeric uses of b.

panic under go 1.3.3

$ interfacer ./...
zsh: correct './...' to './..' [nyae]? n
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x4ee77]

goroutine 16 [running]:
runtime.panic(0x2582c0, 0x3e22e4)
    /usr/local/go/src/pkg/runtime/panic.c:279 +0xf5
github.com/mvdan/interfacer.orderedPkgs(0xc208058040, 0x0, 0x0, 0x0, 0x0, 0x0)
    /Users/holys/code/src/github.com/mvdan/interfacer/check.go:105 +0x3b7
github.com/mvdan/interfacer.CheckArgs(0xc20800e010, 0x1, 0x1, 0x456318, 0xc20803a008, 0x2d8e00, 0x0, 0x0)
    /Users/holys/code/src/github.com/mvdan/interfacer/check.go:123 +0x1c5
main.main()
    /Users/holys/code/src/github.com/mvdan/interfacer/cmd/interfacer/main.go:20 +0xaa

goroutine 19 [finalizer wait]:
runtime.park(0x14350, 0x3e58b0, 0x3e4c29)
    /usr/local/go/src/pkg/runtime/proc.c:1369 +0x89
runtime.parkunlock(0x3e58b0, 0x3e4c29)
    /usr/local/go/src/pkg/runtime/proc.c:1385 +0x3b
runfinq()
    /usr/local/go/src/pkg/runtime/mgc0.c:2644 +0xcf
runtime.goexit()
    /usr/local/go/src/pkg/runtime/proc.c:1445

$ go version
go version go1.3.3 darwin/amd64

ignore packages that fail to compile

I'm not proud of this, but we have a big repo with a lot of go code and some of it is outdated and hasn't been compiled/tested in a while, so it doesn't compile. It would be nice to have an option in interfacer to ignore packages that fail to compile and keep running on the rest so that we can at least see the results from the ones that do compile. I'm not familiar with go's code analysis tools so I don't know how easy/hard this is.

Panic's on main package

$ interfacer ./...
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x47f2b1]

goroutine 1 [running]:
github.com/mvdan/interfacer.orderedPkgs(0xc820012700, 0x0, 0x0, 0x0, 0x0, 0x0)
    /go/src/github.com/mvdan/interfacer/check.go:105 +0x321
github.com/mvdan/interfacer.CheckArgs(0xc82000a3b0, 0x1, 0x1, 0x7f58780906f0, 0xc820034010, 0x0, 0x0, 0x0)
    /go/src/github.com/mvdan/interfacer/check.go:123 +0x1c8
main.main()
    /go/src/github.com/mvdan/interfacer/cmd/interfacer/main.go:20 +0xa4

Cooler example

If you change the example as:

func ProcessInput(f *os.File) error {
+       defer f.Close()
        b, err := ioutil.ReadAll(f)
        if err != nil {
                return err
        }
        return processBytes(b)
}

it suggests io.ReadCloser, which IMO is really cool... Thanks for this project!

Panic on Hugo

https://github.com/spf13/hugo

panic: assignment to entry in nil map

goroutine 1 [running]:
github.com/mvdan/interfacer.(*visitor).addUsed(0xc82b76bf40, 0xc8206f6c00, 0x4, 0x64c2b8, 0x422ac0)
    /Users/bep/go/src/github.com/mvdan/interfacer/check.go:229 +0x2f5
github.com/mvdan/interfacer.(*visitor).Visit(0xc82b76bf40, 0x7cbba0, 0xc820b82a40, 0x0, 0x0)
    /Users/bep/go/src/github.com/mvdan/interfacer/check.go:273 +0x980
go/ast.Walk(0x7cb848, 0xc82b76bf40, 0x7cbba0, 0xc820b82a40)
    /usr/local/go/src/go/ast/walk.go:52 +0x56
go/ast.walkStmtList(0x7cb848, 0xc82b76bf40, 0xc8204c1a00, 0x8, 0x8)
    /usr/local/go/src/go/ast/walk.go:32 +0xd5
go/ast.Walk(0x7cb848, 0xc82b76bf40, 0x6c66e8, 0xc8206116b0)
    /usr/local/go/src/go/ast/walk.go:224 +0x3e19
go/ast.Walk(0x7cb848, 0xc82b76bf40, 0x7cbab0, 0xc8206f6dc0)
    /usr/local/go/src/go/ast/walk.go:98 +0x31f7
go/ast.Walk(0x7cb848, 0xc82b76bf40, 0x7cba80, 0xc8206116e0)
    /usr/local/go/src/go/ast/walk.go:151 +0x1593
go/ast.walkExprList(0x7cb848, 0xc82b76bf40, 0xc820b82500, 0x4, 0x4)
    /usr/local/go/src/go/ast/walk.go:26 +0xd5
go/ast.Walk(0x7cb848, 0xc82b76bf40, 0x7cba50, 0xc820b82bc0)
    /usr/local/go/src/go/ast/walk.go:104 +0xdb2
go/ast.Walk(0x7cb848, 0xc82b76bf40, 0x7cba20, 0xc820b5b020)
    /usr/local/go/src/go/ast/walk.go:143 +0x17ff
go/ast.walkExprList(0x7cb848, 0xc82b76bf40, 0xc8206f6dd0, 0x1, 0x1)
    /usr/local/go/src/go/ast/walk.go:26 +0xd5
go/ast.Walk(0x7cb848, 0xc82b76bf40, 0x7cb9f0, 0xc820920000)
    /usr/local/go/src/go/ast/walk.go:308 +0xf63
go/ast.Walk(0x7cb848, 0xc82b76bf40, 0x7cb8a0, 0xc820b82c00)
    /usr/local/go/src/go/ast/walk.go:331 +0x1f7d
go/ast.walkDeclList(0x7cb848, 0xc82b76bf40, 0xc820b82c40, 0x4, 0x4)
    /usr/local/go/src/go/ast/walk.go:38 +0xd5
go/ast.Walk(0x7cb848, 0xc82b76bf40, 0x6d6550, 0xc8204c1b00)
    /usr/local/go/src/go/ast/walk.go:353 +0x29b9
github.com/mvdan/interfacer.checkPkg(0xc8200a00c0, 0xc82084a8c0, 0x64c6f0, 0xc820030010)
    /Users/bep/go/src/github.com/mvdan/interfacer/check.go:144 +0x17b
github.com/mvdan/interfacer.CheckArgs(0xc82000a1d0, 0x1, 0x1, 0x64c6f0, 0xc820030010, 0x0, 0x0, 0x0)
    /Users/bep/go/src/github.com/mvdan/interfacer/check.go:132 +0x44d
main.main()
    /Users/bep/go/src/github.com/mvdan/interfacer/cmd/interfacer/main.go:20 +0xa4

Package does not compile anymore with Go 1.5

$ go get github.com/mvdan/interfacer
# github.com/mvdan/interfacer
github.com/mvdan/interfacer/check.go:66: cannot use info.Pkg (type *"go/types".Package) as type *"golang.org/x/tools/go/types".Package in assignment
github.com/mvdan/interfacer/check.go:112: cannot use pkg (type *"golang.org/x/tools/go/types".Package) as type *"go/types".Package in map index
github.com/mvdan/interfacer/check.go:174: impossible type assertion:
    *"golang.org/x/tools/go/types".Var does not implement "go/types".Object (wrong type for Parent method)
        have Parent() *"golang.org/x/tools/go/types".Scope
        want Parent() *"go/types".Scope
github.com/mvdan/interfacer/check.go:251: impossible type assertion:
    *"golang.org/x/tools/go/types".Signature does not implement "go/types".Type (wrong type for Underlying method)
        have Underlying() "golang.org/x/tools/go/types".Type
        want Underlying() "go/types".Type
github.com/mvdan/interfacer/check.go:256: impossible type assertion:
    *"golang.org/x/tools/go/types".Signature does not implement "go/types".Type (wrong type for Underlying method)
        have Underlying() "golang.org/x/tools/go/types".Type
        want Underlying() "go/types".Type
github.com/mvdan/interfacer/check.go:312: cannot use v.PackageInfo.Info.Types[left].Type (type "go/types".Type) as type "golang.org/x/tools/go/types".Type in argument to v.addUsed:
    "go/types".Type does not implement "golang.org/x/tools/go/types".Type (wrong type for Underlying method)
        have Underlying() "go/types".Type
        want Underlying() "golang.org/x/tools/go/types".Type
github.com/mvdan/interfacer/check.go:321: cannot use v.PackageInfo.Info.TypeOf(kv.Value) (type "go/types".Type) as type "golang.org/x/tools/go/types".Type in argument to v.addUsed:
    "go/types".Type does not implement "golang.org/x/tools/go/types".Type (wrong type for Underlying method)
        have Underlying() "go/types".Type
        want Underlying() "golang.org/x/tools/go/types".Type
github.com/mvdan/interfacer/check.go:324: cannot use v.PackageInfo.Info.TypeOf(kv.Key) (type "go/types".Type) as type "golang.org/x/tools/go/types".Type in argument to v.addUsed:
    "go/types".Type does not implement "golang.org/x/tools/go/types".Type (wrong type for Underlying method)
        have Underlying() "go/types".Type
        want Underlying() "golang.org/x/tools/go/types".Type
github.com/mvdan/interfacer/check.go:337: impossible type assertion:
    *"golang.org/x/tools/go/types".Signature does not implement "go/types".Type (wrong type for Underlying method)
        have Underlying() "golang.org/x/tools/go/types".Type
        want Underlying() "go/types".Type

I guess it is caused by alandonovan's commits on golang/tools on January 6th: https://github.com/golang/tools/commits/master

Provide --version flag

It's good for debugging/reporting errors!

$ interfacer --version
flag provided but not defined: -version
Usage of interfacer:
  -v    print the names of packages as they are checked

Panics on github.com/tucnak/kamu

$ go version
go version go1.5 darwin/amd64
$ interfacer ./...
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x7f241]

goroutine 1 [running]:
github.com/mvdan/interfacer.orderedPkgs(0x82050a840, 0x0, 0x0, 0x0, 0x0, 0x0)
    /Users/tucnak/Development/gopher/src/github.com/mvdan/interfacer/check.go:105 +0x321
github.com/mvdan/interfacer.CheckArgs(0x820508030, 0x1, 0x1, 0x88206906c8, 0x82051e008, 0x0, 0x0, 0x0)
    /Users/tucnak/Development/gopher/src/github.com/mvdan/interfacer/check.go:123 +0x1c8
main.main()
    /Users/tucnak/Development/gopher/src/github.com/mvdan/interfacer/cmd/interfacer/main.go:20 +0xa4

Support for multiple Go versions

Right now generate/std and consequently std.go run with Go 1.5.2, so all of 1.5 is covered since as far as I know there can't be any std API changes between 1.5 and 1.5.x.

We should generate one std.go per supported Go version and use build tags to select the correct one. We could start with 1.4 and 1.6.

Doesn't work on std packages

 $ interfacer bytes
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x28 pc=0x5cdf99]

goroutine 1 [running]:
github.com/mvdan/interfacer.(*visitor).onCall(0xc420f94b40, 0xc4200deb00)
        /home/mvdan/go/src/github.com/mvdan/interfacer/check.go:394 +0x59
github.com/mvdan/interfacer.(*visitor).Visit(0xc420f94b40, 0x737e60, 0xc4200deb00, 0x0, 0xc4200ecac0)
        /home/mvdan/go/src/github.com/mvdan/interfacer/check.go:325 +0x48b
go/ast.Walk(0x737420, 0xc420f94b40, 0x737e60, 0xc4200deb00)
        /home/mvdan/tip/src/go/ast/walk.go:52 +0x66
go/ast.walkExprList(0x737420, 0xc420f94b40, 0xc420124540, 0x1, 0x1)
        /home/mvdan/tip/src/go/ast/walk.go:26 +0x89
go/ast.Walk(0x737420, 0xc420f94b40, 0x7f626bdff138, 0xc4200ecbc0)
        /home/mvdan/tip/src/go/ast/walk.go:216 +0x261e
go/ast.walkStmtList(0x737420, 0xc420f94b40, 0xc4200ecbe0, 0x2, 0x2)
        /home/mvdan/tip/src/go/ast/walk.go:32 +0x89
go/ast.Walk(0x737420, 0xc420f94b40, 0x737e20, 0xc4200e2750)
        /home/mvdan/tip/src/go/ast/walk.go:224 +0x1f1f
go/ast.Walk(0x737420, 0xc420f94b40, 0x7f626bdff0d8, 0xc4200e2780)
        /home/mvdan/tip/src/go/ast/walk.go:344 +0xf63
go/ast.walkDeclList(0x737420, 0xc420f94b40, 0xc420110600, 0x20, 0x20)
        /home/mvdan/tip/src/go/ast/walk.go:38 +0x89
go/ast.Walk(0x737420, 0xc420f94b40, 0x737fe0, 0xc42012c800)
        /home/mvdan/tip/src/go/ast/walk.go:353 +0x2bb4
github.com/mvdan/interfacer.(*visitor).checkPkg(0xc420f94b40, 0xc4200d6000, 0xc42004bb80, 0xc420550048, 0x0)
        /home/mvdan/go/src/github.com/mvdan/interfacer/check.go:195 +0x1de
github.com/mvdan/interfacer.CheckArgs(0xc42000a290, 0x1, 0x1, 0xc420037ef8, 0xc420068060, 0xc42000a290)
        /home/mvdan/go/src/github.com/mvdan/interfacer/check.go:151 +0x27c
github.com/mvdan/interfacer.CheckArgsOutput(0xc42000a290, 0x1, 0x1, 0x737560, 0xc42000c018, 0x0, 0x5f7100, 0x652518)
        /home/mvdan/go/src/github.com/mvdan/interfacer/check.go:178 +0x8e
main.main()
        /home/mvdan/go/src/github.com/mvdan/interfacer/cmd/interfacer/main.go:18 +0x72

I honestly don't know if it ever worked - tried older versions and couldn't get it to work.

Happens both when running 1.7.x from my distro and with tip built from source.

Adding a nil check to prevent the panic simply makes the linter do nothing on interfacer std, which is definitely wrong.

Fails on unknown field

Running the tool on the follow code fails with the error:

$ interfacer ./...
p/a/t/h/main.go:185:3: unknown field Pdeathsig in struct literal
cmd := exec.Command("foo")
cmd.SysProcAttr = &syscall.SysProcAttr{
    Pdeathsig: syscall.SIGTERM,
}

Poorly behaved on *_test files

I have been running interfacer with neomake whenever I save a golang file. This has been working fine, until I attempted to edit a _test.go file, where I recieved the following error:

$ interfacer smlr/http_test.go 
smlr/http_test.go:22:12: undeclared name: HTTPWaiter

(where HTTPWaiter is declared in `smlr/http.go). Many other tools handle this discrepancy well, I wonder if interfacer could.

Unfortunately, I can't tell you what version of interfacer this is:

$ interfacer --version
flag provided but not defined: -version
Usage of interfacer:
  -v    print the names of packages as they are checked

Here is my neomake configuration, if that helps:

let g:neomake_go_interfacer_maker = {
    \ 'errorformat': '%f:%l:%c: %m'
    \ }
let g:neomake_go_enabled_makers = ['go', 'golint', 'govet', 'interfacer']

Some imports fail

For example:

$ cd $GOPATH/src/github.com/mvdan/fdroidcl/cmd/fdroidcl
$ interfacer .
devices.go:10:2: could not import github.com/mvdan/fdroidcl/adb (can't find import: github.com/mvdan/fdroidcl/adb)

go build succeeds. I should note that gotype also fails:

 % gotype .
devices.go:10:2: could not import github.com/mvdan/fdroidcl/adb (can't find import: github.com/mvdan/fdroidcl/adb)

Almost all imports work. The fact that gotype fails and seeing how we don't import packages ourselves, it could be a bug in a go/* package.

The only pattern I have seen that these follow is that they go back up in the GOPATH source tree - foo/bar imports foo, etc.

It is better for interfacer not to analyze vendor folder

interfacer is a good tool for gophers. I have tried it and got many help. I have a small issue that is currently the interfacer tries to analyze the vendor folder in the golang repo. In my opinion, It is better for interfacer not to analyze vendor folder.

$interfacer ./...
/Users/tony/Test/GoToolsProjects/src/app-weixin/vendor/github.com/astaxie/beego/session/couchbase/sess_couchbase.go:40:12: could not import github.com/couchbase/go-couchbase (cannot find package "github.com/couchbase/go-couchbase" in any of:
	/Users/tony/Test/GoToolsProjects/src/app-weixin/vendor/github.com/couchbase/go-couchbase (vendor tree)
	/Users/tony/.bin/go17/src/github.com/couchbase/go-couchbase (from $GOROOT)
	/Users/tony/Test/GoToolsProjects/src/github.com/couchbase/go-couchbase (from $GOPATH))

inconsistent definition for type ssa.NamedConst during import

When I run : go get -u github.com/mvdan/interfacer/cmd/interfacer
I get:

../../mvdan/interfacer/check.go:19: inconsistent definition for type ssa.NamedConst during import
struct { ssa.object *types.Const; Value *ssa.Const; ssa.pkg *ssa.Package } (in "golang.org/x/tools/go/ssa")
struct { ssa.object *types.Const; Value *ssa.Const; ssa.pos token.Pos; ssa.pkg *ssa.Package } (in "github.com/mvdan/lint")

../../mvdan/interfacer/check.go:19: method redeclared: ssa.Program.CreateTestMainPackage
method(*ssa.Program) func(*ssa.Package) *ssa.Package
method(*ssa.Program) func(...*ssa.Package) *ssa.Package

panic: runtime error: invalid memory address or nil pointer dereference

This may not be very useful to you, as it's just the report, I've not had time to dig into it yet:

go version go1.5.1 darwin/amd64

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x7f361]

goroutine 1 [running]:
github.com/mvdan/interfacer.orderedPkgs(0xc8200725c0, 0x0, 0x0, 0x0, 0x0, 0x0)
    /Users/lantins/devel/golang/src/github.com/mvdan/interfacer/check.go:105 +0x321
github.com/mvdan/interfacer.CheckArgs(0xc820070030, 0x1, 0x1, 0x68c6c8, 0xc820086008, 0x0, 0x0, 0x0)
    /Users/lantins/devel/golang/src/github.com/mvdan/interfacer/check.go:123 +0x1c8
main.main()
    /Users/lantins/devel/golang/src/github.com/mvdan/interfacer/cmd/interfacer/main.go:20 +0xa4

Suggestion breaks interface

package main

import "fmt"

type StringerVar string

func (myx StringerVar) String() string {
    return string(myx)
}

type StringerInterface fmt.Stringer

type SomeInterface interface {
    FunctionA(StringerVar)
    FunctionB(StringerInterface) string
}

type SomeVar struct{}

func (i SomeVar) FunctionA(a StringerVar) {
    i.FunctionB(a)
}
func (i SomeVar) FunctionB(a StringerInterface) string {
    return a.String()
}

func main() {

    var somevar SomeInterface

    somevar = SomeVar{}
    somevar.FunctionA(StringerVar("hallo"))

}

interfacer suggests: filename.go:20:28: a can be fmt.Stringer
which would make
func (i SomeVar) FunctionA(a StringerVar) {
to
func (i SomeVar) FunctionA(a fmt.Stringer) {
which makes line 31 (somevar = SomeVar{}) invalid, since SomeVar no longer is implementing FunctionA correctly and thus it's not a SomeInterface anymore.

I thought this was fixed in #1 (or #2)

Proper way to get packages/files from arguments

It's mostly working, but failing for recursive non-local paths like foo/bar/....

This is something that many Go programs do, especially checkers and linters. There should be a package that did this... so far I have only seen programs like golint implementing this on their own.

Not getting output for your `readme.md`s example

Copied the example in readme.md nearly verbatim into here (senseless code but just attempting to evade any potential compiler-side code removal..) but interfacer github.com/metaleap/go-devgo works for some 1-3 secs but prints nothing, same with interfacer -v github.com/metaleap/go-devgo --- what am I missing?

Recognize embeded interfaces

I have interface:

type IBusinessRuleContext interface {
    IRWLocker
    Value(interface{}) interface{}
}
type IRWLocker interface {
    sync.Locker
    RLock()
    RUnlock()
}

And when i create some object with type IBusinessRuleContext interfacer suggests:
{MyType} can be sync.Locker

But sync.Locker is embedded to IRWLocker and it embedded to biggest interface IBusinessRuleContext.

support for build tags

i use https://github.com/mattn/go-sqlite3 with -tags trace functionality
and use your great linter with gometalinter
i try add custom configuration for .gometalinter.json

{
  "Linters": {
    "interfacer": "interfacer tags -trace {path}:PATH:LINE:COL:MESSAGE"
    "gotype": {"Command": "gotype -tags trace"},
    "varcheck": {"Command": "varcheck -tags trace"},
    "maligned": {"Command": "maligned -tags trace"},
    "megacheck": {"Command": "megacheck -tags trace"},
    "errcheck": {"Command": "errcheck -tags trace"},
    "unconvert": {"Command": "unconvert -tags trace"},
    "structcheck": {"Command": "structcheck -tags trace"},
    "gocyclo": {"Command": "gocyclo -over 15"},
  },
  "EnableAll": true,
  "EnableGC": true
}

but catch following errors

database.go:78:2:warning: TraceStmt not declared by package sqlite3 (interfacer)
database.go:79:2:warning: TraceRow not declared by package sqlite3 (interfacer)
database.go:80:2:warning: TraceProfile not declared by package sqlite3 (interfacer)
database.go:81:2:warning: TraceClose not declared by package sqlite3 (interfacer)
database.go:84:31:warning: TraceInfo not declared by package sqlite3 (interfacer)

Could you provide support for custom build tags ?

Could we ignore the vendor folder?

I noticed that the vendor folder is included in the results from interfacer. The vendor folder is a little beyond my control and I don't think that interfacer should check the vendor folder.

For example, one of my projects vendors github.com/stretchr/testify and I see this error from interfacer:

interfacer ./...
vendor/github.com/stretchr/testify/mock/mock.go:276:36: t can be assert.TestingT

[readme.md] so, what exactly is `go/loader`?

In the repo readme:

This package relies on go/types for the heavy lifting: name resolution, constant folding and type inference. It also uses go/loader to resolve the packages specified by import paths.

I'd be curious to use the latter in other code, but I don't find any actual go/loader imports in your .go sources here and no mention of loader at https://golang.org/pkg/go/ either --- what is it?

Keep track of function assignments

We don't right now, which results in false positives such as these:

type st struct{}

func (s st) Close() error {
        return nil
}

func FuncAssign() {
        f := func(s st) error {
                s.Close()
                return nil
        }
        var _ func(st) error = f
}

We incorrectly suggest that s be an io.Closer, which will break compilation.

Don't warn about struct types passed by value

See the discussion in #17.

Basically, it seems that warning aobut parameter types that are passed by value and not by reference is not a good idea. The cause is that passing by reference means that the data is copied to the heap, which might be a noticeable overhead if it's a hot path or if the struct is large and not already in the heap.

Some questions come to mind:

  • Should this apply to all types, not just structs?
type foo string
func (f foo) Close() error {}

func bar(f foo) { // Should we warn about io.Closer?
    f.Close()
}
  • If it only applies to structs, should we keep the struct size in mind?
  • Should this apply only to unexported functions? I would think they are more likely to be hot paths, where such copying overhead could be an issue. Public APIs shouldn't be tuned for speed, I would think.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.