Skip to content

Commit ef1e87c

Browse files
committed
feat: add rowserr linter
Add rowserr a linter which checks for missing sql Rows.Err() calls that supports generics.
1 parent 95813b7 commit ef1e87c

File tree

7 files changed

+61
-0
lines changed

7 files changed

+61
-0
lines changed

.golangci.reference.yml

+10
Original file line numberDiff line numberDiff line change
@@ -1632,6 +1632,14 @@ linters-settings:
16321632
severity: warning
16331633
disabled: false
16341634

1635+
rowserr:
1636+
# packages sets additional packages to check.
1637+
# The following know sql packages are always checked:
1638+
# - database/sql
1639+
# - github.com/jmoiron/sqlx
1640+
# Default: []
1641+
packages: []
1642+
16351643
rowserrcheck:
16361644
# database/sql is always checked
16371645
# Default: []
@@ -2035,6 +2043,7 @@ linters:
20352043
- promlinter
20362044
- reassign
20372045
- revive
2046+
- rowserr
20382047
- rowserrcheck
20392048
- scopelint
20402049
- sqlclosecheck
@@ -2142,6 +2151,7 @@ linters:
21422151
- promlinter
21432152
- reassign
21442153
- revive
2154+
- rowserr
21452155
- rowserrcheck
21462156
- scopelint
21472157
- sqlclosecheck

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ require (
9393
github.com/spf13/viper v1.12.0
9494
github.com/ssgreg/nlreturn/v2 v2.2.1
9595
github.com/stbenjam/no-sprintf-host-port v0.1.1
96+
github.com/stevenh/go-rowserr v0.2.0
9697
github.com/stretchr/testify v1.8.1
9798
github.com/tdakkota/asciicheck v0.1.1
9899
github.com/tetafro/godot v1.4.11

go.sum

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

pkg/config/linters_settings.go

+4
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ type LintersSettings struct {
190190
Promlinter PromlinterSettings
191191
Reassign ReassignSettings
192192
Revive ReviveSettings
193+
RowsErr RowsErrSettings
193194
RowsErrCheck RowsErrCheckSettings
194195
Staticcheck StaticCheckSettings
195196
Structcheck StructCheckSettings
@@ -599,6 +600,9 @@ type ReviveSettings struct {
599600
Severity string
600601
}
601602
}
603+
type RowsErrSettings struct {
604+
Packages []string
605+
}
602606

603607
type RowsErrCheckSettings struct {
604608
Packages []string

pkg/golinters/rowserr.go

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package golinters
2+
3+
import (
4+
"github.com/stevenh/go-rowserr/pkg/rowserr"
5+
"golang.org/x/tools/go/analysis"
6+
7+
"github.com/golangci/golangci-lint/pkg/config"
8+
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
9+
)
10+
11+
func NewRowsErr(settings *config.RowsErrSettings) *goanalysis.Linter {
12+
a := rowserr.NewAnalyzer(settings.Packages...)
13+
return goanalysis.NewLinter(
14+
a.Name,
15+
a.Doc,
16+
[]*analysis.Analyzer{a},
17+
nil,
18+
).WithLoadMode(goanalysis.LoadModeTypesInfo)
19+
}

pkg/lint/lintersdb/manager.go

+8
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
158158
promlinterCfg *config.PromlinterSettings
159159
reassignCfg *config.ReassignSettings
160160
reviveCfg *config.ReviveSettings
161+
rowserrCfg *config.RowsErrSettings
161162
rowserrcheckCfg *config.RowsErrCheckSettings
162163
staticcheckCfg *config.StaticCheckSettings
163164
structcheckCfg *config.StructCheckSettings
@@ -234,6 +235,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
234235
promlinterCfg = &m.cfg.LintersSettings.Promlinter
235236
reassignCfg = &m.cfg.LintersSettings.Reassign
236237
reviveCfg = &m.cfg.LintersSettings.Revive
238+
rowserrCfg = &m.cfg.LintersSettings.RowsErr
237239
rowserrcheckCfg = &m.cfg.LintersSettings.RowsErrCheck
238240
staticcheckCfg = &m.cfg.LintersSettings.Staticcheck
239241
structcheckCfg = &m.cfg.LintersSettings.Structcheck
@@ -707,6 +709,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
707709
ConsiderSlow().
708710
WithURL("https://github.com/mgechev/revive"),
709711

712+
linter.NewConfig(golinters.NewRowsErr(rowserrCfg)).
713+
WithSince("v1.51.0").
714+
WithLoadForGoAnalysis().
715+
WithPresets(linter.PresetBugs, linter.PresetSQL).
716+
WithURL("https://github.com/stevenh/go-rowserr"),
717+
710718
linter.NewConfig(golinters.NewRowsErrCheck(rowserrcheckCfg)).
711719
WithSince("v1.23.0").
712720
WithLoadForGoAnalysis().

test/testdata/rowserr/rowserr.go

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//golangcitest:args -Erowserr
2+
package testdata
3+
4+
import (
5+
"database/sql"
6+
)
7+
8+
func RowsErrNotChecked(db *sql.DB) {
9+
rows, err := db.Query("select id from tb") // want "rows.Err\\(\\) must be checked"
10+
if err != nil {
11+
// Handle error.
12+
}
13+
14+
for rows.Next() {
15+
// Handle row.
16+
}
17+
}

0 commit comments

Comments
 (0)