Skip to content

Commit 9f2528a

Browse files
authored
mirror: linter that suggest using alternative string/[]byte functions (#3825)
1 parent 13de250 commit 9f2528a

File tree

6 files changed

+93
-0
lines changed

6 files changed

+93
-0
lines changed

.golangci.reference.yml

+2
Original file line numberDiff line numberDiff line change
@@ -2140,6 +2140,7 @@ linters:
21402140
- maintidx
21412141
- makezero
21422142
- maligned
2143+
- mirror
21432144
- misspell
21442145
- musttag
21452146
- nakedret
@@ -2253,6 +2254,7 @@ linters:
22532254
- maintidx
22542255
- makezero
22552256
- maligned
2257+
- mirror
22562258
- misspell
22572259
- musttag
22582260
- nakedret

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ require (
2424
github.com/breml/bidichk v0.2.4
2525
github.com/breml/errchkjson v0.3.1
2626
github.com/butuzov/ireturn v0.2.0
27+
github.com/butuzov/mirror v1.1.0
2728
github.com/charithe/durationcheck v0.0.10
2829
github.com/curioswitch/go-reassign v0.2.0
2930
github.com/daixiang0/gci v0.10.1

go.sum

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/golinters/mirror.go

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package golinters
2+
3+
import (
4+
"sync"
5+
6+
"github.com/butuzov/mirror"
7+
"golang.org/x/tools/go/analysis"
8+
9+
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
10+
"github.com/golangci/golangci-lint/pkg/lint/linter"
11+
"github.com/golangci/golangci-lint/pkg/result"
12+
)
13+
14+
func NewMirror() *goanalysis.Linter {
15+
var (
16+
mu sync.Mutex
17+
issues []goanalysis.Issue
18+
)
19+
20+
a := mirror.NewAnalyzer()
21+
a.Run = func(pass *analysis.Pass) (any, error) {
22+
// mirror only lints test files if the `--with-tests` flag is passed,
23+
// so we pass the `with-tests` flag as true to the analyzer before running it.
24+
// This can be turned off by using the regular golangci-lint flags such as `--tests` or `--skip-files`
25+
// or can be disabled per linter via exclude rules.
26+
// (see https://github.com/golangci/golangci-lint/issues/2527#issuecomment-1023707262)
27+
violations := mirror.Run(pass, true)
28+
29+
if len(violations) == 0 {
30+
return nil, nil
31+
}
32+
33+
for index := range violations {
34+
i := violations[index].Issue(pass.Fset)
35+
36+
issue := result.Issue{
37+
FromLinter: a.Name,
38+
Text: i.Message,
39+
Pos: i.Start,
40+
}
41+
42+
if len(i.InlineFix) > 0 {
43+
issue.Replacement = &result.Replacement{
44+
Inline: &result.InlineFix{
45+
StartCol: i.Start.Column - 1,
46+
Length: len(i.Original),
47+
NewString: i.InlineFix,
48+
},
49+
}
50+
}
51+
52+
mu.Lock()
53+
issues = append(issues, goanalysis.NewIssue(&issue, pass))
54+
mu.Unlock()
55+
}
56+
57+
return nil, nil
58+
}
59+
60+
analyzer := goanalysis.NewLinter(
61+
a.Name,
62+
a.Doc,
63+
[]*analysis.Analyzer{a},
64+
nil,
65+
).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
66+
return issues
67+
}).WithLoadMode(goanalysis.LoadModeTypesInfo)
68+
69+
return analyzer
70+
}

pkg/lint/lintersdb/manager.go

+6
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
654654
WithURL("https://github.com/mdempsky/maligned").
655655
Deprecated("The repository of the linter has been archived by the owner.", "v1.38.0", "govet 'fieldalignment'"),
656656

657+
linter.NewConfig(golinters.NewMirror()).
658+
WithSince("v1.53.0").
659+
WithPresets(linter.PresetStyle).
660+
WithLoadForGoAnalysis().
661+
WithURL("https://github.com/butuzov/mirror"),
662+
657663
linter.NewConfig(golinters.NewMisspell(misspellCfg)).
658664
WithSince("v1.8.0").
659665
WithPresets(linter.PresetStyle, linter.PresetComment).

test/testdata/mirror.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//golangcitest:args -Emirror
2+
package testdata
3+
4+
import (
5+
"strings"
6+
"unicode/utf8"
7+
)
8+
9+
func foobar() {
10+
_ = utf8.RuneCount([]byte("foobar")) // want `avoid allocations with utf8\.RuneCountInString`
11+
_ = strings.Compare(string([]byte{'f', 'o', 'o', 'b', 'a', 'r'}), string([]byte{'f', 'o', 'o', 'b', 'a', 'r'})) // want `avoid allocations with bytes\.Compare`
12+
}

0 commit comments

Comments
 (0)