group of fixes after running on golang source code
This commit is contained in:
parent
6f384926cf
commit
d993d3a264
4
Gopkg.lock
generated
4
Gopkg.lock
generated
@ -101,7 +101,7 @@
|
|||||||
"lib/cfg",
|
"lib/cfg",
|
||||||
"lib/whitelist"
|
"lib/whitelist"
|
||||||
]
|
]
|
||||||
revision = "31bebf17d90d40b728c41fecdd5acf5fb8654fc7"
|
revision = "1a9ab8120ec96a014df3afab2d6c47f7e12d8928"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
@ -140,7 +140,7 @@
|
|||||||
"golangci",
|
"golangci",
|
||||||
"internal/errcheck"
|
"internal/errcheck"
|
||||||
]
|
]
|
||||||
revision = "7a3d63cfc6fbd9e46f2e551f9b8d1e9c69bffab1"
|
revision = "d2c0791055c651c4bb6798ee1aacbd27ad377aa8"
|
||||||
source = "github.com/golangci/errcheck"
|
source = "github.com/golangci/errcheck"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
@ -3,6 +3,7 @@ package commands
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/golangci/golangci-lint/pkg"
|
"github.com/golangci/golangci-lint/pkg"
|
||||||
@ -20,7 +21,7 @@ func (e *Executor) initLinters() {
|
|||||||
|
|
||||||
func printLinterConfigs(lcs []pkg.LinterConfig) {
|
func printLinterConfigs(lcs []pkg.LinterConfig) {
|
||||||
for _, lc := range lcs {
|
for _, lc := range lcs {
|
||||||
fmt.Printf("%s: %s\n", color.YellowString(lc.Linter.Name()), lc.Desc)
|
fmt.Printf("%s: %s\n", color.YellowString(lc.Linter.Name()), lc.Linter.Desc())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,5 +40,15 @@ func (e Executor) executeLinters(cmd *cobra.Command, args []string) {
|
|||||||
color.Red("\nDisabled by default linters:\n")
|
color.Red("\nDisabled by default linters:\n")
|
||||||
printLinterConfigs(disabledLCs)
|
printLinterConfigs(disabledLCs)
|
||||||
|
|
||||||
|
color.Green("\nLinters presets:")
|
||||||
|
for _, p := range pkg.AllPresets() {
|
||||||
|
linters := pkg.GetAllLintersForPreset(p)
|
||||||
|
linterNames := []string{}
|
||||||
|
for _, linter := range linters {
|
||||||
|
linterNames = append(linterNames, linter.Name())
|
||||||
|
}
|
||||||
|
fmt.Printf("%s: %s\n", color.YellowString(p), strings.Join(linterNames, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
|
"go/token"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -38,16 +39,16 @@ func (e *Executor) initRun() {
|
|||||||
fmt.Sprintf("Format of output: %s", strings.Join(config.OutFormats, "|")))
|
fmt.Sprintf("Format of output: %s", strings.Join(config.OutFormats, "|")))
|
||||||
runCmd.Flags().BoolVar(&rc.PrintIssuedLine, "print-issued-lines", true, "Print lines of code with issue")
|
runCmd.Flags().BoolVar(&rc.PrintIssuedLine, "print-issued-lines", true, "Print lines of code with issue")
|
||||||
runCmd.Flags().BoolVar(&rc.PrintLinterName, "print-linter-name", true, "Print linter name in issue line")
|
runCmd.Flags().BoolVar(&rc.PrintLinterName, "print-linter-name", true, "Print linter name in issue line")
|
||||||
|
runCmd.Flags().BoolVar(&rc.PrintWelcomeMessage, "print-welcome", true, "Print welcome message")
|
||||||
|
|
||||||
runCmd.Flags().IntVar(&rc.ExitCodeIfIssuesFound, "issues-exit-code",
|
runCmd.Flags().IntVar(&rc.ExitCodeIfIssuesFound, "issues-exit-code",
|
||||||
1, "Exit code when issues were found")
|
1, "Exit code when issues were found")
|
||||||
runCmd.Flags().StringSliceVar(&rc.BuildTags, "build-tags", []string{}, "Build tags (not all linters support them)")
|
runCmd.Flags().StringSliceVar(&rc.BuildTags, "build-tags", []string{}, "Build tags (not all linters support them)")
|
||||||
|
|
||||||
runCmd.Flags().BoolVar(&rc.Errcheck.CheckClose, "errcheck.check-close", false, "Errcheck: check missed error checks on .Close() calls")
|
|
||||||
runCmd.Flags().BoolVar(&rc.Errcheck.CheckTypeAssertions, "errcheck.check-type-assertions", false, "Errcheck: check for ignored type assertion results")
|
runCmd.Flags().BoolVar(&rc.Errcheck.CheckTypeAssertions, "errcheck.check-type-assertions", false, "Errcheck: check for ignored type assertion results")
|
||||||
runCmd.Flags().BoolVar(&rc.Errcheck.CheckAssignToBlank, "errcheck.check-blank", false, "Errcheck: check for errors assigned to blank identifier: _ = errFunc()")
|
runCmd.Flags().BoolVar(&rc.Errcheck.CheckAssignToBlank, "errcheck.check-blank", false, "Errcheck: check for errors assigned to blank identifier: _ = errFunc()")
|
||||||
|
|
||||||
runCmd.Flags().BoolVar(&rc.Govet.CheckShadowing, "govet.check-shadowing", true, "Govet: check for shadowed variables")
|
runCmd.Flags().BoolVar(&rc.Govet.CheckShadowing, "govet.check-shadowing", false, "Govet: check for shadowed variables")
|
||||||
|
|
||||||
runCmd.Flags().Float64Var(&rc.Golint.MinConfidence, "golint.min-confidence", 0.8, "Golint: minimum confidence of a problem to print it")
|
runCmd.Flags().Float64Var(&rc.Golint.MinConfidence, "golint.min-confidence", 0.8, "Golint: minimum confidence of a problem to print it")
|
||||||
|
|
||||||
@ -90,6 +91,9 @@ func (e *Executor) initRun() {
|
|||||||
runCmd.Flags().StringVar(&rc.DiffFromRevision, "new-from-rev", "", "Show only new issues created after git revision `REV`")
|
runCmd.Flags().StringVar(&rc.DiffFromRevision, "new-from-rev", "", "Show only new issues created after git revision `REV`")
|
||||||
runCmd.Flags().StringVar(&rc.DiffPatchFilePath, "new-from-patch", "", "Show only new issues created in git patch with file path `PATH`")
|
runCmd.Flags().StringVar(&rc.DiffPatchFilePath, "new-from-patch", "", "Show only new issues created in git patch with file path `PATH`")
|
||||||
runCmd.Flags().BoolVar(&rc.AnalyzeTests, "tests", false, "Analyze tests (*_test.go)")
|
runCmd.Flags().BoolVar(&rc.AnalyzeTests, "tests", false, "Analyze tests (*_test.go)")
|
||||||
|
|
||||||
|
runCmd.Flags().StringSliceVarP(&rc.Presets, "presets", "p", []string{},
|
||||||
|
fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint linters' to see them. This option implies option --disable-all", strings.Join(pkg.AllPresets(), "|")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func isFullImportNeeded(linters []pkg.Linter) bool {
|
func isFullImportNeeded(linters []pkg.Linter) bool {
|
||||||
@ -208,10 +212,15 @@ func (e *Executor) runAnalysis(ctx context.Context, args []string) (chan result.
|
|||||||
if len(excludePatterns) != 0 {
|
if len(excludePatterns) != 0 {
|
||||||
excludeTotalPattern = fmt.Sprintf("(%s)", strings.Join(excludePatterns, "|"))
|
excludeTotalPattern = fmt.Sprintf("(%s)", strings.Join(excludePatterns, "|"))
|
||||||
}
|
}
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
if lintCtx.Program != nil {
|
||||||
|
fset = lintCtx.Program.Fset
|
||||||
|
}
|
||||||
runner := pkg.SimpleRunner{
|
runner := pkg.SimpleRunner{
|
||||||
Processors: []processors.Processor{
|
Processors: []processors.Processor{
|
||||||
processors.NewExclude(excludeTotalPattern),
|
processors.NewExclude(excludeTotalPattern),
|
||||||
processors.NewNolint(lintCtx.Program.Fset),
|
processors.NewCgo(),
|
||||||
|
processors.NewNolint(fset),
|
||||||
processors.NewUniqByLine(),
|
processors.NewUniqByLine(),
|
||||||
processors.NewDiff(e.cfg.Run.Diff, e.cfg.Run.DiffFromRevision, e.cfg.Run.DiffPatchFilePath),
|
processors.NewDiff(e.cfg.Run.Diff, e.cfg.Run.DiffFromRevision, e.cfg.Run.DiffPatchFilePath),
|
||||||
processors.NewMaxPerFileFromLinter(),
|
processors.NewMaxPerFileFromLinter(),
|
||||||
@ -231,6 +240,10 @@ func (e *Executor) executeRun(cmd *cobra.Command, args []string) {
|
|||||||
logrus.Infof("Run took %s", time.Since(startedAt))
|
logrus.Infof("Run took %s", time.Since(startedAt))
|
||||||
}(time.Now())
|
}(time.Now())
|
||||||
|
|
||||||
|
if e.cfg.Run.PrintWelcomeMessage {
|
||||||
|
fmt.Println("Run this tool in cloud on every github pull request in https://golangci.com for free (public repos)")
|
||||||
|
}
|
||||||
|
|
||||||
f := func() error {
|
f := func() error {
|
||||||
issues, err := e.runAnalysis(ctx, args)
|
issues, err := e.runAnalysis(ctx, args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -15,6 +15,7 @@ const (
|
|||||||
var OutFormats = []string{OutFormatColoredLineNumber, OutFormatLineNumber, OutFormatJSON}
|
var OutFormats = []string{OutFormatColoredLineNumber, OutFormatLineNumber, OutFormatJSON}
|
||||||
|
|
||||||
var DefaultExcludePatterns = []string{
|
var DefaultExcludePatterns = []string{
|
||||||
|
"Error return value of `(os\\.Std(out|err)\\.Write|.*\\.Close)` is not checked",
|
||||||
"should have comment",
|
"should have comment",
|
||||||
"comment on exported method",
|
"comment on exported method",
|
||||||
"G104", // disable what errcheck does: it reports on Close etc
|
"G104", // disable what errcheck does: it reports on Close etc
|
||||||
@ -33,14 +34,14 @@ type Run struct { // nolint:maligned
|
|||||||
|
|
||||||
BuildTags []string
|
BuildTags []string
|
||||||
|
|
||||||
OutFormat string
|
OutFormat string
|
||||||
PrintIssuedLine bool
|
PrintIssuedLine bool
|
||||||
PrintLinterName bool
|
PrintLinterName bool
|
||||||
|
PrintWelcomeMessage bool
|
||||||
|
|
||||||
ExitCodeIfIssuesFound int
|
ExitCodeIfIssuesFound int
|
||||||
|
|
||||||
Errcheck struct {
|
Errcheck struct {
|
||||||
CheckClose bool
|
|
||||||
CheckTypeAssertions bool
|
CheckTypeAssertions bool
|
||||||
CheckAssignToBlank bool
|
CheckAssignToBlank bool
|
||||||
}
|
}
|
||||||
@ -83,6 +84,8 @@ type Run struct { // nolint:maligned
|
|||||||
EnableAllLinters bool
|
EnableAllLinters bool
|
||||||
DisableAllLinters bool
|
DisableAllLinters bool
|
||||||
|
|
||||||
|
Presets []string
|
||||||
|
|
||||||
ExcludePatterns []string
|
ExcludePatterns []string
|
||||||
UseDefaultExcludes bool
|
UseDefaultExcludes bool
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package pkg
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/golangci/golangci-lint/pkg/config"
|
"github.com/golangci/golangci-lint/pkg/config"
|
||||||
@ -10,12 +11,61 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
PresetFormatting = "format"
|
||||||
|
PresetComplexity = "complexity"
|
||||||
|
PresetStyle = "style"
|
||||||
|
PresetBugs = "bugs"
|
||||||
|
PresetUnused = "unused"
|
||||||
|
PresetPerformance = "performance"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AllPresets() []string {
|
||||||
|
return []string{PresetBugs, PresetUnused, PresetFormatting, PresetStyle, PresetComplexity, PresetPerformance}
|
||||||
|
}
|
||||||
|
|
||||||
|
func allPresetsSet() map[string]bool {
|
||||||
|
ret := map[string]bool{}
|
||||||
|
for _, p := range AllPresets() {
|
||||||
|
ret[p] = true
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
type LinterConfig struct {
|
type LinterConfig struct {
|
||||||
Desc string
|
|
||||||
Linter Linter
|
Linter Linter
|
||||||
EnabledByDefault bool
|
EnabledByDefault bool
|
||||||
DoesFullImport bool
|
DoesFullImport bool
|
||||||
NeedsSSARepr bool
|
NeedsSSARepr bool
|
||||||
|
InPresets []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lc LinterConfig) WithFullImport() LinterConfig {
|
||||||
|
lc.DoesFullImport = true
|
||||||
|
return lc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lc LinterConfig) WithSSA() LinterConfig {
|
||||||
|
lc.DoesFullImport = true
|
||||||
|
lc.NeedsSSARepr = true
|
||||||
|
return lc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lc LinterConfig) WithPresets(presets ...string) LinterConfig {
|
||||||
|
lc.InPresets = presets
|
||||||
|
return lc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lc LinterConfig) WithDisabledByDefault() LinterConfig {
|
||||||
|
lc.EnabledByDefault = false
|
||||||
|
return lc
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLinterConfig(linter Linter) LinterConfig {
|
||||||
|
return LinterConfig{
|
||||||
|
Linter: linter,
|
||||||
|
EnabledByDefault: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var nameToLC map[string]LinterConfig
|
var nameToLC map[string]LinterConfig
|
||||||
@ -37,46 +87,26 @@ func GetLinterConfig(name string) *LinterConfig {
|
|||||||
return &lc
|
return &lc
|
||||||
}
|
}
|
||||||
|
|
||||||
func enabledByDefault(linter Linter, desc string, doesFullImport, needsSSARepr bool) LinterConfig {
|
|
||||||
return LinterConfig{
|
|
||||||
EnabledByDefault: true,
|
|
||||||
Linter: linter,
|
|
||||||
Desc: desc,
|
|
||||||
DoesFullImport: doesFullImport,
|
|
||||||
NeedsSSARepr: needsSSARepr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func disabledByDefault(linter Linter, desc string, doesFullImport, needsSSARepr bool) LinterConfig {
|
|
||||||
return LinterConfig{
|
|
||||||
EnabledByDefault: false,
|
|
||||||
Linter: linter,
|
|
||||||
Desc: desc,
|
|
||||||
DoesFullImport: doesFullImport,
|
|
||||||
NeedsSSARepr: needsSSARepr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAllSupportedLinterConfigs() []LinterConfig {
|
func GetAllSupportedLinterConfigs() []LinterConfig {
|
||||||
return []LinterConfig{
|
return []LinterConfig{
|
||||||
enabledByDefault(golinters.Govet{}, "Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string", false, false),
|
newLinterConfig(golinters.Govet{}).WithPresets(PresetBugs),
|
||||||
enabledByDefault(golinters.Errcheck{}, "Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases", true, false),
|
newLinterConfig(golinters.Errcheck{}).WithFullImport().WithPresets(PresetBugs),
|
||||||
enabledByDefault(golinters.Golint{}, "Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes", false, false),
|
newLinterConfig(golinters.Golint{}).WithDisabledByDefault().WithPresets(PresetStyle),
|
||||||
enabledByDefault(golinters.Megacheck{}, "Megacheck: 3 sub-linters in one: staticcheck, gosimple and unused", true, true),
|
newLinterConfig(golinters.Megacheck{}).WithSSA().WithPresets(PresetBugs, PresetUnused, PresetStyle),
|
||||||
enabledByDefault(golinters.Gas{}, "Inspects source code for security problems", true, false),
|
newLinterConfig(golinters.Gas{}).WithFullImport().WithPresets(PresetBugs),
|
||||||
enabledByDefault(golinters.Structcheck{}, "Finds unused struct fields", true, false),
|
newLinterConfig(golinters.Structcheck{}).WithFullImport().WithPresets(PresetUnused),
|
||||||
enabledByDefault(golinters.Varcheck{}, "Finds unused global variables and constants", true, false),
|
newLinterConfig(golinters.Varcheck{}).WithFullImport().WithPresets(PresetUnused),
|
||||||
enabledByDefault(golinters.Interfacer{}, "Linter that suggests narrower interface types", true, true),
|
newLinterConfig(golinters.Interfacer{}).WithDisabledByDefault().WithSSA().WithPresets(PresetStyle),
|
||||||
enabledByDefault(golinters.Unconvert{}, "Remove unnecessary type conversions", true, false),
|
newLinterConfig(golinters.Unconvert{}).WithDisabledByDefault().WithFullImport().WithPresets(PresetStyle),
|
||||||
enabledByDefault(golinters.Ineffassign{}, "Detects when assignments to existing variables are not used", false, false),
|
newLinterConfig(golinters.Ineffassign{}).WithPresets(PresetUnused),
|
||||||
enabledByDefault(golinters.Dupl{}, "Tool for code clone detection", false, false),
|
newLinterConfig(golinters.Dupl{}).WithDisabledByDefault().WithPresets(PresetStyle),
|
||||||
enabledByDefault(golinters.Goconst{}, "Finds repeated strings that could be replaced by a constant", false, false),
|
newLinterConfig(golinters.Goconst{}).WithDisabledByDefault().WithPresets(PresetStyle),
|
||||||
enabledByDefault(golinters.Deadcode{}, "Finds unused code", true, false),
|
newLinterConfig(golinters.Deadcode{}).WithFullImport().WithPresets(PresetUnused),
|
||||||
enabledByDefault(golinters.Gocyclo{}, "Computes and checks the cyclomatic complexity of functions", false, false),
|
newLinterConfig(golinters.Gocyclo{}).WithDisabledByDefault().WithPresets(PresetComplexity),
|
||||||
|
|
||||||
disabledByDefault(golinters.Gofmt{}, "Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification", false, false),
|
newLinterConfig(golinters.Gofmt{}).WithDisabledByDefault().WithPresets(PresetFormatting),
|
||||||
disabledByDefault(golinters.Gofmt{UseGoimports: true}, "Goimports does everything that gofmt does. Additionally it checks unused imports", false, false),
|
newLinterConfig(golinters.Gofmt{UseGoimports: true}).WithDisabledByDefault().WithPresets(PresetFormatting),
|
||||||
disabledByDefault(golinters.Maligned{}, "Tool to detect Go structs that would take less memory if their fields were sorted", true, false),
|
newLinterConfig(golinters.Maligned{}).WithFullImport().WithDisabledByDefault().WithPresets(PresetPerformance),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,6 +162,17 @@ func validateEnabledDisabledLintersConfig(cfg *config.Run) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allPresets := allPresetsSet()
|
||||||
|
for _, p := range cfg.Presets {
|
||||||
|
if !allPresets[p] {
|
||||||
|
return fmt.Errorf("no such preset %q: only next presets exist: (%s)", p, strings.Join(AllPresets(), "|"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(cfg.Presets) != 0 && cfg.EnableAllLinters {
|
||||||
|
return fmt.Errorf("--presets is incompatible with --enable-all")
|
||||||
|
}
|
||||||
|
|
||||||
if cfg.EnableAllLinters && cfg.DisableAllLinters {
|
if cfg.EnableAllLinters && cfg.DisableAllLinters {
|
||||||
return fmt.Errorf("--enable-all and --disable-all options must not be combined")
|
return fmt.Errorf("--enable-all and --disable-all options must not be combined")
|
||||||
}
|
}
|
||||||
@ -164,12 +205,29 @@ func validateEnabledDisabledLintersConfig(cfg *config.Run) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetAllLintersForPreset(p string) []Linter {
|
||||||
|
ret := []Linter{}
|
||||||
|
for _, lc := range GetAllSupportedLinterConfigs() {
|
||||||
|
for _, ip := range lc.InPresets {
|
||||||
|
if p == ip {
|
||||||
|
ret = append(ret, lc.Linter)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
func GetEnabledLinters(ctx context.Context, cfg *config.Run) ([]Linter, error) {
|
func GetEnabledLinters(ctx context.Context, cfg *config.Run) ([]Linter, error) {
|
||||||
if err := validateEnabledDisabledLintersConfig(cfg); err != nil {
|
if err := validateEnabledDisabledLintersConfig(cfg); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resultLintersSet := map[string]Linter{}
|
resultLintersSet := map[string]Linter{}
|
||||||
switch {
|
switch {
|
||||||
|
case len(cfg.Presets) != 0:
|
||||||
|
break // imply --disable-all
|
||||||
case cfg.EnableAllLinters:
|
case cfg.EnableAllLinters:
|
||||||
resultLintersSet = lintersToMap(getAllSupportedLinters())
|
resultLintersSet = lintersToMap(getAllSupportedLinters())
|
||||||
case cfg.DisableAllLinters:
|
case cfg.DisableAllLinters:
|
||||||
@ -182,6 +240,32 @@ func GetEnabledLinters(ctx context.Context, cfg *config.Run) ([]Linter, error) {
|
|||||||
resultLintersSet[name] = getLinterByName(name)
|
resultLintersSet[name] = getLinterByName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: hacks because of sub-linters in megacheck
|
||||||
|
megacheckWasEnabledByUser := resultLintersSet["megacheck"] != nil
|
||||||
|
if !megacheckWasEnabledByUser {
|
||||||
|
cfg.Megacheck.EnableGosimple = false
|
||||||
|
cfg.Megacheck.EnableStaticcheck = false
|
||||||
|
cfg.Megacheck.EnableUnused = false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range cfg.Presets {
|
||||||
|
for _, linter := range GetAllLintersForPreset(p) {
|
||||||
|
resultLintersSet[linter.Name()] = linter
|
||||||
|
}
|
||||||
|
|
||||||
|
if !megacheckWasEnabledByUser {
|
||||||
|
if p == PresetBugs {
|
||||||
|
cfg.Megacheck.EnableStaticcheck = true
|
||||||
|
}
|
||||||
|
if p == PresetStyle {
|
||||||
|
cfg.Megacheck.EnableGosimple = true
|
||||||
|
}
|
||||||
|
if p == PresetUnused {
|
||||||
|
cfg.Megacheck.EnableUnused = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, name := range cfg.DisabledLinters {
|
for _, name := range cfg.DisabledLinters {
|
||||||
delete(resultLintersSet, name)
|
delete(resultLintersSet, name)
|
||||||
}
|
}
|
||||||
@ -192,7 +276,10 @@ func GetEnabledLinters(ctx context.Context, cfg *config.Run) ([]Linter, error) {
|
|||||||
resultLinters = append(resultLinters, linter)
|
resultLinters = append(resultLinters, linter)
|
||||||
resultLinterNames = append(resultLinterNames, name)
|
resultLinterNames = append(resultLinterNames, name)
|
||||||
}
|
}
|
||||||
logrus.Infof("Enabled linters: %s", resultLinterNames)
|
logrus.Infof("Active linters: %s", resultLinterNames)
|
||||||
|
if len(cfg.Presets) != 0 {
|
||||||
|
logrus.Infof("Active presets: %s", cfg.Presets)
|
||||||
|
}
|
||||||
|
|
||||||
return resultLinters, nil
|
return resultLinters, nil
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,8 @@ func testOneSource(t *testing.T, sourcePath string) {
|
|||||||
"--print-issued-lines=false",
|
"--print-issued-lines=false",
|
||||||
"--print-linter-name=false",
|
"--print-linter-name=false",
|
||||||
"--out-format=line-number",
|
"--out-format=line-number",
|
||||||
|
"--print-welcome=false",
|
||||||
|
"--govet.check-shadowing=true",
|
||||||
sourcePath)
|
sourcePath)
|
||||||
runGoErrchk(cmd, t)
|
runGoErrchk(cmd, t)
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,10 @@ func (Deadcode) Name() string {
|
|||||||
return "deadcode"
|
return "deadcode"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Deadcode) Desc() string {
|
||||||
|
return "Finds unused code"
|
||||||
|
}
|
||||||
|
|
||||||
func (d Deadcode) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (d Deadcode) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
issues, err := deadcodeAPI.Run(lintCtx.Program)
|
issues, err := deadcodeAPI.Run(lintCtx.Program)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -15,6 +15,10 @@ func (Dupl) Name() string {
|
|||||||
return "dupl"
|
return "dupl"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Dupl) Desc() string {
|
||||||
|
return "Tool for code clone detection"
|
||||||
|
}
|
||||||
|
|
||||||
func (d Dupl) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (d Dupl) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
issues, err := duplAPI.Run(lintCtx.Paths.Files, lintCtx.RunCfg().Dupl.Threshold)
|
issues, err := duplAPI.Run(lintCtx.Paths.Files, lintCtx.RunCfg().Dupl.Threshold)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3,7 +3,6 @@ package golinters
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/golangci/golangci-lint/pkg/result"
|
"github.com/golangci/golangci-lint/pkg/result"
|
||||||
errcheckAPI "github.com/kisielk/errcheck/golangci"
|
errcheckAPI "github.com/kisielk/errcheck/golangci"
|
||||||
@ -15,6 +14,10 @@ func (Errcheck) Name() string {
|
|||||||
return "errcheck"
|
return "errcheck"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Errcheck) Desc() string {
|
||||||
|
return "Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases"
|
||||||
|
}
|
||||||
|
|
||||||
func (e Errcheck) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (e Errcheck) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
errCfg := &lintCtx.RunCfg().Errcheck
|
errCfg := &lintCtx.RunCfg().Errcheck
|
||||||
issues, err := errcheckAPI.Run(lintCtx.Program, errCfg.CheckAssignToBlank, errCfg.CheckTypeAssertions)
|
issues, err := errcheckAPI.Run(lintCtx.Program, errCfg.CheckAssignToBlank, errCfg.CheckTypeAssertions)
|
||||||
@ -24,10 +27,6 @@ func (e Errcheck) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, er
|
|||||||
|
|
||||||
var res []result.Issue
|
var res []result.Issue
|
||||||
for _, i := range issues {
|
for _, i := range issues {
|
||||||
if !errCfg.CheckClose && strings.HasSuffix(i.FuncName, ".Close") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var text string
|
var text string
|
||||||
if i.FuncName != "" {
|
if i.FuncName != "" {
|
||||||
text = fmt.Sprintf("Error return value of %s is not checked", formatCode(i.FuncName, lintCtx.RunCfg()))
|
text = fmt.Sprintf("Error return value of %s is not checked", formatCode(i.FuncName, lintCtx.RunCfg()))
|
||||||
|
@ -19,6 +19,10 @@ func (Gas) Name() string {
|
|||||||
return "gas"
|
return "gas"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Gas) Desc() string {
|
||||||
|
return "Inspects source code for security problems"
|
||||||
|
}
|
||||||
|
|
||||||
func (lint Gas) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (lint Gas) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
gasConfig := gas.NewConfig()
|
gasConfig := gas.NewConfig()
|
||||||
enabledRules := rules.Generate()
|
enabledRules := rules.Generate()
|
||||||
|
@ -14,17 +14,27 @@ func (Goconst) Name() string {
|
|||||||
return "goconst"
|
return "goconst"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Goconst) Desc() string {
|
||||||
|
return "Finds repeated strings that could be replaced by a constant"
|
||||||
|
}
|
||||||
|
|
||||||
func (lint Goconst) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (lint Goconst) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
issues, err := goconstAPI.Run(lintCtx.Paths.Files, true,
|
var goconstIssues []goconstAPI.Issue
|
||||||
lintCtx.RunCfg().Goconst.MinStringLen,
|
// TODO: make it cross-package: pass package names inside goconst
|
||||||
lintCtx.RunCfg().Goconst.MinOccurrencesCount,
|
for _, files := range lintCtx.Paths.FilesGrouppedByDirs() {
|
||||||
)
|
issues, err := goconstAPI.Run(files, true,
|
||||||
if err != nil {
|
lintCtx.RunCfg().Goconst.MinStringLen,
|
||||||
return nil, err
|
lintCtx.RunCfg().Goconst.MinOccurrencesCount,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
goconstIssues = append(goconstIssues, issues...)
|
||||||
}
|
}
|
||||||
|
|
||||||
var res []result.Issue
|
var res []result.Issue
|
||||||
for _, i := range issues {
|
for _, i := range goconstIssues {
|
||||||
textBegin := fmt.Sprintf("string %s has %d occurrences", formatCode(i.Str, lintCtx.RunCfg()), i.OccurencesCount)
|
textBegin := fmt.Sprintf("string %s has %d occurrences", formatCode(i.Str, lintCtx.RunCfg()), i.OccurencesCount)
|
||||||
var textEnd string
|
var textEnd string
|
||||||
if i.MatchingConst == "" {
|
if i.MatchingConst == "" {
|
||||||
|
@ -14,6 +14,10 @@ func (Gocyclo) Name() string {
|
|||||||
return "gocyclo"
|
return "gocyclo"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Gocyclo) Desc() string {
|
||||||
|
return "Computes and checks the cyclomatic complexity of functions"
|
||||||
|
}
|
||||||
|
|
||||||
func (g Gocyclo) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (g Gocyclo) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
stats := gocycloAPI.Run(lintCtx.Paths.MixedPaths())
|
stats := gocycloAPI.Run(lintCtx.Paths.MixedPaths())
|
||||||
|
|
||||||
|
@ -25,6 +25,14 @@ func (g Gofmt) Name() string {
|
|||||||
return "gofmt"
|
return "gofmt"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g Gofmt) Desc() string {
|
||||||
|
if g.UseGoimports {
|
||||||
|
return "Goimports does everything that gofmt does. Additionally it checks unused imports"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification"
|
||||||
|
}
|
||||||
|
|
||||||
func getFirstDeletedAndAddedLineNumberInHunk(h *diff.Hunk) (int, int, error) {
|
func getFirstDeletedAndAddedLineNumberInHunk(h *diff.Hunk) (int, int, error) {
|
||||||
lines := bytes.Split(h.Body, []byte{'\n'})
|
lines := bytes.Split(h.Body, []byte{'\n'})
|
||||||
lineNumber := int(h.OrigStartLine - 1)
|
lineNumber := int(h.OrigStartLine - 1)
|
||||||
|
@ -15,6 +15,10 @@ func (Golint) Name() string {
|
|||||||
return "golint"
|
return "golint"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Golint) Desc() string {
|
||||||
|
return "Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes"
|
||||||
|
}
|
||||||
|
|
||||||
func (g Golint) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (g Golint) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
var issues []result.Issue
|
var issues []result.Issue
|
||||||
for _, pkgFiles := range lintCtx.Paths.FilesGrouppedByDirs() {
|
for _, pkgFiles := range lintCtx.Paths.FilesGrouppedByDirs() {
|
||||||
|
@ -13,14 +13,23 @@ func (Govet) Name() string {
|
|||||||
return "govet"
|
return "govet"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Govet) Desc() string {
|
||||||
|
return "Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string"
|
||||||
|
}
|
||||||
|
|
||||||
func (g Govet) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (g Govet) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
issues, err := govetAPI.Run(lintCtx.Paths.MixedPaths(), lintCtx.RunCfg().BuildTags, lintCtx.RunCfg().Govet.CheckShadowing)
|
// TODO: check .S asm files: govet can do it if pass dirs
|
||||||
if err != nil {
|
var govetIssues []govetAPI.Issue
|
||||||
return nil, err
|
for _, files := range lintCtx.Paths.FilesGrouppedByDirs() {
|
||||||
|
issues, err := govetAPI.Run(files, lintCtx.RunCfg().Govet.CheckShadowing)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
govetIssues = append(govetIssues, issues...)
|
||||||
}
|
}
|
||||||
|
|
||||||
var res []result.Issue
|
var res []result.Issue
|
||||||
for _, i := range issues {
|
for _, i := range govetIssues {
|
||||||
res = append(res, result.Issue{
|
res = append(res, result.Issue{
|
||||||
Pos: i.Pos,
|
Pos: i.Pos,
|
||||||
Text: i.Message,
|
Text: i.Message,
|
||||||
|
@ -14,6 +14,10 @@ func (Ineffassign) Name() string {
|
|||||||
return "ineffassign"
|
return "ineffassign"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Ineffassign) Desc() string {
|
||||||
|
return "Detects when assignments to existing variables are not used"
|
||||||
|
}
|
||||||
|
|
||||||
func (lint Ineffassign) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (lint Ineffassign) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
issues := ineffassignAPI.Run(lintCtx.Paths.Files)
|
issues := ineffassignAPI.Run(lintCtx.Paths.Files)
|
||||||
|
|
||||||
|
@ -14,6 +14,10 @@ func (Interfacer) Name() string {
|
|||||||
return "interfacer"
|
return "interfacer"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Interfacer) Desc() string {
|
||||||
|
return "Linter that suggests narrower interface types"
|
||||||
|
}
|
||||||
|
|
||||||
func (lint Interfacer) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (lint Interfacer) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
c := new(check.Checker)
|
c := new(check.Checker)
|
||||||
c.Program(lintCtx.Program)
|
c.Program(lintCtx.Program)
|
||||||
|
@ -14,6 +14,10 @@ func (Maligned) Name() string {
|
|||||||
return "maligned"
|
return "maligned"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Maligned) Desc() string {
|
||||||
|
return "Tool to detect Go structs that would take less memory if their fields were sorted"
|
||||||
|
}
|
||||||
|
|
||||||
func (m Maligned) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (m Maligned) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
issues := malignedAPI.Run(lintCtx.Program)
|
issues := malignedAPI.Run(lintCtx.Program)
|
||||||
|
|
||||||
|
@ -13,6 +13,10 @@ func (Megacheck) Name() string {
|
|||||||
return "megacheck"
|
return "megacheck"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Megacheck) Desc() string {
|
||||||
|
return "Megacheck: 3 sub-linters in one: staticcheck, gosimple and unused"
|
||||||
|
}
|
||||||
|
|
||||||
func (m Megacheck) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (m Megacheck) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
c := lintCtx.RunCfg().Megacheck
|
c := lintCtx.RunCfg().Megacheck
|
||||||
issues := megacheckAPI.Run(lintCtx.Program, lintCtx.LoaderConfig, lintCtx.SSAProgram, c.EnableStaticcheck, c.EnableGosimple, c.EnableUnused)
|
issues := megacheckAPI.Run(lintCtx.Program, lintCtx.LoaderConfig, lintCtx.SSAProgram, c.EnableStaticcheck, c.EnableGosimple, c.EnableUnused)
|
||||||
|
@ -14,6 +14,10 @@ func (Structcheck) Name() string {
|
|||||||
return "structcheck"
|
return "structcheck"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Structcheck) Desc() string {
|
||||||
|
return "Finds unused struct fields"
|
||||||
|
}
|
||||||
|
|
||||||
func (s Structcheck) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (s Structcheck) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
issues := structcheckAPI.Run(lintCtx.Program, lintCtx.RunCfg().Structcheck.CheckExportedFields)
|
issues := structcheckAPI.Run(lintCtx.Program, lintCtx.RunCfg().Structcheck.CheckExportedFields)
|
||||||
|
|
||||||
|
@ -13,6 +13,10 @@ func (Unconvert) Name() string {
|
|||||||
return "unconvert"
|
return "unconvert"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Unconvert) Desc() string {
|
||||||
|
return "Remove unnecessary type conversions"
|
||||||
|
}
|
||||||
|
|
||||||
func (lint Unconvert) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (lint Unconvert) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
positions := unconvertAPI.Run(lintCtx.Program)
|
positions := unconvertAPI.Run(lintCtx.Program)
|
||||||
var res []result.Issue
|
var res []result.Issue
|
||||||
|
@ -14,6 +14,10 @@ func (Varcheck) Name() string {
|
|||||||
return "varcheck"
|
return "varcheck"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Varcheck) Desc() string {
|
||||||
|
return "Finds unused global variables and constants"
|
||||||
|
}
|
||||||
|
|
||||||
func (v Varcheck) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (v Varcheck) Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
issues := varcheckAPI.Run(lintCtx.Program, lintCtx.RunCfg().Varcheck.CheckExportedFields)
|
issues := varcheckAPI.Run(lintCtx.Program, lintCtx.RunCfg().Varcheck.CheckExportedFields)
|
||||||
|
|
||||||
|
@ -10,4 +10,5 @@ import (
|
|||||||
type Linter interface {
|
type Linter interface {
|
||||||
Run(ctx context.Context, lintCtx *golinters.Context) ([]result.Issue, error)
|
Run(ctx context.Context, lintCtx *golinters.Context) ([]result.Issue, error)
|
||||||
Name() string
|
Name() string
|
||||||
|
Desc() string
|
||||||
}
|
}
|
||||||
|
30
pkg/result/processors/cgo.go
Normal file
30
pkg/result/processors/cgo.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package processors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/golangci/golangci-lint/pkg/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Cgo struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Processor = Cgo{}
|
||||||
|
|
||||||
|
func NewCgo() *Cgo {
|
||||||
|
return &Cgo{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Cgo) Name() string {
|
||||||
|
return "cgo"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Cgo) Process(issues []result.Issue) ([]result.Issue, error) {
|
||||||
|
return filterIssues(issues, func(i *result.Issue) bool {
|
||||||
|
// some linters (.e.g gas, deadcode) return incorrect filepaths for cgo issues,
|
||||||
|
// it breaks next processing, so skip them
|
||||||
|
return !strings.HasSuffix(i.FilePath(), "/C")
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Cgo) Finish() {}
|
@ -1,6 +1,7 @@
|
|||||||
package processors
|
package processors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
@ -43,7 +44,7 @@ func (p *Nolint) shouldPassIssue(i *result.Issue) (bool, error) {
|
|||||||
if comments == nil {
|
if comments == nil {
|
||||||
file, err := parser.ParseFile(p.fset, i.FilePath(), nil, parser.ParseComments)
|
file, err := parser.ParseFile(p.fset, i.FilePath(), nil, parser.ParseComments)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, err
|
return false, fmt.Errorf("can't parse file %s", i.FilePath())
|
||||||
}
|
}
|
||||||
|
|
||||||
comments = extractFileComments(p.fset, file.Comments...)
|
comments = extractFileComments(p.fset, file.Comments...)
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package processors
|
package processors
|
||||||
|
|
||||||
import "github.com/golangci/golangci-lint/pkg/result"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/golangci/golangci-lint/pkg/result"
|
||||||
|
)
|
||||||
|
|
||||||
func filterIssues(issues []result.Issue, filter func(i *result.Issue) bool) []result.Issue {
|
func filterIssues(issues []result.Issue, filter func(i *result.Issue) bool) []result.Issue {
|
||||||
retIssues := make([]result.Issue, 0, len(issues))
|
retIssues := make([]result.Issue, 0, len(issues))
|
||||||
@ -18,8 +22,9 @@ func filterIssuesErr(issues []result.Issue, filter func(i *result.Issue) (bool,
|
|||||||
for _, i := range issues {
|
for _, i := range issues {
|
||||||
ok, err := filter(&i)
|
ok, err := filter(&i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("can't filter issue %#v: %s", i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
retIssues = append(retIssues, i)
|
retIssues = append(retIssues, i)
|
||||||
}
|
}
|
||||||
|
@ -34,11 +34,7 @@ func (r *SimpleRunner) runLinter(ctx context.Context, linter Linter, lintCtx *go
|
|||||||
startedAt := time.Now()
|
startedAt := time.Now()
|
||||||
res, err = linter.Run(ctx, lintCtx)
|
res, err = linter.Run(ctx, lintCtx)
|
||||||
|
|
||||||
if err == nil && len(res) != 0 {
|
logrus.Infof("worker #%d: linter %s took %s and found %d issues (before processing them)", i, linter.Name(),
|
||||||
res = r.processIssues(ctx, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
logrus.Infof("worker #%d: linter %s took %s and found %d issues", i, linter.Name(),
|
|
||||||
time.Since(startedAt), len(res))
|
time.Since(startedAt), len(res))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -120,6 +116,11 @@ func (r SimpleRunner) runGo(ctx context.Context, linters []Linter, lintCtx *goli
|
|||||||
}
|
}
|
||||||
|
|
||||||
finishedN++
|
finishedN++
|
||||||
|
|
||||||
|
if len(res.issues) != 0 {
|
||||||
|
res.issues = r.processIssues(ctx, res.issues)
|
||||||
|
}
|
||||||
|
|
||||||
for _, i := range res.issues {
|
for _, i := range res.issues {
|
||||||
retIssues <- i
|
retIssues <- i
|
||||||
}
|
}
|
||||||
|
5
pkg/testdata/with_issues/errcheck.go
vendored
5
pkg/testdata/with_issues/errcheck.go
vendored
@ -32,3 +32,8 @@ func IgnoreCloseInDeferMissingErrHandling() {
|
|||||||
|
|
||||||
panic(resp)
|
panic(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IgnoreStdxWrite() {
|
||||||
|
os.Stdout.Write([]byte{})
|
||||||
|
os.Stderr.Write([]byte{})
|
||||||
|
}
|
||||||
|
35
vendor/github.com/golangci/govet/golangci.go
generated
vendored
35
vendor/github.com/golangci/govet/golangci.go
generated
vendored
@ -1,9 +1,7 @@
|
|||||||
package govet
|
package govet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"go/token"
|
"go/token"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,7 +12,7 @@ type Issue struct {
|
|||||||
|
|
||||||
var foundIssues []Issue
|
var foundIssues []Issue
|
||||||
|
|
||||||
func Run(paths, buildTags []string, checkShadowing bool) ([]Issue, error) {
|
func Run(files []string, checkShadowing bool) ([]Issue, error) {
|
||||||
foundIssues = nil
|
foundIssues = nil
|
||||||
|
|
||||||
if checkShadowing {
|
if checkShadowing {
|
||||||
@ -26,37 +24,16 @@ func Run(paths, buildTags []string, checkShadowing bool) ([]Issue, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tagList = buildTags
|
|
||||||
|
|
||||||
initPrintFlags()
|
initPrintFlags()
|
||||||
initUnusedFlags()
|
initUnusedFlags()
|
||||||
|
|
||||||
for _, name := range paths {
|
filesRun = true
|
||||||
// Is it a directory?
|
for _, name := range files {
|
||||||
fi, err := os.Stat(name)
|
if !strings.HasSuffix(name, "_test.go") {
|
||||||
if err != nil {
|
includesNonTest = true
|
||||||
warnf("error walking tree: %s", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fi.IsDir() {
|
|
||||||
dirsRun = true
|
|
||||||
} else {
|
|
||||||
filesRun = true
|
|
||||||
if !strings.HasSuffix(name, "_test.go") {
|
|
||||||
includesNonTest = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if dirsRun && filesRun {
|
if doPackage(files, nil) == nil {
|
||||||
return nil, fmt.Errorf("can't mix dirs and files")
|
|
||||||
}
|
|
||||||
if dirsRun {
|
|
||||||
for _, name := range paths {
|
|
||||||
doPackageDir(name)
|
|
||||||
}
|
|
||||||
return foundIssues, nil
|
|
||||||
}
|
|
||||||
if doPackage(paths, nil) == nil {
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
vendor/github.com/kisielk/errcheck/internal/errcheck/errcheck.go
generated
vendored
18
vendor/github.com/kisielk/errcheck/internal/errcheck/errcheck.go
generated
vendored
@ -226,6 +226,18 @@ type visitor struct {
|
|||||||
errors []UncheckedError
|
errors []UncheckedError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSelName(sel *ast.SelectorExpr) string {
|
||||||
|
if ident, ok := sel.X.(*ast.Ident); ok {
|
||||||
|
return fmt.Sprintf("%s.%s", ident.Name, sel.Sel.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s, ok := sel.X.(*ast.SelectorExpr); ok {
|
||||||
|
return fmt.Sprintf("%s.%s", getSelName(s), sel.Sel.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (v *visitor) fullName(call *ast.CallExpr) (string, bool) {
|
func (v *visitor) fullName(call *ast.CallExpr) (string, bool) {
|
||||||
if ident, ok := call.Fun.(*ast.Ident); ok {
|
if ident, ok := call.Fun.(*ast.Ident); ok {
|
||||||
return ident.Name, true
|
return ident.Name, true
|
||||||
@ -235,6 +247,12 @@ func (v *visitor) fullName(call *ast.CallExpr) (string, bool) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name := getSelName(sel)
|
||||||
|
if name != "" {
|
||||||
|
return name, true
|
||||||
|
}
|
||||||
|
|
||||||
fn, ok := v.pkg.ObjectOf(sel.Sel).(*types.Func)
|
fn, ok := v.pkg.ObjectOf(sel.Sel).(*types.Func)
|
||||||
if !ok {
|
if !ok {
|
||||||
// Shouldn't happen, but be paranoid
|
// Shouldn't happen, but be paranoid
|
||||||
|
Loading…
x
Reference in New Issue
Block a user