Skip to content

Commit c6d65a4

Browse files
committed
pkg/analyzer: fix pgx interface method call detection
Fix issue #36 where the linter failed to detect missing Close() calls when methods like rows.Next() or rows.Err() were called on pgx.Rows. The root cause was that interface method calls (SSA "invoke mode") were not handled in getAction(). For interface calls, instr.Call.Method is set and StaticCallee() returns nil, causing the code to incorrectly return actionPassed instead of continuing to check for Close(). The fix adds handling for invoke mode at the start of the *ssa.Call case: check if instr.Call.Method is set, verify the receiver is a target type, and return actionClosed for Close() or actionNoOp for other methods like Next(), Err(), and Scan(). Also updates golang.org/x/tools for Go 1.25 compatibility.
1 parent 3ec3977 commit c6d65a4

File tree

174 files changed

+30346
-22032
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

174 files changed

+30346
-22032
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
steps:
1212
- uses: actions/setup-go@v5
1313
with:
14-
go-version: 1.23
14+
go-version: "1.24"
1515
- uses: actions/checkout@v4
1616
- run: make lint
1717
- run: make test

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ test: build
2424
diff -a pgx_examples_results.txt ./testdata/pgx_examples/expected_results.txt
2525

2626
lint:
27-
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.62.2
27+
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.63.4
2828
./bin/golangci-lint run

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
module github.com/ryanrolds/sqlclosecheck
22

3-
go 1.23.0
3+
go 1.24.0
44

55
require (
66
github.com/go-sql-driver/mysql v1.7.1
77
github.com/jackc/pgx/v5 v5.5.4
88
github.com/jmoiron/sqlx v1.3.5
9-
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d
9+
golang.org/x/tools v0.40.0
1010
)
1111

1212
require (
1313
github.com/jackc/pgpassfile v1.0.0 // indirect
1414
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
1515
github.com/jackc/puddle/v2 v2.2.1 // indirect
1616
golang.org/x/crypto v0.35.0 // indirect
17-
golang.org/x/mod v0.17.0 // indirect
18-
golang.org/x/sync v0.11.0 // indirect
17+
golang.org/x/mod v0.31.0 // indirect
18+
golang.org/x/sync v0.19.0 // indirect
1919
golang.org/x/text v0.22.0 // indirect
2020
)

go.sum

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
44
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
55
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
66
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
7+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
8+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
79
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
810
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
911
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
@@ -27,14 +29,14 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs
2729
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
2830
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
2931
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
30-
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
31-
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
32-
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
33-
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
32+
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
33+
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
34+
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
35+
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
3436
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
3537
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
36-
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
37-
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
38+
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
39+
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
3840
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
3941
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
4042
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

pkg/analyzer/defer_only.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,17 @@ func getAction(instr ssa.Instruction, targetTypes []any) action {
260260

261261
return actionUnvaluedDefer
262262
case *ssa.Call:
263+
if instr.Call.Method != nil {
264+
receiverType := instr.Call.Value.Type()
265+
if isTargetType(receiverType, targetTypes) {
266+
if instr.Call.Method.Name() == closeMethod {
267+
return actionClosed
268+
}
269+
270+
return actionNoOp
271+
}
272+
}
273+
263274
if instr.Call.Value == nil {
264275
return actionUnvaluedCall
265276
}

pkg/analyzer/testdata/pgx/correct_defer.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ func correctDeferPgxPool() {
2626
if err != nil {
2727
log.Fatal(err)
2828
}
29-
3029
defer rows.Close()
30+
31+
for rows.Next() {
32+
var username string
33+
rows.Scan(&username)
34+
}
3135
}

pkg/analyzer/testdata/pgx/missing_close.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,8 @@ func missingClosePgxPool() {
2828
log.Fatal(err)
2929
}
3030

31-
_ = rows
31+
for rows.Next() {
32+
var username string
33+
rows.Scan(&username)
34+
}
3235
}

vendor/golang.org/x/mod/LICENSE

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/golang.org/x/mod/modfile/print.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/golang.org/x/mod/modfile/read.go

Lines changed: 11 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)