Skip to content

Commit 7be313c

Browse files
committed
add nolint skip support
1 parent a2c3e11 commit 7be313c

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,23 @@ func NoInheritCancel(_ context.Context) (context.Context,context.CancelFunc) {
9494
}
9595
```
9696

97+
You can add `// nolint: contextcheck` in function decl doc comment, to skip this linter in some false-positive case.
98+
99+
```go
100+
// nolint: contextcheck
101+
func call1() {
102+
doSomeThing(context.Background()) // add nolint will no issuss for that
103+
}
104+
105+
func call2(ctx context.Context) {
106+
call1()
107+
}
108+
109+
func call3() {
110+
call2(context.Background())
111+
}
112+
```
113+
97114
## Installation
98115

99116
You can get `contextcheck` by `go get` command.

contextcheck.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package contextcheck
33
import (
44
"go/ast"
55
"go/types"
6+
"regexp"
67
"strconv"
78
"strings"
89
"sync"
@@ -239,9 +240,41 @@ func (r *runner) checkIsEntry(f *ssa.Function) entryType {
239240
return EntryWithHttpHandler
240241
}
241242

243+
if r.skipByNolint(f) {
244+
return EntryNone
245+
}
246+
242247
return EntryNormal
243248
}
244249

250+
var nolintRe = regexp.MustCompile(`^//\s?nolint:`)
251+
252+
func (r *runner) skipByNolint(f *ssa.Function) bool {
253+
file := analysisutil.File(r.pass, f.Pos())
254+
if file == nil {
255+
return false
256+
}
257+
258+
// only support FuncDecl comment
259+
var fd *ast.FuncDecl
260+
for _, v := range file.Decls {
261+
if tmp, ok := v.(*ast.FuncDecl); ok && tmp.Name.Pos() == f.Pos() {
262+
fd = tmp
263+
break
264+
}
265+
}
266+
if fd == nil || fd.Doc == nil || len(fd.Doc.List) == 0 {
267+
return false
268+
}
269+
270+
for _, v := range fd.Doc.List {
271+
if len(nolintRe.FindString(v.Text)) > 0 && strings.Contains(v.Text, "contextcheck") {
272+
return true
273+
}
274+
}
275+
return false
276+
}
277+
245278
func (r *runner) checkIsCtx(f *ssa.Function) (in, out bool) {
246279
// check params
247280
tuple := f.Signature.Params()

testdata/src/a/a.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ func f10(in bool, w http.ResponseWriter, r *http.Request) {
109109
f8(context.Background(), w, r)
110110
}
111111

112+
// nolint: contextcheck
113+
func f14(w http.ResponseWriter, r *http.Request, err error) {
114+
f8(r.Context(), w, r)
115+
}
116+
112117
func f11() {
113118
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
114119
f8(r.Context(), w, r)
@@ -118,6 +123,8 @@ func f11() {
118123

119124
// f10 should be like `func f10(ctx context.Context, in bool, w http.ResponseWriter, r *http.Request)`
120125
f10(true, w, r) // want "Function `f10` should pass the context parameter"
126+
127+
f14(w, r, nil)
121128
})
122129
}
123130

0 commit comments

Comments
 (0)