Skip to content

Commit 3d17f2f

Browse files
authored
gocritic: support autofix (#2450)
1 parent 891b9da commit 3d17f2f

File tree

5 files changed

+80
-3
lines changed

5 files changed

+80
-3
lines changed

Makefile

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ test: build
2929
GL_TEST_RUN=1 go test -v -parallel 2 ./...
3030
.PHONY: test
3131

32+
# ex: T=gofmt.go make test_fix
33+
# the value of `T` is the name of a file from `test/testdata/fix`
34+
test_fix: build
35+
GL_TEST_RUN=1 go test -v ./test -count 1 -run TestFix/$T
36+
.PHONY: test_fix
37+
3238
test_race: build_race
3339
GL_TEST_RUN=1 ./golangci-lint run -v --timeout=5m
3440
.PHONY: test_race

pkg/golinters/gocritic.go

+16-3
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ Dynamic rules are written declaratively with AST patterns, filters, report messa
4848
}
4949

5050
linterCtx.SetPackageInfo(pass.TypesInfo, pass.Pkg)
51-
var res []goanalysis.Issue
5251
pkgIssues := runGocriticOnPackage(linterCtx, enabledCheckers, pass.Files)
52+
res := make([]goanalysis.Issue, 0, len(pkgIssues))
53+
5354
for i := range pkgIssues {
5455
res = append(res, goanalysis.NewIssue(&pkgIssues[i], pass))
5556
}
@@ -179,11 +180,23 @@ func runGocriticOnFile(ctx *gocriticlinter.Context, f *ast.File, checkers []*goc
179180
// as read-only structure, so no copying is required.
180181
for _, warn := range c.Check(f) {
181182
pos := ctx.FileSet.Position(warn.Node.Pos())
182-
res = append(res, result.Issue{
183+
issue := result.Issue{
183184
Pos: pos,
184185
Text: fmt.Sprintf("%s: %s", c.Info.Name, warn.Text),
185186
FromLinter: gocriticName,
186-
})
187+
}
188+
189+
if warn.HasQuickFix() {
190+
issue.Replacement = &result.Replacement{
191+
Inline: &result.InlineFix{
192+
StartCol: pos.Column - 1,
193+
Length: int(warn.Node.End() - warn.Node.Pos()),
194+
NewString: string(warn.Suggestion.Replacement),
195+
},
196+
}
197+
}
198+
199+
res = append(res, issue)
187200
}
188201
}
189202

test/ruleguard/rangeExprCopy.go

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// go:build ruleguard
2+
package ruleguard
3+
4+
import (
5+
"github.com/quasilyte/go-ruleguard/dsl"
6+
)
7+
8+
func RangeExprVal(m dsl.Matcher) {
9+
m.Match(`for _, $_ := range $x { $*_ }`, `for _, $_ = range $x { $*_ }`).
10+
Where(m["x"].Addressable && m["x"].Type.Size >= 512).
11+
Report(`$x copy can be avoided with &$x`).
12+
At(m["x"]).
13+
Suggest(`&$x`)
14+
}

test/testdata/fix/in/gocritic.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//args: -Egocritic
2+
//config: linters-settings.gocritic.enabled-checks=ruleguard
3+
//config: linters-settings.gocritic.settings.ruleguard.rules=ruleguard/rangeExprCopy.go,ruleguard/strings_simplify.go
4+
package p
5+
6+
import (
7+
"strings"
8+
)
9+
10+
func gocritic() {
11+
var xs [2048]byte
12+
13+
// xs -> &xs
14+
for _, x := range xs {
15+
print(x)
16+
}
17+
18+
// strings.Count("foo", "bar") == 0 -> !strings.Contains("foo", "bar")
19+
if strings.Count("foo", "bar") == 0 {
20+
print("qu")
21+
}
22+
}

test/testdata/fix/out/gocritic.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//args: -Egocritic
2+
//config: linters-settings.gocritic.enabled-checks=ruleguard
3+
//config: linters-settings.gocritic.settings.ruleguard.rules=ruleguard/rangeExprCopy.go,ruleguard/strings_simplify.go
4+
package p
5+
6+
import (
7+
"strings"
8+
)
9+
10+
func gocritic() {
11+
var xs [2048]byte
12+
13+
// xs -> &xs
14+
for _, x := range &xs {
15+
print(x)
16+
}
17+
18+
// strings.Count("foo", "bar") == 0 -> !strings.Contains("foo", "bar")
19+
if !strings.Contains("foo", "bar") {
20+
print("qu")
21+
}
22+
}

0 commit comments

Comments
 (0)