Skip to content

Commit

Permalink
Run one process per linter (again) (alecthomas#315)
Browse files Browse the repository at this point in the history
  • Loading branch information
dnephin authored and alecthomas committed Jul 7, 2017
1 parent 24dab94 commit a04df08
Show file tree
Hide file tree
Showing 12 changed files with 580 additions and 222 deletions.
40 changes: 24 additions & 16 deletions _linters/src/github.com/jgautheron/goconst/cmd/goconst/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"flag"
"fmt"
"io"
"log"
"os"
"strconv"
Expand All @@ -16,7 +17,7 @@ const usageDoc = `goconst: find repeated strings that could be replaced by a con
Usage:
goconst ARGS <directory>
goconst ARGS <directory> [<directory>...]
Flags:
Expand All @@ -26,8 +27,8 @@ Flags:
-min-length only report strings with the minimum given length (default: 3)
-match-constant look for existing constants matching the strings
-numbers search also for duplicated numbers
-min minimum value, only works with -numbers
-max maximum value, only works with -numbers
-min minimum value, only works with -numbers
-max maximum value, only works with -numbers
-output output formatting (text or json)
Examples:
Expand All @@ -52,17 +53,25 @@ var (

func main() {
flag.Usage = func() {
fmt.Fprint(os.Stderr, usage)
usage(os.Stderr)
}
flag.Parse()
log.SetPrefix("goconst: ")

args := flag.Args()
if len(args) != 1 {
usage()
if len(args) < 1 {
usage(os.Stderr)
os.Exit(1)
}
for _, path := range args {
if err := run(path); err != nil {
log.Println(err)
os.Exit(1)
}
}
path := args[0]
}

func run(path string) error {
gco := goconst.New(
path,
*flagIgnore,
Expand All @@ -73,19 +82,17 @@ func main() {
)
strs, consts, err := gco.ParseTree()
if err != nil {
log.Println(err)
os.Exit(1)
return err
}

printOutput(strs, consts, *flagOutput, *flagMinOccurrences, *flagMin, *flagMax)
return printOutput(strs, consts, *flagOutput, *flagMinOccurrences, *flagMin, *flagMax)
}

func usage() {
fmt.Fprintf(os.Stderr, usageDoc)
os.Exit(1)
func usage(out io.Writer) {
fmt.Fprintf(out, usageDoc)
}

func printOutput(strs goconst.Strings, consts goconst.Constants, output string, minOccurrences, min, max int) {
func printOutput(strs goconst.Strings, consts goconst.Constants, output string, minOccurrences, min, max int) error {
for str, item := range strs {
// Filter out items whose occurrences don't match the min value
if len(item) < minOccurrences {
Expand Down Expand Up @@ -113,7 +120,7 @@ func printOutput(strs goconst.Strings, consts goconst.Constants, output string,
strs, consts,
})
if err != nil {
log.Fatal(err)
return err
}
case "text":
for str, item := range strs {
Expand All @@ -140,8 +147,9 @@ func printOutput(strs goconst.Strings, consts goconst.Constants, output string,
}
}
default:
fmt.Printf(`Unsupported output format: %s`, output)
return fmt.Errorf(`Unsupported output format: %s`, output)
}
return nil
}

func occurrences(item []goconst.ExtendedPos, current goconst.ExtendedPos) string {
Expand Down
4 changes: 2 additions & 2 deletions _linters/src/manifest
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"importpath": "github.com/jgautheron/goconst",
"repository": "https://github.com/jgautheron/goconst",
"vcs": "git",
"revision": "6a7633b712b6fb1d6821d33851d086a1d545dacd",
"revision": "9740945f5dcb78c2faa8eedcce78c2a04aa6e1e9",
"branch": "master",
"notests": true
},
Expand Down Expand Up @@ -418,4 +418,4 @@
"notests": true
}
]
}
}
7 changes: 7 additions & 0 deletions aggregate.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ type (
}
)

func maybeAggregateIssues(issues chan *Issue) chan *Issue {
if !config.Aggregate {
return issues
}
return aggregateIssues(issues)
}

func aggregateIssues(issues chan *Issue) chan *Issue {
out := make(chan *Issue, 1000000)
issueMap := make(map[issueKey]*multiIssue)
Expand Down
82 changes: 33 additions & 49 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import (
"runtime"
"text/template"
"time"

"gopkg.in/alecthomas/kingpin.v3-unstable"
)

// Config for gometalinter. This can be loaded from a JSON file with --config.
Expand Down Expand Up @@ -59,10 +57,7 @@ type Config struct { // nolint: aligncheck
var (
vetRe = `^(?:vet:.*?\.go:\s+(?P<path>.*?\.go):(?P<line>\d+):(?P<col>\d+):\s*(?P<message>.*))|(?:(?P<path>.*?\.go):(?P<line>\d+):\s*(?P<message>.*))$`

predefinedPatterns = map[string]string{
"PATH:LINE:COL:MESSAGE": `^(?P<path>.*?\.go):(?P<line>\d+):(?P<col>\d+):\s*(?P<message>.*)$`,
"PATH:LINE:MESSAGE": `^(?P<path>.*?\.go):(?P<line>\d+):\s*(?P<message>.*)$`,
}
// TODO: should be a field on Config struct
formatTemplate = &template.Template{}
installMap = map[string]string{
"aligncheck": "github.com/opennota/check/cmd/aligncheck",
Expand All @@ -89,56 +84,45 @@ var (
"unused": "honnef.co/go/tools/cmd/unused",
"varcheck": "github.com/opennota/check/cmd/varcheck",
}
acceptsEllipsis = map[string]bool{
"aligncheck": true,
"errcheck": true,
"golint": true,
"gosimple": true,
"interfacer": true,
"megacheck": true,
"staticcheck": true,
"structcheck": true,
"test": true,
"varcheck": true,
"unconvert": true,
}
slowLinters = []string{"structcheck", "varcheck", "errcheck", "aligncheck", "testify", "test", "interfacer", "unconvert", "deadcode", "safesql", "staticcheck", "unparam", "unused", "gosimple", "megacheck"}
sortKeys = []string{"none", "path", "line", "column", "severity", "message", "linter"}

linterTakesFiles = newStringSet("dupl", "gofmt", "goimports", "lll", "misspell")

linterTakesFilesGroupedByPackage = newStringSet("vet", "vetshadow")

// Linter definitions.
linterDefinitions = map[string]string{
"aligncheck": `aligncheck {path}:^(?:[^:]+: )?(?P<path>.*?\.go):(?P<line>\d+):(?P<col>\d+):\s*(?P<message>.+)$`,
"deadcode": `deadcode {path}:^deadcode: (?P<path>.*?\.go):(?P<line>\d+):(?P<col>\d+):\s*(?P<message>.*)$`,
"dupl": `dupl -plumbing -threshold {duplthreshold} {path}/*.go:^(?P<path>.*?\.go):(?P<line>\d+)-\d+:\s*(?P<message>.*)$`,
"errcheck": `errcheck -abspath {path}:PATH:LINE:COL:MESSAGE`,
"gas": `gas -fmt=csv {path}/*.go:^(?P<path>.*?\.go),(?P<line>\d+),(?P<message>[^,]+,[^,]+,[^,]+)`,
"goconst": `goconst -min-occurrences {min_occurrences} -min-length {min_const_length} {path}:PATH:LINE:COL:MESSAGE`,
"gocyclo": `gocyclo -over {mincyclo} {path}:^(?P<cyclo>\d+)\s+\S+\s(?P<function>\S+)\s+(?P<path>.*?\.go):(?P<line>\d+):(\d+)$`,
"gofmt": `gofmt -l -s {path}/*.go:^(?P<path>.*?\.go)$`,
"goimports": `goimports -l {path}/*.go:^(?P<path>.*?\.go)$`,
"golint": "golint -min_confidence {min_confidence} {path}:PATH:LINE:COL:MESSAGE",
"gosimple": "gosimple {path}:PATH:LINE:COL:MESSAGE",
"gotype": "gotype -e {tests=-a} {path}:PATH:LINE:COL:MESSAGE",
"ineffassign": `ineffassign -n {path}:PATH:LINE:COL:MESSAGE`,
"interfacer": `interfacer {path}:PATH:LINE:COL:MESSAGE`,
"lll": `lll -g -l {maxlinelength} {path}/*.go:PATH:LINE:MESSAGE`,
"megacheck": "megacheck {path}:PATH:LINE:COL:MESSAGE",
"misspell": "misspell -j 1 {path}/*.go:PATH:LINE:COL:MESSAGE",
"safesql": `safesql {path}:^- (?P<path>.*?\.go):(?P<line>\d+):(?P<col>\d+)$`,
"staticcheck": "staticcheck {path}:PATH:LINE:COL:MESSAGE",
"structcheck": `structcheck {tests=-t} {path}:^(?:[^:]+: )?(?P<path>.*?\.go):(?P<line>\d+):(?P<col>\d+):\s*(?P<message>.+)$`,
"test": `go test {path}:^--- FAIL: .*$\s+(?P<path>.*?\.go):(?P<line>\d+): (?P<message>.*)$`,
"testify": `go test {path}:Location:\s+(?P<path>.*?\.go):(?P<line>\d+)$\s+Error:\s+(?P<message>[^\n]+)`,
"unconvert": "unconvert {path}:PATH:LINE:COL:MESSAGE",
"unparam": `unparam {path}:PATH:LINE:COL:MESSAGE`,
"unused": `unused {path}:PATH:LINE:COL:MESSAGE`,
"varcheck": `varcheck {path}:^(?:[^:]+: )?(?P<path>.*?\.go):(?P<line>\d+):(?P<col>\d+):\s*(?P<message>.*)$`,
"vet": `go tool vet {path}/*.go:` + vetRe,
"vetshadow": `go tool vet --shadow {path}/*.go:` + vetRe,
"aligncheck": `aligncheck:^(?:[^:]+: )?(?P<path>.*?\.go):(?P<line>\d+):(?P<col>\d+):\s*(?P<message>.+)$`,
"deadcode": `deadcode:^deadcode: (?P<path>.*?\.go):(?P<line>\d+):(?P<col>\d+):\s*(?P<message>.*)$`,
"dupl": `dupl -plumbing -threshold {duplthreshold}:^(?P<path>.*?\.go):(?P<line>\d+)-\d+:\s*(?P<message>.*)$`,
"errcheck": `errcheck -abspath:PATH:LINE:COL:MESSAGE`,
"gas": `gas -fmt=csv:^(?P<path>.*?\.go),(?P<line>\d+),(?P<message>[^,]+,[^,]+,[^,]+)`,
"goconst": `goconst -min-occurrences {min_occurrences} -min-length {min_const_length}:PATH:LINE:COL:MESSAGE`,
"gocyclo": `gocyclo -over {mincyclo}:^(?P<cyclo>\d+)\s+\S+\s(?P<function>\S+)\s+(?P<path>.*?\.go):(?P<line>\d+):(\d+)$`,
"gofmt": `gofmt -l -s:^(?P<path>.*?\.go)$`,
"goimports": `goimports -l:^(?P<path>.*?\.go)$`,
"golint": "golint -min_confidence {min_confidence}:PATH:LINE:COL:MESSAGE",
"gosimple": "gosimple:PATH:LINE:COL:MESSAGE",
"gotype": "gotype -e {tests=-a}:PATH:LINE:COL:MESSAGE",
"ineffassign": `ineffassign -n:PATH:LINE:COL:MESSAGE`,
"interfacer": `interfacer:PATH:LINE:COL:MESSAGE`,
"lll": `lll -g -l {maxlinelength}:PATH:LINE:MESSAGE`,
"megacheck": "megacheck:PATH:LINE:COL:MESSAGE",
"misspell": "misspell -j 1:PATH:LINE:COL:MESSAGE",
"safesql": `safesql:^- (?P<path>.*?\.go):(?P<line>\d+):(?P<col>\d+)$`,
"staticcheck": "staticcheck:PATH:LINE:COL:MESSAGE",
"structcheck": `structcheck {tests=-t}:^(?:[^:]+: )?(?P<path>.*?\.go):(?P<line>\d+):(?P<col>\d+):\s*(?P<message>.+)$`,
"test": `go test:^--- FAIL: .*$\s+(?P<path>.*?\.go):(?P<line>\d+): (?P<message>.*)$`,
"testify": `go test:Location:\s+(?P<path>.*?\.go):(?P<line>\d+)$\s+Error:\s+(?P<message>[^\n]+)`,
"unconvert": "unconvert:PATH:LINE:COL:MESSAGE",
"unparam": `unparam:PATH:LINE:COL:MESSAGE`,
"unused": `unused:PATH:LINE:COL:MESSAGE`,
"varcheck": `varcheck:^(?:[^:]+: )?(?P<path>.*?\.go):(?P<line>\d+):(?P<col>\d+):\s*(?P<message>.*)$`,
"vet": `go tool vet:` + vetRe,
"vetshadow": `go tool vet --shadow:` + vetRe,
}

pathsArg = kingpin.Arg("path", "Directories to lint. Defaults to \".\". <path>/... will recurse.").Strings()

config = &Config{
Format: "{{.Path}}:{{.Line}}:{{if .Col}}{{.Col}}{{end}}:{{.Severity}}: {{.Message}} ({{.Linter}})",

Expand Down
Loading

0 comments on commit a04df08

Please sign in to comment.