Fix #96: support lll
This commit is contained in:
parent
7b2a63dfa6
commit
1a9af12d6d
@ -104,6 +104,9 @@ linters-settings:
|
|||||||
# Default is to use a neutral variety of English.
|
# Default is to use a neutral variety of English.
|
||||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||||
locale: US
|
locale: US
|
||||||
|
lll:
|
||||||
|
# max line length, lines longer will be reported. Default is 120. '\t' is counted as 1 character.
|
||||||
|
line-length: 120
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
|
@ -114,6 +114,7 @@ maligned: Tool to detect Go structs that would take less memory if their fields
|
|||||||
megacheck: 3 sub-linters in one: unused, gosimple and staticcheck [fast: false]
|
megacheck: 3 sub-linters in one: unused, gosimple and staticcheck [fast: false]
|
||||||
depguard: Go linter that checks if package imports are in a list of acceptable packages [fast: false]
|
depguard: Go linter that checks if package imports are in a list of acceptable packages [fast: false]
|
||||||
misspell: Finds commonly misspelled English words in comments [fast: true]
|
misspell: Finds commonly misspelled English words in comments [fast: true]
|
||||||
|
lll: Reports long lines [fast: true]
|
||||||
```
|
```
|
||||||
|
|
||||||
Pass `-E/--enable` to enable linter and `-D/--disable` to disable:
|
Pass `-E/--enable` to enable linter and `-D/--disable` to disable:
|
||||||
@ -220,6 +221,7 @@ golangci-lint linters
|
|||||||
- [megacheck](https://github.com/dominikh/go-tools/tree/master/cmd/megacheck) - 3 sub-linters in one: unused, gosimple and staticcheck
|
- [megacheck](https://github.com/dominikh/go-tools/tree/master/cmd/megacheck) - 3 sub-linters in one: unused, gosimple and staticcheck
|
||||||
- [depguard](https://github.com/OpenPeeDeeP/depguard) - Go linter that checks if package imports are in a list of acceptable packages
|
- [depguard](https://github.com/OpenPeeDeeP/depguard) - Go linter that checks if package imports are in a list of acceptable packages
|
||||||
- [misspell](https://github.com/client9/misspell) - Finds commonly misspelled English words in comments
|
- [misspell](https://github.com/client9/misspell) - Finds commonly misspelled English words in comments
|
||||||
|
- [lll](https://github.com/walle/lll) - Reports long lines
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
The config file has lower priority than command-line options. If the same bool/string/int option is provided on the command-line
|
The config file has lower priority than command-line options. If the same bool/string/int option is provided on the command-line
|
||||||
@ -422,6 +424,9 @@ linters-settings:
|
|||||||
# Default is to use a neutral variety of English.
|
# Default is to use a neutral variety of English.
|
||||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||||
locale: US
|
locale: US
|
||||||
|
lll:
|
||||||
|
# max line length, lines longer will be reported. Default is 120. '\t' is counted as 1 character.
|
||||||
|
line-length: 120
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
@ -601,6 +606,7 @@ Thanks to developers and authors of used linters:
|
|||||||
- [alecthomas](https://github.com/alecthomas)
|
- [alecthomas](https://github.com/alecthomas)
|
||||||
- [OpenPeeDeeP](https://github.com/OpenPeeDeeP)
|
- [OpenPeeDeeP](https://github.com/OpenPeeDeeP)
|
||||||
- [client9](https://github.com/client9)
|
- [client9](https://github.com/client9)
|
||||||
|
- [walle](https://github.com/walle)
|
||||||
|
|
||||||
# Future Plans
|
# Future Plans
|
||||||
1. Upstream all changes of forked linters.
|
1. Upstream all changes of forked linters.
|
||||||
|
@ -23,7 +23,7 @@ type Executor struct {
|
|||||||
|
|
||||||
func NewExecutor(version, commit, date string) *Executor {
|
func NewExecutor(version, commit, date string) *Executor {
|
||||||
e := &Executor{
|
e := &Executor{
|
||||||
cfg: &config.Config{},
|
cfg: config.NewDefault(),
|
||||||
version: version,
|
version: version,
|
||||||
commit: commit,
|
commit: commit,
|
||||||
date: date,
|
date: date,
|
||||||
|
@ -32,7 +32,8 @@ func getDefaultExcludeHelp() string {
|
|||||||
return strings.Join(parts, "\n")
|
return strings.Join(parts, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
const welcomeMessage = "Run this tool in cloud on every github pull request in https://golangci.com for free (public repos)"
|
const welcomeMessage = "Run this tool in cloud on every github pull " +
|
||||||
|
"request in https://golangci.com for free (public repos)"
|
||||||
|
|
||||||
func wh(text string) string {
|
func wh(text string) string {
|
||||||
return color.GreenString(text)
|
return color.GreenString(text)
|
||||||
@ -62,7 +63,8 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) {
|
|||||||
fs.StringSliceVar(&rc.BuildTags, "build-tags", nil, wh("Build tags"))
|
fs.StringSliceVar(&rc.BuildTags, "build-tags", nil, wh("Build tags"))
|
||||||
fs.DurationVar(&rc.Deadline, "deadline", time.Minute, wh("Deadline for total work"))
|
fs.DurationVar(&rc.Deadline, "deadline", time.Minute, wh("Deadline for total work"))
|
||||||
fs.BoolVar(&rc.AnalyzeTests, "tests", true, wh("Analyze tests (*_test.go)"))
|
fs.BoolVar(&rc.AnalyzeTests, "tests", true, wh("Analyze tests (*_test.go)"))
|
||||||
fs.BoolVar(&rc.PrintResourcesUsage, "print-resources-usage", false, wh("Print avg and max memory usage of golangci-lint and total time"))
|
fs.BoolVar(&rc.PrintResourcesUsage, "print-resources-usage", false,
|
||||||
|
wh("Print avg and max memory usage of golangci-lint and total time"))
|
||||||
fs.StringVarP(&rc.Config, "config", "c", "", wh("Read config from file path `PATH`"))
|
fs.StringVarP(&rc.Config, "config", "c", "", wh("Read config from file path `PATH`"))
|
||||||
fs.BoolVar(&rc.NoConfig, "no-config", false, wh("Don't read config"))
|
fs.BoolVar(&rc.NoConfig, "no-config", false, wh("Don't read config"))
|
||||||
fs.StringSliceVar(&rc.SkipDirs, "skip-dirs", nil, wh("Regexps of directories to skip"))
|
fs.StringSliceVar(&rc.SkipDirs, "skip-dirs", nil, wh("Regexps of directories to skip"))
|
||||||
@ -75,16 +77,20 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) {
|
|||||||
// but when number of linters started to grow it became ovious that
|
// but when number of linters started to grow it became ovious that
|
||||||
// we can't fill 90% of flags by linters settings: common flags became hard to find.
|
// we can't fill 90% of flags by linters settings: common flags became hard to find.
|
||||||
// New linters settings should be done only through config file.
|
// New linters settings should be done only through config file.
|
||||||
fs.BoolVar(&lsc.Errcheck.CheckTypeAssertions, "errcheck.check-type-assertions", false, "Errcheck: check for ignored type assertion results")
|
fs.BoolVar(&lsc.Errcheck.CheckTypeAssertions, "errcheck.check-type-assertions",
|
||||||
|
false, "Errcheck: check for ignored type assertion results")
|
||||||
hideFlag("errcheck.check-type-assertions")
|
hideFlag("errcheck.check-type-assertions")
|
||||||
|
|
||||||
fs.BoolVar(&lsc.Errcheck.CheckAssignToBlank, "errcheck.check-blank", false, "Errcheck: check for errors assigned to blank identifier: _ = errFunc()")
|
fs.BoolVar(&lsc.Errcheck.CheckAssignToBlank, "errcheck.check-blank", false,
|
||||||
|
"Errcheck: check for errors assigned to blank identifier: _ = errFunc()")
|
||||||
hideFlag("errcheck.check-blank")
|
hideFlag("errcheck.check-blank")
|
||||||
|
|
||||||
fs.BoolVar(&lsc.Govet.CheckShadowing, "govet.check-shadowing", false, "Govet: check for shadowed variables")
|
fs.BoolVar(&lsc.Govet.CheckShadowing, "govet.check-shadowing", false,
|
||||||
|
"Govet: check for shadowed variables")
|
||||||
hideFlag("govet.check-shadowing")
|
hideFlag("govet.check-shadowing")
|
||||||
|
|
||||||
fs.Float64Var(&lsc.Golint.MinConfidence, "golint.min-confidence", 0.8, "Golint: minimum confidence of a problem to print it")
|
fs.Float64Var(&lsc.Golint.MinConfidence, "golint.min-confidence", 0.8,
|
||||||
|
"Golint: minimum confidence of a problem to print it")
|
||||||
hideFlag("golint.min-confidence")
|
hideFlag("golint.min-confidence")
|
||||||
|
|
||||||
fs.BoolVar(&lsc.Gofmt.Simplify, "gofmt.simplify", true, "Gofmt: simplify code")
|
fs.BoolVar(&lsc.Gofmt.Simplify, "gofmt.simplify", true, "Gofmt: simplify code")
|
||||||
@ -94,7 +100,8 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) {
|
|||||||
30, "Minimal complexity of function to report it")
|
30, "Minimal complexity of function to report it")
|
||||||
hideFlag("gocyclo.min-complexity")
|
hideFlag("gocyclo.min-complexity")
|
||||||
|
|
||||||
fs.BoolVar(&lsc.Maligned.SuggestNewOrder, "maligned.suggest-new", false, "Maligned: print suggested more optimal struct fields ordering")
|
fs.BoolVar(&lsc.Maligned.SuggestNewOrder, "maligned.suggest-new", false,
|
||||||
|
"Maligned: print suggested more optimal struct fields ordering")
|
||||||
hideFlag("maligned.suggest-new")
|
hideFlag("maligned.suggest-new")
|
||||||
|
|
||||||
fs.IntVar(&lsc.Dupl.Threshold, "dupl.threshold",
|
fs.IntVar(&lsc.Dupl.Threshold, "dupl.threshold",
|
||||||
@ -124,7 +131,8 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) {
|
|||||||
fs.BoolVar(&lc.EnableAll, "enable-all", false, wh("Enable all linters"))
|
fs.BoolVar(&lc.EnableAll, "enable-all", false, wh("Enable all linters"))
|
||||||
fs.BoolVar(&lc.DisableAll, "disable-all", false, wh("Disable all linters"))
|
fs.BoolVar(&lc.DisableAll, "disable-all", false, wh("Disable all linters"))
|
||||||
fs.StringSliceVarP(&lc.Presets, "presets", "p", nil,
|
fs.StringSliceVarP(&lc.Presets, "presets", "p", nil,
|
||||||
wh(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint linters' to see them. This option implies option --disable-all", strings.Join(lintersdb.AllPresets(), "|"))))
|
wh(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint linters' to see "+
|
||||||
|
"them. This option implies option --disable-all", strings.Join(lintersdb.AllPresets(), "|"))))
|
||||||
fs.BoolVar(&lc.Fast, "fast", false, wh("Run only fast linters from enabled linters set"))
|
fs.BoolVar(&lc.Fast, "fast", false, wh("Run only fast linters from enabled linters set"))
|
||||||
|
|
||||||
// Issues config
|
// Issues config
|
||||||
@ -132,13 +140,20 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) {
|
|||||||
fs.StringSliceVarP(&ic.ExcludePatterns, "exclude", "e", nil, wh("Exclude issue by regexp"))
|
fs.StringSliceVarP(&ic.ExcludePatterns, "exclude", "e", nil, wh("Exclude issue by regexp"))
|
||||||
fs.BoolVar(&ic.UseDefaultExcludes, "exclude-use-default", true, getDefaultExcludeHelp())
|
fs.BoolVar(&ic.UseDefaultExcludes, "exclude-use-default", true, getDefaultExcludeHelp())
|
||||||
|
|
||||||
fs.IntVar(&ic.MaxIssuesPerLinter, "max-issues-per-linter", 50, wh("Maximum issues count per one linter. Set to 0 to disable"))
|
fs.IntVar(&ic.MaxIssuesPerLinter, "max-issues-per-linter", 50,
|
||||||
fs.IntVar(&ic.MaxSameIssues, "max-same-issues", 3, wh("Maximum count of issues with the same text. Set to 0 to disable"))
|
wh("Maximum issues count per one linter. Set to 0 to disable"))
|
||||||
|
fs.IntVar(&ic.MaxSameIssues, "max-same-issues", 3,
|
||||||
|
wh("Maximum count of issues with the same text. Set to 0 to disable"))
|
||||||
|
|
||||||
fs.BoolVarP(&ic.Diff, "new", "n", false,
|
fs.BoolVarP(&ic.Diff, "new", "n", false,
|
||||||
wh("Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.\nIt's a super-useful option for integration of golangci-lint into existing large codebase.\nIt's not practical to fix all existing issues at the moment of integration: much better don't allow issues in new code"))
|
wh("Show only new issues: if there are unstaged changes or untracked files, only those changes "+
|
||||||
fs.StringVar(&ic.DiffFromRevision, "new-from-rev", "", wh("Show only new issues created after git revision `REV`"))
|
"are analyzed, else only changes in HEAD~ are analyzed.\nIt's a super-useful option for integration "+
|
||||||
fs.StringVar(&ic.DiffPatchFilePath, "new-from-patch", "", wh("Show only new issues created in git patch with file path `PATH`"))
|
"of golangci-lint into existing large codebase.\nIt's not practical to fix all existing issues at "+
|
||||||
|
"the moment of integration: much better don't allow issues in new code"))
|
||||||
|
fs.StringVar(&ic.DiffFromRevision, "new-from-rev", "",
|
||||||
|
wh("Show only new issues created after git revision `REV`"))
|
||||||
|
fs.StringVar(&ic.DiffPatchFilePath, "new-from-patch", "",
|
||||||
|
wh("Show only new issues created in git patch with file path `PATH`"))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,12 +30,14 @@ type ExcludePattern struct {
|
|||||||
|
|
||||||
var DefaultExcludePatterns = []ExcludePattern{
|
var DefaultExcludePatterns = []ExcludePattern{
|
||||||
{
|
{
|
||||||
Pattern: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?|.*printf?|os\\.(Un)?Setenv). is not checked",
|
Pattern: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close" +
|
||||||
|
"|.*Flush|os\\.Remove(All)?|.*printf?|os\\.(Un)?Setenv). is not checked",
|
||||||
Linter: "errcheck",
|
Linter: "errcheck",
|
||||||
Why: "Almost all programs ignore errors on these functions and in most cases it's ok",
|
Why: "Almost all programs ignore errors on these functions and in most cases it's ok",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pattern: "(comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)",
|
Pattern: "(comment on exported (method|function|type|const)|" +
|
||||||
|
"should have( a package)? comment|comment should be of the form)",
|
||||||
Linter: "golint",
|
Linter: "golint",
|
||||||
Why: "Annoying issue about not having a comment. The rare codebase has such comments",
|
Why: "Annoying issue about not having a comment. The rare codebase has such comments",
|
||||||
},
|
},
|
||||||
@ -156,6 +158,17 @@ type LintersSettings struct {
|
|||||||
Misspell struct {
|
Misspell struct {
|
||||||
Locale string
|
Locale string
|
||||||
}
|
}
|
||||||
|
Lll LllSettings
|
||||||
|
}
|
||||||
|
|
||||||
|
type LllSettings struct {
|
||||||
|
LineLength int `mapstructure:"line-length"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultLintersSettings = LintersSettings{
|
||||||
|
Lll: LllSettings{
|
||||||
|
LineLength: 120,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
type Linters struct {
|
type Linters struct {
|
||||||
@ -196,3 +209,9 @@ type Config struct { //nolint:maligned
|
|||||||
|
|
||||||
InternalTest bool // Option is used only for testing golangci-lint code, don't use it
|
InternalTest bool // Option is used only for testing golangci-lint code, don't use it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewDefault() *Config {
|
||||||
|
return &Config{
|
||||||
|
LintersSettings: defaultLintersSettings,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -16,7 +16,8 @@ func (Errcheck) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (Errcheck) Desc() string {
|
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"
|
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 *linter.Context) ([]result.Issue, error) {
|
func (e Errcheck) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) {
|
||||||
|
@ -31,7 +31,8 @@ func (g Gofmt) Desc() string {
|
|||||||
return "Goimports does everything that gofmt does. Additionally it checks unused imports"
|
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"
|
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) {
|
||||||
|
@ -25,7 +25,8 @@ func (Govet) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (Govet) Desc() string {
|
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"
|
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 *linter.Context) ([]result.Issue, error) {
|
func (g Govet) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) {
|
||||||
|
72
pkg/golinters/lll.go
Normal file
72
pkg/golinters/lll.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package golinters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"go/token"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/golangci/golangci-lint/pkg/lint/linter"
|
||||||
|
"github.com/golangci/golangci-lint/pkg/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Lll struct{}
|
||||||
|
|
||||||
|
func (Lll) Name() string {
|
||||||
|
return "lll"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Lll) Desc() string {
|
||||||
|
return "Reports long lines"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lint Lll) getIssuesForFile(filename string, maxLineLen int) ([]result.Issue, error) {
|
||||||
|
var res []result.Issue
|
||||||
|
|
||||||
|
f, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't open file %s: %s", filename, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
lineNumber := 1
|
||||||
|
scanner := bufio.NewScanner(f)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
line = strings.Replace(line, "\t", " ", -1)
|
||||||
|
lineLen := utf8.RuneCountInString(line)
|
||||||
|
if lineLen > maxLineLen {
|
||||||
|
res = append(res, result.Issue{
|
||||||
|
Pos: token.Position{
|
||||||
|
Filename: filename,
|
||||||
|
Line: lineNumber,
|
||||||
|
Column: 1,
|
||||||
|
},
|
||||||
|
Text: fmt.Sprintf("line is %d characters", lineLen),
|
||||||
|
FromLinter: lint.Name(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
lineNumber++
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return nil, fmt.Errorf("can't scan file %s: %s", filename, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lint Lll) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) {
|
||||||
|
var res []result.Issue
|
||||||
|
for _, f := range lintCtx.PkgProgram.Files(lintCtx.Cfg.Run.AnalyzeTests) {
|
||||||
|
issues, err := lint.getIssuesForFile(f, lintCtx.Settings().Lll.LineLength)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res = append(res, issues...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
@ -14,7 +14,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func AllPresets() []string {
|
func AllPresets() []string {
|
||||||
return []string{linter.PresetBugs, linter.PresetUnused, linter.PresetFormatting, linter.PresetStyle, linter.PresetComplexity, linter.PresetPerformance}
|
return []string{linter.PresetBugs, linter.PresetUnused, linter.PresetFormatting,
|
||||||
|
linter.PresetStyle, linter.PresetComplexity, linter.PresetPerformance}
|
||||||
}
|
}
|
||||||
|
|
||||||
func allPresetsSet() map[string]bool {
|
func allPresetsSet() map[string]bool {
|
||||||
@ -166,6 +167,10 @@ func GetAllSupportedLinterConfigs() []linter.Config {
|
|||||||
WithPresets(linter.PresetStyle).
|
WithPresets(linter.PresetStyle).
|
||||||
WithSpeed(7).
|
WithSpeed(7).
|
||||||
WithURL("https://github.com/client9/misspell"),
|
WithURL("https://github.com/client9/misspell"),
|
||||||
|
linter.NewConfig(golinters.Lll{}).
|
||||||
|
WithPresets(linter.PresetStyle).
|
||||||
|
WithSpeed(10).
|
||||||
|
WithURL("https://github.com/walle/lll"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.Getenv("GOLANGCI_COM_RUN") == "1" {
|
if os.Getenv("GOLANGCI_COM_RUN") == "1" {
|
||||||
@ -175,6 +180,7 @@ func GetAllSupportedLinterConfigs() []linter.Config {
|
|||||||
golinters.Maligned{}.Name(): true, // rarely usable
|
golinters.Maligned{}.Name(): true, // rarely usable
|
||||||
golinters.TypeCheck{}.Name(): true, // annoying because of different building envs
|
golinters.TypeCheck{}.Name(): true, // annoying because of different building envs
|
||||||
golinters.Misspell{}.Name(): true, // unsure about false-positives number
|
golinters.Misspell{}.Name(): true, // unsure about false-positives number
|
||||||
|
golinters.Lll{}.Name(): true, // annoying
|
||||||
}
|
}
|
||||||
return enableLinterConfigs(lcs, func(lc *linter.Config) bool {
|
return enableLinterConfigs(lcs, func(lc *linter.Config) bool {
|
||||||
return !disabled[lc.Linter.Name()]
|
return !disabled[lc.Linter.Name()]
|
||||||
@ -314,7 +320,10 @@ func GetAllLinterConfigsForPreset(p string) []linter.Config {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEnabledLintersSet(lcfg *config.Linters, enabledByDefaultLinters []linter.Config) map[string]*linter.Config { // nolint:gocyclo
|
// nolint:gocyclo
|
||||||
|
func getEnabledLintersSet(lcfg *config.Linters,
|
||||||
|
enabledByDefaultLinters []linter.Config) map[string]*linter.Config {
|
||||||
|
|
||||||
resultLintersSet := map[string]*linter.Config{}
|
resultLintersSet := map[string]*linter.Config{}
|
||||||
switch {
|
switch {
|
||||||
case len(lcfg.Presets) != 0:
|
case len(lcfg.Presets) != 0:
|
||||||
|
@ -109,7 +109,9 @@ func isLocalProjectAnalysis(args []string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTypeCheckFuncBodies(cfg *config.Run, linters []linter.Config, pkgProg *packages.Program, log logutils.Log) func(string) bool {
|
func getTypeCheckFuncBodies(cfg *config.Run, linters []linter.Config,
|
||||||
|
pkgProg *packages.Program, log logutils.Log) func(string) bool {
|
||||||
|
|
||||||
if !isLocalProjectAnalysis(cfg.Args) {
|
if !isLocalProjectAnalysis(cfg.Args) {
|
||||||
loadDebugf("analysis in nonlocal, don't optimize loading by not typechecking func bodies")
|
loadDebugf("analysis in nonlocal, don't optimize loading by not typechecking func bodies")
|
||||||
return nil
|
return nil
|
||||||
@ -155,7 +157,9 @@ func getTypeCheckFuncBodies(cfg *config.Run, linters []linter.Config, pkgProg *p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadWholeAppIfNeeded(ctx context.Context, linters []linter.Config, cfg *config.Config, pkgProg *packages.Program, log logutils.Log) (*loader.Program, *loader.Config, error) {
|
func loadWholeAppIfNeeded(ctx context.Context, linters []linter.Config, cfg *config.Config,
|
||||||
|
pkgProg *packages.Program, log logutils.Log) (*loader.Program, *loader.Config, error) {
|
||||||
|
|
||||||
if !isFullImportNeeded(linters, cfg) {
|
if !isFullImportNeeded(linters, cfg) {
|
||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
@ -255,7 +259,9 @@ func separateNotCompilingPackages(lintCtx *linter.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
func LoadContext(ctx context.Context, linters []linter.Config, cfg *config.Config, log logutils.Log) (*linter.Context, error) {
|
func LoadContext(ctx context.Context, linters []linter.Config, cfg *config.Config,
|
||||||
|
log logutils.Log) (*linter.Context, error) {
|
||||||
|
|
||||||
// Set GOROOT to have working cross-compilation: cross-compiled binaries
|
// Set GOROOT to have working cross-compilation: cross-compiled binaries
|
||||||
// have invalid GOROOT. XXX: can't use runtime.GOROOT().
|
// have invalid GOROOT. XXX: can't use runtime.GOROOT().
|
||||||
goroot, err := goutils.DiscoverGoRoot()
|
goroot, err := goutils.DiscoverGoRoot()
|
||||||
|
@ -66,7 +66,9 @@ type lintRes struct {
|
|||||||
issues []result.Issue
|
issues []result.Issue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context, lc linter.Config) (ret []result.Issue, err error) {
|
func (r Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context,
|
||||||
|
lc linter.Config) (ret []result.Issue, err error) {
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if panicData := recover(); panicData != nil {
|
if panicData := recover(); panicData != nil {
|
||||||
err = fmt.Errorf("panic occurred: %s", panicData)
|
err = fmt.Errorf("panic occurred: %s", panicData)
|
||||||
@ -88,7 +90,9 @@ func (r Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context, lc l
|
|||||||
return issues, nil
|
return issues, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Runner) runWorker(ctx context.Context, lintCtx *linter.Context, tasksCh <-chan linter.Config, lintResultsCh chan<- lintRes, name string) {
|
func (r Runner) runWorker(ctx context.Context, lintCtx *linter.Context,
|
||||||
|
tasksCh <-chan linter.Config, lintResultsCh chan<- lintRes, name string) {
|
||||||
|
|
||||||
sw := timeutils.NewStopwatch(name, r.Log)
|
sw := timeutils.NewStopwatch(name, r.Log)
|
||||||
defer sw.Print()
|
defer sw.Print()
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
@ -140,18 +139,15 @@ func (p Text) printUnderLinePointer(i *result.Issue, line string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var j int
|
col0 := i.Pos.Column - 1
|
||||||
for ; j < len(line) && line[j] == '\t'; j++ {
|
prefixRunes := make([]rune, 0, len(line))
|
||||||
|
for j := 0; j < len(line) && j < col0; j++ {
|
||||||
|
if line[j] == '\t' {
|
||||||
|
prefixRunes = append(prefixRunes, '\t')
|
||||||
|
} else {
|
||||||
|
prefixRunes = append(prefixRunes, ' ')
|
||||||
}
|
}
|
||||||
tabsCount := j
|
|
||||||
spacesCount := i.Pos.Column - 1 - tabsCount
|
|
||||||
prefix := ""
|
|
||||||
if tabsCount != 0 {
|
|
||||||
prefix += strings.Repeat("\t", tabsCount)
|
|
||||||
}
|
|
||||||
if spacesCount != 0 {
|
|
||||||
prefix += strings.Repeat(" ", spacesCount)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(logutils.StdOut, "%s%s\n", prefix, p.SprintfColored(color.FgYellow, "^"))
|
fmt.Fprintf(logutils.StdOut, "%s%s\n", string(prefixRunes), p.SprintfColored(color.FgYellow, "^"))
|
||||||
}
|
}
|
||||||
|
@ -103,10 +103,12 @@ func getDoc(f *ast.File, fset *token.FileSet, filePath string) string {
|
|||||||
var importPos token.Pos
|
var importPos token.Pos
|
||||||
if len(f.Imports) != 0 {
|
if len(f.Imports) != 0 {
|
||||||
importPos = f.Imports[0].Pos()
|
importPos = f.Imports[0].Pos()
|
||||||
autogenDebugf("file %q: search comments until first import pos %d (%s)", filePath, importPos, fset.Position(importPos))
|
autogenDebugf("file %q: search comments until first import pos %d (%s)",
|
||||||
|
filePath, importPos, fset.Position(importPos))
|
||||||
} else {
|
} else {
|
||||||
importPos = f.End()
|
importPos = f.End()
|
||||||
autogenDebugf("file %q: search comments until EOF pos %d (%s)", filePath, importPos, fset.Position(importPos))
|
autogenDebugf("file %q: search comments until EOF pos %d (%s)",
|
||||||
|
filePath, importPos, fset.Position(importPos))
|
||||||
}
|
}
|
||||||
|
|
||||||
var neededComments []string
|
var neededComments []string
|
||||||
|
@ -39,7 +39,8 @@ func TestIsAutogeneratedDetection(t *testing.T) {
|
|||||||
// DO NOT EDIT ** This file was generated with the bake tool ** DO NOT EDIT //
|
// DO NOT EDIT ** This file was generated with the bake tool ** DO NOT EDIT //
|
||||||
|
|
||||||
// Generated by running
|
// Generated by running
|
||||||
// maketables --tables=all --data=http://www.unicode.org/Public/8.0.0/ucd/UnicodeData.txt --casefolding=http://www.unicode.org/Public/8.0.0/ucd/CaseFolding.txt
|
// maketables --tables=all --data=http://www.unicode.org/Public/8.0.0/ucd/UnicodeData.txt
|
||||||
|
// --casefolding=http://www.unicode.org/Public/8.0.0/ucd/CaseFolding.txt
|
||||||
// DO NOT EDIT
|
// DO NOT EDIT
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
6
test/testdata/lll.go
vendored
Normal file
6
test/testdata/lll.go
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// args: -Elll
|
||||||
|
package testdata
|
||||||
|
|
||||||
|
func Lll() {
|
||||||
|
// In my experience, long lines are the lines with comments, not the code. So this is a long comment // ERROR "line is 135 characters"
|
||||||
|
}
|
19
third_party/lll/LICENSE
vendored
Normal file
19
third_party/lll/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2016 Fredrik Wallgren
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
Loading…
x
Reference in New Issue
Block a user