Fix #109, #116, #131: don't report in deadcode about unused test functions in main package

This commit is contained in:
Denis Isaev 2018-06-28 10:09:44 +03:00 committed by Isaev Denis
parent 5ef542facd
commit 88ebabc4bc
3 changed files with 37 additions and 8 deletions

2
Gopkg.lock generated
View File

@ -69,7 +69,7 @@
branch = "master"
name = "github.com/golangci/go-misc"
packages = ["deadcode"]
revision = "a61b005a223b50d3656798639dd87073ca5c1981"
revision = "927a3d87b613e9f6f0fb7ef8bb8de8b83c30a5a2"
[[projects]]
branch = "master"

View File

@ -0,0 +1,15 @@
package main
import "testing"
func TestF(t *testing.T) {
}
func BenchmarkF(t *testing.B) {
}
func ExampleF() {
}

View File

@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"sort"
"strings"
"golang.org/x/tools/go/loader"
)
@ -50,9 +51,8 @@ type Context struct {
program *loader.Program
}
// error formats the error to standard error, adding program
// identification and a newline
func (ctx *Context) errorf(pos token.Pos, format string, args ...interface{}) {
// pos resolves a compact position encoding into a verbose one
func (ctx *Context) pos(pos token.Pos) token.Position {
if ctx.cwd == "" {
ctx.cwd, _ = os.Getwd()
}
@ -61,6 +61,13 @@ func (ctx *Context) errorf(pos token.Pos, format string, args ...interface{}) {
if err == nil {
p.Filename = f
}
return p
}
// error formats the error to standard error, adding program
// identification and a newline
func (ctx *Context) errorf(pos token.Pos, format string, args ...interface{}) {
p := ctx.pos(pos)
fmt.Fprintf(os.Stderr, p.String()+": "+format+"\n", args...)
exitCode = 2
}
@ -73,18 +80,22 @@ func (ctx *Context) Process() []types.Object {
prog := ctx.program
var allUnused []types.Object
for _, pkg := range prog.Imported {
unused := doPackage(prog, pkg)
unused := ctx.doPackage(prog, pkg)
allUnused = append(allUnused, unused...)
}
for _, pkg := range prog.Created {
unused := doPackage(prog, pkg)
unused := ctx.doPackage(prog, pkg)
allUnused = append(allUnused, unused...)
}
sort.Sort(objects(allUnused))
return allUnused
}
func doPackage(prog *loader.Program, pkg *loader.PackageInfo) []types.Object {
func isTestFuncByName(name string) bool {
return strings.HasPrefix(name, "Test") || strings.HasPrefix(name, "Benchmark") || strings.HasPrefix(name, "Example")
}
func (ctx *Context) doPackage(prog *loader.Program, pkg *loader.PackageInfo) []types.Object {
used := make(map[types.Object]bool)
for _, file := range pkg.Files {
ast.Inspect(file, func(n ast.Node) bool {
@ -107,7 +118,10 @@ func doPackage(prog *loader.Program, pkg *loader.PackageInfo) []types.Object {
continue
}
obj := global.Lookup(name)
if !used[obj] && (pkg.Pkg.Name() == "main" || !ast.IsExported(name)) {
_, isSig := obj.Type().(*types.Signature)
pos := ctx.pos(obj.Pos())
isTestMethod := isSig && isTestFuncByName(obj.Name()) && strings.HasSuffix(pos.Filename, "_test.go")
if !used[obj] && ((pkg.Pkg.Name() == "main" && !isTestMethod) || !ast.IsExported(name)) {
unused = append(unused, obj)
}
}