From 20c10da9027bad9d852ae23374cb8d25d7ecb745 Mon Sep 17 00:00:00 2001 From: sylvia7788 <1227977886@qq.com> Date: Sat, 4 Sep 2021 16:28:08 +0800 Subject: [PATCH] modify prompt --- README.md | 17 +++++++++++++---- contextcheck.go | 8 ++++---- testdata/src/a/a.go | 17 ++++++++++++++--- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 9ab5a42..dc951ac 100644 --- a/README.md +++ b/README.md @@ -3,16 +3,20 @@ # contextcheck -`contextcheck` is a static analysis tool, it is used to check a function whether use context.Background() or context.TODO() directly instead of the input ctx when calling the sub-function, or even don't pass the ctx, which will result in a broken call link. +`contextcheck` is a static analysis tool, it is used to check the function whether use a non-inherited context, which will result in a broken call link. For example: ```go func call1(ctx context.Context) { ... - call2(context.Background()) // should use ctx - call3() // should pass the ctx + ctx = getNewCtx(ctx) + call2(ctx) // OK + + call2(context.Background()) // Non-inherited new context, use function like `context.WithXXX` instead + + call3() // Function `call3` should pass the context parameter ... } @@ -24,6 +28,11 @@ func call3() { ctx := context.TODO() call2(ctx) } + +func getNewCtx(ctx context.Context) (newCtx context.Context) { + ... + return +} ``` ## Installation @@ -48,5 +57,5 @@ Invoke `contextcheck` with your package name ```bash $ contextcheck ./... $ # or -$ contextcheck github.com/you/yourproject/... +$ go vet -vettool=`which contextcheck` ./... ``` diff --git a/contextcheck.go b/contextcheck.go index eaf770d..543a802 100644 --- a/contextcheck.go +++ b/contextcheck.go @@ -17,7 +17,7 @@ import ( func NewAnalyzer() *analysis.Analyzer { return &analysis.Analyzer{ Name: "contextcheck", - Doc: "checkInstr for using context.Background() and context.TODO() directly", + Doc: "check the function whether use a non-inherited context", Run: NewRun(), Requires: []*analysis.Analyzer{ buildssa.Analyzer, @@ -247,7 +247,7 @@ func (r *runner) collectCtxRef(f *ssa.Function) (refMap map[ssa.Instruction]bool for instr := range storeInstrs { if !checkedRefMap[instr.Val] { - r.pass.Reportf(instr.Pos(), "Invalid call to get new context, please replace it with another way, such as context.WithValue(ctx, key, val)") + r.pass.Reportf(instr.Pos(), "Non-inherited new context, use function like `context.WithXXX` instead") ok = false } } @@ -255,7 +255,7 @@ func (r *runner) collectCtxRef(f *ssa.Function) (refMap map[ssa.Instruction]bool for instr := range phiInstrs { for _, v := range instr.Edges { if !checkedRefMap[v] { - r.pass.Reportf(instr.Pos(), "Invalid call to get new context, please replace it with another way, such as context.WithValue(ctx, key, val)") + r.pass.Reportf(instr.Pos(), "Non-inherited new context, use function like `context.WithXXX` instead") ok = false } } @@ -299,7 +299,7 @@ func (r *runner) checkFuncWithCtx(f *ssa.Function) { if tp&CtxIn != 0 { if !refMap[instr] { - r.pass.Reportf(instr.Pos(), "The context param may be context.TODO() or context.Background(), please replace it with another way, such as context.WithValue(ctx, key, val)") + r.pass.Reportf(instr.Pos(), "Non-inherited new context, use function like `context.WithXXX` instead") } } diff --git a/testdata/src/a/a.go b/testdata/src/a/a.go index e864b83..3ae0dba 100644 --- a/testdata/src/a/a.go +++ b/testdata/src/a/a.go @@ -45,7 +45,7 @@ func f1(ctx context.Context) { f2(ctx) }(ctx) - f2(context.Background()) // want `The context param may be context\.TODO\(\) or context\.Background\(\), please replace it with another way, such as context\.WithValue\(ctx, key, val\)` + f2(context.Background()) // want "Non-inherited new context, use function like `context.WithXXX` instead" thunk := MyInt.F thunk(0) @@ -63,7 +63,7 @@ func f3() { func f4(ctx context.Context) { f2(ctx) ctx = context.Background() - f2(ctx) // want `The context param may be context\.TODO\(\) or context\.Background\(\), please replace it with another way, such as context\.WithValue\(ctx, key, val\)` + f2(ctx) // want "Non-inherited new context, use function like `context.WithXXX` instead" } func f5(ctx context.Context) { @@ -71,10 +71,21 @@ func f5(ctx context.Context) { f2(ctx) }() - ctx = context.Background() // want `Invalid call to get new context, please replace it with another way, such as context\.WithValue\(ctx, key, val\)` + ctx = context.Background() // want "Non-inherited new context, use function like `context.WithXXX` instead" f2(ctx) } func f6() { f3() // want "Function `f3` should pass the context parameter" } + +func f7(ctx context.Context) { + ctx, cancel := getNewCtx(ctx) + defer cancel() + + f2(ctx) // OK +} + +func getNewCtx(ctx context.Context) (newCtx context.Context, cancel context.CancelFunc) { + return context.WithCancel(ctx) +}