Isaev Denis 95ec0cf21e
dramatically reduce memory usage ()
Run all linters per package. It allows unloading package data when it's
processed. It dramatically reduces memory (and CPU because of GC) usage.

Relates: 
2019-09-30 16:19:41 +03:00

86 lines
2.5 KiB
Go

package golinters
import (
"go/token"
"sync"
"github.com/pkg/errors"
"golang.org/x/tools/go/analysis"
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
"github.com/golangci/golangci-lint/pkg/lint/linter"
"github.com/golangci/golangci-lint/pkg/result"
"github.com/ultraware/whitespace"
)
func NewWhitespace() *goanalysis.Linter {
const linterName = "whitespace"
var mu sync.Mutex
var resIssues []result.Issue
analyzer := &analysis.Analyzer{
Name: goanalysis.TheOnlyAnalyzerName,
Doc: goanalysis.TheOnlyanalyzerDoc,
}
return goanalysis.NewLinter(
linterName,
"Tool for detection of leading and trailing whitespace",
[]*analysis.Analyzer{analyzer},
nil,
).WithContextSetter(func(lintCtx *linter.Context) {
settings := whitespace.Settings{MultiIf: lintCtx.Cfg.LintersSettings.Whitespace.MultiIf}
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
var issues []whitespace.Message
for _, file := range pass.Files {
issues = append(issues, whitespace.Run(file, pass.Fset, settings)...)
}
if len(issues) == 0 {
return nil, nil
}
res := make([]result.Issue, len(issues))
for k, i := range issues {
issue := result.Issue{
Pos: token.Position{
Filename: i.Pos.Filename,
Line: i.Pos.Line,
},
LineRange: &result.Range{From: i.Pos.Line, To: i.Pos.Line},
Text: i.Message,
FromLinter: linterName,
Replacement: &result.Replacement{},
}
bracketLine, err := lintCtx.LineCache.GetLine(issue.Pos.Filename, issue.Pos.Line)
if err != nil {
return nil, errors.Wrapf(err, "failed to get line %s:%d", issue.Pos.Filename, issue.Pos.Line)
}
switch i.Type {
case whitespace.MessageTypeLeading:
issue.LineRange.To++ // cover two lines by the issue: opening bracket "{" (issue.Pos.Line) and following empty line
case whitespace.MessageTypeTrailing:
issue.LineRange.From-- // cover two lines by the issue: closing bracket "}" (issue.Pos.Line) and preceding empty line
issue.Pos.Line-- // set in sync with LineRange.From to not break fixer and other code features
case whitespace.MessageTypeAddAfter:
bracketLine += "\n"
}
issue.Replacement.NewLines = []string{bracketLine}
res[k] = issue
}
mu.Lock()
resIssues = append(resIssues, res...)
mu.Unlock()
return nil, nil
}
}).WithIssuesReporter(func(*linter.Context) []result.Issue {
return resIssues
}).WithLoadMode(goanalysis.LoadModeSyntax)
}