dev: clean context loader (#4480)
This commit is contained in:
parent
1aa28ec6a4
commit
6fda81008d
@ -363,19 +363,18 @@ func (c *runCommand) runAnalysis(ctx context.Context, args []string) ([]result.I
|
|||||||
c.reportData.AddLinter(lc.Name(), isEnabled, lc.EnabledByDefault)
|
c.reportData.AddLinter(lc.Name(), isEnabled, lc.EnabledByDefault)
|
||||||
}
|
}
|
||||||
|
|
||||||
lintCtx, err := c.contextLoader.Load(ctx, lintersToRun)
|
lintCtx, err := c.contextLoader.Load(ctx, c.log.Child(logutils.DebugKeyLintersContext), lintersToRun)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("context loading failed: %w", err)
|
return nil, fmt.Errorf("context loading failed: %w", err)
|
||||||
}
|
}
|
||||||
lintCtx.Log = c.log.Child(logutils.DebugKeyLintersContext)
|
|
||||||
|
|
||||||
runner, err := lint.NewRunner(c.log.Child(logutils.DebugKeyRunner),
|
runner, err := lint.NewRunner(c.log.Child(logutils.DebugKeyRunner),
|
||||||
c.cfg, c.goenv, c.lineCache, c.fileCache, c.dbManager, lintCtx.Packages)
|
c.cfg, c.goenv, c.lineCache, c.fileCache, c.dbManager, lintCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return runner.Run(ctx, lintersToRun, lintCtx)
|
return runner.Run(ctx, lintersToRun)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *runCommand) setOutputToDevNull() (savedStdout, savedStderr *os.File) {
|
func (c *runCommand) setOutputToDevNull() (savedStdout, savedStderr *os.File) {
|
||||||
|
@ -50,6 +50,37 @@ func NewContextLoader(cfg *config.Config, log logutils.Log, goenv *goutil.Env,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cl *ContextLoader) Load(ctx context.Context, log logutils.Log, linters []*linter.Config) (*linter.Context, error) {
|
||||||
|
loadMode := cl.findLoadMode(linters)
|
||||||
|
pkgs, err := cl.loadPackages(ctx, loadMode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to load packages: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
deduplicatedPkgs := cl.filterDuplicatePackages(pkgs)
|
||||||
|
|
||||||
|
if len(deduplicatedPkgs) == 0 {
|
||||||
|
return nil, exitcodes.ErrNoGoFiles
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := &linter.Context{
|
||||||
|
Packages: deduplicatedPkgs,
|
||||||
|
|
||||||
|
// At least `unused` linters works properly only on original (not deduplicated) packages,
|
||||||
|
// see https://github.com/golangci/golangci-lint/pull/585.
|
||||||
|
OriginalPackages: pkgs,
|
||||||
|
|
||||||
|
Cfg: cl.cfg,
|
||||||
|
Log: log,
|
||||||
|
FileCache: cl.fileCache,
|
||||||
|
LineCache: cl.lineCache,
|
||||||
|
PkgCache: cl.pkgCache,
|
||||||
|
LoadGuard: cl.loadGuard,
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (cl *ContextLoader) prepareBuildContext() {
|
func (cl *ContextLoader) prepareBuildContext() {
|
||||||
// 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().
|
||||||
@ -213,13 +244,6 @@ func (cl *ContextLoader) loadPackages(ctx context.Context, loadMode packages.Loa
|
|||||||
return nil, fmt.Errorf("failed to load with go/packages: %w", err)
|
return nil, fmt.Errorf("failed to load with go/packages: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently, go/packages doesn't guarantee that error will be returned
|
|
||||||
// if context was canceled. See
|
|
||||||
// https://github.com/golang/tools/commit/c5cec6710e927457c3c29d6c156415e8539a5111#r39261855
|
|
||||||
if ctx.Err() != nil {
|
|
||||||
return nil, fmt.Errorf("timed out to load packages: %w", ctx.Err())
|
|
||||||
}
|
|
||||||
|
|
||||||
if loadMode&packages.NeedSyntax == 0 {
|
if loadMode&packages.NeedSyntax == 0 {
|
||||||
// Needed e.g. for go/analysis loading.
|
// Needed e.g. for go/analysis loading.
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
@ -293,34 +317,3 @@ func (cl *ContextLoader) filterDuplicatePackages(pkgs []*packages.Package) []*pa
|
|||||||
|
|
||||||
return retPkgs
|
return retPkgs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cl *ContextLoader) Load(ctx context.Context, linters []*linter.Config) (*linter.Context, error) {
|
|
||||||
loadMode := cl.findLoadMode(linters)
|
|
||||||
pkgs, err := cl.loadPackages(ctx, loadMode)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to load packages: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
deduplicatedPkgs := cl.filterDuplicatePackages(pkgs)
|
|
||||||
|
|
||||||
if len(deduplicatedPkgs) == 0 {
|
|
||||||
return nil, exitcodes.ErrNoGoFiles
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := &linter.Context{
|
|
||||||
Packages: deduplicatedPkgs,
|
|
||||||
|
|
||||||
// At least `unused` linters works properly only on original (not deduplicated) packages,
|
|
||||||
// see https://github.com/golangci/golangci-lint/pull/585.
|
|
||||||
OriginalPackages: pkgs,
|
|
||||||
|
|
||||||
Cfg: cl.cfg,
|
|
||||||
Log: cl.log,
|
|
||||||
FileCache: cl.fileCache,
|
|
||||||
LineCache: cl.lineCache,
|
|
||||||
PkgCache: cl.pkgCache,
|
|
||||||
LoadGuard: cl.loadGuard,
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
@ -7,8 +7,6 @@ import (
|
|||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
gopackages "golang.org/x/tools/go/packages"
|
|
||||||
|
|
||||||
"github.com/golangci/golangci-lint/internal/errorutil"
|
"github.com/golangci/golangci-lint/internal/errorutil"
|
||||||
"github.com/golangci/golangci-lint/pkg/config"
|
"github.com/golangci/golangci-lint/pkg/config"
|
||||||
"github.com/golangci/golangci-lint/pkg/fsutils"
|
"github.com/golangci/golangci-lint/pkg/fsutils"
|
||||||
@ -22,14 +20,21 @@ import (
|
|||||||
"github.com/golangci/golangci-lint/pkg/timeutils"
|
"github.com/golangci/golangci-lint/pkg/timeutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type processorStat struct {
|
||||||
|
inCount int
|
||||||
|
outCount int
|
||||||
|
}
|
||||||
|
|
||||||
type Runner struct {
|
type Runner struct {
|
||||||
Processors []processors.Processor
|
|
||||||
Log logutils.Log
|
Log logutils.Log
|
||||||
|
|
||||||
|
lintCtx *linter.Context
|
||||||
|
Processors []processors.Processor
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRunner(log logutils.Log, cfg *config.Config, goenv *goutil.Env,
|
func NewRunner(log logutils.Log, cfg *config.Config, goenv *goutil.Env,
|
||||||
lineCache *fsutils.LineCache, fileCache *fsutils.FileCache,
|
lineCache *fsutils.LineCache, fileCache *fsutils.FileCache,
|
||||||
dbManager *lintersdb.Manager, pkgs []*gopackages.Package) (*Runner, error) {
|
dbManager *lintersdb.Manager, lintCtx *linter.Context) (*Runner, error) {
|
||||||
// Beware that some processors need to add the path prefix when working with paths
|
// Beware that some processors need to add the path prefix when working with paths
|
||||||
// because they get invoked before the path prefixer (exclude and severity rules)
|
// because they get invoked before the path prefixer (exclude and severity rules)
|
||||||
// or process other paths (skip files).
|
// or process other paths (skip files).
|
||||||
@ -75,7 +80,7 @@ func NewRunner(log logutils.Log, cfg *config.Config, goenv *goutil.Env,
|
|||||||
processors.NewCgo(goenv),
|
processors.NewCgo(goenv),
|
||||||
|
|
||||||
// Must go after Cgo.
|
// Must go after Cgo.
|
||||||
processors.NewFilenameUnadjuster(pkgs, log.Child(logutils.DebugKeyFilenameUnadjuster)),
|
processors.NewFilenameUnadjuster(lintCtx.Packages, log.Child(logutils.DebugKeyFilenameUnadjuster)),
|
||||||
|
|
||||||
// Must be before diff, nolint and exclude autogenerated processor at least.
|
// Must be before diff, nolint and exclude autogenerated processor at least.
|
||||||
processors.NewPathPrettifier(),
|
processors.NewPathPrettifier(),
|
||||||
@ -107,10 +112,38 @@ func NewRunner(log logutils.Log, cfg *config.Config, goenv *goutil.Env,
|
|||||||
processors.NewPathPrefixer(cfg.Output.PathPrefix),
|
processors.NewPathPrefixer(cfg.Output.PathPrefix),
|
||||||
processors.NewSortResults(cfg),
|
processors.NewSortResults(cfg),
|
||||||
},
|
},
|
||||||
|
lintCtx: lintCtx,
|
||||||
Log: log,
|
Log: log,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Runner) Run(ctx context.Context, linters []*linter.Config) ([]result.Issue, error) {
|
||||||
|
sw := timeutils.NewStopwatch("linters", r.Log)
|
||||||
|
defer sw.Print()
|
||||||
|
|
||||||
|
var (
|
||||||
|
lintErrors error
|
||||||
|
issues []result.Issue
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, lc := range linters {
|
||||||
|
lc := lc
|
||||||
|
sw.TrackStage(lc.Name(), func() {
|
||||||
|
linterIssues, err := r.runLinterSafe(ctx, r.lintCtx, lc)
|
||||||
|
if err != nil {
|
||||||
|
lintErrors = errors.Join(lintErrors, fmt.Errorf("can't run linter %s", lc.Linter.Name()), err)
|
||||||
|
r.Log.Warnf("Can't run linter %s: %v", lc.Linter.Name(), err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
issues = append(issues, linterIssues...)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.processLintResults(issues), lintErrors
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context,
|
func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context,
|
||||||
lc *linter.Config) (ret []result.Issue, err error) {
|
lc *linter.Config) (ret []result.Issue, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -151,12 +184,7 @@ func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context,
|
|||||||
return issues, nil
|
return issues, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type processorStat struct {
|
func (r *Runner) processLintResults(inIssues []result.Issue) []result.Issue {
|
||||||
inCount int
|
|
||||||
outCount int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r Runner) processLintResults(inIssues []result.Issue) []result.Issue {
|
|
||||||
sw := timeutils.NewStopwatch("processing", r.Log)
|
sw := timeutils.NewStopwatch("processing", r.Log)
|
||||||
|
|
||||||
var issuesBefore, issuesAfter int
|
var issuesBefore, issuesAfter int
|
||||||
@ -187,7 +215,7 @@ func (r Runner) processLintResults(inIssues []result.Issue) []result.Issue {
|
|||||||
return outIssues
|
return outIssues
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Runner) printPerProcessorStat(stat map[string]processorStat) {
|
func (r *Runner) printPerProcessorStat(stat map[string]processorStat) {
|
||||||
parts := make([]string, 0, len(stat))
|
parts := make([]string, 0, len(stat))
|
||||||
for name, ps := range stat {
|
for name, ps := range stat {
|
||||||
if ps.inCount != 0 {
|
if ps.inCount != 0 {
|
||||||
@ -199,33 +227,6 @@ func (r Runner) printPerProcessorStat(stat map[string]processorStat) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Runner) Run(ctx context.Context, linters []*linter.Config, lintCtx *linter.Context) ([]result.Issue, error) {
|
|
||||||
sw := timeutils.NewStopwatch("linters", r.Log)
|
|
||||||
defer sw.Print()
|
|
||||||
|
|
||||||
var (
|
|
||||||
lintErrors error
|
|
||||||
issues []result.Issue
|
|
||||||
)
|
|
||||||
|
|
||||||
for _, lc := range linters {
|
|
||||||
lc := lc
|
|
||||||
sw.TrackStage(lc.Name(), func() {
|
|
||||||
linterIssues, err := r.runLinterSafe(ctx, lintCtx, lc)
|
|
||||||
if err != nil {
|
|
||||||
lintErrors = errors.Join(lintErrors, fmt.Errorf("can't run linter %s", lc.Linter.Name()), err)
|
|
||||||
r.Log.Warnf("Can't run linter %s: %v", lc.Linter.Name(), err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
issues = append(issues, linterIssues...)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.processLintResults(issues), lintErrors
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Runner) processIssues(issues []result.Issue, sw *timeutils.Stopwatch, statPerProcessor map[string]processorStat) []result.Issue {
|
func (r *Runner) processIssues(issues []result.Issue, sw *timeutils.Stopwatch, statPerProcessor map[string]processorStat) []result.Issue {
|
||||||
for _, p := range r.Processors {
|
for _, p := range r.Processors {
|
||||||
var newIssues []result.Issue
|
var newIssues []result.Issue
|
||||||
|
Loading…
x
Reference in New Issue
Block a user