Skip to content

dev: use slice of pointers #5854

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/src/docs/contributing/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ The abstraction is simple:

```go title=pkg/result/processors/processor.go
type Processor interface {
Process(issues []result.Issue) ([]result.Issue, error)
Process(issues []*result.Issue) ([]*result.Issue, error)
Name() string
Finish()
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/commands/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ func (c *runCommand) runAndPrint(ctx context.Context) error {
}

// runAnalysis executes the linters that have been enabled in the configuration.
func (c *runCommand) runAnalysis(ctx context.Context) ([]result.Issue, error) {
func (c *runCommand) runAnalysis(ctx context.Context) ([]*result.Issue, error) {
lintersToRun, err := c.dbManager.GetOptimizedLinters()
if err != nil {
return nil, err
Expand Down Expand Up @@ -408,7 +408,7 @@ func (c *runCommand) setOutputToDevNull() (savedStdout, savedStderr *os.File) {
return
}

func (c *runCommand) setExitCodeIfIssuesFound(issues []result.Issue) {
func (c *runCommand) setExitCodeIfIssuesFound(issues []*result.Issue) {
if len(issues) != 0 {
c.exitCode = c.cfg.Run.ExitCodeIfIssuesFound
}
Expand All @@ -433,7 +433,7 @@ func (c *runCommand) printDeprecatedLinterMessages(enabledLinters map[string]*li
}
}

func (c *runCommand) printStats(issues []result.Issue) {
func (c *runCommand) printStats(issues []*result.Issue) {
if !c.cfg.Output.ShowStats {
return
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/goanalysis/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import (
)

type Issue struct {
result.Issue
*result.Issue
Pass *analysis.Pass
}

func NewIssue(issue *result.Issue, pass *analysis.Pass) Issue {
return Issue{
Issue: *issue,
func NewIssue(issue *result.Issue, pass *analysis.Pass) *Issue {
return &Issue{
Issue: issue,
Pass: pass,
}
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/goanalysis/linter.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type Linter struct {
name, desc string
analyzers []*analysis.Analyzer
cfg map[string]map[string]any
issuesReporter func(*linter.Context) []Issue
issuesReporter func(*linter.Context) []*Issue
contextSetter func(*linter.Context)
loadMode LoadMode
needUseOriginalPackages bool
Expand All @@ -54,7 +54,7 @@ func NewLinterFromAnalyzer(analyzer *analysis.Analyzer) *Linter {
return NewLinter(analyzer.Name, analyzer.Doc, []*analysis.Analyzer{analyzer}, nil)
}

func (lnt *Linter) Run(_ context.Context, lintCtx *linter.Context) ([]result.Issue, error) {
func (lnt *Linter) Run(_ context.Context, lintCtx *linter.Context) ([]*result.Issue, error) {
if err := lnt.preRun(lintCtx); err != nil {
return nil, err
}
Expand Down Expand Up @@ -93,7 +93,7 @@ func (lnt *Linter) WithLoadMode(loadMode LoadMode) *Linter {
return lnt
}

func (lnt *Linter) WithIssuesReporter(r func(*linter.Context) []Issue) *Linter {
func (lnt *Linter) WithIssuesReporter(r func(*linter.Context) []*Issue) *Linter {
lnt.issuesReporter = r
return lnt
}
Expand Down Expand Up @@ -193,7 +193,7 @@ func (lnt *Linter) useOriginalPackages() bool {
return lnt.needUseOriginalPackages
}

func (lnt *Linter) reportIssues(lintCtx *linter.Context) []Issue {
func (lnt *Linter) reportIssues(lintCtx *linter.Context) []*Issue {
if lnt.issuesReporter != nil {
return lnt.issuesReporter(lintCtx)
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/goanalysis/metalinter.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func NewMetaLinter(linters []*Linter) *MetaLinter {
return ml
}

func (ml MetaLinter) Run(_ context.Context, lintCtx *linter.Context) ([]result.Issue, error) {
func (ml MetaLinter) Run(_ context.Context, lintCtx *linter.Context) ([]*result.Issue, error) {
for _, l := range ml.linters {
if err := l.preRun(lintCtx); err != nil {
return nil, fmt.Errorf("failed to pre-run %s: %w", l.Name(), err)
Expand Down Expand Up @@ -65,8 +65,8 @@ func (MetaLinter) useOriginalPackages() bool {
return false // `unused` can't be run by this metalinter
}

func (ml MetaLinter) reportIssues(lintCtx *linter.Context) []Issue {
var ret []Issue
func (ml MetaLinter) reportIssues(lintCtx *linter.Context) []*Issue {
var ret []*Issue
for _, lnt := range ml.linters {
if lnt.issuesReporter != nil {
ret = append(ret, lnt.issuesReporter(lintCtx)...)
Expand Down
6 changes: 3 additions & 3 deletions pkg/goanalysis/pkgerrors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ func (e *IllTypedError) Error() string {
return fmt.Sprintf("IllTypedError: errors in package: %v", e.Pkg.Errors)
}

func BuildIssuesFromIllTypedError(errs []error, lintCtx *linter.Context) ([]result.Issue, error) {
var issues []result.Issue
func BuildIssuesFromIllTypedError(errs []error, lintCtx *linter.Context) ([]*result.Issue, error) {
var issues []*result.Issue
uniqReportedIssues := map[string]bool{}

var other error
Expand All @@ -43,7 +43,7 @@ func BuildIssuesFromIllTypedError(errs []error, lintCtx *linter.Context) ([]resu
lintCtx.Log.Errorf("typechecking error: %s", err.Msg)
} else {
issue.Pkg = ill.Pkg // to save to cache later
issues = append(issues, *issue)
issues = append(issues, issue)
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/goanalysis/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func newRunner(prefix string, logger logutils.Log, pkgCache *cache.Cache, loadGu
// It provides most of the logic for the main functions of both the
// singlechecker and the multi-analysis commands.
// It returns the appropriate exit code.
func (r *runner) run(analyzers []*analysis.Analyzer, initialPackages []*packages.Package) ([]Diagnostic,
func (r *runner) run(analyzers []*analysis.Analyzer, initialPackages []*packages.Package) ([]*Diagnostic,
[]error, map[*analysis.Pass]*packages.Package,
) {
debugf("Analyzing %d packages on load mode %s", len(initialPackages), r.loadMode)
Expand Down Expand Up @@ -275,7 +275,7 @@ func (r *runner) analyze(pkgs []*packages.Package, analyzers []*analysis.Analyze
return rootActions
}

func extractDiagnostics(roots []*action) (retDiags []Diagnostic, retErrors []error) {
func extractDiagnostics(roots []*action) (retDiags []*Diagnostic, retErrors []error) {
extracted := make(map[*action]bool)
var extract func(*action)
var visitAll func(actions []*action)
Expand Down Expand Up @@ -322,7 +322,7 @@ func extractDiagnostics(roots []*action) (retDiags []Diagnostic, retErrors []err
}
seen[k] = true

retDiag := Diagnostic{
retDiag := &Diagnostic{
File: file,
Diagnostic: diag,
Analyzer: act.Analyzer,
Expand Down
35 changes: 18 additions & 17 deletions pkg/goanalysis/runners.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package goanalysis
import (
"fmt"
"go/token"
"slices"
"strings"

"golang.org/x/tools/go/analysis"
Expand All @@ -20,11 +21,11 @@ type runAnalyzersConfig interface {
getLinterNameForDiagnostic(*Diagnostic) string
getAnalyzers() []*analysis.Analyzer
useOriginalPackages() bool
reportIssues(*linter.Context) []Issue
reportIssues(*linter.Context) []*Issue
getLoadMode() LoadMode
}

func runAnalyzers(cfg runAnalyzersConfig, lintCtx *linter.Context) ([]result.Issue, error) {
func runAnalyzers(cfg runAnalyzersConfig, lintCtx *linter.Context) ([]*result.Issue, error) {
log := lintCtx.Log.Child(logutils.DebugKeyGoAnalysis)
sw := timeutils.NewStopwatch("analyzers", log)

Expand Down Expand Up @@ -56,18 +57,19 @@ func runAnalyzers(cfg runAnalyzersConfig, lintCtx *linter.Context) ([]result.Iss
}
}()

buildAllIssues := func() []result.Issue {
var retIssues []result.Issue
buildAllIssues := func() []*result.Issue {
var retIssues []*result.Issue

reportedIssues := cfg.reportIssues(lintCtx)
for i := range reportedIssues {
issue := &reportedIssues[i].Issue
if issue.Pkg == nil {
issue.Pkg = passToPkg[reportedIssues[i].Pass]
for _, reportedIssue := range reportedIssues {
if reportedIssue.Pkg == nil {
reportedIssue.Pkg = passToPkg[reportedIssue.Pass]
}
retIssues = append(retIssues, *issue)

retIssues = append(retIssues, reportedIssue.Issue)
}
retIssues = append(retIssues, buildIssues(diags, cfg.getLinterNameForDiagnostic)...)
return retIssues

return slices.Concat(retIssues, buildIssues(diags, cfg.getLinterNameForDiagnostic))
}

errIssues, err := pkgerrors.BuildIssuesFromIllTypedError(errs, lintCtx)
Expand All @@ -81,11 +83,10 @@ func runAnalyzers(cfg runAnalyzersConfig, lintCtx *linter.Context) ([]result.Iss
return issues, nil
}

func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) string) []result.Issue {
var issues []result.Issue
func buildIssues(diags []*Diagnostic, linterNameBuilder func(diag *Diagnostic) string) []*result.Issue {
var issues []*result.Issue

for i := range diags {
diag := &diags[i]
for _, diag := range diags {
linterName := linterNameBuilder(diag)

var text string
Expand Down Expand Up @@ -126,7 +127,7 @@ func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) st
suggestedFixes = append(suggestedFixes, nsf)
}

issues = append(issues, result.Issue{
issues = append(issues, &result.Issue{
FromLinter: linterName,
Text: text,
Pos: diag.Position,
Expand All @@ -142,7 +143,7 @@ func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) st
relatedPos = diag.Position
}

issues = append(issues, result.Issue{
issues = append(issues, &result.Issue{
FromLinter: linterName,
Text: fmt.Sprintf("%s(related information): %s", diag.Analyzer.Name, info.Message),
Pos: relatedPos,
Expand Down
43 changes: 20 additions & 23 deletions pkg/goanalysis/runners_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@ import (
)

func saveIssuesToCache(allPkgs []*packages.Package, pkgsFromCache map[*packages.Package]bool,
issues []result.Issue, lintCtx *linter.Context, analyzers []*analysis.Analyzer,
issues []*result.Issue, lintCtx *linter.Context, analyzers []*analysis.Analyzer,
) {
startedAt := time.Now()
perPkgIssues := map[*packages.Package][]result.Issue{}
for ind := range issues {
i := &issues[ind]
perPkgIssues[i.Pkg] = append(perPkgIssues[i.Pkg], *i)
perPkgIssues := map[*packages.Package][]*result.Issue{}
for _, issue := range issues {
perPkgIssues[issue.Pkg] = append(perPkgIssues[issue.Pkg], issue)
}

var savedIssuesCount int64 = 0
Expand All @@ -34,23 +33,22 @@ func saveIssuesToCache(allPkgs []*packages.Package, pkgsFromCache map[*packages.
wg.Add(workerCount)

pkgCh := make(chan *packages.Package, len(allPkgs))
for i := 0; i < workerCount; i++ {
for range workerCount {
go func() {
defer wg.Done()
for pkg := range pkgCh {
pkgIssues := perPkgIssues[pkg]
encodedIssues := make([]EncodingIssue, 0, len(pkgIssues))
for ind := range pkgIssues {
i := &pkgIssues[ind]
for _, issue := range pkgIssues {
encodedIssues = append(encodedIssues, EncodingIssue{
FromLinter: i.FromLinter,
Text: i.Text,
Severity: i.Severity,
Pos: i.Pos,
LineRange: i.LineRange,
SuggestedFixes: i.SuggestedFixes,
ExpectNoLint: i.ExpectNoLint,
ExpectedNoLintLinter: i.ExpectedNoLintLinter,
FromLinter: issue.FromLinter,
Text: issue.Text,
Severity: issue.Severity,
Pos: issue.Pos,
LineRange: issue.LineRange,
SuggestedFixes: issue.SuggestedFixes,
ExpectNoLint: issue.ExpectNoLint,
ExpectedNoLintLinter: issue.ExpectedNoLintLinter,
})
}

Expand Down Expand Up @@ -81,12 +79,12 @@ func saveIssuesToCache(allPkgs []*packages.Package, pkgsFromCache map[*packages.

func loadIssuesFromCache(pkgs []*packages.Package, lintCtx *linter.Context,
analyzers []*analysis.Analyzer,
) (issuesFromCache []result.Issue, pkgsFromCache map[*packages.Package]bool) {
) (issuesFromCache []*result.Issue, pkgsFromCache map[*packages.Package]bool) {
startedAt := time.Now()

lintResKey := getIssuesCacheKey(analyzers)
type cacheRes struct {
issues []result.Issue
issues []*result.Issue
loadErr error
}
pkgToCacheRes := make(map[*packages.Package]*cacheRes, len(pkgs))
Expand All @@ -103,7 +101,7 @@ func loadIssuesFromCache(pkgs []*packages.Package, lintCtx *linter.Context,
go func() {
defer wg.Done()
for pkg := range pkgCh {
var pkgIssues []EncodingIssue
var pkgIssues []*EncodingIssue
err := lintCtx.PkgCache.Get(pkg, cache.HashModeNeedAllDeps, lintResKey, &pkgIssues)
cacheRes := pkgToCacheRes[pkg]
cacheRes.loadErr = err
Expand All @@ -114,10 +112,9 @@ func loadIssuesFromCache(pkgs []*packages.Package, lintCtx *linter.Context,
continue
}

issues := make([]result.Issue, 0, len(pkgIssues))
for i := range pkgIssues {
issue := &pkgIssues[i]
issues = append(issues, result.Issue{
issues := make([]*result.Issue, 0, len(pkgIssues))
for _, issue := range pkgIssues {
issues = append(issues, &result.Issue{
FromLinter: issue.FromLinter,
Text: issue.Text,
Severity: issue.Severity,
Expand Down
8 changes: 4 additions & 4 deletions pkg/golinters/dupl/dupl.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const linterName = "dupl"

func New(settings *config.DuplSettings) *goanalysis.Linter {
var mu sync.Mutex
var resIssues []goanalysis.Issue
var resIssues []*goanalysis.Issue

return goanalysis.
NewLinterFromAnalyzer(&analysis.Analyzer{
Expand All @@ -43,13 +43,13 @@ func New(settings *config.DuplSettings) *goanalysis.Linter {
return nil, nil
},
}).
WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue {
return resIssues
}).
WithLoadMode(goanalysis.LoadModeSyntax)
}

func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]goanalysis.Issue, error) {
func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]*goanalysis.Issue, error) {
issues, err := duplAPI.Run(internal.GetGoFileNames(pass), settings.Threshold)
if err != nil {
return nil, err
Expand All @@ -59,7 +59,7 @@ func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]goanalysis.I
return nil, nil
}

res := make([]goanalysis.Issue, 0, len(issues))
res := make([]*goanalysis.Issue, 0, len(issues))

for _, i := range issues {
toFilename, err := fsutils.ShortestRelPath(i.To.Filename(), "")
Expand Down
8 changes: 4 additions & 4 deletions pkg/golinters/errcheck/errcheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const linterName = "errcheck"

func New(settings *config.ErrcheckSettings) *goanalysis.Linter {
var mu sync.Mutex
var resIssues []goanalysis.Issue
var resIssues []*goanalysis.Issue

analyzer := &analysis.Analyzer{
Name: linterName,
Expand Down Expand Up @@ -50,13 +50,13 @@ func New(settings *config.ErrcheckSettings) *goanalysis.Linter {
return nil, nil
}
}).
WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue {
return resIssues
}).
WithLoadMode(goanalysis.LoadModeTypesInfo)
}

func runErrCheck(pass *analysis.Pass, checker *errcheck.Checker, verbose bool) []goanalysis.Issue {
func runErrCheck(pass *analysis.Pass, checker *errcheck.Checker, verbose bool) []*goanalysis.Issue {
pkg := &packages.Package{
Fset: pass.Fset,
Syntax: pass.Files,
Expand All @@ -69,7 +69,7 @@ func runErrCheck(pass *analysis.Pass, checker *errcheck.Checker, verbose bool) [
return nil
}

issues := make([]goanalysis.Issue, len(lintIssues.UncheckedErrors))
issues := make([]*goanalysis.Issue, len(lintIssues.UncheckedErrors))

for i, err := range lintIssues.UncheckedErrors {
text := "Error return value is not checked"
Expand Down
Loading
Loading