Repository: alecthomas/gometalinter (go)

Issue:
Pass -ignoretests to errcheck when "tests" flag is false
`  -t, --tests               Include test files for linters that support this option`
And yet - without it being set, errcheck checks tests files while it supports a flag to skip them.

Pull request:
Set errcheck -ignoretests when tests are not enabled
Fixes #272

Patch:
diff --git a/execute.go b/execute.go
index 6276ae2..57267a5 100644
--- a/execute.go
+++ b/execute.go
@@ -42,8 +42,6 @@ func (v Vars) Replace(s string) string {
 
 type linterState struct {
 	*Linter
-	id       int
-	paths    []string
 	issues   chan *Issue
 	vars     Vars
 	exclude  *regexp.Regexp
@@ -51,19 +49,22 @@ type linterState struct {
 	deadline <-chan time.Time
 }
 
-func (l *linterState) Partitions() ([][]string, error) {
-	command := l.vars.Replace(l.Command)
-	cmdArgs, err := parseCommand(command)
+func (l *linterState) Partitions(paths []string) ([][]string, error) {
+	cmdArgs, err := parseCommand(l.command())
 	if err != nil {
 		return nil, err
 	}
-	parts, err := l.Linter.PartitionStrategy(cmdArgs, l.paths)
+	parts, err := l.Linter.PartitionStrategy(cmdArgs, paths)
 	if err != nil {
 		return nil, err
 	}
 	return parts, nil
 }
 
+func (l *linterState) command() string {
+	return l.vars.Replace(l.Command)
+}
+
 func runLinters(linters map[string]*Linter, paths []string, concurrency int, exclude, include *regexp.Regexp) (chan *Issue, chan error) {
 	errch := make(chan error, len(linters))
 	concurrencych := make(chan bool, concurrency)
@@ -85,9 +86,11 @@ func runLinters(linters map[string]*Linter, paths []string, concurrency int, exc
 		"min_occurrences":  fmt.Sprintf("%d", config.MinOccurrences),
 		"min_const_length": fmt.Sprintf("%d", config.MinConstLength),
 		"tests":            "",
+		"not_tests":        "true",
 	}
 	if config.Test {
-		vars["tests"] = "-t"
+		vars["tests"] = "true"
+		vars["not_tests"] = ""
 	}
 
 	wg := &sync.WaitGroup{}
@@ -97,14 +100,13 @@ func runLinters(linters map[string]*Linter, paths []string, concurrency int, exc
 		state := &linterState{
 			Linter:   linter,
 			issues:   incomingIssues,
-			paths:    paths,
 			vars:     vars,
 			exclude:  exclude,
 			include:  include,
 			deadline: deadline,
 		}
 
-		partitions, err := state.Partitions()
+		partitions, err := state.Partitions(paths)
 		if err != nil {
 			errch <- err
 			continue
diff --git a/linters.go b/linters.go
index 740ab3b..ff287a8 100644
--- a/linters.go
+++ b/linters.go
@@ -222,7 +222,7 @@ var defaultLinters = map[string]LinterConfig{
 		IsFast:            true,
 	},
 	"errcheck": {
-		Command:           `errcheck -abspath`,
+		Command:           `errcheck -abspath {not_tests=-ignoretests}`,
 		Pattern:           `PATH:LINE:COL:MESSAGE`,
 		InstallFrom:       "github.com/kisielk/errcheck",
 		PartitionStrategy: partitionPathsAsPackages,
@@ -368,7 +368,7 @@ var defaultLinters = map[string]LinterConfig{
 		defaultEnabled:    true,
 	},
 	"unparam": {
-		Command:           `unparam`,
+		Command:           `unparam {not_tests=-tests=false}`,
 		Pattern:           `PATH:LINE:COL:MESSAGE`,
 		InstallFrom:       "mvdan.cc/unparam",
 		PartitionStrategy: partitionPathsAsPackages,


Test patch:
diff --git a/execute_test.go b/execute_test.go
new file mode 100644
index 0000000..cc2703a
--- /dev/null
+++ b/execute_test.go
@@ -0,0 +1,67 @@
+package main
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestLinterStateCommand(t *testing.T) {
+	varsDefault := Vars{"tests": "", "not_tests": "true"}
+	varsWithTest := Vars{"tests": "true", "not_tests": ""}
+
+	var testcases = []struct {
+		linter   string
+		vars     Vars
+		expected string
+	}{
+		{
+			linter:   "errcheck",
+			vars:     varsWithTest,
+			expected: `errcheck -abspath `,
+		},
+		{
+			linter:   "errcheck",
+			vars:     varsDefault,
+			expected: `errcheck -abspath -ignoretests`,
+		},
+		{
+			linter:   "gotype",
+			vars:     varsDefault,
+			expected: `gotype -e `,
+		},
+		{
+			linter:   "gotype",
+			vars:     varsWithTest,
+			expected: `gotype -e -t`,
+		},
+		{
+			linter:   "structcheck",
+			vars:     varsDefault,
+			expected: `structcheck `,
+		},
+		{
+			linter:   "structcheck",
+			vars:     varsWithTest,
+			expected: `structcheck -t`,
+		},
+		{
+			linter: "unparam",
+			vars: varsDefault,
+			expected: `unparam -tests=false`,
+		},
+		{
+			linter: "unparam",
+			vars: varsWithTest,
+			expected: `unparam `,
+		},
+	}
+
+	for _, testcase := range testcases {
+		ls := linterState{
+			Linter: getLinterByName(testcase.linter, LinterConfig{}),
+			vars:   testcase.vars,
+		}
+		assert.Equal(t, testcase.expected, ls.command())
+	}
+}