aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/jjti
diff options
context:
space:
mode:
authordependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>2024-04-02 14:37:40 +0000
committerTaras Madan <tarasmadan@google.com>2024-04-03 09:59:40 +0000
commit9d2a90af8850a414d2da20b806d7aa8fd9a297ae (patch)
treeb6ce5a1bc2ecaed9f94b06b36eca20b98929970c /vendor/github.com/jjti
parentb90978ba49e3321a2d1cd77c07c196b088c97386 (diff)
mod: bump github.com/golangci/golangci-lint from 1.56.2 to 1.57.2
Bumps [github.com/golangci/golangci-lint](https://github.com/golangci/golangci-lint) from 1.56.2 to 1.57.2. - [Release notes](https://github.com/golangci/golangci-lint/releases) - [Changelog](https://github.com/golangci/golangci-lint/blob/master/CHANGELOG.md) - [Commits](https://github.com/golangci/golangci-lint/compare/v1.56.2...v1.57.2) --- updated-dependencies: - dependency-name: github.com/golangci/golangci-lint dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Diffstat (limited to 'vendor/github.com/jjti')
-rw-r--r--vendor/github.com/jjti/go-spancheck/README.md47
-rw-r--r--vendor/github.com/jjti/go-spancheck/spancheck.go146
2 files changed, 117 insertions, 76 deletions
diff --git a/vendor/github.com/jjti/go-spancheck/README.md b/vendor/github.com/jjti/go-spancheck/README.md
index 98aedec28..953489d7a 100644
--- a/vendor/github.com/jjti/go-spancheck/README.md
+++ b/vendor/github.com/jjti/go-spancheck/README.md
@@ -10,13 +10,6 @@ Checks usage of:
- [OpenTelemetry spans](https://opentelemetry.io/docs/instrumentation/go/manual/) from [go.opentelemetry.io/otel/trace](go.opentelemetry.io/otel/trace)
- [OpenCensus spans](https://opencensus.io/quickstart/go/tracing/) from [go.opencensus.io/trace](https://pkg.go.dev/go.opencensus.io/trace#Span)
-## Installation & Usage
-
-```bash
-go install github.com/jjti/go-spancheck/cmd/spancheck@latest
-spancheck ./...
-```
-
## Example
```bash
@@ -43,6 +36,44 @@ func _() error {
## Configuration
+### golangci-lint
+
+Docs on configuring the linter are also available at [https://golangci-lint.run/usage/linters/#spancheck](https://golangci-lint.run/usage/linters/#spancheck):
+
+```yaml
+linters:
+ enable:
+ - spancheck
+
+linters-settings:
+ spancheck:
+ # Checks to enable.
+ # Options include:
+ # - `end`: check that `span.End()` is called
+ # - `record-error`: check that `span.RecordError(err)` is called when an error is returned
+ # - `set-status`: check that `span.SetStatus(codes.Error, msg)` is called when an error is returned
+ # Default: ["end"]
+ checks:
+ - end
+ - record-error
+ - set-status
+ # A list of regexes for function signatures that silence `record-error` and `set-status` reports
+ # if found in the call path to a returned error.
+ # https://github.com/jjti/go-spancheck#ignore-check-signatures
+ # Default: []
+ ignore-check-signatures:
+ - "telemetry.RecordError"
+```
+
+### CLI
+
+To install the linter as a CLI:
+
+```bash
+go install github.com/jjti/go-spancheck/cmd/spancheck@latest
+spancheck ./...
+```
+
Only the `span.End()` check is enabled by default. The others can be enabled with `-checks 'end,set-status,record-error'`.
```txt
@@ -55,7 +86,7 @@ Flags:
comma-separated list of regex for function signatures that disable checks on errors
```
-### Ignore check signatures
+### Ignore Check Signatures
The `span.SetStatus()` and `span.RecordError()` checks warn when there is:
diff --git a/vendor/github.com/jjti/go-spancheck/spancheck.go b/vendor/github.com/jjti/go-spancheck/spancheck.go
index ebfc1ac68..6f069a033 100644
--- a/vendor/github.com/jjti/go-spancheck/spancheck.go
+++ b/vendor/github.com/jjti/go-spancheck/spancheck.go
@@ -3,7 +3,6 @@ package spancheck
import (
"go/ast"
"go/types"
- "log"
"regexp"
"golang.org/x/tools/go/analysis"
@@ -170,7 +169,7 @@ func runFunc(pass *analysis.Pass, node ast.Node, config *Config) {
for _, sv := range spanVars {
if config.endCheckEnabled {
// Check if there's no End to the span.
- if ret := missingSpanCalls(pass, g, sv, "End", func(pass *analysis.Pass, ret *ast.ReturnStmt) *ast.ReturnStmt { return ret }, nil); ret != nil {
+ if ret := getMissingSpanCalls(pass, g, sv, "End", func(pass *analysis.Pass, ret *ast.ReturnStmt) *ast.ReturnStmt { return ret }, nil); ret != nil {
pass.ReportRangef(sv.stmt, "%s.End is not called on all paths, possible memory leak", sv.vr.Name())
pass.ReportRangef(ret, "return can be reached without calling %s.End", sv.vr.Name())
}
@@ -178,7 +177,7 @@ func runFunc(pass *analysis.Pass, node ast.Node, config *Config) {
if config.setStatusEnabled {
// Check if there's no SetStatus to the span setting an error.
- if ret := missingSpanCalls(pass, g, sv, "SetStatus", returnsErr, config.ignoreChecksSignatures); ret != nil {
+ if ret := getMissingSpanCalls(pass, g, sv, "SetStatus", getErrorReturn, config.ignoreChecksSignatures); ret != nil {
pass.ReportRangef(sv.stmt, "%s.SetStatus is not called on all paths", sv.vr.Name())
pass.ReportRangef(ret, "return can be reached without calling %s.SetStatus", sv.vr.Name())
}
@@ -186,7 +185,7 @@ func runFunc(pass *analysis.Pass, node ast.Node, config *Config) {
if config.recordErrorEnabled && sv.spanType == spanOpenTelemetry { // RecordError only exists in OpenTelemetry
// Check if there's no RecordError to the span setting an error.
- if ret := missingSpanCalls(pass, g, sv, "RecordError", returnsErr, config.ignoreChecksSignatures); ret != nil {
+ if ret := getMissingSpanCalls(pass, g, sv, "RecordError", getErrorReturn, config.ignoreChecksSignatures); ret != nil {
pass.ReportRangef(sv.stmt, "%s.RecordError is not called on all paths", sv.vr.Name())
pass.ReportRangef(ret, "return can be reached without calling %s.RecordError", sv.vr.Name())
}
@@ -236,9 +235,9 @@ func getID(node ast.Node) *ast.Ident {
return nil
}
-// missingSpanCalls finds a path through the CFG, from stmt (which defines
+// getMissingSpanCalls finds a path through the CFG, from stmt (which defines
// the 'span' variable v) to a return statement, that doesn't call the passed selector on the span.
-func missingSpanCalls(
+func getMissingSpanCalls(
pass *analysis.Pass,
g *cfg.CFG,
sv spanVar,
@@ -246,66 +245,12 @@ func missingSpanCalls(
checkErr func(pass *analysis.Pass, ret *ast.ReturnStmt) *ast.ReturnStmt,
ignoreCheckSig *regexp.Regexp,
) *ast.ReturnStmt {
- // usesCall reports whether stmts contain a use of the selName call on variable v.
- usesCall := func(pass *analysis.Pass, stmts []ast.Node) bool {
- found, reAssigned := false, false
- for _, subStmt := range stmts {
- stack := []ast.Node{}
- ast.Inspect(subStmt, func(n ast.Node) bool {
- switch n := n.(type) {
- case *ast.FuncLit:
- if len(stack) > 0 {
- return false // don't stray into nested functions
- }
- case *ast.CallExpr:
- if ident, ok := n.Fun.(*ast.Ident); ok {
- fnSig := pass.TypesInfo.ObjectOf(ident).String()
- if ignoreCheckSig != nil && ignoreCheckSig.MatchString(fnSig) {
- found = true
- return false
- }
- }
- case nil:
- stack = stack[:len(stack)-1] // pop
- return true
- }
- stack = append(stack, n) // push
-
- // Check whether the span was assigned over top of its old value.
- _, spanStart := isSpanStart(pass.TypesInfo, n)
- if spanStart {
- if id := getID(stack[len(stack)-3]); id != nil && id.Obj.Decl == sv.id.Obj.Decl {
- reAssigned = true
- return false
- }
- }
-
- if n, ok := n.(*ast.SelectorExpr); ok {
- // Selector (End, SetStatus, RecordError) hit.
- if n.Sel.Name == selName {
- id, ok := n.X.(*ast.Ident)
- found = ok && id.Obj.Decl == sv.id.Obj.Decl
- }
-
- // Check if an ignore signature matches.
- fnSig := pass.TypesInfo.ObjectOf(n.Sel).String()
- if ignoreCheckSig != nil && ignoreCheckSig.MatchString(fnSig) {
- found = true
- }
- }
-
- return !found
- })
- }
- return found && !reAssigned
- }
-
// blockUses computes "uses" for each block, caching the result.
memo := make(map[*cfg.Block]bool)
blockUses := func(pass *analysis.Pass, b *cfg.Block) bool {
res, ok := memo[b]
if !ok {
- res = usesCall(pass, b.Nodes)
+ res = usesCall(pass, b.Nodes, sv, selName, ignoreCheckSig, 0)
memo[b] = res
}
return res
@@ -325,12 +270,9 @@ outer:
}
}
}
- if defBlock == nil {
- log.Default().Print("[ERROR] internal error: can't find defining block for span var")
- }
// Is the call "used" in the remainder of its defining block?
- if usesCall(pass, rest) {
+ if usesCall(pass, rest, sv, selName, ignoreCheckSig, 0) {
return nil
}
@@ -356,12 +298,12 @@ outer:
}
// Found path to return statement?
- if ret := returnsErr(pass, b.Return()); ret != nil {
+ if ret := getErrorReturn(pass, b.Return()); ret != nil {
return ret // found
}
// Recur
- if ret := returnsErr(pass, search(b.Succs)); ret != nil {
+ if ret := getErrorReturn(pass, search(b.Succs)); ret != nil {
return ret
}
}
@@ -371,7 +313,75 @@ outer:
return search(defBlock.Succs)
}
-func returnsErr(pass *analysis.Pass, ret *ast.ReturnStmt) *ast.ReturnStmt {
+// usesCall reports whether stmts contain a use of the selName call on variable v.
+func usesCall(pass *analysis.Pass, stmts []ast.Node, sv spanVar, selName string, ignoreCheckSig *regexp.Regexp, depth int) bool {
+ if depth > 1 { // for perf reasons, do not dive too deep thru func literals, just one level deep check.
+ return false
+ }
+
+ found, reAssigned := false, false
+ for _, subStmt := range stmts {
+ stack := []ast.Node{}
+ ast.Inspect(subStmt, func(n ast.Node) bool {
+ switch n := n.(type) {
+ case *ast.FuncLit:
+ if len(stack) > 0 {
+ cfgs := pass.ResultOf[ctrlflow.Analyzer].(*ctrlflow.CFGs)
+ g := cfgs.FuncLit(n)
+ if g != nil && len(g.Blocks) > 0 {
+ return usesCall(pass, g.Blocks[0].Nodes, sv, selName, ignoreCheckSig, depth+1)
+ }
+
+ return false
+ }
+ case *ast.CallExpr:
+ if ident, ok := n.Fun.(*ast.Ident); ok {
+ fnSig := pass.TypesInfo.ObjectOf(ident).String()
+ if ignoreCheckSig != nil && ignoreCheckSig.MatchString(fnSig) {
+ found = true
+ return false
+ }
+ }
+ case nil:
+ if len(stack) > 0 {
+ stack = stack[:len(stack)-1] // pop
+ return true
+ }
+ return false
+ }
+ stack = append(stack, n) // push
+
+ // Check whether the span was assigned over top of its old value.
+ _, spanStart := isSpanStart(pass.TypesInfo, n)
+ if spanStart {
+ if id := getID(stack[len(stack)-3]); id != nil && id.Obj.Decl == sv.id.Obj.Decl {
+ reAssigned = true
+ return false
+ }
+ }
+
+ if n, ok := n.(*ast.SelectorExpr); ok {
+ // Selector (End, SetStatus, RecordError) hit.
+ if n.Sel.Name == selName {
+ id, ok := n.X.(*ast.Ident)
+ found = ok && id.Obj.Decl == sv.id.Obj.Decl
+ }
+
+ // Check if an ignore signature matches.
+ fnSig := pass.TypesInfo.ObjectOf(n.Sel).String()
+ if ignoreCheckSig != nil && ignoreCheckSig.MatchString(fnSig) {
+ found = true
+ }
+ }
+
+ return !found
+ })
+ }
+
+ return found && !reAssigned
+}
+
+func getErrorReturn(pass *analysis.Pass, ret *ast.ReturnStmt) *ast.ReturnStmt {
if ret == nil {
return nil
}