diff options
| author | dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> | 2024-03-04 17:40:11 +0000 |
|---|---|---|
| committer | Taras Madan <tarasmadan@google.com> | 2024-03-04 18:34:55 +0000 |
| commit | 5fc5366972c874b919f93165bb4ed4e2bcb7c350 (patch) | |
| tree | 287c3361a0dee0c72af80d9a1a66714a06e98a62 /vendor/github.com/ykadowak | |
| parent | 1be5ce38a9059c356eb193a8c34d60d61c9fc31f (diff) | |
mod: bump github.com/golangci/golangci-lint from 1.55.2 to 1.56.2
Bumps [github.com/golangci/golangci-lint](https://github.com/golangci/golangci-lint) from 1.55.2 to 1.56.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.55.2...v1.56.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/ykadowak')
| -rw-r--r-- | vendor/github.com/ykadowak/zerologlint/.goreleaser.yaml | 7 | ||||
| -rw-r--r-- | vendor/github.com/ykadowak/zerologlint/zerologlint.go | 102 |
2 files changed, 82 insertions, 27 deletions
diff --git a/vendor/github.com/ykadowak/zerologlint/.goreleaser.yaml b/vendor/github.com/ykadowak/zerologlint/.goreleaser.yaml index c1b23f00e..f3af3f212 100644 --- a/vendor/github.com/ykadowak/zerologlint/.goreleaser.yaml +++ b/vendor/github.com/ykadowak/zerologlint/.goreleaser.yaml @@ -11,13 +11,6 @@ builds: - linux - windows - darwin -archives: - - replacements: - darwin: Darwin - linux: Linux - windows: Windows - 386: i386 - amd64: x86_64 checksum: name_template: 'checksums.txt' snapshot: diff --git a/vendor/github.com/ykadowak/zerologlint/zerologlint.go b/vendor/github.com/ykadowak/zerologlint/zerologlint.go index bec50e52b..8c8fb74fc 100644 --- a/vendor/github.com/ykadowak/zerologlint/zerologlint.go +++ b/vendor/github.com/ykadowak/zerologlint/zerologlint.go @@ -13,8 +13,8 @@ import ( ) var Analyzer = &analysis.Analyzer{ - Name: "zerologlinter", - Doc: "finds cases where zerolog methods are not followed by Msg or Send", + Name: "zerologlint", + Doc: "Detects the wrong usage of `zerolog` that a user forgets to dispatch with `Send` or `Msg`", Run: run, Requires: []*analysis.Analyzer{ buildssa.Analyzer, @@ -26,42 +26,65 @@ type posser interface { Pos() token.Pos } -// posser is an interface just to hold both ssa.Call and ssa.Defer in our set +// callDefer is an interface just to hold both ssa.Call and ssa.Defer in our set type callDefer interface { Common() *ssa.CallCommon Pos() token.Pos } -func run(pass *analysis.Pass) (interface{}, error) { - srcFuncs := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA).SrcFuncs - - // This set holds all the ssa block that is a zerolog.Event type instance +type linter struct { + // eventSet holds all the ssa block that is a zerolog.Event type instance // that should be dispatched. // Everytime the zerolog.Event is dispatched with Msg() or Send(), // deletes that block from this set. // At the end, check if the set is empty, or report the not dispatched block. - set := make(map[posser]struct{}) + eventSet map[posser]struct{} + // deleteLater holds the ssa block that should be deleted from eventSet after + // all the inspection is done. + // this is required because `else` ssa block comes after the dispatch of `if`` block. + // e.g., if err != nil { log.Error() } else { log.Info() } log.Send() + // deleteLater takes care of the log.Info() block. + deleteLater map[posser]struct{} + recLimit uint +} + +func run(pass *analysis.Pass) (interface{}, error) { + srcFuncs := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA).SrcFuncs + + l := &linter{ + eventSet: make(map[posser]struct{}), + deleteLater: make(map[posser]struct{}), + recLimit: 100, + } for _, sf := range srcFuncs { for _, b := range sf.Blocks { for _, instr := range b.Instrs { if c, ok := instr.(*ssa.Call); ok { - inspect(c, &set) + l.inspect(c) } else if c, ok := instr.(*ssa.Defer); ok { - inspect(c, &set) + l.inspect(c) } } } } + + // apply deleteLater to envetSet for else branches of if-else cases + + for k := range l.deleteLater { + delete(l.eventSet, k) + } + // At the end, if the set is clear -> ok. - // Otherwise, there must be a left zerolog.Event var that weren't dispached. So report it. - for k := range set { + // Otherwise, there must be a left zerolog.Event var that weren't dispatched. So report it. + for k := range l.eventSet { pass.Reportf(k.Pos(), "must be dispatched by Msg or Send method") } + return nil, nil } -func inspect(cd callDefer, set *map[posser]struct{}) { +func (l *linter) inspect(cd callDefer) { c := cd.Common() // check if it's in github.com/rs/zerolog/log since there's some @@ -70,7 +93,7 @@ func inspect(cd callDefer, set *map[posser]struct{}) { if isInLogPkg(*c) || isLoggerRecv(*c) { if isZerologEvent(c.Value) { // this ssa block should be dispatched afterwards at some point - (*set)[cd] = struct{}{} + l.eventSet[cd] = struct{}{} return } } @@ -88,7 +111,7 @@ func inspect(cd callDefer, set *map[posser]struct{}) { for _, p := range f.Params { if isZerologEvent(p) { // check if this zerolog.Event as a parameter is dispatched in the function - // TODO: specifically, it can be dispatched in another function that is called in this function, and + // TODO: technically, it can be dispatched in another function that is called in this function, and // this algorithm cannot track that. But I'm tired of thinking about that for now. for _, b := range f.Blocks { for _, instr := range b.Instrs { @@ -96,10 +119,12 @@ func inspect(cd callDefer, set *map[posser]struct{}) { case *ssa.Call: if inspectDispatchInFunction(v.Common()) { shouldReturn = false + break } case *ssa.Defer: if inspectDispatchInFunction(v.Common()) { shouldReturn = false + break } } } @@ -112,19 +137,56 @@ func inspect(cd callDefer, set *map[posser]struct{}) { } for _, arg := range c.Args { if isZerologEvent(arg) { - val := getRootSsaValue(arg) - // if there's branch, remove both ways from the set - if phi, ok := val.(*ssa.Phi); ok { + // if there's branch, track both ways + // this is for the case like: + // logger := log.Info() + // if err != nil { + // logger = log.Error() + // } + // logger.Send() + // + // Similar case like below goes to the same root but that doesn't + // have any side effect. + // logger := log.Info() + // if err != nil { + // logger = logger.Str("a", "b") + // } + // logger.Send() + if phi, ok := arg.(*ssa.Phi); ok { for _, edge := range phi.Edges { - delete(*set, edge) + l.dfsEdge(edge, make(map[ssa.Value]struct{}), 0) } } else { - delete(*set, val) + val := getRootSsaValue(arg) + delete(l.eventSet, val) } } } } +func (l *linter) dfsEdge(v ssa.Value, visit map[ssa.Value]struct{}, cnt uint) { + // only for safety + if cnt > l.recLimit { + return + } + cnt++ + + if _, ok := visit[v]; ok { + return + } + visit[v] = struct{}{} + + val := getRootSsaValue(v) + phi, ok := val.(*ssa.Phi) + if !ok { + l.deleteLater[val] = struct{}{} + return + } + for _, edge := range phi.Edges { + l.dfsEdge(edge, visit, cnt) + } +} + func inspectDispatchInFunction(cc *ssa.CallCommon) bool { if isDispatchMethod(cc.StaticCallee()) { for _, arg := range cc.Args { |
