aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/go-critic
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2025-01-22 16:07:17 +0100
committerTaras Madan <tarasmadan@google.com>2025-01-23 10:42:36 +0000
commit7b4377ad9d8a7205416df8d6217ef2b010f89481 (patch)
treee6fec4fd12ff807a16d847923f501075bf71d16c /vendor/github.com/go-critic
parent475a4c203afb8b7d3af51c4fd32bb170ff32a45e (diff)
vendor: delete
Diffstat (limited to 'vendor/github.com/go-critic')
-rw-r--r--vendor/github.com/go-critic/go-critic/LICENSE21
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/appendAssign_checker.go103
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/appendCombine_checker.go103
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/badCond_checker.go161
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/badRegexp_checker.go446
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/boolExprSimplify_checker.go346
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/builtinShadowDecl_checker.go63
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/builtinShadow_checker.go36
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/captLocal_checker.go49
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/caseOrder_checker.go88
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/checkers.go19
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/codegenComment_checker.go61
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/commentFormatting_checker.go123
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/commentedOutCode_checker.go167
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/commentedOutImport_checker.go76
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/defaultCaseOrder_checker.go65
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/deferInLoop_checker.go70
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/deprecatedComment_checker.go156
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/docStub_checker.go95
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/dupBranchBody_checker.go59
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/dupCase_checker.go70
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/dupImports_checker.go63
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/dupSubExpr_checker.go103
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/elseif_checker.go72
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/embedded_rules.go108
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/emptyFallthrough_checker.go70
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/evalOrder_checker.go88
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/exitAfterDefer_checker.go85
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/filepathJoin_checker.go51
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/flagName_checker.go89
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/hexLiteral_checker.go61
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/hugeParam_checker.go83
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/ifElseChain_checker.go110
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/importShadow_checker.go47
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/initClause_checker.go57
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/comment_walker.go41
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/doc_comment_walker.go48
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/expr_walker.go31
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/func_decl_walker.go23
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_comment_walker.go32
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_def_visitor.go49
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_def_walker.go118
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_expr_walker.go29
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/stmt_list_walker.go33
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/stmt_walker.go29
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/type_expr_walker.go119
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/visitor.go77
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/walk_handler.go34
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/walker.go57
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astfind.go41
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astflow.go86
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astset.go44
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/zero_value.go94
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/mapKey_checker.go125
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/methodExprCall_checker.go58
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/nestingReduce_checker.go73
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/newDeref_checker.go51
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/nilValReturn_checker.go72
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/octalLiteral_checker.go51
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/paramTypeCombine_checker.go97
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/ptrToRefParam_checker.go70
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/rangeAppendAll_checker.go100
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/rangeExprCopy_checker.go80
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/rangeValCopy_checker.go76
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/regexpPattern_checker.go68
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/regexpSimplify_checker.go512
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/ruleguard_checker.go322
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/rulesdata/rulesdata.go2521
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/singleCaseSwitch_checker.go85
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/sloppyReassign_checker.go81
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/sloppyTypeAssert_checker.go56
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/sortSlice_checker.go136
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/sqlQuery_checker.go168
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/todoCommentWithoutDetail_checker.go50
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/tooManyResults_checker.go54
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/truncateCmp_checker.go124
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/typeAssertChain_checker.go133
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/typeDefFirst_checker.go92
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/typeSwitchVar_checker.go98
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/typeUnparen_checker.go96
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/underef_checker.go128
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/unlabelStmt_checker.go181
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/unlambda_checker.go118
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/unnamedResult_checker.go103
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/unnecessaryBlock_checker.go78
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/unnecessaryDefer_checker.go112
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/utils.go311
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/weakCond_checker.go78
-rw-r--r--vendor/github.com/go-critic/go-critic/checkers/whyNoLint_checker.go50
-rw-r--r--vendor/github.com/go-critic/go-critic/linter/go_version.go52
-rw-r--r--vendor/github.com/go-critic/go-critic/linter/helpers.go136
-rw-r--r--vendor/github.com/go-critic/go-critic/linter/linter.go401
92 files changed, 0 insertions, 11646 deletions
diff --git a/vendor/github.com/go-critic/go-critic/LICENSE b/vendor/github.com/go-critic/go-critic/LICENSE
deleted file mode 100644
index 5198a4a94..000000000
--- a/vendor/github.com/go-critic/go-critic/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2018-2021 go-critic team
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/vendor/github.com/go-critic/go-critic/checkers/appendAssign_checker.go b/vendor/github.com/go-critic/go-critic/checkers/appendAssign_checker.go
deleted file mode 100644
index 2a67dccec..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/appendAssign_checker.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astequal"
- "github.com/go-toolsmith/astp"
- "golang.org/x/tools/go/ast/astutil"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "appendAssign"
- info.Tags = []string{linter.DiagnosticTag}
- info.Summary = "Detects suspicious append result assignments"
- info.Before = `
-p.positives = append(p.negatives, x)
-p.negatives = append(p.negatives, y)`
- info.After = `
-p.positives = append(p.positives, x)
-p.negatives = append(p.negatives, y)`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&appendAssignChecker{ctx: ctx}), nil
- })
-}
-
-type appendAssignChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *appendAssignChecker) VisitStmt(stmt ast.Stmt) {
- assign, ok := stmt.(*ast.AssignStmt)
- if !ok || (assign.Tok != token.ASSIGN && assign.Tok != token.DEFINE) || len(assign.Lhs) != len(assign.Rhs) {
- return
- }
- for i, rhs := range assign.Rhs {
- call, ok := rhs.(*ast.CallExpr)
- if !ok || qualifiedName(call.Fun) != "append" {
- continue
- }
- c.checkAppend(assign.Lhs[i], call)
- }
-}
-
-func (c *appendAssignChecker) checkAppend(x ast.Expr, call *ast.CallExpr) {
- if call.Ellipsis != token.NoPos {
- // Try to detect `xs = append(ys, xs...)` idiom.
- for _, arg := range call.Args[1:] {
- y := arg
- if arg, ok := arg.(*ast.SliceExpr); ok {
- y = arg.X
- }
- if astequal.Expr(x, y) {
- return
- }
- }
- }
-
- switch x := x.(type) {
- case *ast.Ident:
- if x.Name == "_" {
- return // Don't check assignments to blank ident
- }
- case *ast.IndexExpr:
- if !astp.IsIndexExpr(call.Args[0]) {
- // Most likely `m[k] = append(x, ...)`
- // pattern, where x was retrieved by m[k] before.
- //
- // TODO: it's possible to record such map/slice reads
- // and check whether it was done before this call.
- // But for now, treat it like x belongs to m[k].
- return
- }
- }
-
- switch y := call.Args[0].(type) {
- case *ast.SliceExpr:
- if _, ok := c.ctx.TypeOf(y.X).(*types.Array); ok {
- // Arrays are frequently used as scratch storages.
- return
- }
- c.matchSlices(call, x, y.X)
- case *ast.IndexExpr, *ast.Ident, *ast.SelectorExpr:
- c.matchSlices(call, x, y)
- }
-}
-
-func (c *appendAssignChecker) matchSlices(cause ast.Node, x, y ast.Expr) {
- if !astequal.Expr(x, astutil.Unparen(y)) {
- c.warn(cause)
- }
-}
-
-func (c *appendAssignChecker) warn(cause ast.Node) {
- c.ctx.Warn(cause, "append result not assigned to the same slice")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/appendCombine_checker.go b/vendor/github.com/go-critic/go-critic/checkers/appendCombine_checker.go
deleted file mode 100644
index 81a7aa30b..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/appendCombine_checker.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "github.com/go-toolsmith/astequal"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "appendCombine"
- info.Tags = []string{linter.PerformanceTag}
- info.Summary = "Detects `append` chains to the same slice that can be done in a single `append` call"
- info.Before = `
-xs = append(xs, 1)
-xs = append(xs, 2)`
- info.After = `xs = append(xs, 1, 2)`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmtList(&appendCombineChecker{ctx: ctx}), nil
- })
-}
-
-type appendCombineChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *appendCombineChecker) VisitStmtList(_ ast.Node, list []ast.Stmt) {
- var cause ast.Node // First append
- var slice ast.Expr // Slice being appended to
- chain := 0 // How much appends in a row we've seen
-
- // Break the chain.
- // If enough appends are in chain, print warning.
- flush := func() {
- if chain > 1 {
- c.warn(cause, chain)
- }
- chain = 0
- slice = nil
- }
-
- for _, stmt := range list {
- call := c.matchAppend(stmt, slice)
- if call == nil {
- flush()
- continue
- }
-
- if chain == 0 {
- // First append in a chain.
- chain = 1
- slice = call.Args[0]
- cause = stmt
- } else {
- chain++
- }
- }
-
- // Required for printing chains that consist of trailing
- // statements from the list.
- flush()
-}
-
-func (c *appendCombineChecker) matchAppend(stmt ast.Stmt, slice ast.Expr) *ast.CallExpr {
- // Seeking for:
- // slice = append(slice, xs...)
- // xs are 0-N append arguments, but not variadic argument,
- // because it makes append combining impossible.
-
- assign := astcast.ToAssignStmt(stmt)
- if len(assign.Lhs) != 1 || len(assign.Rhs) != 1 {
- return nil
- }
-
- call, ok := assign.Rhs[0].(*ast.CallExpr)
- {
- cond := ok &&
- qualifiedName(call.Fun) == "append" &&
- call.Ellipsis == token.NoPos &&
- astequal.Expr(assign.Lhs[0], call.Args[0])
- if !cond {
- return nil
- }
- }
-
- // Check that current append slice match previous append slice.
- // Otherwise we should break the chain.
- if slice == nil || astequal.Expr(slice, call.Args[0]) {
- return call
- }
- return nil
-}
-
-func (c *appendCombineChecker) warn(cause ast.Node, chain int) {
- c.ctx.Warn(cause, "can combine chain of %d appends into one", chain)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/badCond_checker.go b/vendor/github.com/go-critic/go-critic/checkers/badCond_checker.go
deleted file mode 100644
index 9be45ccc7..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/badCond_checker.go
+++ /dev/null
@@ -1,161 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/constant"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/checkers/internal/lintutil"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "github.com/go-toolsmith/astcopy"
- "github.com/go-toolsmith/astequal"
- "github.com/go-toolsmith/typep"
- "golang.org/x/tools/go/ast/astutil"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "badCond"
- info.Tags = []string{linter.DiagnosticTag}
- info.Summary = "Detects suspicious condition expressions"
- info.Before = `
-for i := 0; i > n; i++ {
- xs[i] = 0
-}`
- info.After = `
-for i := 0; i < n; i++ {
- xs[i] = 0
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForFuncDecl(&badCondChecker{ctx: ctx}), nil
- })
-}
-
-type badCondChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *badCondChecker) VisitFuncDecl(decl *ast.FuncDecl) {
- ast.Inspect(decl.Body, func(n ast.Node) bool {
- switch n := n.(type) {
- case *ast.ForStmt:
- c.checkForStmt(n)
- case ast.Expr:
- c.checkExpr(n)
- }
- return true
- })
-}
-
-func (c *badCondChecker) checkExpr(expr ast.Expr) {
- // TODO(quasilyte): recognize more patterns.
-
- cond := astcast.ToBinaryExpr(expr)
- lhs := astcast.ToBinaryExpr(astutil.Unparen(cond.X))
- rhs := astcast.ToBinaryExpr(astutil.Unparen(cond.Y))
-
- if cond.Op != token.LAND {
- return
- }
-
- // Notes:
- // `x != a || x != b` handled by go vet.
-
- // Pattern 1.
- // `x < a && x > b`; Where `a` is less than `b`.
- if c.lessAndGreater(lhs, rhs) {
- c.warnCond(cond, "always false")
- return
- }
-
- // Pattern 2.
- // `x == a && x == b`
- //
- // Valid when `b == a` is intended, but still reported.
- // We can disable "just suspicious" warnings by default
- // is users are upset with the current behavior.
- if c.equalToBoth(lhs, rhs) {
- c.warnCond(cond, "suspicious")
- return
- }
-}
-
-func (c *badCondChecker) equalToBoth(lhs, rhs *ast.BinaryExpr) bool {
- return lhs.Op == token.EQL && rhs.Op == token.EQL &&
- astequal.Expr(lhs.X, rhs.X)
-}
-
-func (c *badCondChecker) lessAndGreater(lhs, rhs *ast.BinaryExpr) bool {
- if lhs.Op != token.LSS || rhs.Op != token.GTR {
- return false
- }
- if !astequal.Expr(lhs.X, rhs.X) {
- return false
- }
- a := c.ctx.TypesInfo.Types[lhs.Y].Value
- b := c.ctx.TypesInfo.Types[rhs.Y].Value
- return a != nil && b != nil && constant.Compare(a, token.LSS, b)
-}
-
-func (c *badCondChecker) checkForStmt(stmt *ast.ForStmt) {
- // TODO(quasilyte): handle other kinds of bad conditionals.
-
- init := astcast.ToAssignStmt(stmt.Init)
- if init.Tok != token.DEFINE || len(init.Lhs) != 1 || len(init.Rhs) != 1 {
- return
- }
- if astcast.ToBasicLit(init.Rhs[0]).Value != "0" {
- return
- }
-
- iter := astcast.ToIdent(init.Lhs[0])
- cond := astcast.ToBinaryExpr(stmt.Cond)
-
- var i, n ast.Expr
- var op token.Token
- switch {
- case cond.Op == token.GTR && astequal.Expr(iter, cond.X):
- i = cond.X
- n = cond.Y
- op = token.LSS
- case cond.Op == token.LSS && astequal.Expr(iter, cond.Y):
- i = cond.Y
- n = cond.X
- op = token.GTR
- default:
- return
- }
-
- if !typep.SideEffectFree(c.ctx.TypesInfo, n) {
- return
- }
-
- post := astcast.ToIncDecStmt(stmt.Post)
- if post.Tok != token.INC || !astequal.Expr(iter, i) {
- return
- }
-
- mutated := lintutil.CouldBeMutated(c.ctx.TypesInfo, stmt.Body, n) ||
- lintutil.CouldBeMutated(c.ctx.TypesInfo, stmt.Body, iter)
- if mutated {
- return
- }
-
- c.warnForStmt(stmt, op, cond)
-}
-
-func (c *badCondChecker) warnForStmt(cause ast.Node, op token.Token, cond *ast.BinaryExpr) {
- suggest := astcopy.BinaryExpr(cond)
- suggest.Op = op
- c.ctx.Warn(cause, "`%s` in loop; probably meant `%s`?",
- cond, suggest)
-}
-
-func (c *badCondChecker) warnCond(cond *ast.BinaryExpr, tag string) {
- c.ctx.Warn(cond, "`%s` condition is %s", cond, tag)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/badRegexp_checker.go b/vendor/github.com/go-critic/go-critic/checkers/badRegexp_checker.go
deleted file mode 100644
index 6c6845053..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/badRegexp_checker.go
+++ /dev/null
@@ -1,446 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/constant"
- "sort"
- "strconv"
- "unicode"
- "unicode/utf8"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/quasilyte/regex/syntax"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "badRegexp"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects suspicious regexp patterns"
- info.Before = "regexp.MustCompile(`(?:^aa|bb|cc)foo[aba]`)"
- info.After = "regexp.MustCompile(`^(?:aa|bb|cc)foo[ab]`)"
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- opts := &syntax.ParserOptions{}
- c := &badRegexpChecker{
- ctx: ctx,
- parser: syntax.NewParser(opts),
- }
- return astwalk.WalkerForExpr(c), nil
- })
-}
-
-type badRegexpChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- parser *syntax.Parser
- cause ast.Expr
-
- flagStates []regexpFlagState
- goodAnchors []syntax.Position
-}
-
-type regexpFlagState [utf8.RuneSelf]bool
-
-func (c *badRegexpChecker) VisitExpr(x ast.Expr) {
- call, ok := x.(*ast.CallExpr)
- if !ok {
- return
- }
-
- switch qualifiedName(call.Fun) {
- case "regexp.Compile", "regexp.MustCompile":
- cv := c.ctx.TypesInfo.Types[call.Args[0]].Value
- if cv == nil || cv.Kind() != constant.String {
- return
- }
- pat := constant.StringVal(cv)
- c.cause = call.Args[0]
- c.checkPattern(pat)
- }
-}
-
-func (c *badRegexpChecker) checkPattern(pat string) {
- re, err := c.parser.Parse(pat)
- if err != nil {
- return
- }
-
- c.flagStates = c.flagStates[:0]
- c.goodAnchors = c.goodAnchors[:0]
-
- // In Go all flags (modifiers) are set to false by default,
- // so we start from the empty flag set.
- c.flagStates = append(c.flagStates, regexpFlagState{})
-
- c.markGoodCarets(re.Expr)
- c.walk(re.Expr)
-}
-
-func (c *badRegexpChecker) markGoodCarets(e syntax.Expr) {
- canSkip := func(e syntax.Expr) bool {
- switch e.Op {
- case syntax.OpFlagOnlyGroup:
- return true
- case syntax.OpGroup:
- x := e.Args[0]
- return x.Op == syntax.OpConcat && len(x.Args) == 0
- }
- return false
- }
-
- if e.Op == syntax.OpConcat && len(e.Args) > 1 {
- i := 0
- for i < len(e.Args) && canSkip(e.Args[i]) {
- i++
- }
- if i < len(e.Args) {
- c.markGoodCarets(e.Args[i])
- }
- return
- }
- if e.Op == syntax.OpCaret {
- c.addGoodAnchor(e.Pos)
- }
- for _, a := range e.Args {
- c.markGoodCarets(a)
- }
-}
-
-func (c *badRegexpChecker) walk(e syntax.Expr) {
- switch e.Op {
- case syntax.OpAlt:
- c.checkAltAnchor(e)
- c.checkAltDups(e)
- for _, a := range e.Args {
- c.walk(a)
- }
-
- case syntax.OpCharClass, syntax.OpNegCharClass:
- if c.checkCharClassRanges(e) {
- c.checkCharClassDups(e)
- }
-
- case syntax.OpStar, syntax.OpPlus:
- c.checkNestedQuantifier(e)
- c.walk(e.Args[0])
-
- case syntax.OpFlagOnlyGroup:
- c.updateFlagState(c.currentFlagState(), e, e.Args[0].Value)
- case syntax.OpGroupWithFlags:
- // Creates a new context using the current context copy.
- // New flags are evaluated inside a new context.
- // After nested expressions are processed, previous context is restored.
- nflags := len(c.flagStates)
- c.flagStates = append(c.flagStates, *c.currentFlagState())
- c.updateFlagState(c.currentFlagState(), e, e.Args[1].Value)
- c.walk(e.Args[0])
- c.flagStates = c.flagStates[:nflags]
- case syntax.OpGroup, syntax.OpCapture, syntax.OpNamedCapture:
- // Like with OpGroupWithFlags, but doesn't evaluate any new flags.
- nflags := len(c.flagStates)
- c.flagStates = append(c.flagStates, *c.currentFlagState())
- c.walk(e.Args[0])
- c.flagStates = c.flagStates[:nflags]
-
- case syntax.OpCaret:
- if !c.isGoodAnchor(e) {
- c.warn("dangling or redundant ^, maybe \\^ is intended?")
- }
-
- default:
- for _, a := range e.Args {
- c.walk(a)
- }
- }
-}
-
-func (c *badRegexpChecker) currentFlagState() *regexpFlagState {
- return &c.flagStates[len(c.flagStates)-1]
-}
-
-func (c *badRegexpChecker) updateFlagState(state *regexpFlagState, e syntax.Expr, flagString string) {
- clearing := false
- for i := 0; i < len(flagString); i++ {
- ch := flagString[i]
- if ch == '-' {
- clearing = true
- continue
- }
- if int(ch) >= len(state) {
- continue // Should never happen in practice, but we don't want a panic
- }
-
- if clearing {
- if !state[ch] {
- c.warn("clearing unset flag %c in %s", ch, e.Value)
- }
- } else {
- if state[ch] {
- c.warn("redundant flag %c in %s", ch, e.Value)
- }
- }
- state[ch] = !clearing
- }
-}
-
-func (c *badRegexpChecker) checkNestedQuantifier(e syntax.Expr) {
- x := e.Args[0]
- switch x.Op {
- case syntax.OpGroup, syntax.OpCapture, syntax.OpGroupWithFlags:
- if len(e.Args) == 1 {
- x = x.Args[0]
- }
- }
-
- switch x.Op {
- case syntax.OpPlus, syntax.OpStar:
- c.warn("repeated greedy quantifier in %s", e.Value)
- }
-}
-
-func (c *badRegexpChecker) checkAltDups(alt syntax.Expr) {
- // Seek duplicated alternation expressions.
-
- set := make(map[string]struct{}, len(alt.Args))
- for _, a := range alt.Args {
- if _, ok := set[a.Value]; ok {
- c.warn("`%s` is duplicated in %s", a.Value, alt.Value)
- }
- set[a.Value] = struct{}{}
- }
-}
-
-func (c *badRegexpChecker) isCharOrLit(e syntax.Expr) bool {
- return e.Op == syntax.OpChar || e.Op == syntax.OpLiteral
-}
-
-func (c *badRegexpChecker) checkAltAnchor(alt syntax.Expr) {
- // Seek suspicious anchors.
-
- // Case 1: an alternation of literals where 1st expr begins with ^ anchor.
- first := alt.Args[0]
- if first.Op == syntax.OpConcat && len(first.Args) == 2 && first.Args[0].Op == syntax.OpCaret && c.isCharOrLit(first.Args[1]) {
- matched := true
- for _, a := range alt.Args[1:] {
- if !c.isCharOrLit(a) {
- matched = false
- break
- }
- }
- if matched {
- c.warn("^ applied only to `%s` in %s", first.Value[len(`^`):], alt.Value)
- }
- }
-
- // Case 2: an alternation of literals where last expr ends with $ anchor.
- last := alt.Args[len(alt.Args)-1]
- if last.Op == syntax.OpConcat && len(last.Args) == 2 && last.Args[1].Op == syntax.OpDollar && c.isCharOrLit(last.Args[0]) {
- matched := true
- for _, a := range alt.Args[:len(alt.Args)-1] {
- if !c.isCharOrLit(a) {
- matched = false
- break
- }
- }
- if matched {
- c.warn("$ applied only to `%s` in %s", last.Value[:len(last.Value)-len(`$`)], alt.Value)
- }
- }
-}
-
-func (c *badRegexpChecker) checkCharClassRanges(cc syntax.Expr) bool {
- // Seek for suspicious ranges like `!-_`.
- //
- // We permit numerical ranges (0-9, hex and octal literals)
- // and simple ascii letter ranges.
-
- for _, e := range cc.Args {
- if e.Op != syntax.OpCharRange {
- continue
- }
- switch e.Args[0].Op {
- case syntax.OpEscapeOctal, syntax.OpEscapeHex:
- continue
- }
- ch := c.charClassBoundRune(e.Args[0])
- if ch == 0 {
- return false
- }
- good := unicode.IsLetter(ch) || (ch >= '0' && ch <= '9')
- if !good {
- c.warnSloppyCharRange(e.Value, cc.Value)
- }
- }
-
- return true
-}
-
-func (c *badRegexpChecker) checkCharClassDups(cc syntax.Expr) {
- // Seek for excessive elements inside a character class.
- // Report them as intersections.
-
- if len(cc.Args) == 1 {
- return // Can't had duplicates.
- }
-
- type charRange struct {
- low rune
- high rune
- source string
- }
- ranges := make([]charRange, 0, 8)
- addRange := func(source string, low, high rune) {
- ranges = append(ranges, charRange{source: source, low: low, high: high})
- }
- addRange1 := func(source string, ch rune) {
- addRange(source, ch, ch)
- }
-
- // 1. Collect ranges, O(n).
- for _, e := range cc.Args {
- switch e.Op {
- case syntax.OpEscapeOctal:
- addRange1(e.Value, c.octalToRune(e))
- case syntax.OpEscapeHex:
- addRange1(e.Value, c.hexToRune(e))
- case syntax.OpChar:
- addRange1(e.Value, c.stringToRune(e.Value))
- case syntax.OpCharRange:
- addRange(e.Value, c.charClassBoundRune(e.Args[0]), c.charClassBoundRune(e.Args[1]))
- case syntax.OpEscapeMeta:
- addRange1(e.Value, rune(e.Value[1]))
- case syntax.OpEscapeChar:
- ch := c.stringToRune(e.Value[len(`\`):])
- if unicode.IsPunct(ch) {
- addRange1(e.Value, ch)
- break
- }
- switch e.Value {
- case `\|`, `\<`, `\>`, `\+`, `\=`: // How to cover all symbols?
- addRange1(e.Value, c.stringToRune(e.Value[len(`\`):]))
- case `\t`:
- addRange1(e.Value, '\t')
- case `\n`:
- addRange1(e.Value, '\n')
- case `\r`:
- addRange1(e.Value, '\r')
- case `\v`:
- addRange1(e.Value, '\v')
- case `\d`:
- addRange(e.Value, '0', '9')
- case `\D`:
- addRange(e.Value, 0, '0'-1)
- addRange(e.Value, '9'+1, utf8.MaxRune)
- case `\s`:
- addRange(e.Value, '\t', '\n') // 9-10
- addRange(e.Value, '\f', '\r') // 12-13
- addRange1(e.Value, ' ') // 32
- case `\S`:
- addRange(e.Value, 0, '\t'-1)
- addRange(e.Value, '\n'+1, '\f'-1)
- addRange(e.Value, '\r'+1, ' '-1)
- addRange(e.Value, ' '+1, utf8.MaxRune)
- case `\w`:
- addRange(e.Value, '0', '9') // 48-57
- addRange(e.Value, 'A', 'Z') // 65-90
- addRange1(e.Value, '_') // 95
- addRange(e.Value, 'a', 'z') // 97-122
- case `\W`:
- addRange(e.Value, 0, '0'-1)
- addRange(e.Value, '9'+1, 'A'-1)
- addRange(e.Value, 'Z'+1, '_'-1)
- addRange(e.Value, '_'+1, 'a'-1)
- addRange(e.Value, 'z'+1, utf8.MaxRune)
- default:
- // Give up: unknown escape sequence.
- return
- }
- default:
- // Give up: unexpected operation inside char class.
- return
- }
- }
-
- // 2. Sort ranges, O(nlogn).
- sort.SliceStable(ranges, func(i, j int) bool {
- return ranges[i].low < ranges[j].low
- })
-
- // 3. Search for duplicates, O(n).
- for i := 0; i < len(ranges)-1; i++ {
- x := ranges[i+0]
- y := ranges[i+1]
- if x.high >= y.low {
- c.warnCharClassDup(x.source, y.source, cc.Value)
- break
- }
- }
-}
-
-func (c *badRegexpChecker) charClassBoundRune(e syntax.Expr) rune {
- switch e.Op {
- case syntax.OpChar:
- return c.stringToRune(e.Value)
- case syntax.OpEscapeHex:
- return c.hexToRune(e)
- case syntax.OpEscapeOctal:
- return c.octalToRune(e)
- default:
- return 0
- }
-}
-
-func (c *badRegexpChecker) octalToRune(e syntax.Expr) rune {
- v, _ := strconv.ParseInt(e.Value[len(`\`):], 8, 32)
- return rune(v)
-}
-
-func (c *badRegexpChecker) hexToRune(e syntax.Expr) rune {
- var s string
- switch e.Form {
- case syntax.FormEscapeHexFull:
- s = e.Value[len(`\x{`) : len(e.Value)-len(`}`)]
- default:
- s = e.Value[len(`\x`):]
- }
- v, _ := strconv.ParseInt(s, 16, 32)
- return rune(v)
-}
-
-func (c *badRegexpChecker) stringToRune(s string) rune {
- ch, _ := utf8.DecodeRuneInString(s)
- return ch
-}
-
-func (c *badRegexpChecker) addGoodAnchor(pos syntax.Position) {
- c.goodAnchors = append(c.goodAnchors, pos)
-}
-
-func (c *badRegexpChecker) isGoodAnchor(e syntax.Expr) bool {
- for _, pos := range c.goodAnchors {
- if e.Pos == pos {
- return true
- }
- }
- return false
-}
-
-func (c *badRegexpChecker) warn(format string, args ...interface{}) {
- c.ctx.Warn(c.cause, format, args...)
-}
-
-func (c *badRegexpChecker) warnSloppyCharRange(rng, charClass string) {
- c.ctx.Warn(c.cause, "suspicious char range `%s` in %s", rng, charClass)
-}
-
-func (c *badRegexpChecker) warnCharClassDup(x, y, charClass string) {
- if x == y {
- c.ctx.Warn(c.cause, "`%s` is duplicated in %s", x, charClass)
- } else {
- c.ctx.Warn(c.cause, "`%s` intersects with `%s` in %s", x, y, charClass)
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/boolExprSimplify_checker.go b/vendor/github.com/go-critic/go-critic/checkers/boolExprSimplify_checker.go
deleted file mode 100644
index a1c69cb7a..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/boolExprSimplify_checker.go
+++ /dev/null
@@ -1,346 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
- "strconv"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/checkers/internal/lintutil"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "github.com/go-toolsmith/astcopy"
- "github.com/go-toolsmith/astequal"
- "github.com/go-toolsmith/astp"
- "github.com/go-toolsmith/typep"
- "golang.org/x/tools/go/ast/astutil"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "boolExprSimplify"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag}
- info.Summary = "Detects bool expressions that can be simplified"
- info.Before = `
-a := !(elapsed >= expectElapsedMin)
-b := !(x) == !(y)`
- info.After = `
-a := elapsed < expectElapsedMin
-b := (x) == (y)`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForExpr(&boolExprSimplifyChecker{ctx: ctx}), nil
- })
-}
-
-type boolExprSimplifyChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
- hasFloats bool
-}
-
-func (c *boolExprSimplifyChecker) VisitExpr(x ast.Expr) {
- if !astp.IsBinaryExpr(x) && !astp.IsUnaryExpr(x) {
- return
- }
-
- // Throw away non-bool expressions and avoid redundant
- // AST copying below.
- if typ := c.ctx.TypeOf(x); typ == nil || !typep.HasBoolKind(typ.Underlying()) {
- return
- }
-
- // We'll loose all types info after a copy,
- // this is why we record valuable info before doing it.
- c.hasFloats = lintutil.ContainsNode(x, func(n ast.Node) bool {
- if x, ok := n.(*ast.BinaryExpr); ok {
- return typep.HasFloatProp(c.ctx.TypeOf(x.X).Underlying()) ||
- typep.HasFloatProp(c.ctx.TypeOf(x.Y).Underlying())
- }
- return false
- })
-
- y := c.simplifyBool(astcopy.Expr(x))
- if !astequal.Expr(x, y) {
- c.warn(x, y)
- }
-}
-
-func (c *boolExprSimplifyChecker) simplifyBool(x ast.Expr) ast.Expr {
- return astutil.Apply(x, nil, func(cur *astutil.Cursor) bool {
- return c.doubleNegation(cur) ||
- c.negatedEquals(cur) ||
- c.invertComparison(cur) ||
- c.combineChecks(cur) ||
- c.removeIncDec(cur) ||
- c.foldRanges(cur) ||
- true
- }).(ast.Expr)
-}
-
-func (c *boolExprSimplifyChecker) doubleNegation(cur *astutil.Cursor) bool {
- neg1 := astcast.ToUnaryExpr(cur.Node())
- neg2 := astcast.ToUnaryExpr(astutil.Unparen(neg1.X))
- if neg1.Op == token.NOT && neg2.Op == token.NOT {
- cur.Replace(astutil.Unparen(neg2.X))
- return true
- }
- return false
-}
-
-func (c *boolExprSimplifyChecker) negatedEquals(cur *astutil.Cursor) bool {
- x, ok := cur.Node().(*ast.BinaryExpr)
- if !ok || x.Op != token.EQL {
- return false
- }
- neg1 := astcast.ToUnaryExpr(x.X)
- neg2 := astcast.ToUnaryExpr(x.Y)
- if neg1.Op == token.NOT && neg2.Op == token.NOT {
- x.X = neg1.X
- x.Y = neg2.X
- return true
- }
- return false
-}
-
-func (c *boolExprSimplifyChecker) invertComparison(cur *astutil.Cursor) bool {
- if c.hasFloats { // See #673
- return false
- }
-
- neg := astcast.ToUnaryExpr(cur.Node())
- cmp := astcast.ToBinaryExpr(astutil.Unparen(neg.X))
- if neg.Op != token.NOT {
- return false
- }
-
- // Replace operator to its negated form.
- switch cmp.Op {
- case token.EQL:
- cmp.Op = token.NEQ
- case token.NEQ:
- cmp.Op = token.EQL
- case token.LSS:
- cmp.Op = token.GEQ
- case token.GTR:
- cmp.Op = token.LEQ
- case token.LEQ:
- cmp.Op = token.GTR
- case token.GEQ:
- cmp.Op = token.LSS
-
- default:
- return false
- }
- cur.Replace(cmp)
- return true
-}
-
-func (c *boolExprSimplifyChecker) isSafe(x ast.Expr) bool {
- return typep.SideEffectFree(c.ctx.TypesInfo, x)
-}
-
-func (c *boolExprSimplifyChecker) combineChecks(cur *astutil.Cursor) bool {
- or, ok := cur.Node().(*ast.BinaryExpr)
- if !ok || or.Op != token.LOR {
- return false
- }
-
- lhs := astcast.ToBinaryExpr(astutil.Unparen(or.X))
- rhs := astcast.ToBinaryExpr(astutil.Unparen(or.Y))
-
- if !astequal.Expr(lhs.X, rhs.X) || !astequal.Expr(lhs.Y, rhs.Y) {
- return false
- }
- if !c.isSafe(lhs.X) || !c.isSafe(lhs.Y) {
- return false
- }
-
- combTable := [...]struct {
- x token.Token
- y token.Token
- result token.Token
- }{
- {token.GTR, token.EQL, token.GEQ},
- {token.EQL, token.GTR, token.GEQ},
- {token.LSS, token.EQL, token.LEQ},
- {token.EQL, token.LSS, token.LEQ},
- }
- for _, comb := range &combTable {
- if comb.x == lhs.Op && comb.y == rhs.Op {
- lhs.Op = comb.result
- cur.Replace(lhs)
- return true
- }
- }
- return false
-}
-
-func (c *boolExprSimplifyChecker) removeIncDec(cur *astutil.Cursor) bool {
- cmp := astcast.ToBinaryExpr(cur.Node())
-
- matchOneWay := func(op token.Token, x, y *ast.BinaryExpr) bool {
- if x.Op != op || astcast.ToBasicLit(x.Y).Value != "1" {
- return false
- }
- if y.Op == op && astcast.ToBasicLit(y.Y).Value == "1" {
- return false
- }
- return true
- }
- replace := func(lhsOp, rhsOp, replacement token.Token) bool {
- lhs := astcast.ToBinaryExpr(cmp.X)
- rhs := astcast.ToBinaryExpr(cmp.Y)
- switch {
- case matchOneWay(lhsOp, lhs, rhs):
- cmp.X = lhs.X
- cmp.Op = replacement
- cur.Replace(cmp)
- return true
- case matchOneWay(rhsOp, rhs, lhs):
- cmp.Y = rhs.X
- cmp.Op = replacement
- cur.Replace(cmp)
- return true
- default:
- return false
- }
- }
-
- switch cmp.Op {
- case token.GTR:
- // `x > y-1` => `x >= y`
- // `x+1 > y` => `x >= y`
- return replace(token.ADD, token.SUB, token.GEQ)
-
- case token.GEQ:
- // `x >= y+1` => `x > y`
- // `x-1 >= y` => `x > y`
- return replace(token.SUB, token.ADD, token.GTR)
-
- case token.LSS:
- // `x < y+1` => `x <= y`
- // `x-1 < y` => `x <= y`
- return replace(token.SUB, token.ADD, token.LEQ)
-
- case token.LEQ:
- // `x <= y-1` => `x < y`
- // `x+1 <= y` => `x < y`
- return replace(token.ADD, token.SUB, token.LSS)
-
- default:
- return false
- }
-}
-
-func (c *boolExprSimplifyChecker) foldRanges(cur *astutil.Cursor) bool {
- if c.hasFloats { // See #848
- return false
- }
-
- e, ok := cur.Node().(*ast.BinaryExpr)
- if !ok {
- return false
- }
- lhs := astcast.ToBinaryExpr(e.X)
- rhs := astcast.ToBinaryExpr(e.Y)
- if !c.isSafe(lhs.X) || !c.isSafe(rhs.X) {
- return false
- }
- if !astequal.Expr(lhs.X, rhs.X) {
- return false
- }
-
- c1, ok := c.int64val(lhs.Y)
- if !ok {
- return false
- }
- c2, ok := c.int64val(rhs.Y)
- if !ok {
- return false
- }
-
- type combination struct {
- lhsOp token.Token
- rhsOp token.Token
- rhsDiff int64
- resDelta int64
- }
- match := func(comb *combination) bool {
- if lhs.Op != comb.lhsOp || rhs.Op != comb.rhsOp {
- return false
- }
- if c2-c1 != comb.rhsDiff {
- return false
- }
- return true
- }
-
- switch e.Op {
- case token.LAND:
- combTable := [...]combination{
- // `x > c && x < c+2` => `x == c+1`
- {token.GTR, token.LSS, 2, 1},
- // `x >= c && x < c+1` => `x == c`
- {token.GEQ, token.LSS, 1, 0},
- // `x > c && x <= c+1` => `x == c+1`
- {token.GTR, token.LEQ, 1, 1},
- // `x >= c && x <= c` => `x == c`
- {token.GEQ, token.LEQ, 0, 0},
- }
- for i := range combTable {
- comb := combTable[i]
- if match(&comb) {
- lhs.Op = token.EQL
- v := c1 + comb.resDelta
- lhs.Y.(*ast.BasicLit).Value = strconv.FormatInt(v, 10)
- cur.Replace(lhs)
- return true
- }
- }
-
- case token.LOR:
- combTable := [...]combination{
- // `x < c || x > c` => `x != c`
- {token.LSS, token.GTR, 0, 0},
- // `x <= c || x > c+1` => `x != c+1`
- {token.LEQ, token.GTR, 1, 1},
- // `x < c || x >= c+1` => `x != c`
- {token.LSS, token.GEQ, 1, 0},
- // `x <= c || x >= c+2` => `x != c+1`
- {token.LEQ, token.GEQ, 2, 1},
- }
- for i := range combTable {
- comb := combTable[i]
- if match(&comb) {
- lhs.Op = token.NEQ
- v := c1 + comb.resDelta
- lhs.Y.(*ast.BasicLit).Value = strconv.FormatInt(v, 10)
- cur.Replace(lhs)
- return true
- }
- }
- }
-
- return false
-}
-
-func (c *boolExprSimplifyChecker) int64val(x ast.Expr) (int64, bool) {
- // TODO(quasilyte): if we had types info, we could use TypesInfo.Types[x].Value,
- // but since copying erases leaves us without it, only basic literals are handled.
- lit, ok := x.(*ast.BasicLit)
- if !ok {
- return 0, false
- }
- v, err := strconv.ParseInt(lit.Value, 10, 64)
- if err != nil {
- return 0, false
- }
- return v, true
-}
-
-func (c *boolExprSimplifyChecker) warn(cause, suggestion ast.Expr) {
- c.SkipChilds = true
- c.ctx.Warn(cause, "can simplify `%s` to `%s`", cause, suggestion)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/builtinShadowDecl_checker.go b/vendor/github.com/go-critic/go-critic/checkers/builtinShadowDecl_checker.go
deleted file mode 100644
index d8be10ce9..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/builtinShadowDecl_checker.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "builtinShadowDecl"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects top-level declarations that shadow the predeclared identifiers"
- info.Before = `type int struct {}`
- info.After = `type myInt struct {}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return &builtinShadowDeclChecker{ctx: ctx}, nil
- })
-}
-
-type builtinShadowDeclChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *builtinShadowDeclChecker) WalkFile(f *ast.File) {
- for _, decl := range f.Decls {
- switch decl := decl.(type) {
- case *ast.FuncDecl:
- // Don't check methods. They can shadow anything safely.
- if decl.Recv == nil {
- c.checkName(decl.Name)
- }
- case *ast.GenDecl:
- c.visitGenDecl(decl)
- }
- }
-}
-
-func (c *builtinShadowDeclChecker) visitGenDecl(decl *ast.GenDecl) {
- for _, spec := range decl.Specs {
- switch spec := spec.(type) {
- case *ast.ValueSpec:
- for _, name := range spec.Names {
- c.checkName(name)
- }
- case *ast.TypeSpec:
- c.checkName(spec.Name)
- }
- }
-}
-
-func (c *builtinShadowDeclChecker) checkName(name *ast.Ident) {
- if isBuiltin(name.Name) {
- c.warn(name)
- }
-}
-
-func (c *builtinShadowDeclChecker) warn(ident *ast.Ident) {
- c.ctx.Warn(ident, "shadowing of predeclared identifier: %s", ident)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/builtinShadow_checker.go b/vendor/github.com/go-critic/go-critic/checkers/builtinShadow_checker.go
deleted file mode 100644
index 0b4b7bafb..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/builtinShadow_checker.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "builtinShadow"
- info.Tags = []string{linter.StyleTag, linter.OpinionatedTag}
- info.Summary = "Detects when predeclared identifiers are shadowed in assignments"
- info.Before = `len := 10`
- info.After = `length := 10`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForLocalDef(&builtinShadowChecker{ctx: ctx}, ctx.TypesInfo), nil
- })
-}
-
-type builtinShadowChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *builtinShadowChecker) VisitLocalDef(name astwalk.Name, _ ast.Expr) {
- if isBuiltin(name.ID.Name) {
- c.warn(name.ID)
- }
-}
-
-func (c *builtinShadowChecker) warn(ident *ast.Ident) {
- c.ctx.Warn(ident, "shadowing of predeclared identifier: %s", ident)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/captLocal_checker.go b/vendor/github.com/go-critic/go-critic/checkers/captLocal_checker.go
deleted file mode 100644
index b31a6f7fd..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/captLocal_checker.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "captLocal"
- info.Tags = []string{linter.StyleTag}
- info.Params = linter.CheckerParams{
- "paramsOnly": {
- Value: true,
- Usage: "whether to restrict checker to params only",
- },
- }
- info.Summary = "Detects capitalized names for local variables"
- info.Before = `func f(IN int, OUT *int) (ERR error) {}`
- info.After = `func f(in int, out *int) (err error) {}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- c := &captLocalChecker{ctx: ctx}
- c.paramsOnly = info.Params.Bool("paramsOnly")
- return astwalk.WalkerForLocalDef(c, ctx.TypesInfo), nil
- })
-}
-
-type captLocalChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- paramsOnly bool
-}
-
-func (c *captLocalChecker) VisitLocalDef(def astwalk.Name, _ ast.Expr) {
- if c.paramsOnly && def.Kind != astwalk.NameParam {
- return
- }
- if ast.IsExported(def.ID.Name) {
- c.warn(def.ID)
- }
-}
-
-func (c *captLocalChecker) warn(id ast.Node) {
- c.ctx.Warn(id, "`%s' should not be capitalized", id)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/caseOrder_checker.go b/vendor/github.com/go-critic/go-critic/checkers/caseOrder_checker.go
deleted file mode 100644
index 345274f1c..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/caseOrder_checker.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "caseOrder"
- info.Tags = []string{linter.DiagnosticTag}
- info.Summary = "Detects erroneous case order inside switch statements"
- info.Before = `
-switch x.(type) {
-case ast.Expr:
- fmt.Println("expr")
-case *ast.BasicLit:
- fmt.Println("basic lit") // Never executed
-}`
- info.After = `
-switch x.(type) {
-case *ast.BasicLit:
- fmt.Println("basic lit") // Now reachable
-case ast.Expr:
- fmt.Println("expr")
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&caseOrderChecker{ctx: ctx}), nil
- })
-}
-
-type caseOrderChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *caseOrderChecker) VisitStmt(stmt ast.Stmt) {
- switch stmt := stmt.(type) {
- case *ast.TypeSwitchStmt:
- c.checkTypeSwitch(stmt)
- case *ast.SwitchStmt:
- c.checkSwitch(stmt)
- }
-}
-
-func (c *caseOrderChecker) checkTypeSwitch(s *ast.TypeSwitchStmt) {
- type ifaceType struct {
- node ast.Node
- typ *types.Interface
- }
- var ifaces []ifaceType // Interfaces seen so far
- for _, cc := range s.Body.List {
- cc := cc.(*ast.CaseClause)
- for _, x := range cc.List {
- typ := c.ctx.TypeOf(x)
- if typ == linter.UnknownType {
- c.warnUnknownType(cc, x)
- return
- }
- for _, iface := range ifaces {
- if types.Implements(typ, iface.typ) {
- c.warnTypeSwitch(cc, x, iface.node)
- break
- }
- }
- if iface, ok := typ.Underlying().(*types.Interface); ok {
- ifaces = append(ifaces, ifaceType{node: x, typ: iface})
- }
- }
- }
-}
-
-func (c *caseOrderChecker) warnTypeSwitch(cause, concrete, iface ast.Node) {
- c.ctx.Warn(cause, "case %s must go before the %s case", concrete, iface)
-}
-
-func (c *caseOrderChecker) warnUnknownType(cause, concrete ast.Node) {
- c.ctx.Warn(cause, "type is not defined %s", concrete)
-}
-
-func (c *caseOrderChecker) checkSwitch(_ *ast.SwitchStmt) {
- // TODO(quasilyte): can handle expression cases that overlap.
- // Cases that have narrower value range should go before wider ones.
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/checkers.go b/vendor/github.com/go-critic/go-critic/checkers/checkers.go
deleted file mode 100644
index 5797dafdf..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/checkers.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Package checkers is a gocritic linter main checkers collection.
-package checkers
-
-import (
- "os"
-
- "github.com/go-critic/go-critic/linter"
-)
-
-var collection = &linter.CheckerCollection{
- URL: "https://github.com/go-critic/go-critic/checkers",
-}
-
-var debug = func() func() bool {
- v := os.Getenv("DEBUG") != ""
- return func() bool {
- return v
- }
-}()
diff --git a/vendor/github.com/go-critic/go-critic/checkers/codegenComment_checker.go b/vendor/github.com/go-critic/go-critic/checkers/codegenComment_checker.go
deleted file mode 100644
index 6eeb0bb5d..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/codegenComment_checker.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "regexp"
- "strings"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "codegenComment"
- info.Tags = []string{linter.DiagnosticTag}
- info.Summary = "Detects malformed 'code generated' file comments"
- info.Before = `// This file was automatically generated by foogen`
- info.After = `// Code generated by foogen. DO NOT EDIT.`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- patterns := []string{
- "this (?:file|code) (?:was|is) auto(?:matically)? generated",
- "this (?:file|code) (?:was|is) generated automatically",
- "this (?:file|code) (?:was|is) generated by",
- "this (?:file|code) (?:was|is) (?:auto(?:matically)? )?generated",
- "this (?:file|code) (?:was|is) generated",
- "code in this file (?:was|is) auto(?:matically)? generated",
- "generated (?:file|code) - do not edit",
- // TODO(quasilyte): more of these.
- }
- re := regexp.MustCompile("(?i)" + strings.Join(patterns, "|"))
- return &codegenCommentChecker{
- ctx: ctx,
- badCommentRE: re,
- }, nil
- })
-}
-
-type codegenCommentChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- badCommentRE *regexp.Regexp
-}
-
-func (c *codegenCommentChecker) WalkFile(f *ast.File) {
- if f.Doc == nil {
- return
- }
-
- for _, comment := range f.Doc.List {
- if c.badCommentRE.MatchString(comment.Text) {
- c.warn(comment)
- return
- }
- }
-}
-
-func (c *codegenCommentChecker) warn(cause ast.Node) {
- c.ctx.Warn(cause, "comment should match `Code generated .* DO NOT EDIT.` regexp")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/commentFormatting_checker.go b/vendor/github.com/go-critic/go-critic/checkers/commentFormatting_checker.go
deleted file mode 100644
index b834158ec..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/commentFormatting_checker.go
+++ /dev/null
@@ -1,123 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "regexp"
- "strings"
- "unicode"
- "unicode/utf8"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "commentFormatting"
- info.Tags = []string{linter.StyleTag}
- info.Summary = "Detects comments with non-idiomatic formatting"
- info.Before = `//This is a comment`
- info.After = `// This is a comment`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- regexpPatterns := []*regexp.Regexp{
- regexp.MustCompile(`^//[\w-]+:.*$`), // e.g.: key: value
- }
- equalPatterns := []string{
- "//nolint",
- }
- parts := []string{
- "//go:generate ", // e.g.: go:generate value
- "//line /", // e.g.: line /path/to/file:123
- "//nolint ", // e.g.: nolint
- "//noinspection ", // e.g.: noinspection ALL, some GoLand and friends versions
- "//region", // e.g.: region awawa, used by GoLand and friends for custom folding
- "//endregion", // e.g.: endregion awawa or endregion, closes GoLand regions
- "//<editor-fold", // e.g.: <editor-fold desc="awawa"> or <editor-fold>, used by VSCode for custom folding
- "//</editor-fold>", // e.g.: </editor-fold>, closes VSCode regions
- "//export ", // e.g.: export Foo
- "///", // e.g.: vertical breaker /////////////
- "//+",
- "//#",
- "//-",
- "//!",
- }
-
- return astwalk.WalkerForComment(&commentFormattingChecker{
- ctx: ctx,
- partPatterns: parts,
- equalPatterns: equalPatterns,
- regexpPatterns: regexpPatterns,
- }), nil
- })
-}
-
-type commentFormattingChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- partPatterns []string
- equalPatterns []string
- regexpPatterns []*regexp.Regexp
-}
-
-func (c *commentFormattingChecker) VisitComment(cg *ast.CommentGroup) {
- if strings.HasPrefix(cg.List[0].Text, "/*") {
- return
- }
-
-outerLoop:
- for _, comment := range cg.List {
- commentLen := len(comment.Text)
- if commentLen <= len("// ") {
- continue
- }
-
- for _, p := range c.partPatterns {
- if commentLen < len(p) {
- continue
- }
-
- if strings.EqualFold(comment.Text[:len(p)], p) {
- continue outerLoop
- }
- }
-
- for _, p := range c.equalPatterns {
- if strings.EqualFold(comment.Text, p) {
- continue outerLoop
- }
- }
-
- for _, p := range c.regexpPatterns {
- if p.MatchString(comment.Text) {
- continue outerLoop
- }
- }
-
- // Make a decision based on a first comment text rune.
- r, _ := utf8.DecodeRuneInString(comment.Text[len("//"):])
- if !c.specialChar(r) && !unicode.IsSpace(r) {
- c.warn(comment)
- return
- }
- }
-}
-
-func (c *commentFormattingChecker) specialChar(r rune) bool {
- // Permitted list to avoid false-positives.
- switch r {
- case '+', '-', '#', '!':
- return true
- default:
- return false
- }
-}
-
-func (c *commentFormattingChecker) warn(comment *ast.Comment) {
- c.ctx.WarnFixable(comment, linter.QuickFix{
- From: comment.Pos(),
- To: comment.End(),
- Replacement: []byte(strings.Replace(comment.Text, "//", "// ", 1)),
- }, "put a space between `//` and comment text")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/commentedOutCode_checker.go b/vendor/github.com/go-critic/go-critic/checkers/commentedOutCode_checker.go
deleted file mode 100644
index 8595b7951..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/commentedOutCode_checker.go
+++ /dev/null
@@ -1,167 +0,0 @@
-package checkers
-
-import (
- "fmt"
- "go/ast"
- "go/token"
- "regexp"
- "strings"
- "unicode/utf8"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/strparse"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "commentedOutCode"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects commented-out code inside function bodies"
- info.Params = linter.CheckerParams{
- "minLength": {
- Value: 15,
- Usage: "min length of the comment that triggers a warning",
- },
- }
- info.Before = `
-// fmt.Println("Debugging hard")
-foo(1, 2)`
- info.After = `foo(1, 2)`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForLocalComment(&commentedOutCodeChecker{
- ctx: ctx,
- notQuiteFuncCall: regexp.MustCompile(`\w+\s+\([^)]*\)\s*$`),
- minLength: info.Params.Int("minLength"),
- }), nil
- })
-}
-
-type commentedOutCodeChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
- fn *ast.FuncDecl
-
- notQuiteFuncCall *regexp.Regexp
- minLength int
-}
-
-func (c *commentedOutCodeChecker) EnterFunc(fn *ast.FuncDecl) bool {
- c.fn = fn // Need to store current function inside checker context
- return fn.Body != nil
-}
-
-func (c *commentedOutCodeChecker) VisitLocalComment(cg *ast.CommentGroup) {
- s := cg.Text() // Collect text once
-
- // We do multiple heuristics to avoid false positives.
- // Many things can be improved here.
-
- markers := []string{
- "TODO", // TODO comments with code are permitted.
-
- // "http://" is interpreted as a label with comment.
- // There are other protocols we might want to include.
- "http://",
- "https://",
-
- "e.g. ", // Clearly not a "selector expr" (mostly due to extra space)
- }
- for _, m := range markers {
- if strings.Contains(s, m) {
- return
- }
- }
-
- // Some very short comment that can be skipped.
- // Usually triggering on these results in false positive.
- // Unless there is a very popular call like print/println.
- cond := utf8.RuneCountInString(s) < c.minLength &&
- !strings.Contains(s, "print") &&
- !strings.Contains(s, "fmt.") &&
- !strings.Contains(s, "log.")
- if cond {
- return
- }
-
- // Almost looks like a commented-out function call,
- // but there is a whitespace between function name and
- // parameters list. Skip these to avoid false positives.
- if c.notQuiteFuncCall.MatchString(s) {
- return
- }
-
- stmt := strparse.Stmt(s)
-
- if c.isPermittedStmt(stmt) {
- return
- }
-
- if stmt != strparse.BadStmt {
- c.warn(cg)
- return
- }
-
- // Don't try to parse one-liner as block statement
- if len(cg.List) == 1 && !strings.Contains(s, "\n") {
- return
- }
-
- // Some attempts to avoid false positives.
- if c.skipBlock(s) {
- return
- }
-
- // Add braces to make block statement from
- // multiple statements.
- stmt = strparse.Stmt(fmt.Sprintf("{ %s }", s))
-
- if stmt, ok := stmt.(*ast.BlockStmt); ok && len(stmt.List) != 0 {
- c.warn(cg)
- }
-}
-
-func (c *commentedOutCodeChecker) skipBlock(s string) bool {
- lines := strings.Split(s, "\n") // There is at least 1 line, that's invariant
-
- // Special example test block.
- if isExampleTestFunc(c.fn) && strings.Contains(lines[0], "Output:") {
- return true
- }
-
- return false
-}
-
-func (c *commentedOutCodeChecker) isPermittedStmt(stmt ast.Stmt) bool {
- switch stmt := stmt.(type) {
- case *ast.ExprStmt:
- return c.isPermittedExpr(stmt.X)
- case *ast.LabeledStmt:
- return c.isPermittedStmt(stmt.Stmt)
- case *ast.DeclStmt:
- decl := stmt.Decl.(*ast.GenDecl)
- return decl.Tok == token.TYPE
- default:
- return false
- }
-}
-
-func (c *commentedOutCodeChecker) isPermittedExpr(x ast.Expr) bool {
- // Permit anything except expressions that can be used
- // with complete result discarding.
- switch x := x.(type) {
- case *ast.CallExpr:
- return false
- case *ast.UnaryExpr:
- // "<-" channel receive is not permitted.
- return x.Op != token.ARROW
- default:
- return true
- }
-}
-
-func (c *commentedOutCodeChecker) warn(cause ast.Node) {
- c.ctx.Warn(cause, "may want to remove commented-out code")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/commentedOutImport_checker.go b/vendor/github.com/go-critic/go-critic/checkers/commentedOutImport_checker.go
deleted file mode 100644
index e0855da81..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/commentedOutImport_checker.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
- "regexp"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "commentedOutImport"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag}
- info.Summary = "Detects commented-out imports"
- info.Before = `
-import (
- "fmt"
- //"os"
-)`
- info.After = `
-import (
- "fmt"
-)`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- const pattern = `(?m)^(?://|/\*)?\s*"([a-zA-Z0-9_/]+)"\s*(?:\*/)?$`
- return &commentedOutImportChecker{
- ctx: ctx,
- importStringRE: regexp.MustCompile(pattern),
- }, nil
- })
-}
-
-type commentedOutImportChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- importStringRE *regexp.Regexp
-}
-
-func (c *commentedOutImportChecker) WalkFile(f *ast.File) {
- // TODO(quasilyte): handle commented-out import spec,
- // for example: // import "errors".
-
- for _, decl := range f.Decls {
- decl, ok := decl.(*ast.GenDecl)
- if !ok || decl.Tok != token.IMPORT {
- // Import decls can only be in the beginning of the file.
- // If we've met some other decl, there will be no more
- // import decls.
- break
- }
-
- // Find comments inside this import decl span.
- for _, cg := range f.Comments {
- if cg.Pos() > decl.Rparen {
- break // Below the decl, stop.
- }
- if cg.Pos() < decl.Lparen {
- continue // Before the decl, skip.
- }
-
- for _, comment := range cg.List {
- for _, m := range c.importStringRE.FindAllStringSubmatch(comment.Text, -1) {
- c.warn(comment, m[1])
- }
- }
- }
- }
-}
-
-func (c *commentedOutImportChecker) warn(cause ast.Node, path string) {
- c.ctx.Warn(cause, "remove commented-out %q import", path)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/defaultCaseOrder_checker.go b/vendor/github.com/go-critic/go-critic/checkers/defaultCaseOrder_checker.go
deleted file mode 100644
index cdebaef98..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/defaultCaseOrder_checker.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "defaultCaseOrder"
- info.Tags = []string{linter.StyleTag}
- info.Summary = "Detects when default case in switch isn't on 1st or last position"
- info.Before = `
-switch {
-case x > y:
- // ...
-default: // <- not the best position
- // ...
-case x == 10:
- // ...
-}`
- info.After = `
-switch {
-case x > y:
- // ...
-case x == 10:
- // ...
-default: // <- last case (could also be the first one)
- // ...
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&defaultCaseOrderChecker{ctx: ctx}), nil
- })
-}
-
-type defaultCaseOrderChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *defaultCaseOrderChecker) VisitStmt(stmt ast.Stmt) {
- swtch, ok := stmt.(*ast.SwitchStmt)
- if !ok {
- return
- }
- for i, stmt := range swtch.Body.List {
- caseStmt, ok := stmt.(*ast.CaseClause)
- if !ok {
- continue
- }
- // is `default` case
- if caseStmt.List == nil {
- if i != 0 && i != len(swtch.Body.List)-1 {
- c.warn(caseStmt)
- }
- }
- }
-}
-
-func (c *defaultCaseOrderChecker) warn(cause *ast.CaseClause) {
- c.ctx.Warn(cause, "consider to make `default` case as first or as last case")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/deferInLoop_checker.go b/vendor/github.com/go-critic/go-critic/checkers/deferInLoop_checker.go
deleted file mode 100644
index 37c80c864..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/deferInLoop_checker.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "deferInLoop"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects loops inside functions that use defer"
- info.Before = `
-for _, filename := range []string{"foo", "bar"} {
- f, err := os.Open(filename)
-
- defer f.Close()
-}
-`
- info.After = `
-func process(filename string) {
- f, err := os.Open(filename)
-
- defer f.Close()
-}
-/* ... */
-for _, filename := range []string{"foo", "bar"} {
- process(filename)
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForFuncDecl(&deferInLoopChecker{ctx: ctx}), nil
- })
-}
-
-type deferInLoopChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
- inFor bool
-}
-
-func (c *deferInLoopChecker) VisitFuncDecl(fn *ast.FuncDecl) {
- ast.Inspect(fn.Body, c.traversalFunc)
-}
-
-func (c deferInLoopChecker) traversalFunc(cur ast.Node) bool {
- switch n := cur.(type) {
- case *ast.DeferStmt:
- if c.inFor {
- c.warn(n)
- }
- case *ast.RangeStmt, *ast.ForStmt:
- if !c.inFor {
- ast.Inspect(cur, deferInLoopChecker{ctx: c.ctx, inFor: true}.traversalFunc)
- return false
- }
- case *ast.FuncLit:
- ast.Inspect(n.Body, deferInLoopChecker{ctx: c.ctx, inFor: false}.traversalFunc)
- return false
- case nil:
- return false
- }
- return true
-}
-
-func (c *deferInLoopChecker) warn(cause *ast.DeferStmt) {
- c.ctx.Warn(cause, "Possible resource leak, 'defer' is called in the 'for' loop")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/deprecatedComment_checker.go b/vendor/github.com/go-critic/go-critic/checkers/deprecatedComment_checker.go
deleted file mode 100644
index c61d773da..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/deprecatedComment_checker.go
+++ /dev/null
@@ -1,156 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "strings"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "deprecatedComment"
- info.Tags = []string{linter.DiagnosticTag}
- info.Summary = "Detects malformed 'deprecated' doc-comments"
- info.Before = `
-// deprecated, use FuncNew instead
-func FuncOld() int`
- info.After = `
-// Deprecated: use FuncNew instead
-func FuncOld() int`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- c := &deprecatedCommentChecker{ctx: ctx}
-
- c.commonPatterns = []string{
- "this type is deprecated",
- "this function is deprecated",
- "[[deprecated]]",
- "note: deprecated",
- "deprecated in",
- "deprecated. use",
- "deprecated! use",
- "deprecated use",
- // TODO(quasilyte): more of these?
- }
-
- // TODO(quasilyte): may want to generate this list programmatically.
- //
- // TODO(quasilyte): currently it only handles a single missing letter.
- // Might want to handle other kinds of common misspell/typo kinds.
- c.commonTypos = []string{
- "Dprecated: ",
- "Derecated: ",
- "Depecated: ",
- "Depekated: ",
- "Deprcated: ",
- "Depreated: ",
- "Deprected: ",
- "Deprecaed: ",
- "Deprecatd: ",
- "Deprecate: ",
- "Derpecate: ",
- "Derpecated: ",
- "Depreacted: ",
- }
- for i := range c.commonTypos {
- c.commonTypos[i] = strings.ToUpper(c.commonTypos[i])
- }
-
- return astwalk.WalkerForDocComment(c), nil
- })
-}
-
-type deprecatedCommentChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- commonPatterns []string
- commonTypos []string
-}
-
-func (c *deprecatedCommentChecker) VisitDocComment(doc *ast.CommentGroup) {
- // There are 3 accepted forms of deprecation comments:
- //
- // 1. inline, that can't be handled with a DocCommentVisitor.
- // Note that "Deprecated: " may not even be the comment prefix there.
- // Example: "The line number in the input. Deprecated: Kept for compatibility."
- // TODO(quasilyte): fix it.
- //
- // 2. Longer form-1. It's a doc-comment that only contains "deprecation" notice.
- //
- // 3. Like form-2, but may also include doc-comment text.
- // Distinguished by an empty line.
- //
- // See https://github.com/golang/go/issues/10909#issuecomment-136492606.
- //
- // It's desirable to see how people make mistakes with the format,
- // this is why there is currently no special treatment for these cases.
- // TODO(quasilyte): do more audits and grow the negative tests suite.
- //
- // TODO(quasilyte): there are also multi-line deprecation comments.
-
- for _, comment := range doc.List {
- if strings.HasPrefix(comment.Text, "/*") {
- // TODO(quasilyte): handle multi-line doc comments.
- continue
- }
- l := comment.Text[len("//"):]
- if len(l) < len("Deprecated: ") {
- continue
- }
- l = strings.TrimSpace(l)
-
- // Check whether someone messed up with a prefix casing.
- upcase := strings.ToUpper(l)
- if strings.HasPrefix(upcase, "DEPRECATED: ") && !strings.HasPrefix(l, "Deprecated: ") {
- c.warnCasing(comment, l)
- return
- }
-
- // Check is someone used comma instead of a colon.
- if strings.HasPrefix(l, "Deprecated, ") {
- c.warnComma(comment)
- return
- }
-
- // Check for other commonly used patterns.
- for _, pat := range c.commonPatterns {
- if len(l) < len(pat) {
- continue
- }
-
- if strings.EqualFold(l[:len(pat)], pat) {
- c.warnPattern(comment)
- return
- }
- }
-
- // Detect some simple typos.
- for _, prefixWithTypo := range c.commonTypos {
- if strings.HasPrefix(upcase, prefixWithTypo) {
- c.warnTypo(comment, l)
- return
- }
- }
- }
-}
-
-func (c *deprecatedCommentChecker) warnCasing(cause ast.Node, line string) {
- prefix := line[:len("DEPRECATED: ")]
- c.ctx.Warn(cause, "use `Deprecated: ` (note the casing) instead of `%s`", prefix)
-}
-
-func (c *deprecatedCommentChecker) warnPattern(cause ast.Node) {
- c.ctx.Warn(cause, "the proper format is `Deprecated: <text>`")
-}
-
-func (c *deprecatedCommentChecker) warnComma(cause ast.Node) {
- c.ctx.Warn(cause, "use `:` instead of `,` in `Deprecated, `")
-}
-
-func (c *deprecatedCommentChecker) warnTypo(cause ast.Node, line string) {
- word := strings.Split(line, ":")[0]
- c.ctx.Warn(cause, "typo in `%s`; should be `Deprecated`", word)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/docStub_checker.go b/vendor/github.com/go-critic/go-critic/checkers/docStub_checker.go
deleted file mode 100644
index aa23de42c..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/docStub_checker.go
+++ /dev/null
@@ -1,95 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
- "regexp"
- "strings"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "docStub"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag}
- info.Summary = "Detects comments that silence go lint complaints about doc-comment"
- info.Before = `
-// Foo ...
-func Foo() {
-}`
- info.After = `
-// (A) - remove the doc-comment stub
-func Foo() {}
-// (B) - replace it with meaningful comment
-// Foo is a demonstration-only function.
-func Foo() {}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- re := `(?i)^\.\.\.$|^\.$|^xxx\.?$|^whatever\.?$`
- c := &docStubChecker{
- ctx: ctx,
- stubCommentRE: regexp.MustCompile(re),
- }
- return c, nil
- })
-}
-
-type docStubChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- stubCommentRE *regexp.Regexp
-}
-
-func (c *docStubChecker) WalkFile(f *ast.File) {
- for _, decl := range f.Decls {
- switch decl := decl.(type) {
- case *ast.FuncDecl:
- c.visitDoc(decl, decl.Name, decl.Doc, false)
- case *ast.GenDecl:
- if decl.Tok != token.TYPE {
- continue
- }
- if len(decl.Specs) == 1 {
- spec := decl.Specs[0].(*ast.TypeSpec)
- // Only 1 spec, use doc from the decl itself.
- c.visitDoc(spec, spec.Name, decl.Doc, true)
- }
- // N specs, use per-spec doc.
- for _, spec := range decl.Specs {
- spec := spec.(*ast.TypeSpec)
- c.visitDoc(spec, spec.Name, spec.Doc, true)
- }
- }
- }
-}
-
-func (c *docStubChecker) visitDoc(decl ast.Node, sym *ast.Ident, doc *ast.CommentGroup, article bool) {
- if !sym.IsExported() || doc == nil {
- return
- }
- line := strings.TrimSpace(doc.List[0].Text[len("//"):])
- if article {
- // Skip optional article.
- for _, a := range []string{"The ", "An ", "A "} {
- if strings.HasPrefix(line, a) {
- line = line[len(a):]
- break
- }
- }
- }
- if !strings.HasPrefix(line, sym.Name) {
- return
- }
- line = strings.TrimSpace(line[len(sym.Name):])
- // Now try to detect the "stub" part.
- if c.stubCommentRE.MatchString(line) {
- c.warn(decl)
- }
-}
-
-func (c *docStubChecker) warn(cause ast.Node) {
- c.ctx.Warn(cause, "silencing go lint doc-comment warnings is unadvised")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/dupBranchBody_checker.go b/vendor/github.com/go-critic/go-critic/checkers/dupBranchBody_checker.go
deleted file mode 100644
index c4f018387..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/dupBranchBody_checker.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astequal"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "dupBranchBody"
- info.Tags = []string{linter.DiagnosticTag}
- info.Summary = "Detects duplicated branch bodies inside conditional statements"
- info.Before = `
-if cond {
- println("cond=true")
-} else {
- println("cond=true")
-}`
- info.After = `
-if cond {
- println("cond=true")
-} else {
- println("cond=false")
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&dupBranchBodyChecker{ctx: ctx}), nil
- })
-}
-
-type dupBranchBodyChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *dupBranchBodyChecker) VisitStmt(stmt ast.Stmt) {
- // TODO(quasilyte): extend to check switch statements as well.
- // Should be very careful with type switches.
-
- if stmt, ok := stmt.(*ast.IfStmt); ok {
- c.checkIf(stmt)
- }
-}
-
-func (c *dupBranchBodyChecker) checkIf(stmt *ast.IfStmt) {
- thenBody := stmt.Body
- elseBody, ok := stmt.Else.(*ast.BlockStmt)
- if ok && astequal.Stmt(thenBody, elseBody) {
- c.warnIf(stmt)
- }
-}
-
-func (c *dupBranchBodyChecker) warnIf(cause ast.Node) {
- c.ctx.Warn(cause, "both branches in if statement have same body")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/dupCase_checker.go b/vendor/github.com/go-critic/go-critic/checkers/dupCase_checker.go
deleted file mode 100644
index 381bad68b..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/dupCase_checker.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/checkers/internal/lintutil"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "dupCase"
- info.Tags = []string{linter.DiagnosticTag}
- info.Summary = "Detects duplicated case clauses inside switch or select statements"
- info.Before = `
-switch x {
-case ys[0], ys[1], ys[2], ys[0], ys[4]:
-}`
- info.After = `
-switch x {
-case ys[0], ys[1], ys[2], ys[3], ys[4]:
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&dupCaseChecker{ctx: ctx}), nil
- })
-}
-
-type dupCaseChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- astSet lintutil.AstSet
-}
-
-func (c *dupCaseChecker) VisitStmt(stmt ast.Stmt) {
- switch stmt := stmt.(type) {
- case *ast.SwitchStmt:
- c.checkSwitch(stmt)
- case *ast.SelectStmt:
- c.checkSelect(stmt)
- }
-}
-
-func (c *dupCaseChecker) checkSwitch(stmt *ast.SwitchStmt) {
- c.astSet.Clear()
- for i := range stmt.Body.List {
- cc := stmt.Body.List[i].(*ast.CaseClause)
- for _, x := range cc.List {
- if !c.astSet.Insert(x) {
- c.warn(x)
- }
- }
- }
-}
-
-func (c *dupCaseChecker) checkSelect(stmt *ast.SelectStmt) {
- c.astSet.Clear()
- for i := range stmt.Body.List {
- x := stmt.Body.List[i].(*ast.CommClause).Comm
- if !c.astSet.Insert(x) {
- c.warn(x)
- }
- }
-}
-
-func (c *dupCaseChecker) warn(cause ast.Node) {
- c.ctx.Warn(cause, "'case %s' is duplicated", cause)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/dupImports_checker.go b/vendor/github.com/go-critic/go-critic/checkers/dupImports_checker.go
deleted file mode 100644
index ed674eb85..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/dupImports_checker.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package checkers
-
-import (
- "fmt"
- "go/ast"
-
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "dupImport"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag}
- info.Summary = "Detects multiple imports of the same package under different aliases"
- info.Before = `
-import (
- "fmt"
- printing "fmt" // Imported the second time
-)`
- info.After = `
-import(
- "fmt"
-)`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return &dupImportChecker{ctx: ctx}, nil
- })
-}
-
-type dupImportChecker struct {
- ctx *linter.CheckerContext
-}
-
-func (c *dupImportChecker) WalkFile(f *ast.File) {
- imports := make(map[string][]*ast.ImportSpec)
- for _, importDcl := range f.Imports {
- pkg := importDcl.Path.Value
- imports[pkg] = append(imports[pkg], importDcl)
- }
-
- for _, importList := range imports {
- if len(importList) == 1 {
- continue
- }
- c.warn(importList)
- }
-}
-
-func (c *dupImportChecker) warn(importList []*ast.ImportSpec) {
- msg := fmt.Sprintf("package is imported %d times under different aliases on lines", len(importList))
- for idx, importDcl := range importList {
- switch {
- case idx == len(importList)-1:
- msg += " and"
- case idx > 0:
- msg += ","
- }
- msg += fmt.Sprintf(" %d", c.ctx.FileSet.Position(importDcl.Pos()).Line)
- }
- for _, importDcl := range importList {
- c.ctx.Warn(importDcl, msg)
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/dupSubExpr_checker.go b/vendor/github.com/go-critic/go-critic/checkers/dupSubExpr_checker.go
deleted file mode 100644
index 9ab75945c..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/dupSubExpr_checker.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astequal"
- "github.com/go-toolsmith/typep"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "dupSubExpr"
- info.Tags = []string{linter.DiagnosticTag}
- info.Summary = "Detects suspicious duplicated sub-expressions"
- info.Before = `
-sort.Slice(xs, func(i, j int) bool {
- return xs[i].v < xs[i].v // Duplicated index
-})`
- info.After = `
-sort.Slice(xs, func(i, j int) bool {
- return xs[i].v < xs[j].v
-})`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- c := &dupSubExprChecker{ctx: ctx}
-
- ops := []struct {
- op token.Token
- float bool // Whether float args require special care
- }{
- {op: token.LOR}, // x || x
- {op: token.LAND}, // x && x
- {op: token.OR}, // x | x
- {op: token.AND}, // x & x
- {op: token.XOR}, // x ^ x
- {op: token.LSS}, // x < x
- {op: token.GTR}, // x > x
- {op: token.AND_NOT}, // x &^ x
- {op: token.REM}, // x % x
-
- {op: token.EQL, float: true}, // x == x
- {op: token.NEQ, float: true}, // x != x
- {op: token.LEQ, float: true}, // x <= x
- {op: token.GEQ, float: true}, // x >= x
- {op: token.QUO, float: true}, // x / x
- {op: token.SUB, float: true}, // x - x
- }
-
- c.opSet = make(map[token.Token]bool)
- c.floatOpsSet = make(map[token.Token]bool)
- for _, opInfo := range ops {
- c.opSet[opInfo.op] = true
- if opInfo.float {
- c.floatOpsSet[opInfo.op] = true
- }
- }
-
- return astwalk.WalkerForExpr(c), nil
- })
-}
-
-type dupSubExprChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- // opSet is a set of binary operations that do not make
- // sense with duplicated (same) RHS and LHS.
- opSet map[token.Token]bool
-
- floatOpsSet map[token.Token]bool
-}
-
-func (c *dupSubExprChecker) VisitExpr(expr ast.Expr) {
- if expr, ok := expr.(*ast.BinaryExpr); ok {
- c.checkBinaryExpr(expr)
- }
-}
-
-func (c *dupSubExprChecker) checkBinaryExpr(expr *ast.BinaryExpr) {
- if !c.opSet[expr.Op] {
- return
- }
- if c.resultIsFloat(expr.X) && c.floatOpsSet[expr.Op] {
- return
- }
- if typep.SideEffectFree(c.ctx.TypesInfo, expr) && c.opSet[expr.Op] && astequal.Expr(expr.X, expr.Y) {
- c.warn(expr)
- }
-}
-
-func (c *dupSubExprChecker) resultIsFloat(expr ast.Expr) bool {
- typ, ok := c.ctx.TypeOf(expr).(*types.Basic)
- return ok && typ.Info()&types.IsFloat != 0
-}
-
-func (c *dupSubExprChecker) warn(cause *ast.BinaryExpr) {
- c.ctx.Warn(cause, "suspicious identical LHS and RHS for `%s` operator", cause.Op)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/elseif_checker.go b/vendor/github.com/go-critic/go-critic/checkers/elseif_checker.go
deleted file mode 100644
index 857d09fa0..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/elseif_checker.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astp"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "elseif"
- info.Tags = []string{linter.StyleTag}
- info.Params = linter.CheckerParams{
- "skipBalanced": {
- Value: true,
- Usage: "whether to skip balanced if-else pairs",
- },
- }
- info.Summary = "Detects else with nested if statement that can be replaced with else-if"
- info.Before = `
-if cond1 {
-} else {
- if x := cond2; x {
- }
-}`
- info.After = `
-if cond1 {
-} else if x := cond2; x {
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- c := &elseifChecker{ctx: ctx}
- c.skipBalanced = info.Params.Bool("skipBalanced")
- return astwalk.WalkerForStmt(c), nil
- })
-}
-
-type elseifChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- skipBalanced bool
-}
-
-func (c *elseifChecker) VisitStmt(stmt ast.Stmt) {
- if stmt, ok := stmt.(*ast.IfStmt); ok {
- elseBody, ok := stmt.Else.(*ast.BlockStmt)
- if !ok || len(elseBody.List) != 1 {
- return
- }
- innerIfStmt, ok := elseBody.List[0].(*ast.IfStmt)
- if !ok {
- return
- }
- balanced := len(stmt.Body.List) == 1 &&
- astp.IsIfStmt(stmt.Body.List[0])
- if balanced && c.skipBalanced {
- return // Configured to skip balanced statements
- }
- if innerIfStmt.Else != nil || innerIfStmt.Init != nil {
- return
- }
- c.warn(stmt.Else)
- }
-}
-
-func (c *elseifChecker) warn(cause ast.Node) {
- c.ctx.Warn(cause, "can replace 'else {if cond {}}' with 'else if cond {}'")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/embedded_rules.go b/vendor/github.com/go-critic/go-critic/checkers/embedded_rules.go
deleted file mode 100644
index ad507425e..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/embedded_rules.go
+++ /dev/null
@@ -1,108 +0,0 @@
-package checkers
-
-import (
- "fmt"
- "go/ast"
- "go/build"
- "go/token"
- "os"
-
- "github.com/go-critic/go-critic/checkers/rulesdata"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/quasilyte/go-ruleguard/ruleguard"
-)
-
-//go:generate go run ./rules/precompile.go -rules ./rules/rules.go -o ./rulesdata/rulesdata.go
-
-func InitEmbeddedRules() error {
- filename := "rules/rules.go"
-
- fset := token.NewFileSet()
- var groups []ruleguard.GoRuleGroup
-
- var buildContext *build.Context
-
- ruleguardDebug := os.Getenv("GOCRITIC_RULEGUARD_DEBUG") != ""
-
- // First we create an Engine to parse all rules.
- // We need it to get the structured info about our rules
- // that will be used to generate checkers.
- // We introduce an extra scope in hope that rootEngine
- // will be garbage-collected after we don't need it.
- // LoadedGroups() returns a slice copy and that's all what we need.
- {
- rootEngine := ruleguard.NewEngine()
- rootEngine.InferBuildContext()
- buildContext = rootEngine.BuildContext
-
- loadContext := &ruleguard.LoadContext{
- Fset: fset,
- DebugImports: ruleguardDebug,
- DebugPrint: func(s string) {
- fmt.Println("debug:", s)
- },
- }
- if err := rootEngine.LoadFromIR(loadContext, filename, rulesdata.PrecompiledRules); err != nil {
- return fmt.Errorf("load embedded ruleguard rules: %w", err)
- }
- groups = rootEngine.LoadedGroups()
- }
-
- // For every rules group we create a new checker and a separate engine.
- // That dedicated ruleguard engine will contain rules only from one group.
- for i := range groups {
- g := groups[i]
- info := &linter.CheckerInfo{
- Name: g.Name,
- Summary: g.DocSummary,
- Before: g.DocBefore,
- After: g.DocAfter,
- Note: g.DocNote,
- Tags: g.DocTags,
-
- EmbeddedRuleguard: true,
- }
- collection.AddChecker(info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- parseContext := &ruleguard.LoadContext{
- Fset: fset,
- GroupFilter: func(gr *ruleguard.GoRuleGroup) bool {
- return gr.Name == g.Name
- },
- DebugImports: ruleguardDebug,
- DebugPrint: func(s string) {
- fmt.Println("debug:", s)
- },
- }
- engine := ruleguard.NewEngine()
- engine.BuildContext = buildContext
- err := engine.LoadFromIR(parseContext, filename, rulesdata.PrecompiledRules)
- if err != nil {
- return nil, err
- }
- c := &embeddedRuleguardChecker{
- ctx: ctx,
- engine: engine,
- }
- return c, nil
- })
- }
-
- return nil
-}
-
-type embeddedRuleguardChecker struct {
- ctx *linter.CheckerContext
- engine *ruleguard.Engine
-}
-
-func (c *embeddedRuleguardChecker) WalkFile(f *ast.File) {
- runRuleguardEngine(c.ctx, f, c.engine, &ruleguard.RunContext{
- Pkg: c.ctx.Pkg,
- Types: c.ctx.TypesInfo,
- Sizes: c.ctx.SizesInfo,
- GoVersion: ruleguard.GoVersion(c.ctx.GoVersion),
- Fset: c.ctx.FileSet,
- TruncateLen: 100,
- })
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/emptyFallthrough_checker.go b/vendor/github.com/go-critic/go-critic/checkers/emptyFallthrough_checker.go
deleted file mode 100644
index a008c6187..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/emptyFallthrough_checker.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "emptyFallthrough"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag}
- info.Summary = "Detects fallthrough that can be avoided by using multi case values"
- info.Before = `switch kind {
-case reflect.Int:
- fallthrough
-case reflect.Int32:
- return Int
-}`
- info.After = `switch kind {
-case reflect.Int, reflect.Int32:
- return Int
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&emptyFallthroughChecker{ctx: ctx}), nil
- })
-}
-
-type emptyFallthroughChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *emptyFallthroughChecker) VisitStmt(stmt ast.Stmt) {
- ss, ok := stmt.(*ast.SwitchStmt)
- if !ok {
- return
- }
-
- prevCaseDefault := false
- for i := len(ss.Body.List) - 1; i >= 0; i-- {
- if cc, ok := ss.Body.List[i].(*ast.CaseClause); ok {
- warn := false
- if len(cc.Body) == 1 {
- if bs, ok := cc.Body[0].(*ast.BranchStmt); ok && bs.Tok == token.FALLTHROUGH {
- warn = true
- if prevCaseDefault {
- c.warnDefault(bs)
- } else if cc.List != nil {
- c.warn(bs)
- }
- }
- }
- if !warn {
- prevCaseDefault = cc.List == nil
- }
- }
- }
-}
-
-func (c *emptyFallthroughChecker) warnDefault(cause ast.Node) {
- c.ctx.Warn(cause, "remove empty case containing only fallthrough to default case")
-}
-
-func (c *emptyFallthroughChecker) warn(cause ast.Node) {
- c.ctx.Warn(cause, "replace empty case containing only fallthrough with expression list")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/evalOrder_checker.go b/vendor/github.com/go-critic/go-critic/checkers/evalOrder_checker.go
deleted file mode 100644
index f8c5ae542..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/evalOrder_checker.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/checkers/internal/lintutil"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "github.com/go-toolsmith/astequal"
- "github.com/go-toolsmith/typep"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "evalOrder"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects unwanted dependencies on the evaluation order"
- info.Before = `return x, f(&x)`
- info.After = `
-err := f(&x)
-return x, err
-`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&evalOrderChecker{ctx: ctx}), nil
- })
-}
-
-type evalOrderChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *evalOrderChecker) VisitStmt(stmt ast.Stmt) {
- ret := astcast.ToReturnStmt(stmt)
- if len(ret.Results) < 2 {
- return
- }
-
- // TODO(quasilyte): handle selector expressions like o.val in addition
- // to bare identifiers.
- addrTake := &ast.UnaryExpr{Op: token.AND}
- for _, res := range ret.Results {
- id, ok := res.(*ast.Ident)
- if !ok {
- continue
- }
- addrTake.X = id // addrTake is &id now
- for _, res := range ret.Results {
- call, ok := res.(*ast.CallExpr)
- if !ok {
- continue
- }
-
- // 1. Check if there is a call in form of id.method() where
- // method takes id by a pointer.
- if sel, ok := call.Fun.(*ast.SelectorExpr); ok {
- if astequal.Node(sel.X, id) && c.hasPtrRecv(sel.Sel) {
- c.warn(call)
- }
- }
-
- // 2. Check that there is no call that uses &id as an argument.
- dependency := lintutil.ContainsNode(call, func(n ast.Node) bool {
- return astequal.Node(addrTake, n)
- })
- if dependency {
- c.warn(call)
- }
- }
- }
-}
-
-func (c *evalOrderChecker) hasPtrRecv(fn *ast.Ident) bool {
- sig, ok := c.ctx.TypeOf(fn).(*types.Signature)
- if !ok {
- return false
- }
- return typep.IsPointer(sig.Recv().Type())
-}
-
-func (c *evalOrderChecker) warn(call *ast.CallExpr) {
- c.ctx.Warn(call, "may want to evaluate %s before the return statement", call)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/exitAfterDefer_checker.go b/vendor/github.com/go-critic/go-critic/checkers/exitAfterDefer_checker.go
deleted file mode 100644
index 9889f48e8..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/exitAfterDefer_checker.go
+++ /dev/null
@@ -1,85 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astfmt"
- "github.com/go-toolsmith/astp"
- "golang.org/x/tools/go/ast/astutil"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "exitAfterDefer"
- info.Tags = []string{linter.DiagnosticTag}
- info.Summary = "Detects calls to exit/fatal inside functions that use defer"
- info.Before = `
-defer os.Remove(filename)
-if bad {
- log.Fatalf("something bad happened")
-}`
- info.After = `
-defer os.Remove(filename)
-if bad {
- log.Printf("something bad happened")
- return
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForFuncDecl(&exitAfterDeferChecker{ctx: ctx}), nil
- })
-}
-
-type exitAfterDeferChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *exitAfterDeferChecker) VisitFuncDecl(fn *ast.FuncDecl) {
- // TODO(quasilyte): handle goto and other kinds of flow that break
- // the algorithm below that expects the latter statement to be
- // executed after the ones that come before it.
-
- var deferStmt *ast.DeferStmt
- pre := func(cur *astutil.Cursor) bool {
- // Don't recurse into local anonymous functions.
- return !astp.IsFuncLit(cur.Node())
- }
- post := func(cur *astutil.Cursor) bool {
- switch n := cur.Node().(type) {
- case *ast.DeferStmt:
- deferStmt = n
- case *ast.CallExpr:
- // See #995. We allow `defer os.Exit()` calls
- // as it's harder to determine whether they're going
- // to clutter anything without actually trying to
- // simulate the defer stack + understanding the control flow.
- // TODO: can we use CFG here?
- if _, ok := cur.Parent().(*ast.DeferStmt); ok {
- return true
- }
- if deferStmt != nil {
- switch qualifiedName(n.Fun) {
- case "log.Fatal", "log.Fatalf", "log.Fatalln", "os.Exit":
- c.warn(n, deferStmt)
- return false
- }
- }
- }
- return true
- }
- astutil.Apply(fn.Body, pre, post)
-}
-
-func (c *exitAfterDeferChecker) warn(cause *ast.CallExpr, deferStmt *ast.DeferStmt) {
- s := astfmt.Sprint(deferStmt)
- if fnlit, ok := deferStmt.Call.Fun.(*ast.FuncLit); ok {
- // To avoid long and multi-line warning messages,
- // collapse the function literals.
- s = "defer " + astfmt.Sprint(fnlit.Type) + "{...}(...)"
- }
- c.ctx.Warn(cause, "%s will exit, and `%s` will not run", cause.Fun, s)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/filepathJoin_checker.go b/vendor/github.com/go-critic/go-critic/checkers/filepathJoin_checker.go
deleted file mode 100644
index 17ab0ea83..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/filepathJoin_checker.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "strings"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "filepathJoin"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects problems in filepath.Join() function calls"
- info.Before = `filepath.Join("dir/", filename)`
- info.After = `filepath.Join("dir", filename)`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForExpr(&filepathJoinChecker{ctx: ctx}), nil
- })
-}
-
-type filepathJoinChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *filepathJoinChecker) VisitExpr(expr ast.Expr) {
- call := astcast.ToCallExpr(expr)
- if qualifiedName(call.Fun) != "filepath.Join" {
- return
- }
-
- for _, arg := range call.Args {
- arg, ok := arg.(*ast.BasicLit)
- if ok && c.hasSeparator(arg) {
- c.warnSeparator(arg)
- }
- }
-}
-
-func (c *filepathJoinChecker) hasSeparator(v *ast.BasicLit) bool {
- return strings.ContainsAny(v.Value, `/\`)
-}
-
-func (c *filepathJoinChecker) warnSeparator(sep ast.Expr) {
- c.ctx.Warn(sep, "%s contains a path separator", sep)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/flagName_checker.go b/vendor/github.com/go-critic/go-critic/checkers/flagName_checker.go
deleted file mode 100644
index 701066860..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/flagName_checker.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/constant"
- "go/types"
- "strings"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "flagName"
- info.Tags = []string{linter.DiagnosticTag}
- info.Summary = "Detects suspicious flag names"
- info.Before = `b := flag.Bool(" foo ", false, "description")`
- info.After = `b := flag.Bool("foo", false, "description")`
- info.Note = "https://github.com/golang/go/issues/41792"
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForExpr(&flagNameChecker{ctx: ctx}), nil
- })
-}
-
-type flagNameChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *flagNameChecker) VisitExpr(expr ast.Expr) {
- call := astcast.ToCallExpr(expr)
- calledExpr := astcast.ToSelectorExpr(call.Fun)
- obj, ok := c.ctx.TypesInfo.ObjectOf(astcast.ToIdent(calledExpr.X)).(*types.PkgName)
- if !ok {
- return
- }
- sym := calledExpr.Sel
- pkg := obj.Imported()
- if pkg.Path() != "flag" {
- return
- }
-
- switch sym.Name {
- case "Bool", "Duration", "Float64", "String",
- "Int", "Int64", "Uint", "Uint64":
- c.checkFlagName(call, call.Args[0])
- case "BoolVar", "DurationVar", "Float64Var", "StringVar",
- "IntVar", "Int64Var", "UintVar", "Uint64Var":
- c.checkFlagName(call, call.Args[1])
- }
-}
-
-func (c *flagNameChecker) checkFlagName(call *ast.CallExpr, arg ast.Expr) {
- cv := c.ctx.TypesInfo.Types[arg].Value
- if cv == nil {
- return // Non-constant name
- }
- name := constant.StringVal(cv)
- switch {
- case name == "":
- c.warnEmpty(call)
- case strings.HasPrefix(name, "-"):
- c.warnHyphenPrefix(call, name)
- case strings.Contains(name, "="):
- c.warnEq(call, name)
- case strings.Contains(name, " "):
- c.warnWhitespace(call, name)
- }
-}
-
-func (c *flagNameChecker) warnEmpty(cause ast.Node) {
- c.ctx.Warn(cause, "empty flag name")
-}
-
-func (c *flagNameChecker) warnHyphenPrefix(cause ast.Node, name string) {
- c.ctx.Warn(cause, "flag name %q should not start with a hyphen", name)
-}
-
-func (c *flagNameChecker) warnEq(cause ast.Node, name string) {
- c.ctx.Warn(cause, "flag name %q should not contain '='", name)
-}
-
-func (c *flagNameChecker) warnWhitespace(cause ast.Node, name string) {
- c.ctx.Warn(cause, "flag name %q contains whitespace", name)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/hexLiteral_checker.go b/vendor/github.com/go-critic/go-critic/checkers/hexLiteral_checker.go
deleted file mode 100644
index 7301bd325..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/hexLiteral_checker.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
- "strings"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "hexLiteral"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag}
- info.Summary = "Detects hex literals that have mixed case letter digits"
- info.Before = `
-x := 0X12
-y := 0xfF`
- info.After = `
-x := 0x12
-// (A)
-y := 0xff
-// (B)
-y := 0xFF`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForExpr(&hexLiteralChecker{ctx: ctx}), nil
- })
-}
-
-type hexLiteralChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *hexLiteralChecker) warn0X(lit *ast.BasicLit) {
- suggest := "0x" + lit.Value[len("0X"):]
- c.ctx.Warn(lit, "prefer 0x over 0X, s/%s/%s/", lit.Value, suggest)
-}
-
-func (c *hexLiteralChecker) warnMixedDigits(lit *ast.BasicLit) {
- c.ctx.Warn(lit, "don't mix hex literal letter digits casing")
-}
-
-func (c *hexLiteralChecker) VisitExpr(expr ast.Expr) {
- lit := astcast.ToBasicLit(expr)
- if lit.Kind != token.INT || len(lit.Value) < 3 {
- return
- }
- if strings.HasPrefix(lit.Value, "0X") {
- c.warn0X(lit)
- return
- }
- digits := lit.Value[len("0x"):]
- if strings.ToLower(digits) != digits && strings.ToUpper(digits) != digits {
- c.warnMixedDigits(lit)
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/hugeParam_checker.go b/vendor/github.com/go-critic/go-critic/checkers/hugeParam_checker.go
deleted file mode 100644
index 7b7a3c538..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/hugeParam_checker.go
+++ /dev/null
@@ -1,83 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "hugeParam"
- info.Tags = []string{linter.PerformanceTag}
- info.Params = linter.CheckerParams{
- "sizeThreshold": {
- Value: 80,
- Usage: "size in bytes that makes the warning trigger",
- },
- }
- info.Summary = "Detects params that incur excessive amount of copying"
- info.Before = `func f(x [1024]int) {}`
- info.After = `func f(x *[1024]int) {}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForFuncDecl(&hugeParamChecker{
- ctx: ctx,
- sizeThreshold: int64(info.Params.Int("sizeThreshold")),
- }), nil
- })
-}
-
-type hugeParamChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- sizeThreshold int64
-}
-
-func (c *hugeParamChecker) VisitFuncDecl(decl *ast.FuncDecl) {
- // TODO(quasilyte): maybe it's worthwhile to permit skipping
- // test files for this checker?
- if c.isImplementStringer(decl) {
- return
- }
-
- if decl.Recv != nil {
- c.checkParams(decl.Recv.List)
- }
- c.checkParams(decl.Type.Params.List)
-}
-
-// isImplementStringer check method signature is: String() string.
-func (*hugeParamChecker) isImplementStringer(decl *ast.FuncDecl) bool {
- if decl.Recv != nil &&
- decl.Name.Name == "String" &&
- decl.Type != nil &&
- len(decl.Type.Params.List) == 0 &&
- len(decl.Type.Results.List) == 1 &&
- astcast.ToIdent(decl.Type.Results.List[0].Type).Name == "string" {
- return true
- }
-
- return false
-}
-
-func (c *hugeParamChecker) checkParams(params []*ast.Field) {
- for _, p := range params {
- for _, id := range p.Names {
- typ := c.ctx.TypeOf(id)
- size, ok := c.ctx.SizeOf(typ)
- if ok && size >= c.sizeThreshold {
- c.warn(id, size)
- }
- }
- }
-}
-
-func (c *hugeParamChecker) warn(cause *ast.Ident, size int64) {
- c.ctx.Warn(cause, "%s is heavy (%d bytes); consider passing it by pointer",
- cause, size)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/ifElseChain_checker.go b/vendor/github.com/go-critic/go-critic/checkers/ifElseChain_checker.go
deleted file mode 100644
index e73c609d5..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/ifElseChain_checker.go
+++ /dev/null
@@ -1,110 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "ifElseChain"
- info.Tags = []string{linter.StyleTag}
- info.Params = linter.CheckerParams{
- "minThreshold": {
- Value: 2,
- Usage: "min number of if-else blocks that makes the warning trigger",
- },
- }
- info.Summary = "Detects repeated if-else statements and suggests to replace them with switch statement"
- info.Before = `
-if cond1 {
- // Code A.
-} else if cond2 {
- // Code B.
-} else {
- // Code C.
-}`
- info.After = `
-switch {
-case cond1:
- // Code A.
-case cond2:
- // Code B.
-default:
- // Code C.
-}`
- info.Note = `
-Permits single else or else-if; repeated else-if or else + else-if
-will trigger suggestion to use switch statement.
-See [EffectiveGo#switch](https://golang.org/doc/effective_go.html#switch).`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&ifElseChainChecker{
- ctx: ctx,
- minThreshold: info.Params.Int("minThreshold"),
- }), nil
- })
-}
-
-type ifElseChainChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- cause *ast.IfStmt
- visited map[*ast.IfStmt]bool
-
- minThreshold int
-}
-
-func (c *ifElseChainChecker) EnterFunc(fn *ast.FuncDecl) bool {
- if fn.Body == nil {
- return false
- }
- c.visited = make(map[*ast.IfStmt]bool)
- return true
-}
-
-func (c *ifElseChainChecker) VisitStmt(stmt ast.Stmt) {
- if stmt, ok := stmt.(*ast.IfStmt); ok {
- if c.visited[stmt] {
- return
- }
- c.cause = stmt
- c.checkIfStmt(stmt)
- }
-}
-
-func (c *ifElseChainChecker) checkIfStmt(stmt *ast.IfStmt) {
- if c.countIfelseLen(stmt) >= c.minThreshold {
- c.warn()
- }
-}
-
-func (c *ifElseChainChecker) countIfelseLen(stmt *ast.IfStmt) int {
- count := 0
- for {
- if stmt.Init != nil {
- return 0 // Give up
- }
-
- switch e := stmt.Else.(type) {
- case *ast.IfStmt:
- // Else if.
- stmt = e
- count++
- c.visited[e] = true
- case *ast.BlockStmt:
- // Else branch.
- return count + 1
- default:
- // No else or else if.
- return count
- }
- }
-}
-
-func (c *ifElseChainChecker) warn() {
- c.ctx.Warn(c.cause, "rewrite if-else to switch statement")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/importShadow_checker.go b/vendor/github.com/go-critic/go-critic/checkers/importShadow_checker.go
deleted file mode 100644
index b690487b7..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/importShadow_checker.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "importShadow"
- info.Tags = []string{linter.StyleTag, linter.OpinionatedTag}
- info.Summary = "Detects when imported package names shadowed in the assignments"
- info.Before = `
-// "path/filepath" is imported.
-filepath := "foo.txt"`
- info.After = `
-filename := "foo.txt"`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- ctx.Require.PkgObjects = true
- return astwalk.WalkerForLocalDef(&importShadowChecker{ctx: ctx}, ctx.TypesInfo), nil
- })
-}
-
-type importShadowChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *importShadowChecker) VisitLocalDef(def astwalk.Name, _ ast.Expr) {
- for pkgObj, name := range c.ctx.PkgObjects {
- if name == def.ID.Name && name != "_" {
- c.warn(def.ID, name, pkgObj.Imported())
- }
- }
-}
-
-func (c *importShadowChecker) warn(id ast.Node, importedName string, pkg *types.Package) {
- if isStdlibPkg(pkg) {
- c.ctx.Warn(id, "shadow of imported package '%s'", importedName)
- } else {
- c.ctx.Warn(id, "shadow of imported from '%s' package '%s'", pkg.Path(), importedName)
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/initClause_checker.go b/vendor/github.com/go-critic/go-critic/checkers/initClause_checker.go
deleted file mode 100644
index 8612717b2..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/initClause_checker.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astp"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "initClause"
- info.Tags = []string{linter.StyleTag, linter.OpinionatedTag, linter.ExperimentalTag}
- info.Summary = "Detects non-assignment statements inside if/switch init clause"
- info.Before = `if sideEffect(); cond {
-}`
- info.After = `sideEffect()
-if cond {
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&initClauseChecker{ctx: ctx}), nil
- })
-}
-
-type initClauseChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *initClauseChecker) VisitStmt(stmt ast.Stmt) {
- initClause := c.getInitClause(stmt)
- if initClause != nil && !astp.IsAssignStmt(initClause) {
- c.warn(stmt, initClause)
- }
-}
-
-func (c *initClauseChecker) getInitClause(x ast.Stmt) ast.Stmt {
- switch x := x.(type) {
- case *ast.IfStmt:
- return x.Init
- case *ast.SwitchStmt:
- return x.Init
- default:
- return nil
- }
-}
-
-func (c *initClauseChecker) warn(stmt, clause ast.Stmt) {
- name := "if"
- if astp.IsSwitchStmt(stmt) {
- name = "switch"
- }
- c.ctx.Warn(stmt, "consider to move `%s` before %s", clause, name)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/comment_walker.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/comment_walker.go
deleted file mode 100644
index 6c60e3fed..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/comment_walker.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package astwalk
-
-import (
- "go/ast"
- "strings"
-)
-
-type commentWalker struct {
- visitor CommentVisitor
-}
-
-func (w *commentWalker) WalkFile(f *ast.File) {
- if !w.visitor.EnterFile(f) {
- return
- }
-
- for _, cg := range f.Comments {
- visitCommentGroups(cg, w.visitor.VisitComment)
- }
-}
-
-func visitCommentGroups(cg *ast.CommentGroup, visit func(*ast.CommentGroup)) {
- var group []*ast.Comment
- visitGroup := func(list []*ast.Comment) {
- if len(list) == 0 {
- return
- }
- cg := &ast.CommentGroup{List: list}
- visit(cg)
- }
- for _, comment := range cg.List {
- if strings.HasPrefix(comment.Text, "/*") {
- visitGroup(group)
- group = group[:0]
- visitGroup([]*ast.Comment{comment})
- } else {
- group = append(group, comment)
- }
- }
- visitGroup(group)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/doc_comment_walker.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/doc_comment_walker.go
deleted file mode 100644
index 39b536508..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/doc_comment_walker.go
+++ /dev/null
@@ -1,48 +0,0 @@
-package astwalk
-
-import (
- "go/ast"
-)
-
-type docCommentWalker struct {
- visitor DocCommentVisitor
-}
-
-func (w *docCommentWalker) WalkFile(f *ast.File) {
- for _, decl := range f.Decls {
- switch decl := decl.(type) {
- case *ast.FuncDecl:
- if decl.Doc != nil {
- w.visitor.VisitDocComment(decl.Doc)
- }
- case *ast.GenDecl:
- if decl.Doc != nil {
- w.visitor.VisitDocComment(decl.Doc)
- }
- for _, spec := range decl.Specs {
- switch spec := spec.(type) {
- case *ast.ImportSpec:
- if spec.Doc != nil {
- w.visitor.VisitDocComment(spec.Doc)
- }
- case *ast.ValueSpec:
- if spec.Doc != nil {
- w.visitor.VisitDocComment(spec.Doc)
- }
- case *ast.TypeSpec:
- if spec.Doc != nil {
- w.visitor.VisitDocComment(spec.Doc)
- }
- ast.Inspect(spec.Type, func(n ast.Node) bool {
- if n, ok := n.(*ast.Field); ok {
- if n.Doc != nil {
- w.visitor.VisitDocComment(n.Doc)
- }
- }
- return true
- })
- }
- }
- }
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/expr_walker.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/expr_walker.go
deleted file mode 100644
index de66c1081..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/expr_walker.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package astwalk
-
-import (
- "go/ast"
-)
-
-type exprWalker struct {
- visitor ExprVisitor
-}
-
-func (w *exprWalker) WalkFile(f *ast.File) {
- if !w.visitor.EnterFile(f) {
- return
- }
-
- for _, decl := range f.Decls {
- if decl, ok := decl.(*ast.FuncDecl); ok {
- if !w.visitor.EnterFunc(decl) {
- continue
- }
- }
-
- ast.Inspect(decl, func(x ast.Node) bool {
- if x, ok := x.(ast.Expr); ok {
- w.visitor.VisitExpr(x)
- return !w.visitor.skipChilds()
- }
- return true
- })
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/func_decl_walker.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/func_decl_walker.go
deleted file mode 100644
index c7e3a4371..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/func_decl_walker.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package astwalk
-
-import (
- "go/ast"
-)
-
-type funcDeclWalker struct {
- visitor FuncDeclVisitor
-}
-
-func (w *funcDeclWalker) WalkFile(f *ast.File) {
- if !w.visitor.EnterFile(f) {
- return
- }
-
- for _, decl := range f.Decls {
- decl, ok := decl.(*ast.FuncDecl)
- if !ok || !w.visitor.EnterFunc(decl) {
- continue
- }
- w.visitor.VisitFuncDecl(decl)
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_comment_walker.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_comment_walker.go
deleted file mode 100644
index e042f0d5e..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_comment_walker.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package astwalk
-
-import (
- "go/ast"
-)
-
-type localCommentWalker struct {
- visitor LocalCommentVisitor
-}
-
-func (w *localCommentWalker) WalkFile(f *ast.File) {
- if !w.visitor.EnterFile(f) {
- return
- }
-
- for _, decl := range f.Decls {
- decl, ok := decl.(*ast.FuncDecl)
- if !ok || !w.visitor.EnterFunc(decl) {
- continue
- }
-
- for _, cg := range f.Comments {
- // Not sure that decls/comments are sorted
- // by positions, so do a naive full scan for now.
- if cg.Pos() < decl.Pos() || cg.Pos() > decl.End() {
- continue
- }
-
- visitCommentGroups(cg, w.visitor.VisitLocalComment)
- }
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_def_visitor.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_def_visitor.go
deleted file mode 100644
index 0c9c14955..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_def_visitor.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package astwalk
-
-import (
- "go/ast"
-)
-
-// LocalDefVisitor visits every name definitions inside a function.
-//
-// Next elements are considered as name definitions:
-// - Function parameters (input, output, receiver)
-// - Every LHS of ":=" assignment that defines a new name
-// - Every local var/const declaration.
-//
-// NOTE: this visitor is experimental.
-// This is also why it lives in a separate file.
-type LocalDefVisitor interface {
- walkerEvents
- VisitLocalDef(Name, ast.Expr)
-}
-
-// NameKind describes what kind of name Name object holds.
-type NameKind int
-
-// Name holds ver/const/param definition symbol info.
-type Name struct {
- ID *ast.Ident
- Kind NameKind
-
- // Index is NameVar-specific field that is used to
- // specify nth tuple element being assigned to the name.
- Index int
-}
-
-// NOTE: set of name kinds is not stable and may change over time.
-//
-// TODO(quasilyte): is NameRecv/NameParam/NameResult granularity desired?
-// TODO(quasilyte): is NameVar/NameBind (var vs :=) granularity desired?
-const (
- // NameParam is function/method receiver/input/output name.
- // Initializing expression is always nil.
- NameParam NameKind = iota
- // NameVar is var or ":=" declared name.
- // Initializing expression may be nil for var-declared names
- // without explicit initializing expression.
- NameVar
- // NameConst is const-declared name.
- // Initializing expression is never nil.
- NameConst
-)
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_def_walker.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_def_walker.go
deleted file mode 100644
index f6808cbb4..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_def_walker.go
+++ /dev/null
@@ -1,118 +0,0 @@
-package astwalk
-
-import (
- "go/ast"
- "go/token"
- "go/types"
-)
-
-type localDefWalker struct {
- visitor LocalDefVisitor
- info *types.Info
-}
-
-func (w *localDefWalker) WalkFile(f *ast.File) {
- for _, decl := range f.Decls {
- decl, ok := decl.(*ast.FuncDecl)
- if !ok || !w.visitor.EnterFunc(decl) {
- continue
- }
- w.walkFunc(decl)
- }
-}
-
-func (w *localDefWalker) walkFunc(decl *ast.FuncDecl) {
- w.walkSignature(decl)
- w.walkFuncBody(decl)
-}
-
-func (w *localDefWalker) walkFuncBody(decl *ast.FuncDecl) {
- ast.Inspect(decl.Body, func(x ast.Node) bool {
- switch x := x.(type) {
- case *ast.AssignStmt:
- if x.Tok != token.DEFINE {
- return false
- }
- if len(x.Lhs) != len(x.Rhs) {
- // Multi-value assignment.
- // Invariant: there is only 1 RHS.
- for i, lhs := range x.Lhs {
- id, ok := lhs.(*ast.Ident)
- if !ok || w.info.Defs[id] == nil {
- continue
- }
- def := Name{ID: id, Kind: NameVar, Index: i}
- w.visitor.VisitLocalDef(def, x.Rhs[0])
- }
- } else {
- // Simple 1-1 assignments.
- for i, lhs := range x.Lhs {
- id, ok := lhs.(*ast.Ident)
- if !ok || w.info.Defs[id] == nil {
- continue
- }
- def := Name{ID: id, Kind: NameVar}
- w.visitor.VisitLocalDef(def, x.Rhs[i])
- }
- }
- return false
-
- case *ast.GenDecl:
- // Decls always introduce new names.
- for _, spec := range x.Specs {
- spec, ok := spec.(*ast.ValueSpec)
- if !ok { // Ignore type/import specs
- return false
- }
- switch {
- case len(spec.Values) == 0:
- // var-specific decls without explicit init.
- for _, id := range spec.Names {
- def := Name{ID: id, Kind: NameVar}
- w.visitor.VisitLocalDef(def, nil)
- }
- case len(spec.Names) != len(spec.Values):
- // var-specific decls that assign tuple results.
- for i, id := range spec.Names {
- def := Name{ID: id, Kind: NameVar, Index: i}
- w.visitor.VisitLocalDef(def, spec.Values[0])
- }
- default:
- // Can be either var or const decl.
- kind := NameVar
- if x.Tok == token.CONST {
- kind = NameConst
- }
- for i, id := range spec.Names {
- def := Name{ID: id, Kind: kind}
- w.visitor.VisitLocalDef(def, spec.Values[i])
- }
- }
- }
- return false
- }
-
- return true
- })
-}
-
-func (w *localDefWalker) walkSignature(decl *ast.FuncDecl) {
- for _, p := range decl.Type.Params.List {
- for _, id := range p.Names {
- def := Name{ID: id, Kind: NameParam}
- w.visitor.VisitLocalDef(def, nil)
- }
- }
- if decl.Type.Results != nil {
- for _, p := range decl.Type.Results.List {
- for _, id := range p.Names {
- def := Name{ID: id, Kind: NameParam}
- w.visitor.VisitLocalDef(def, nil)
- }
- }
- }
- if decl.Recv != nil && len(decl.Recv.List[0].Names) != 0 {
- def := Name{ID: decl.Recv.List[0].Names[0], Kind: NameParam}
- w.visitor.VisitLocalDef(def, nil)
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_expr_walker.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_expr_walker.go
deleted file mode 100644
index e455b3f8b..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_expr_walker.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package astwalk
-
-import (
- "go/ast"
-)
-
-type localExprWalker struct {
- visitor LocalExprVisitor
-}
-
-func (w *localExprWalker) WalkFile(f *ast.File) {
- if !w.visitor.EnterFile(f) {
- return
- }
-
- for _, decl := range f.Decls {
- decl, ok := decl.(*ast.FuncDecl)
- if !ok || !w.visitor.EnterFunc(decl) {
- continue
- }
- ast.Inspect(decl.Body, func(x ast.Node) bool {
- if x, ok := x.(ast.Expr); ok {
- w.visitor.VisitLocalExpr(x)
- return !w.visitor.skipChilds()
- }
- return true
- })
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/stmt_list_walker.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/stmt_list_walker.go
deleted file mode 100644
index 403292f66..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/stmt_list_walker.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package astwalk
-
-import (
- "go/ast"
-)
-
-type stmtListWalker struct {
- visitor StmtListVisitor
-}
-
-func (w *stmtListWalker) WalkFile(f *ast.File) {
- if !w.visitor.EnterFile(f) {
- return
- }
-
- for _, decl := range f.Decls {
- decl, ok := decl.(*ast.FuncDecl)
- if !ok || !w.visitor.EnterFunc(decl) {
- continue
- }
- ast.Inspect(decl.Body, func(x ast.Node) bool {
- switch x := x.(type) {
- case *ast.BlockStmt:
- w.visitor.VisitStmtList(x, x.List)
- case *ast.CaseClause:
- w.visitor.VisitStmtList(x, x.Body)
- case *ast.CommClause:
- w.visitor.VisitStmtList(x, x.Body)
- }
- return !w.visitor.skipChilds()
- })
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/stmt_walker.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/stmt_walker.go
deleted file mode 100644
index 912de867d..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/stmt_walker.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package astwalk
-
-import (
- "go/ast"
-)
-
-type stmtWalker struct {
- visitor StmtVisitor
-}
-
-func (w *stmtWalker) WalkFile(f *ast.File) {
- if !w.visitor.EnterFile(f) {
- return
- }
-
- for _, decl := range f.Decls {
- decl, ok := decl.(*ast.FuncDecl)
- if !ok || !w.visitor.EnterFunc(decl) {
- continue
- }
- ast.Inspect(decl.Body, func(x ast.Node) bool {
- if x, ok := x.(ast.Stmt); ok {
- w.visitor.VisitStmt(x)
- return !w.visitor.skipChilds()
- }
- return true
- })
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/type_expr_walker.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/type_expr_walker.go
deleted file mode 100644
index bc9bdef47..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/type_expr_walker.go
+++ /dev/null
@@ -1,119 +0,0 @@
-package astwalk
-
-import (
- "go/ast"
- "go/token"
- "go/types"
-
- "github.com/go-toolsmith/astp"
- "github.com/go-toolsmith/typep"
-)
-
-type typeExprWalker struct {
- visitor TypeExprVisitor
- info *types.Info
-}
-
-func (w *typeExprWalker) WalkFile(f *ast.File) {
- if !w.visitor.EnterFile(f) {
- return
- }
-
- for _, decl := range f.Decls {
- if decl, ok := decl.(*ast.FuncDecl); ok {
- if !w.visitor.EnterFunc(decl) {
- continue
- }
- }
- switch decl := decl.(type) {
- case *ast.FuncDecl:
- if !w.visitor.EnterFunc(decl) {
- continue
- }
- w.walkSignature(decl.Type)
- ast.Inspect(decl.Body, w.walk)
- case *ast.GenDecl:
- if decl.Tok == token.IMPORT {
- continue
- }
- ast.Inspect(decl, w.walk)
- }
- }
-}
-
-func (w *typeExprWalker) visit(x ast.Expr) bool {
- w.visitor.VisitTypeExpr(x)
- return !w.visitor.skipChilds()
-}
-
-func (w *typeExprWalker) walk(x ast.Node) bool {
- switch x := x.(type) {
- case *ast.ChanType:
- return w.visit(x)
- case *ast.ParenExpr:
- if typep.IsTypeExpr(w.info, x.X) {
- return w.visit(x)
- }
- return true
- case *ast.CallExpr:
- // Pointer conversions require parenthesis around pointer type.
- // These casts are represented as call expressions.
- // Because it's impossible for the visitor to distinguish such
- // "required" parenthesis, walker skips outmost parenthesis in such cases.
- return w.inspectInner(x.Fun)
- case *ast.SelectorExpr:
- // Like with conversions, method expressions are another special.
- return w.inspectInner(x.X)
- case *ast.StarExpr:
- if typep.IsTypeExpr(w.info, x.X) {
- return w.visit(x)
- }
- return true
- case *ast.MapType:
- return w.visit(x)
- case *ast.FuncType:
- return w.visit(x)
- case *ast.StructType:
- return w.visit(x)
- case *ast.InterfaceType:
- if !w.visit(x) {
- return false
- }
- for _, method := range x.Methods.List {
- switch x := method.Type.(type) {
- case *ast.FuncType:
- w.walkSignature(x)
- default:
- // Embedded interface.
- w.walk(x)
- }
- }
- return false
- case *ast.ArrayType:
- return w.visit(x)
- }
- return true
-}
-
-func (w *typeExprWalker) inspectInner(x ast.Expr) bool {
- parens, ok := x.(*ast.ParenExpr)
- shouldInspect := ok &&
- typep.IsTypeExpr(w.info, parens.X) &&
- (astp.IsStarExpr(parens.X) || astp.IsFuncType(parens.X))
- if shouldInspect {
- ast.Inspect(parens.X, w.walk)
- return false
- }
- return true
-}
-
-func (w *typeExprWalker) walkSignature(typ *ast.FuncType) {
- for _, p := range typ.Params.List {
- ast.Inspect(p.Type, w.walk)
- }
- if typ.Results != nil {
- for _, p := range typ.Results.List {
- ast.Inspect(p.Type, w.walk)
- }
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/visitor.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/visitor.go
deleted file mode 100644
index 3486a8e62..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/visitor.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package astwalk
-
-import (
- "go/ast"
-)
-
-// DocCommentVisitor visits every doc-comment.
-// Does not visit doc-comments for function-local definitions (types, etc).
-// Also does not visit package doc-comment (file-level doc-comments).
-type DocCommentVisitor interface {
- VisitDocComment(*ast.CommentGroup)
-}
-
-// FuncDeclVisitor visits every top-level function declaration.
-type FuncDeclVisitor interface {
- walkerEvents
- VisitFuncDecl(*ast.FuncDecl)
-}
-
-// ExprVisitor visits every expression inside AST file.
-type ExprVisitor interface {
- walkerEvents
- VisitExpr(ast.Expr)
-}
-
-// LocalExprVisitor visits every expression inside function body.
-type LocalExprVisitor interface {
- walkerEvents
- VisitLocalExpr(ast.Expr)
-}
-
-// StmtListVisitor visits every statement list inside function body.
-// This includes block statement bodies as well as implicit blocks
-// introduced by case clauses and alike.
-type StmtListVisitor interface {
- walkerEvents
- VisitStmtList(ast.Node, []ast.Stmt)
-}
-
-// StmtVisitor visits every statement inside function body.
-type StmtVisitor interface {
- walkerEvents
- VisitStmt(ast.Stmt)
-}
-
-// TypeExprVisitor visits every type describing expression.
-// It also traverses struct types and interface types to run
-// checker over their fields/method signatures.
-type TypeExprVisitor interface {
- walkerEvents
- VisitTypeExpr(ast.Expr)
-}
-
-// LocalCommentVisitor visits every comment inside function body.
-type LocalCommentVisitor interface {
- walkerEvents
- VisitLocalComment(*ast.CommentGroup)
-}
-
-// CommentVisitor visits every comment.
-type CommentVisitor interface {
- walkerEvents
- VisitComment(*ast.CommentGroup)
-}
-
-// walkerEvents describes common hooks available for most visitor types.
-type walkerEvents interface {
- // EnterFile is called for every file that is about to be traversed.
- // If false is returned, file is not visited.
- EnterFile(*ast.File) bool
-
- // EnterFunc is called for every function declaration that is about
- // to be traversed. If false is returned, function is not visited.
- EnterFunc(*ast.FuncDecl) bool
-
- skipChilds() bool
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/walk_handler.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/walk_handler.go
deleted file mode 100644
index 96d2dd0e6..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/walk_handler.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package astwalk
-
-import (
- "go/ast"
-)
-
-// WalkHandler is a type to be embedded into every checker
-// that uses astwalk walkers.
-type WalkHandler struct {
- // SkipChilds controls whether currently analyzed
- // node childs should be traversed.
- //
- // Value is reset after each visitor invocation,
- // so there is no need to set value back to false.
- SkipChilds bool
-}
-
-// EnterFile is a default walkerEvents.EnterFile implementation
-// that reports every file as accepted candidate for checking.
-func (w *WalkHandler) EnterFile(_ *ast.File) bool {
- return true
-}
-
-// EnterFunc is a default walkerEvents.EnterFunc implementation
-// that skips extern function (ones that do not have body).
-func (w *WalkHandler) EnterFunc(decl *ast.FuncDecl) bool {
- return decl.Body != nil
-}
-
-func (w *WalkHandler) skipChilds() bool {
- v := w.SkipChilds
- w.SkipChilds = false
- return v
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/walker.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/walker.go
deleted file mode 100644
index f838a64c1..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/walker.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package astwalk
-
-import (
- "go/types"
-
- "github.com/go-critic/go-critic/linter"
-)
-
-// WalkerForFuncDecl returns file walker implementation for FuncDeclVisitor.
-func WalkerForFuncDecl(v FuncDeclVisitor) linter.FileWalker {
- return &funcDeclWalker{visitor: v}
-}
-
-// WalkerForExpr returns file walker implementation for ExprVisitor.
-func WalkerForExpr(v ExprVisitor) linter.FileWalker {
- return &exprWalker{visitor: v}
-}
-
-// WalkerForLocalExpr returns file walker implementation for LocalExprVisitor.
-func WalkerForLocalExpr(v LocalExprVisitor) linter.FileWalker {
- return &localExprWalker{visitor: v}
-}
-
-// WalkerForStmtList returns file walker implementation for StmtListVisitor.
-func WalkerForStmtList(v StmtListVisitor) linter.FileWalker {
- return &stmtListWalker{visitor: v}
-}
-
-// WalkerForStmt returns file walker implementation for StmtVisitor.
-func WalkerForStmt(v StmtVisitor) linter.FileWalker {
- return &stmtWalker{visitor: v}
-}
-
-// WalkerForTypeExpr returns file walker implementation for TypeExprVisitor.
-func WalkerForTypeExpr(v TypeExprVisitor, info *types.Info) linter.FileWalker {
- return &typeExprWalker{visitor: v, info: info}
-}
-
-// WalkerForLocalComment returns file walker implementation for LocalCommentVisitor.
-func WalkerForLocalComment(v LocalCommentVisitor) linter.FileWalker {
- return &localCommentWalker{visitor: v}
-}
-
-// WalkerForComment returns file walker implementation for CommentVisitor.
-func WalkerForComment(v CommentVisitor) linter.FileWalker {
- return &commentWalker{visitor: v}
-}
-
-// WalkerForDocComment returns file walker implementation for DocCommentVisitor.
-func WalkerForDocComment(v DocCommentVisitor) linter.FileWalker {
- return &docCommentWalker{visitor: v}
-}
-
-// WalkerForLocalDef returns file walker implementation for LocalDefVisitor.
-func WalkerForLocalDef(v LocalDefVisitor, info *types.Info) linter.FileWalker {
- return &localDefWalker{visitor: v, info: info}
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astfind.go b/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astfind.go
deleted file mode 100644
index a6d0ad7c4..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astfind.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package lintutil
-
-import (
- "go/ast"
-
- "golang.org/x/tools/go/ast/astutil"
-)
-
-// FindNode applies pred for root and all it's childs until it returns true.
-// If followFunc is defined, it's called before following any node to check whether it needs to be followed.
-// followFunc has to return true in order to continuing traversing the node and return false otherwise.
-// Matched node is returned.
-// If none of the nodes matched predicate, nil is returned.
-func FindNode(root ast.Node, followFunc, pred func(ast.Node) bool) ast.Node {
- var (
- found ast.Node
- preFunc func(*astutil.Cursor) bool
- )
-
- if followFunc != nil {
- preFunc = func(cur *astutil.Cursor) bool {
- return followFunc(cur.Node())
- }
- }
-
- astutil.Apply(root,
- preFunc,
- func(cur *astutil.Cursor) bool {
- if pred(cur.Node()) {
- found = cur.Node()
- return false
- }
- return true
- })
- return found
-}
-
-// ContainsNode reports whether `FindNode(root, pred)!=nil`.
-func ContainsNode(root ast.Node, pred func(ast.Node) bool) bool {
- return FindNode(root, nil, pred) != nil
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astflow.go b/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astflow.go
deleted file mode 100644
index f64907d69..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astflow.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package lintutil
-
-import (
- "go/ast"
- "go/token"
- "go/types"
-
- "github.com/go-toolsmith/astequal"
- "github.com/go-toolsmith/astp"
- "github.com/go-toolsmith/typep"
-)
-
-// Different utilities to make simple analysis over typed ast values flow.
-//
-// It's primitive and can't replace SSA, but the bright side is that
-// it does not require building an additional IR eagerly.
-// Expected to be used sparingly inside a few checkers.
-//
-// If proven really useful, can be moved to go-toolsmith library.
-
-// IsImmutable reports whether n can be modified through any operation.
-func IsImmutable(info *types.Info, n ast.Expr) bool {
- if astp.IsBasicLit(n) {
- return true
- }
- tv, ok := info.Types[n]
- return ok && !tv.Assignable() && !tv.Addressable()
-}
-
-// CouldBeMutated reports whether dst can be modified inside body.
-//
-// Note that it does not take already existing pointers to dst.
-// An example of safe and correct usage is checking of something
-// that was just defined, so the dst is a result of that definition.
-func CouldBeMutated(info *types.Info, body ast.Node, dst ast.Expr) bool {
- if IsImmutable(info, dst) { // Fast path.
- return false
- }
-
- // We don't track pass-by-value.
- // If it's already a pointer, passing it by value
- // means that there can be a potential indirect modification.
- //
- // It's possible to be less conservative here and find at least
- // one such value pass before giving up.
- if typep.IsPointer(info.TypeOf(dst)) {
- return true
- }
-
- var isDst func(x ast.Expr) bool
- if dst, ok := dst.(*ast.Ident); ok {
- // Identifier can be shadowed,
- // so we need to check the object as well.
- obj := info.ObjectOf(dst)
- if obj == nil {
- return true // Being conservative
- }
- isDst = func(x ast.Expr) bool {
- id, ok := x.(*ast.Ident)
- return ok && id.Name == dst.Name && info.ObjectOf(id) == obj
- }
- } else {
- isDst = func(x ast.Expr) bool {
- return astequal.Expr(dst, x)
- }
- }
-
- return ContainsNode(body, func(n ast.Node) bool {
- switch n := n.(type) {
- case *ast.UnaryExpr:
- if n.Op == token.AND && isDst(n.X) {
- return true // Address taken
- }
- case *ast.AssignStmt:
- for _, lhs := range n.Lhs {
- if isDst(lhs) {
- return true
- }
- }
- case *ast.IncDecStmt:
- // Incremented or decremented.
- return isDst(n.X)
- }
- return false
- })
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astset.go b/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astset.go
deleted file mode 100644
index ebe7835e5..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/astset.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package lintutil
-
-import (
- "go/ast"
-
- "github.com/go-toolsmith/astequal"
-)
-
-// AstSet is a simple ast.Node set.
-// Zero value is ready to use set.
-// Can be reused after Clear call.
-type AstSet struct {
- items []ast.Node
-}
-
-// Contains reports whether s contains x.
-func (s *AstSet) Contains(x ast.Node) bool {
- for i := range s.items {
- if astequal.Node(s.items[i], x) {
- return true
- }
- }
- return false
-}
-
-// Insert pushes x in s if it's not already there.
-// Returns true if element was inserted.
-func (s *AstSet) Insert(x ast.Node) bool {
- if s.Contains(x) {
- return false
- }
- s.items = append(s.items, x)
- return true
-}
-
-// Clear removes all element from set.
-func (s *AstSet) Clear() {
- s.items = s.items[:0]
-}
-
-// Len returns the number of elements contained inside s.
-func (s *AstSet) Len() int {
- return len(s.items)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/zero_value.go b/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/zero_value.go
deleted file mode 100644
index 4370f5818..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/internal/lintutil/zero_value.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package lintutil
-
-import (
- "go/ast"
- "go/constant"
- "go/token"
- "go/types"
-)
-
-// IsZeroValue reports whether x represents zero value of its type.
-//
-// The functions is conservative and may return false for zero values
-// if some cases are not handled in a comprehensive way
-// but is should never return true for something that's not a proper zv.
-func IsZeroValue(info *types.Info, x ast.Expr) bool {
- switch x := x.(type) {
- case *ast.BasicLit:
- typ := info.TypeOf(x).Underlying().(*types.Basic)
- v := info.Types[x].Value
- var z constant.Value
- switch {
- case typ.Kind() == types.String:
- z = constant.MakeString("")
- case typ.Info()&types.IsInteger != 0:
- z = constant.MakeInt64(0)
- case typ.Info()&types.IsUnsigned != 0:
- z = constant.MakeUint64(0)
- case typ.Info()&types.IsFloat != 0:
- z = constant.MakeFloat64(0)
- default:
- return false
- }
- return constant.Compare(v, token.EQL, z)
-
- case *ast.CompositeLit:
- return len(x.Elts) == 0
-
- default:
- // Note that this function is not comprehensive.
- return false
- }
-}
-
-// ZeroValueOf returns a zero value expression for typeExpr of type typ.
-// If function can't find such a value, nil is returned.
-func ZeroValueOf(typeExpr ast.Expr, typ types.Type) ast.Expr {
- switch utyp := typ.Underlying().(type) {
- case *types.Basic:
- info := utyp.Info()
- var zv ast.Expr
- switch {
- case info&types.IsInteger != 0:
- zv = &ast.BasicLit{Kind: token.INT, Value: "0"}
- case info&types.IsFloat != 0:
- zv = &ast.BasicLit{Kind: token.FLOAT, Value: "0.0"}
- case info&types.IsString != 0:
- zv = &ast.BasicLit{Kind: token.STRING, Value: `""`}
- case info&types.IsBoolean != 0:
- zv = &ast.Ident{Name: "false"}
- }
- if isDefaultLiteralType(typ) {
- return zv
- }
- return &ast.CallExpr{
- Fun: typeExpr,
- Args: []ast.Expr{zv},
- }
-
- case *types.Slice, *types.Map, *types.Pointer, *types.Interface:
- return &ast.CallExpr{
- Fun: typeExpr,
- Args: []ast.Expr{&ast.Ident{Name: "nil"}},
- }
-
- case *types.Array, *types.Struct:
- return &ast.CompositeLit{Type: typeExpr}
-
- default:
- return nil
- }
-}
-
-func isDefaultLiteralType(typ types.Type) bool {
- btyp, ok := typ.(*types.Basic)
- if !ok {
- return false
- }
- switch btyp.Kind() {
- case types.Bool, types.Int, types.Float64, types.String:
- return true
- default:
- return false
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/mapKey_checker.go b/vendor/github.com/go-critic/go-critic/checkers/mapKey_checker.go
deleted file mode 100644
index 2885dc725..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/mapKey_checker.go
+++ /dev/null
@@ -1,125 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/types"
- "strings"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/checkers/internal/lintutil"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "github.com/go-toolsmith/astp"
- "github.com/go-toolsmith/typep"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "mapKey"
- info.Tags = []string{linter.DiagnosticTag}
- info.Summary = "Detects suspicious map literal keys"
- info.Before = `
-_ = map[string]int{
- "foo": 1,
- "bar ": 2,
-}`
- info.After = `
-_ = map[string]int{
- "foo": 1,
- "bar": 2,
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForExpr(&mapKeyChecker{ctx: ctx}), nil
- })
-}
-
-type mapKeyChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- astSet lintutil.AstSet
-}
-
-func (c *mapKeyChecker) VisitExpr(expr ast.Expr) {
- lit := astcast.ToCompositeLit(expr)
- if len(lit.Elts) < 2 {
- return
- }
-
- typ, ok := c.ctx.TypeOf(lit).Underlying().(*types.Map)
- if !ok {
- return
- }
- if !typep.HasStringKind(typ.Key().Underlying()) {
- return
- }
-
- c.checkWhitespace(lit)
- c.checkDuplicates(lit)
-}
-
-func (c *mapKeyChecker) checkDuplicates(lit *ast.CompositeLit) {
- c.astSet.Clear()
-
- for _, elt := range lit.Elts {
- kv := astcast.ToKeyValueExpr(elt)
- if astp.IsBasicLit(kv.Key) {
- // Basic lits are handled by the compiler.
- continue
- }
- if !typep.SideEffectFree(c.ctx.TypesInfo, kv.Key) {
- continue
- }
- if !c.astSet.Insert(kv.Key) {
- c.warnDupKey(kv.Key)
- }
- }
-}
-
-func (c *mapKeyChecker) checkWhitespace(lit *ast.CompositeLit) {
- var whitespaceKey ast.Node
- for _, elt := range lit.Elts {
- key := astcast.ToBasicLit(astcast.ToKeyValueExpr(elt).Key)
- if len(key.Value) < len(`" "`) {
- continue
- }
- // s is unquoted string literal value.
- s := key.Value[len(`"`) : len(key.Value)-len(`"`)]
- if !strings.Contains(s, " ") {
- continue
- }
- if whitespaceKey != nil {
- // Already seen something with a whitespace.
- // More than one entry => not suspicious.
- return
- }
- if s == " " {
- // If space is used as a key, maybe this map
- // has something to do with spaces. Give up.
- return
- }
- // Check if it has exactly 1 space prefix or suffix.
- bad := strings.HasPrefix(s, " ") && !strings.HasPrefix(s, " ") ||
- strings.HasSuffix(s, " ") && !strings.HasSuffix(s, " ")
- if !bad {
- // These spaces can be a padding,
- // or a legitimate part of a key. Give up.
- return
- }
- whitespaceKey = key
- }
-
- if whitespaceKey != nil {
- c.warnWhitespace(whitespaceKey)
- }
-}
-
-func (c *mapKeyChecker) warnWhitespace(key ast.Node) {
- c.ctx.Warn(key, "suspicious whitespace in %s key", key)
-}
-
-func (c *mapKeyChecker) warnDupKey(key ast.Node) {
- c.ctx.Warn(key, "suspicious duplicate %s key", key)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/methodExprCall_checker.go b/vendor/github.com/go-critic/go-critic/checkers/methodExprCall_checker.go
deleted file mode 100644
index 755d3b472..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/methodExprCall_checker.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "github.com/go-toolsmith/astcopy"
- "github.com/go-toolsmith/typep"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "methodExprCall"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag}
- info.Summary = "Detects method expression call that can be replaced with a method call"
- info.Before = `f := foo{}
-foo.bar(f)`
- info.After = `f := foo{}
-f.bar()`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForExpr(&methodExprCallChecker{ctx: ctx}), nil
- })
-}
-
-type methodExprCallChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *methodExprCallChecker) VisitExpr(x ast.Expr) {
- call := astcast.ToCallExpr(x)
- s := astcast.ToSelectorExpr(call.Fun)
-
- if len(call.Args) < 1 || astcast.ToIdent(call.Args[0]).Name == "nil" {
- return
- }
-
- if typep.IsTypeExpr(c.ctx.TypesInfo, s.X) {
- c.warn(call, s)
- }
-}
-
-func (c *methodExprCallChecker) warn(cause *ast.CallExpr, s *ast.SelectorExpr) {
- selector := astcopy.SelectorExpr(s)
- selector.X = cause.Args[0]
-
- // Remove "&" from the receiver (if any).
- if u, ok := selector.X.(*ast.UnaryExpr); ok && u.Op == token.AND {
- selector.X = u.X
- }
-
- c.ctx.Warn(cause, "consider to change `%s` to `%s`", cause.Fun, selector)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/nestingReduce_checker.go b/vendor/github.com/go-critic/go-critic/checkers/nestingReduce_checker.go
deleted file mode 100644
index dfe73018c..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/nestingReduce_checker.go
+++ /dev/null
@@ -1,73 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "nestingReduce"
- info.Tags = []string{linter.StyleTag, linter.OpinionatedTag, linter.ExperimentalTag}
- info.Params = linter.CheckerParams{
- "bodyWidth": {
- Value: 5,
- Usage: "min number of statements inside a branch to trigger a warning",
- },
- }
- info.Summary = "Finds where nesting level could be reduced"
- info.Before = `
-for _, v := range a {
- if v.Bool {
- body()
- }
-}`
- info.After = `
-for _, v := range a {
- if !v.Bool {
- continue
- }
- body()
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- c := &nestingReduceChecker{ctx: ctx}
- c.bodyWidth = info.Params.Int("bodyWidth")
- return astwalk.WalkerForStmt(c), nil
- })
-}
-
-type nestingReduceChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- bodyWidth int
-}
-
-func (c *nestingReduceChecker) VisitStmt(stmt ast.Stmt) {
- switch stmt := stmt.(type) {
- case *ast.ForStmt:
- c.checkLoopBody(stmt.Body.List)
- case *ast.RangeStmt:
- c.checkLoopBody(stmt.Body.List)
- }
-}
-
-func (c *nestingReduceChecker) checkLoopBody(body []ast.Stmt) {
- if len(body) != 1 {
- return
- }
- stmt, ok := body[0].(*ast.IfStmt)
- if !ok {
- return
- }
- if len(stmt.Body.List) >= c.bodyWidth && stmt.Else == nil {
- c.warnLoop(stmt)
- }
-}
-
-func (c *nestingReduceChecker) warnLoop(cause ast.Node) {
- c.ctx.Warn(cause, "invert if cond, replace body with `continue`, move old body after the statement")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/newDeref_checker.go b/vendor/github.com/go-critic/go-critic/checkers/newDeref_checker.go
deleted file mode 100644
index 1a1b05e0d..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/newDeref_checker.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/checkers/internal/lintutil"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "golang.org/x/tools/go/ast/astutil"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "newDeref"
- info.Tags = []string{linter.StyleTag}
- info.Summary = "Detects immediate dereferencing of `new` expressions"
- info.Before = `x := *new(bool)`
- info.After = `x := false`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForExpr(&newDerefChecker{ctx: ctx}), nil
- })
-}
-
-type newDerefChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *newDerefChecker) VisitExpr(expr ast.Expr) {
- deref := astcast.ToStarExpr(expr)
- call := astcast.ToCallExpr(deref.X)
- if astcast.ToIdent(call.Fun).Name == "new" {
- typ := c.ctx.TypeOf(call.Args[0])
- // allow *new(T) if T is a type parameter, see #1272 for details
- if _, ok := typ.(*types.TypeParam); ok {
- return
- }
- zv := lintutil.ZeroValueOf(astutil.Unparen(call.Args[0]), typ)
- if zv != nil {
- c.warn(expr, zv)
- }
- }
-}
-
-func (c *newDerefChecker) warn(cause, suggestion ast.Expr) {
- c.ctx.Warn(cause, "replace `%s` with `%s`", cause, suggestion)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/nilValReturn_checker.go b/vendor/github.com/go-critic/go-critic/checkers/nilValReturn_checker.go
deleted file mode 100644
index 9a1213f5c..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/nilValReturn_checker.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astequal"
- "github.com/go-toolsmith/typep"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "nilValReturn"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects return statements those results evaluate to nil"
- info.Before = `
-if err == nil {
- return err
-}`
- info.After = `
-// (A) - return nil explicitly
-if err == nil {
- return nil
-}
-// (B) - typo in "==", change to "!="
-if err != nil {
- return err
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&nilValReturnChecker{ctx: ctx}), nil
- })
-}
-
-type nilValReturnChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *nilValReturnChecker) VisitStmt(stmt ast.Stmt) {
- ifStmt, ok := stmt.(*ast.IfStmt)
- if !ok || len(ifStmt.Body.List) != 1 {
- return
- }
- ret, ok := ifStmt.Body.List[0].(*ast.ReturnStmt)
- if !ok {
- return
- }
- expr, ok := ifStmt.Cond.(*ast.BinaryExpr)
- if !ok {
- return
- }
- xIsNil := expr.Op == token.EQL &&
- typep.SideEffectFree(c.ctx.TypesInfo, expr.X) &&
- qualifiedName(expr.Y) == "nil"
- if !xIsNil {
- return
- }
- for _, res := range ret.Results {
- if astequal.Expr(expr.X, res) {
- c.warn(ret, expr.X)
- break
- }
- }
-}
-
-func (c *nilValReturnChecker) warn(cause, val ast.Node) {
- c.ctx.Warn(cause, "returned expr is always nil; replace %s with nil", val)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/octalLiteral_checker.go b/vendor/github.com/go-critic/go-critic/checkers/octalLiteral_checker.go
deleted file mode 100644
index a25fac85c..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/octalLiteral_checker.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
- "strings"
- "unicode"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "octalLiteral"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag, linter.OpinionatedTag}
- info.Summary = "Detects old-style octal literals"
- info.Before = `foo(02)`
- info.After = `foo(0o2)`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForExpr(&octalLiteralChecker{ctx: ctx}), nil
- })
-}
-
-type octalLiteralChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *octalLiteralChecker) VisitExpr(expr ast.Expr) {
- if !c.ctx.GoVersion.GreaterOrEqual(linter.GoVersion{Major: 1, Minor: 13}) {
- return
- }
- lit := astcast.ToBasicLit(expr)
- if lit.Kind != token.INT {
- return
- }
- if !strings.HasPrefix(lit.Value, "0") || len(lit.Value) == 1 {
- return
- }
- if unicode.IsDigit(rune(lit.Value[1])) {
- c.warn(lit)
- }
-}
-
-func (c *octalLiteralChecker) warn(lit *ast.BasicLit) {
- c.ctx.Warn(lit, "use new octal literal style, 0o%s", lit.Value[len("0"):])
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/paramTypeCombine_checker.go b/vendor/github.com/go-critic/go-critic/checkers/paramTypeCombine_checker.go
deleted file mode 100644
index c777fec9e..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/paramTypeCombine_checker.go
+++ /dev/null
@@ -1,97 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcopy"
- "github.com/go-toolsmith/astequal"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "paramTypeCombine"
- info.Tags = []string{linter.StyleTag, linter.OpinionatedTag}
- info.Summary = "Detects if function parameters could be combined by type and suggest the way to do it"
- info.Before = `func foo(a, b int, c, d int, e, f int, g int) {}`
- info.After = `func foo(a, b, c, d, e, f, g int) {}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForFuncDecl(&paramTypeCombineChecker{ctx: ctx}), nil
- })
-}
-
-type paramTypeCombineChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *paramTypeCombineChecker) EnterFunc(*ast.FuncDecl) bool {
- return true
-}
-
-func (c *paramTypeCombineChecker) VisitFuncDecl(decl *ast.FuncDecl) {
- typ := c.optimizeFuncType(decl.Type)
- if !astequal.Expr(typ, decl.Type) {
- c.warn(decl.Type, typ)
- }
-}
-
-func (c *paramTypeCombineChecker) optimizeFuncType(f *ast.FuncType) *ast.FuncType {
- optimizedParamFunc := astcopy.FuncType(f)
-
- optimizedParamFunc.Params = c.optimizeParams(f.Params)
- optimizedParamFunc.Results = c.optimizeParams(f.Results)
-
- return optimizedParamFunc
-}
-
-func (c *paramTypeCombineChecker) optimizeParams(params *ast.FieldList) *ast.FieldList {
- // To avoid false positives, skip unnamed param lists.
- //
- // We're using a property that Go only permits unnamed params
- // for the whole list, so it's enough to check whether any of
- // ast.Field have empty name list.
- skip := params == nil ||
- len(params.List) < 2 ||
- len(params.List[0].Names) == 0 ||
- c.paramsAreMultiLine(params)
- if skip {
- return params
- }
-
- list := []*ast.Field{}
- names := make([]*ast.Ident, len(params.List[0].Names))
- copy(names, params.List[0].Names)
- list = append(list, &ast.Field{
- Names: names,
- Type: params.List[0].Type,
- })
- for i, p := range params.List[1:] {
- names = make([]*ast.Ident, len(p.Names))
- copy(names, p.Names)
- if astequal.Expr(p.Type, params.List[i].Type) {
- list[len(list)-1].Names = append(list[len(list)-1].Names, names...)
- } else {
- list = append(list, &ast.Field{
- Names: names,
- Type: params.List[i+1].Type,
- })
- }
- }
- return &ast.FieldList{
- List: list,
- }
-}
-
-func (c *paramTypeCombineChecker) warn(f1, f2 *ast.FuncType) {
- c.ctx.Warn(f1, "%s could be replaced with %s", f1, f2)
-}
-
-func (c *paramTypeCombineChecker) paramsAreMultiLine(params *ast.FieldList) bool {
- startPos := c.ctx.FileSet.Position(params.Opening)
- endPos := c.ctx.FileSet.Position(params.Closing)
- return startPos.Line != endPos.Line
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/ptrToRefParam_checker.go b/vendor/github.com/go-critic/go-critic/checkers/ptrToRefParam_checker.go
deleted file mode 100644
index 172a4acb5..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/ptrToRefParam_checker.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "ptrToRefParam"
- info.Tags = []string{linter.StyleTag, linter.OpinionatedTag, linter.ExperimentalTag}
- info.Summary = "Detects input and output parameters that have a type of pointer to referential type"
- info.Before = `func f(m *map[string]int) (*chan *int)`
- info.After = `func f(m map[string]int) (chan *int)`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForFuncDecl(&ptrToRefParamChecker{ctx: ctx}), nil
- })
-}
-
-type ptrToRefParamChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *ptrToRefParamChecker) VisitFuncDecl(fn *ast.FuncDecl) {
- c.checkParams(fn.Type.Params.List)
- if fn.Type.Results != nil {
- c.checkParams(fn.Type.Results.List)
- }
-}
-
-func (c *ptrToRefParamChecker) checkParams(params []*ast.Field) {
- for _, param := range params {
- ptr, ok := c.ctx.TypeOf(param.Type).(*types.Pointer)
- if !ok {
- continue
- }
-
- if c.isRefType(ptr.Elem()) {
- if len(param.Names) == 0 {
- c.ctx.Warn(param, "consider to make non-pointer type for `%s`", param.Type)
- } else {
- for i := range param.Names {
- c.warn(param.Names[i])
- }
- }
- }
- }
-}
-
-func (c *ptrToRefParamChecker) isRefType(x types.Type) bool {
- switch typ := x.(type) {
- case *types.Map, *types.Chan, *types.Interface:
- return true
- case *types.Named:
- // Handle underlying type only for interfaces.
- if _, ok := typ.Underlying().(*types.Interface); ok {
- return true
- }
- }
- return false
-}
-
-func (c *ptrToRefParamChecker) warn(id *ast.Ident) {
- c.ctx.Warn(id, "consider `%s' to be of non-pointer type", id)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/rangeAppendAll_checker.go b/vendor/github.com/go-critic/go-critic/checkers/rangeAppendAll_checker.go
deleted file mode 100644
index f4851d402..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/rangeAppendAll_checker.go
+++ /dev/null
@@ -1,100 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
- "github.com/go-toolsmith/astcast"
- "golang.org/x/tools/go/ast/astutil"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "rangeAppendAll"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects append all its data while range it"
- info.Before = `for _, n := range ns {
- ...
- rs = append(rs, ns...) // append all slice data
- }
-}`
- info.After = `for _, n := range ns {
- ...
- rs = append(rs, n)
- }
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- c := &rangeAppendAllChecker{ctx: ctx}
- return astwalk.WalkerForStmt(c), nil
- })
-}
-
-type rangeAppendAllChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *rangeAppendAllChecker) VisitStmt(stmt ast.Stmt) {
- rangeStmt, ok := stmt.(*ast.RangeStmt)
- if !ok || len(rangeStmt.Body.List) == 0 {
- return
- }
- rangeIdent, ok := rangeStmt.X.(*ast.Ident)
- if !ok {
- return
- }
- rangeObj := c.ctx.TypesInfo.ObjectOf(rangeIdent)
-
- astutil.Apply(rangeStmt.Body, nil, func(cur *astutil.Cursor) bool {
- appendFrom := c.getValidAppendFrom(cur.Node())
- if appendFrom != nil {
- appendFromObj := c.ctx.TypesInfo.ObjectOf(appendFrom)
- if appendFromObj == rangeObj {
- c.warn(appendFrom)
- }
- }
- return true
- })
-}
-
-func (c *rangeAppendAllChecker) getValidAppendFrom(expr ast.Node) *ast.Ident {
- call := astcast.ToCallExpr(expr)
- if len(call.Args) != 2 || call.Ellipsis == token.NoPos {
- return nil
- }
- if qualifiedName(call.Fun) != "append" {
- return nil
- }
- if c.isSliceLiteral(call.Args[0]) {
- return nil
- }
- appendFrom, ok := call.Args[1].(*ast.Ident)
- if !ok {
- return nil
- }
- return appendFrom
-}
-
-func (c *rangeAppendAllChecker) isSliceLiteral(arg ast.Expr) bool {
- switch v := arg.(type) {
- // []T{}, []T{n}
- case *ast.CompositeLit:
- return true
- // []T(nil)
- case *ast.CallExpr:
- if astcast.ToArrayType(v.Fun) != astcast.NilArrayType && len(v.Args) == 1 {
- id := astcast.ToIdent(v.Args[0])
- return id.Name == "nil" && id.Obj == nil
- }
- return false
- default:
- return false
- }
-}
-
-func (c *rangeAppendAllChecker) warn(appendFrom *ast.Ident) {
- c.ctx.Warn(appendFrom, "append all `%s` data while range it", appendFrom)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/rangeExprCopy_checker.go b/vendor/github.com/go-critic/go-critic/checkers/rangeExprCopy_checker.go
deleted file mode 100644
index 3f61ee0bd..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/rangeExprCopy_checker.go
+++ /dev/null
@@ -1,80 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "rangeExprCopy"
- info.Tags = []string{linter.PerformanceTag}
- info.Params = linter.CheckerParams{
- "sizeThreshold": {
- Value: 512,
- Usage: "size in bytes that makes the warning trigger",
- },
- "skipTestFuncs": {
- Value: true,
- Usage: "whether to check test functions",
- },
- }
- info.Summary = "Detects expensive copies of `for` loop range expressions"
- info.Details = "Suggests to use pointer to array to avoid the copy using `&` on range expression."
- info.Before = `
-var xs [2048]byte
-for _, x := range xs { // Copies 2048 bytes
- // Loop body.
-}`
- info.After = `
-var xs [2048]byte
-for _, x := range &xs { // No copy
- // Loop body.
-}`
- info.Note = "See Go issue for details: https://github.com/golang/go/issues/15812."
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- c := &rangeExprCopyChecker{ctx: ctx}
- c.sizeThreshold = int64(info.Params.Int("sizeThreshold"))
- c.skipTestFuncs = info.Params.Bool("skipTestFuncs")
- return astwalk.WalkerForStmt(c), nil
- })
-}
-
-type rangeExprCopyChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- sizeThreshold int64
- skipTestFuncs bool
-}
-
-func (c *rangeExprCopyChecker) EnterFunc(fn *ast.FuncDecl) bool {
- return fn.Body != nil &&
- !(c.skipTestFuncs && isUnitTestFunc(c.ctx, fn))
-}
-
-func (c *rangeExprCopyChecker) VisitStmt(stmt ast.Stmt) {
- rng, ok := stmt.(*ast.RangeStmt)
- if !ok || rng.Key == nil || rng.Value == nil {
- return
- }
- tv := c.ctx.TypesInfo.Types[rng.X]
- if !tv.Addressable() {
- return
- }
- if _, ok := tv.Type.(*types.Array); !ok {
- return
- }
- if size, ok := c.ctx.SizeOf(tv.Type); ok && size >= c.sizeThreshold {
- c.warn(rng, size)
- }
-}
-
-func (c *rangeExprCopyChecker) warn(rng *ast.RangeStmt, size int64) {
- c.ctx.Warn(rng, "copy of %s (%d bytes) can be avoided with &%s",
- rng.X, size, rng.X)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/rangeValCopy_checker.go b/vendor/github.com/go-critic/go-critic/checkers/rangeValCopy_checker.go
deleted file mode 100644
index 6d15c30cd..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/rangeValCopy_checker.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "rangeValCopy"
- info.Tags = []string{linter.PerformanceTag}
- info.Params = linter.CheckerParams{
- "sizeThreshold": {
- Value: 128,
- Usage: "size in bytes that makes the warning trigger",
- },
- "skipTestFuncs": {
- Value: true,
- Usage: "whether to check test functions",
- },
- }
- info.Summary = "Detects loops that copy big objects during each iteration"
- info.Details = "Suggests to use index access or take address and make use pointer instead."
- info.Before = `
-xs := make([][1024]byte, length)
-for _, x := range xs {
- // Loop body.
-}`
- info.After = `
-xs := make([][1024]byte, length)
-for i := range xs {
- x := &xs[i]
- // Loop body.
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- c := &rangeValCopyChecker{ctx: ctx}
- c.sizeThreshold = int64(info.Params.Int("sizeThreshold"))
- c.skipTestFuncs = info.Params.Bool("skipTestFuncs")
- return astwalk.WalkerForStmt(c), nil
- })
-}
-
-type rangeValCopyChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- sizeThreshold int64
- skipTestFuncs bool
-}
-
-func (c *rangeValCopyChecker) EnterFunc(fn *ast.FuncDecl) bool {
- return fn.Body != nil &&
- !(c.skipTestFuncs && isUnitTestFunc(c.ctx, fn))
-}
-
-func (c *rangeValCopyChecker) VisitStmt(stmt ast.Stmt) {
- rng, ok := stmt.(*ast.RangeStmt)
- if !ok || rng.Value == nil {
- return
- }
- typ := c.ctx.TypeOf(rng.Value)
- if typ == nil {
- return
- }
- size, ok := c.ctx.SizeOf(typ)
- if ok && size >= c.sizeThreshold {
- c.warn(rng, size)
- }
-}
-
-func (c *rangeValCopyChecker) warn(n ast.Node, size int64) {
- c.ctx.Warn(n, "each iteration copies %d bytes (consider pointers or indexing)", size)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/regexpPattern_checker.go b/vendor/github.com/go-critic/go-critic/checkers/regexpPattern_checker.go
deleted file mode 100644
index 45aba261b..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/regexpPattern_checker.go
+++ /dev/null
@@ -1,68 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/constant"
- "regexp"
- "strings"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "regexpPattern"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects suspicious regexp patterns"
- info.Before = "regexp.MustCompile(`google.com|yandex.ru`)"
- info.After = "regexp.MustCompile(`google\\.com|yandex\\.ru`)"
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- domains := []string{
- "com",
- "org",
- "info",
- "net",
- "ru",
- "de",
- }
-
- allDomains := strings.Join(domains, "|")
- domainRE := regexp.MustCompile(`[^\\]\.(` + allDomains + `)\b`)
- return astwalk.WalkerForExpr(&regexpPatternChecker{
- ctx: ctx,
- domainRE: domainRE,
- }), nil
- })
-}
-
-type regexpPatternChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- domainRE *regexp.Regexp
-}
-
-func (c *regexpPatternChecker) VisitExpr(x ast.Expr) {
- call, ok := x.(*ast.CallExpr)
- if !ok {
- return
- }
-
- switch qualifiedName(call.Fun) {
- case "regexp.Compile", "regexp.CompilePOSIX", "regexp.MustCompile", "regexp.MustCompilePosix":
- cv := c.ctx.TypesInfo.Types[call.Args[0]].Value
- if cv == nil || cv.Kind() != constant.String {
- return
- }
- s := constant.StringVal(cv)
- if m := c.domainRE.FindStringSubmatch(s); m != nil {
- c.warnDomain(call.Args[0], m[1])
- }
- }
-}
-
-func (c *regexpPatternChecker) warnDomain(cause ast.Expr, domain string) {
- c.ctx.Warn(cause, "'.%s' should probably be '\\.%s'", domain, domain)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/regexpSimplify_checker.go b/vendor/github.com/go-critic/go-critic/checkers/regexpSimplify_checker.go
deleted file mode 100644
index f500f4350..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/regexpSimplify_checker.go
+++ /dev/null
@@ -1,512 +0,0 @@
-package checkers
-
-import (
- "fmt"
- "go/ast"
- "go/constant"
- "log"
- "strings"
- "unicode/utf8"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/quasilyte/regex/syntax"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "regexpSimplify"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag, linter.OpinionatedTag}
- info.Summary = "Detects regexp patterns that can be simplified"
- info.Before = "regexp.MustCompile(`(?:a|b|c) [a-z][a-z]*`)"
- info.After = "regexp.MustCompile(`[abc] {3}[a-z]+`)"
-
- // TODO(quasilyte): add params to control most opinionated replacements
- // like `[0-9] -> \d`
- // `[[:digit:]] -> \d`
- // `[A-Za-z0-9_]` -> `\w`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- opts := &syntax.ParserOptions{
- NoLiterals: true,
- }
- c := &regexpSimplifyChecker{
- ctx: ctx,
- parser: syntax.NewParser(opts),
- out: &strings.Builder{},
- }
- return astwalk.WalkerForExpr(c), nil
- })
-}
-
-type regexpSimplifyChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
- parser *syntax.Parser
-
- // out is a tmp buffer where we build a simplified regexp pattern.
- out *strings.Builder
- // score is a number of applied simplifications
- score int
-}
-
-func (c *regexpSimplifyChecker) VisitExpr(x ast.Expr) {
- call, ok := x.(*ast.CallExpr)
- if !ok {
- return
- }
-
- switch qualifiedName(call.Fun) {
- case "regexp.Compile", "regexp.MustCompile":
- cv := c.ctx.TypesInfo.Types[call.Args[0]].Value
- if cv == nil || cv.Kind() != constant.String {
- return
- }
- pat := constant.StringVal(cv)
- if len(pat) > 60 {
- // Skip scary regexp patterns for now.
- break
- }
-
- // Only do 2 passes.
- simplified := pat
- for pass := 0; pass < 2; pass++ {
- candidate := c.simplify(pass, simplified)
- if candidate == "" {
- break
- }
- simplified = candidate
- }
- if simplified != "" && simplified != pat {
- c.warn(call.Args[0], pat, simplified)
- }
- }
-}
-
-func (c *regexpSimplifyChecker) simplify(pass int, pat string) string {
- re, err := c.parser.Parse(pat)
- if err != nil {
- return ""
- }
-
- c.score = 0
- c.out.Reset()
-
- // TODO(quasilyte): suggest char ranges for things like [012345689]?
- // TODO(quasilyte): evaluate char range to suggest better replacements.
- // TODO(quasilyte): (?:ab|ac) -> a[bc]
- // TODO(quasilyte): suggest "s" and "." flag if things like [\w\W] are used.
- // TODO(quasilyte): x{n}x? -> x{n,n+1}
-
- c.walk(re.Expr)
-
- if debug() {
- // This happens only in one of two cases:
- // 1. Parser has a bug and we got invalid AST for the given pattern.
- // 2. Simplifier incorrectly built a replacement string from the AST.
- if c.score == 0 && c.out.String() != pat {
- log.Printf("pass %d: unexpected pattern diff:\n\thave: %q\n\twant: %q",
- pass, c.out.String(), pat)
- }
- }
-
- if c.score > 0 {
- return c.out.String()
- }
- return ""
-}
-
-func (c *regexpSimplifyChecker) walk(e syntax.Expr) {
- out := c.out
-
- switch e.Op {
- case syntax.OpConcat:
- c.walkConcat(e)
-
- case syntax.OpAlt:
- c.walkAlt(e)
-
- case syntax.OpCharRange:
- s := c.simplifyCharRange(e)
- if s != "" {
- out.WriteString(s)
- c.score++
- } else {
- out.WriteString(e.Value)
- }
-
- case syntax.OpGroupWithFlags:
- out.WriteString("(")
- out.WriteString(e.Args[1].Value)
- out.WriteString(":")
- c.walk(e.Args[0])
- out.WriteString(")")
- case syntax.OpGroup:
- c.walkGroup(e)
- case syntax.OpCapture:
- out.WriteString("(")
- c.walk(e.Args[0])
- out.WriteString(")")
- case syntax.OpNamedCapture:
- out.WriteString("(?P<")
- out.WriteString(e.Args[1].Value)
- out.WriteString(">")
- c.walk(e.Args[0])
- out.WriteString(")")
-
- case syntax.OpRepeat:
- // TODO(quasilyte): is it worth it to analyze repeat argument
- // more closely and handle `{n,n} -> {n}` cases?
- rep := e.Args[1].Value
- switch rep {
- case "{0,1}":
- c.walk(e.Args[0])
- out.WriteString("?")
- c.score++
- case "{1,}":
- c.walk(e.Args[0])
- out.WriteString("+")
- c.score++
- case "{0,}":
- c.walk(e.Args[0])
- out.WriteString("*")
- c.score++
- case "{0}":
- // Maybe {0} should be reported by another check, regexpLint?
- c.score++
- case "{1}":
- c.walk(e.Args[0])
- c.score++
- default:
- c.walk(e.Args[0])
- out.WriteString(rep)
- }
-
- case syntax.OpPosixClass:
- out.WriteString(e.Value)
-
- case syntax.OpNegCharClass:
- s := c.simplifyNegCharClass(e)
- if s != "" {
- c.out.WriteString(s)
- c.score++
- } else {
- out.WriteString("[^")
- for _, e := range e.Args {
- c.walk(e)
- }
- out.WriteString("]")
- }
-
- case syntax.OpCharClass:
- s := c.simplifyCharClass(e)
- if s != "" {
- c.out.WriteString(s)
- c.score++
- } else {
- out.WriteString("[")
- for _, e := range e.Args {
- c.walk(e)
- }
- out.WriteString("]")
- }
-
- case syntax.OpEscapeChar:
- switch e.Value {
- case `\&`, `\#`, `\!`, `\@`, `\%`, `\<`, `\>`, `\:`, `\;`, `\/`, `\,`, `\=`, `\.`:
- c.score++
- out.WriteString(e.Value[len(`\`):])
- default:
- out.WriteString(e.Value)
- }
-
- case syntax.OpQuestion, syntax.OpNonGreedy:
- c.walk(e.Args[0])
- out.WriteString("?")
- case syntax.OpStar:
- c.walk(e.Args[0])
- out.WriteString("*")
- case syntax.OpPlus:
- c.walk(e.Args[0])
- out.WriteString("+")
-
- default:
- out.WriteString(e.Value)
- }
-}
-
-func (c *regexpSimplifyChecker) walkGroup(g syntax.Expr) {
- switch g.Args[0].Op {
- case syntax.OpChar, syntax.OpEscapeChar, syntax.OpEscapeMeta, syntax.OpCharClass:
- c.walk(g.Args[0])
- c.score++
- return
- }
-
- c.out.WriteString("(?:")
- c.walk(g.Args[0])
- c.out.WriteString(")")
-}
-
-func (c *regexpSimplifyChecker) simplifyNegCharClass(e syntax.Expr) string {
- switch e.Value {
- case `[^0-9]`:
- return `\D`
- case `[^\s]`:
- return `\S`
- case `[^\S]`:
- return `\s`
- case `[^\w]`:
- return `\W`
- case `[^\W]`:
- return `\w`
- case `[^\d]`:
- return `\D`
- case `[^\D]`:
- return `\d`
- case `[^[:^space:]]`:
- return `\s`
- case `[^[:space:]]`:
- return `\S`
- case `[^[:^word:]]`:
- return `\w`
- case `[^[:word:]]`:
- return `\W`
- case `[^[:^digit:]]`:
- return `\d`
- case `[^[:digit:]]`:
- return `\D`
- }
-
- return ""
-}
-
-func (c *regexpSimplifyChecker) simplifyCharClass(e syntax.Expr) string {
- switch e.Value {
- case `[0-9]`:
- return `\d`
- case `[[:word:]]`:
- return `\w`
- case `[[:^word:]]`:
- return `\W`
- case `[[:digit:]]`:
- return `\d`
- case `[[:^digit:]]`:
- return `\D`
- case `[[:space:]]`:
- return `\s`
- case `[[:^space:]]`:
- return `\S`
- case `[][]`:
- return `\]\[`
- case `[]]`:
- return `\]`
- }
-
- if len(e.Args) == 1 {
- switch e.Args[0].Op {
- case syntax.OpChar:
- switch v := e.Args[0].Value; v {
- case "|", "*", "+", "?", ".", "[", "^", "$", "(", ")":
- // Can't take outside of the char group without escaping.
- default:
- return v
- }
- case syntax.OpEscapeChar:
- return e.Args[0].Value
- }
- }
-
- return ""
-}
-
-func (c *regexpSimplifyChecker) canMerge(x, y syntax.Expr) bool {
- if x.Op != y.Op {
- return false
- }
- switch x.Op {
- case syntax.OpChar, syntax.OpCharClass, syntax.OpEscapeMeta, syntax.OpEscapeChar, syntax.OpNegCharClass, syntax.OpGroup:
- return x.Value == y.Value
- default:
- return false
- }
-}
-
-func (c *regexpSimplifyChecker) canCombine(x, y syntax.Expr) (threshold int, ok bool) {
- if x.Op != y.Op {
- return 0, false
- }
-
- switch x.Op {
- case syntax.OpDot:
- return 3, true
-
- case syntax.OpChar:
- if x.Value != y.Value {
- return 0, false
- }
- if x.Value == " " {
- return 1, true
- }
- return 4, true
-
- case syntax.OpEscapeMeta, syntax.OpEscapeChar:
- if x.Value == y.Value {
- return 2, true
- }
-
- case syntax.OpCharClass, syntax.OpNegCharClass, syntax.OpGroup:
- if x.Value == y.Value {
- return 1, true
- }
- }
-
- return 0, false
-}
-
-func (c *regexpSimplifyChecker) concatLiteral(e syntax.Expr) string {
- if e.Op == syntax.OpConcat && c.allChars(e) {
- return e.Value
- }
- return ""
-}
-
-func (c *regexpSimplifyChecker) allChars(e syntax.Expr) bool {
- for _, a := range e.Args {
- if a.Op != syntax.OpChar {
- return false
- }
- }
- return true
-}
-
-func (c *regexpSimplifyChecker) factorPrefixSuffix(alt syntax.Expr) bool {
- // TODO: more forms of prefixes/suffixes?
- //
- // A more generalized algorithm could handle `fo|fo1|fo2` -> `fo[12]?`.
- // but it's an open question whether the latter form universally better.
- //
- // Right now it handles only the simplest cases:
- // `http|https` -> `https?`
- // `xfoo|foo` -> `x?foo`
- if len(alt.Args) != 2 {
- return false
- }
- x := c.concatLiteral(alt.Args[0])
- y := c.concatLiteral(alt.Args[1])
- if x == y {
- return false // Reject non-literals and identical strings early
- }
-
- // Let x be a shorter string.
- if len(x) > len(y) {
- x, y = y, x
- }
- // Do we have a common prefix?
- tail := strings.TrimPrefix(y, x)
- if len(tail) <= utf8.UTFMax && utf8.RuneCountInString(tail) == 1 {
- c.out.WriteString(x + tail + "?")
- c.score++
- return true
- }
- // Do we have a common suffix?
- head := strings.TrimSuffix(y, x)
- if len(head) <= utf8.UTFMax && utf8.RuneCountInString(head) == 1 {
- c.out.WriteString(head + "?" + x)
- c.score++
- return true
- }
- return false
-}
-
-func (c *regexpSimplifyChecker) walkAlt(alt syntax.Expr) {
- // `x|y|z` -> `[xyz]`.
- if c.allChars(alt) {
- c.score++
- c.out.WriteString("[")
- for _, e := range alt.Args {
- c.out.WriteString(e.Value)
- }
- c.out.WriteString("]")
- return
- }
-
- if c.factorPrefixSuffix(alt) {
- return
- }
-
- for i, e := range alt.Args {
- c.walk(e)
- if i != len(alt.Args)-1 {
- c.out.WriteString("|")
- }
- }
-}
-
-func (c *regexpSimplifyChecker) walkConcat(concat syntax.Expr) {
- i := 0
- for i < len(concat.Args) {
- x := concat.Args[i]
- c.walk(x)
- i++
-
- if i >= len(concat.Args) {
- break
- }
-
- // Try merging `xy*` into `x+` where x=y.
- if concat.Args[i].Op == syntax.OpStar {
- if c.canMerge(x, concat.Args[i].Args[0]) {
- c.out.WriteString("+")
- c.score++
- i++
- continue
- }
- }
-
- // Try combining `xy` into `x{2}` where x=y.
- threshold, ok := c.canCombine(x, concat.Args[i])
- if !ok {
- continue
- }
- n := 1 // Can combine at least 1 pair.
- for j := i + 1; j < len(concat.Args); j++ {
- _, ok := c.canCombine(x, concat.Args[j])
- if !ok {
- break
- }
- n++
- }
- if n >= threshold {
- fmt.Fprintf(c.out, "{%d}", n+1)
- c.score++
- i += n
- }
- }
-}
-
-func (c *regexpSimplifyChecker) simplifyCharRange(rng syntax.Expr) string {
- if rng.Args[0].Op != syntax.OpChar || rng.Args[1].Op != syntax.OpChar {
- return ""
- }
-
- lo := rng.Args[0].Value
- hi := rng.Args[1].Value
- if len(lo) == 1 && len(hi) == 1 {
- switch hi[0] - lo[0] {
- case 0:
- return lo
- case 1:
- return lo + hi
- case 2:
- return lo + string(lo[0]+1) + hi
- }
- }
-
- return ""
-}
-
-func (c *regexpSimplifyChecker) warn(cause ast.Expr, orig, suggest string) {
- c.ctx.Warn(cause, "can re-write `%s` as `%s`", orig, suggest)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/ruleguard_checker.go b/vendor/github.com/go-critic/go-critic/checkers/ruleguard_checker.go
deleted file mode 100644
index 485819842..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/ruleguard_checker.go
+++ /dev/null
@@ -1,322 +0,0 @@
-package checkers
-
-import (
- "bytes"
- "errors"
- "fmt"
- "go/ast"
- "go/token"
- "log"
- "os"
- "path/filepath"
- "sort"
- "strings"
-
- "github.com/go-critic/go-critic/linter"
-
- "github.com/quasilyte/go-ruleguard/ruleguard"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "ruleguard"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag}
- info.Params = linter.CheckerParams{
- "rules": {
- Value: "",
- Usage: "comma-separated list of gorule file paths. Glob patterns such as 'rules-*.go' may be specified",
- },
- "debug": {
- Value: "",
- Usage: "enable debug for the specified named rules group",
- },
- "failOnError": {
- Value: false,
- Usage: "deprecated, use failOn param; if set to true, identical to failOn='all', otherwise failOn=''",
- },
- "failOn": {
- Value: "",
- Usage: `Determines the behavior when an error occurs while parsing ruleguard files.
-If flag is not set, log error and skip rule files that contain an error.
-If flag is set, the value must be a comma-separated list of error conditions.
-* 'import': rule refers to a package that cannot be loaded.
-* 'dsl': gorule file does not comply with the ruleguard DSL.`,
- },
- "enable": {
- Value: "<all>",
- Usage: "comma-separated list of enabled groups or skip empty to enable everything",
- },
- "disable": {
- Value: "",
- Usage: "comma-separated list of disabled groups or skip empty to enable everything",
- },
- }
- info.Summary = "Runs user-defined rules using ruleguard linter"
- info.Details = "Reads a rules file and turns them into go-critic checkers."
- info.Before = `N/A`
- info.After = `N/A`
- info.Note = "See https://github.com/quasilyte/go-ruleguard."
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return newRuleguardChecker(&info, ctx)
- })
-}
-
-// parseErrorHandler is used to determine whether to ignore or fail ruleguard parsing errors.
-type parseErrorHandler struct {
- // failureConditions is a map of predicates which are evaluated against a ruleguard parsing error.
- // If at least one predicate returns true, then an error is returned.
- // Otherwise, the ruleguard file is skipped.
- failureConditions map[string]func(err error) bool
-}
-
-// failOnParseError returns true if a parseError occurred and that error should be not be ignored.
-func (e parseErrorHandler) failOnParseError(parseError error) bool {
- for _, p := range e.failureConditions {
- if p(parseError) {
- return true
- }
- }
- return false
-}
-
-func newErrorHandler(failOnErrorFlag string) (*parseErrorHandler, error) {
- h := parseErrorHandler{
- failureConditions: make(map[string]func(err error) bool),
- }
- failOnErrorPredicates := map[string]func(error) bool{
- "dsl": func(err error) bool { var e *ruleguard.ImportError; return !errors.As(err, &e) },
- "import": func(err error) bool { var e *ruleguard.ImportError; return errors.As(err, &e) },
- "all": func(_ error) bool { return true },
- }
- for _, k := range strings.Split(failOnErrorFlag, ",") {
- if k == "" {
- continue
- }
- if p, ok := failOnErrorPredicates[k]; ok {
- h.failureConditions[k] = p
- } else {
- // Wrong flag value.
- supportedValues := []string{}
- for key := range failOnErrorPredicates {
- supportedValues = append(supportedValues, key)
- }
- return nil, fmt.Errorf("ruleguard init error: 'failOnError' flag '%s' is invalid. It must be a comma-separated list and supported values are '%s'",
- k, strings.Join(supportedValues, ","))
- }
- }
- return &h, nil
-}
-
-func newRuleguardChecker(info *linter.CheckerInfo, ctx *linter.CheckerContext) (*ruleguardChecker, error) {
- c := &ruleguardChecker{
- ctx: ctx,
- debugGroup: info.Params.String("debug"),
- }
- rulesFlag := info.Params.String("rules")
- if rulesFlag == "" {
- return c, nil
- }
- failOn := info.Params.String("failOn")
- if failOn == "" {
- if info.Params.Bool("failOnError") {
- failOn = "all"
- }
- }
- h, err := newErrorHandler(failOn)
- if err != nil {
- return nil, err
- }
-
- engine := ruleguard.NewEngine()
- engine.InferBuildContext()
- fset := token.NewFileSet()
- filePatterns := strings.Split(rulesFlag, ",")
-
- enabledGroups := make(map[string]bool)
- disabledGroups := make(map[string]bool)
- enabledTags := make(map[string]bool)
- disabledTags := make(map[string]bool)
-
- for _, g := range strings.Split(info.Params.String("disable"), ",") {
- g = strings.TrimSpace(g)
- if strings.HasPrefix(g, "#") {
- disabledTags[strings.TrimPrefix(g, "#")] = true
- continue
- }
-
- disabledGroups[g] = true
- }
- flagEnable := info.Params.String("enable")
- if flagEnable != "<all>" {
- for _, g := range strings.Split(flagEnable, ",") {
- g = strings.TrimSpace(g)
- if strings.HasPrefix(g, "#") {
- enabledTags[strings.TrimPrefix(g, "#")] = true
- continue
- }
-
- enabledGroups[g] = true
- }
- }
-
- if !enabledTags[linter.ExperimentalTag] {
- disabledTags[linter.ExperimentalTag] = true
- }
- ruleguardDebug := os.Getenv("GOCRITIC_RULEGUARD_DEBUG") != ""
-
- inEnabledTags := func(g *ruleguard.GoRuleGroup) bool {
- for _, t := range g.DocTags {
- if enabledTags[t] {
- return true
- }
- }
- return false
- }
- inDisabledTags := func(g *ruleguard.GoRuleGroup) string {
- for _, t := range g.DocTags {
- if disabledTags[t] {
- return t
- }
- }
- return ""
- }
-
- loadContext := &ruleguard.LoadContext{
- Fset: fset,
- DebugImports: ruleguardDebug,
- DebugPrint: debugPrint,
- GroupFilter: func(g *ruleguard.GoRuleGroup) bool {
- enabled := flagEnable == "<all>" || enabledGroups[g.Name] || inEnabledTags(g)
- whyDisabled := ""
-
- switch {
- case !enabled:
- whyDisabled = "not enabled by name or tag (-enable flag)"
- case disabledGroups[g.Name]:
- whyDisabled = "disabled by name (-disable flag)"
- default:
- if tag := inDisabledTags(g); tag != "" {
- whyDisabled = fmt.Sprintf("disabled by %s tag (-disable flag)", tag)
- }
- }
-
- if ruleguardDebug {
- if whyDisabled != "" {
- debugPrint(fmt.Sprintf("(-) %s is %s", g.Name, whyDisabled))
- } else {
- debugPrint(fmt.Sprintf("(+) %s is enabled", g.Name))
- }
- }
- return whyDisabled == ""
- },
- }
-
- loaded := 0
- for _, filePattern := range filePatterns {
- filenames, err := filepath.Glob(strings.TrimSpace(filePattern))
- if err != nil {
- // The only possible returned error is ErrBadPattern, when pattern is malformed.
- log.Printf("ruleguard init error: %+v", err)
- continue
- }
- if len(filenames) == 0 {
- return nil, fmt.Errorf("ruleguard init error: no file matching '%s'", strings.TrimSpace(filePattern))
- }
- for _, filename := range filenames {
- data, err := os.ReadFile(filename)
- if err != nil {
- if h.failOnParseError(err) {
- return nil, fmt.Errorf("ruleguard init error: %+v", err)
- }
- log.Printf("ruleguard init error, skip %s: %+v", filename, err)
- }
- if err := engine.Load(loadContext, filename, bytes.NewReader(data)); err != nil {
- if h.failOnParseError(err) {
- return nil, fmt.Errorf("ruleguard init error: %+v", err)
- }
- log.Printf("ruleguard init error, skip %s: %+v", filename, err)
- }
- loaded++
- }
- }
-
- if loaded != 0 {
- c.engine = engine
- }
- return c, nil
-}
-
-type ruleguardChecker struct {
- ctx *linter.CheckerContext
-
- debugGroup string
- engine *ruleguard.Engine
-}
-
-func (c *ruleguardChecker) WalkFile(f *ast.File) {
- if c.engine == nil {
- return
- }
-
- runRuleguardEngine(c.ctx, f, c.engine, &ruleguard.RunContext{
- Debug: c.debugGroup,
- DebugPrint: func(s string) {
- fmt.Fprintln(os.Stderr, s)
- },
- Pkg: c.ctx.Pkg,
- Types: c.ctx.TypesInfo,
- Sizes: c.ctx.SizesInfo,
- Fset: c.ctx.FileSet,
- TruncateLen: 100,
- })
-}
-
-func runRuleguardEngine(ctx *linter.CheckerContext, f *ast.File, e *ruleguard.Engine, runCtx *ruleguard.RunContext) {
- type ruleguardReport struct {
- pos token.Pos
- message string
- fix linter.QuickFix
- }
- var reports []ruleguardReport
-
- runCtx.Report = func(data *ruleguard.ReportData) {
- // TODO(quasilyte): investigate whether we should add a rule name as
- // a message prefix here.
- r := ruleguardReport{
- pos: data.Node.Pos(),
- message: data.Message,
- }
- fix := data.Suggestion
- if fix != nil {
- r.fix = linter.QuickFix{
- From: fix.From,
- To: fix.To,
- Replacement: fix.Replacement,
- }
- }
- reports = append(reports, r)
- }
-
- if err := e.Run(runCtx, f); err != nil {
- // Normally this should never happen, but since
- // we don't have a better mechanism to report errors,
- // emit a warning.
- ctx.Warn(f, "execution error: %v", err)
- }
-
- sort.Slice(reports, func(i, j int) bool {
- return reports[i].message < reports[j].message
- })
- for _, report := range reports {
- if report.fix.Replacement != nil {
- ctx.WarnFixableWithPos(report.pos, report.fix, "%s", report.message)
- } else {
- ctx.WarnWithPos(report.pos, "%s", report.message)
- }
- }
-}
-
-func debugPrint(s string) {
- fmt.Println("debug:", s)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/rulesdata/rulesdata.go b/vendor/github.com/go-critic/go-critic/checkers/rulesdata/rulesdata.go
deleted file mode 100644
index 4ab31076f..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/rulesdata/rulesdata.go
+++ /dev/null
@@ -1,2521 +0,0 @@
-// Code generated by "precompile.go". DO NOT EDIT.
-
-package rulesdata
-
-import "github.com/quasilyte/go-ruleguard/ruleguard/ir"
-
-var PrecompiledRules = &ir.File{
- PkgPath: "gorules",
- CustomDecls: []string{},
- BundleImports: []ir.BundleImport{},
- RuleGroups: []ir.RuleGroup{
- {
- Line: 11,
- Name: "redundantSprint",
- MatcherName: "m",
- DocTags: []string{"style", "experimental"},
- DocSummary: "Detects redundant fmt.Sprint calls",
- DocBefore: "fmt.Sprint(x)",
- DocAfter: "x.String()",
- Rules: []ir.Rule{
- {
- Line: 12,
- SyntaxPatterns: []ir.PatternString{
- {Line: 12, Value: "fmt.Sprint($x)"},
- {Line: 12, Value: "fmt.Sprintf(\"%s\", $x)"},
- {Line: 12, Value: "fmt.Sprintf(\"%v\", $x)"},
- },
- ReportTemplate: "use $x.String() instead",
- SuggestTemplate: "$x.String()",
- WhereExpr: ir.FilterExpr{
- Line: 13,
- Op: ir.FilterAndOp,
- Src: "!m[\"x\"].Type.Is(`reflect.Value`) && m[\"x\"].Type.Implements(`fmt.Stringer`)",
- Args: []ir.FilterExpr{
- {
- Line: 13,
- Op: ir.FilterNotOp,
- Src: "!m[\"x\"].Type.Is(`reflect.Value`)",
- Args: []ir.FilterExpr{{
- Line: 13,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"x\"].Type.Is(`reflect.Value`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 13, Op: ir.FilterStringOp, Src: "`reflect.Value`", Value: "reflect.Value"}},
- }},
- },
- {
- Line: 13,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"x\"].Type.Implements(`fmt.Stringer`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 13, Op: ir.FilterStringOp, Src: "`fmt.Stringer`", Value: "fmt.Stringer"}},
- },
- },
- },
- },
- {
- Line: 17,
- SyntaxPatterns: []ir.PatternString{
- {Line: 17, Value: "fmt.Sprint($x)"},
- {Line: 17, Value: "fmt.Sprintf(\"%s\", $x)"},
- {Line: 17, Value: "fmt.Sprintf(\"%v\", $x)"},
- },
- ReportTemplate: "$x is already string",
- SuggestTemplate: "$x",
- WhereExpr: ir.FilterExpr{
- Line: 18,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"x\"].Type.Is(`string`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 18, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
- },
- },
- },
- },
- {
- Line: 27,
- Name: "deferUnlambda",
- MatcherName: "m",
- DocTags: []string{"style", "experimental"},
- DocSummary: "Detects deferred function literals that can be simplified",
- DocBefore: "defer func() { f() }()",
- DocAfter: "defer f()",
- Rules: []ir.Rule{
- {
- Line: 28,
- SyntaxPatterns: []ir.PatternString{{Line: 28, Value: "defer func() { $f($*args) }()"}},
- ReportTemplate: "can rewrite as `defer $f($args)`",
- WhereExpr: ir.FilterExpr{
- Line: 29,
- Op: ir.FilterAndOp,
- Src: "m[\"f\"].Node.Is(`Ident`) && m[\"f\"].Text != \"panic\" && m[\"f\"].Text != \"recover\" && m[\"args\"].Const",
- Args: []ir.FilterExpr{
- {
- Line: 29,
- Op: ir.FilterAndOp,
- Src: "m[\"f\"].Node.Is(`Ident`) && m[\"f\"].Text != \"panic\" && m[\"f\"].Text != \"recover\"",
- Args: []ir.FilterExpr{
- {
- Line: 29,
- Op: ir.FilterAndOp,
- Src: "m[\"f\"].Node.Is(`Ident`) && m[\"f\"].Text != \"panic\"",
- Args: []ir.FilterExpr{
- {
- Line: 29,
- Op: ir.FilterVarNodeIsOp,
- Src: "m[\"f\"].Node.Is(`Ident`)",
- Value: "f",
- Args: []ir.FilterExpr{{Line: 29, Op: ir.FilterStringOp, Src: "`Ident`", Value: "Ident"}},
- },
- {
- Line: 29,
- Op: ir.FilterNeqOp,
- Src: "m[\"f\"].Text != \"panic\"",
- Args: []ir.FilterExpr{
- {Line: 29, Op: ir.FilterVarTextOp, Src: "m[\"f\"].Text", Value: "f"},
- {Line: 29, Op: ir.FilterStringOp, Src: "\"panic\"", Value: "panic"},
- },
- },
- },
- },
- {
- Line: 29,
- Op: ir.FilterNeqOp,
- Src: "m[\"f\"].Text != \"recover\"",
- Args: []ir.FilterExpr{
- {Line: 29, Op: ir.FilterVarTextOp, Src: "m[\"f\"].Text", Value: "f"},
- {Line: 29, Op: ir.FilterStringOp, Src: "\"recover\"", Value: "recover"},
- },
- },
- },
- },
- {
- Line: 29,
- Op: ir.FilterVarConstOp,
- Src: "m[\"args\"].Const",
- Value: "args",
- },
- },
- },
- },
- {
- Line: 32,
- SyntaxPatterns: []ir.PatternString{{Line: 32, Value: "defer func() { $pkg.$f($*args) }()"}},
- ReportTemplate: "can rewrite as `defer $pkg.$f($args)`",
- WhereExpr: ir.FilterExpr{
- Line: 33,
- Op: ir.FilterAndOp,
- Src: "m[\"f\"].Node.Is(`Ident`) && m[\"args\"].Const && m[\"pkg\"].Object.Is(`PkgName`)",
- Args: []ir.FilterExpr{
- {
- Line: 33,
- Op: ir.FilterAndOp,
- Src: "m[\"f\"].Node.Is(`Ident`) && m[\"args\"].Const",
- Args: []ir.FilterExpr{
- {
- Line: 33,
- Op: ir.FilterVarNodeIsOp,
- Src: "m[\"f\"].Node.Is(`Ident`)",
- Value: "f",
- Args: []ir.FilterExpr{{Line: 33, Op: ir.FilterStringOp, Src: "`Ident`", Value: "Ident"}},
- },
- {
- Line: 33,
- Op: ir.FilterVarConstOp,
- Src: "m[\"args\"].Const",
- Value: "args",
- },
- },
- },
- {
- Line: 33,
- Op: ir.FilterVarObjectIsOp,
- Src: "m[\"pkg\"].Object.Is(`PkgName`)",
- Value: "pkg",
- Args: []ir.FilterExpr{{Line: 33, Op: ir.FilterStringOp, Src: "`PkgName`", Value: "PkgName"}},
- },
- },
- },
- },
- },
- },
- {
- Line: 41,
- Name: "badLock",
- MatcherName: "m",
- DocTags: []string{"diagnostic", "experimental"},
- DocSummary: "Detects suspicious mutex lock/unlock operations",
- DocBefore: "mu.Lock(); mu.Unlock()",
- DocAfter: "mu.Lock(); defer mu.Unlock()",
- Rules: []ir.Rule{
- {
- Line: 45,
- SyntaxPatterns: []ir.PatternString{{Line: 45, Value: "$mu1.Lock(); $mu2.Unlock()"}},
- ReportTemplate: "defer is missing, mutex is unlocked immediately",
- WhereExpr: ir.FilterExpr{
- Line: 46,
- Op: ir.FilterEqOp,
- Src: "m[\"mu1\"].Text == m[\"mu2\"].Text",
- Args: []ir.FilterExpr{
- {Line: 46, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"},
- {Line: 46, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"},
- },
- },
- LocationVar: "mu2",
- },
- {
- Line: 50,
- SyntaxPatterns: []ir.PatternString{{Line: 50, Value: "$mu1.RLock(); $mu2.RUnlock()"}},
- ReportTemplate: "defer is missing, mutex is unlocked immediately",
- WhereExpr: ir.FilterExpr{
- Line: 51,
- Op: ir.FilterEqOp,
- Src: "m[\"mu1\"].Text == m[\"mu2\"].Text",
- Args: []ir.FilterExpr{
- {Line: 51, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"},
- {Line: 51, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"},
- },
- },
- LocationVar: "mu2",
- },
- {
- Line: 56,
- SyntaxPatterns: []ir.PatternString{{Line: 56, Value: "$mu1.Lock(); defer $mu2.RUnlock()"}},
- ReportTemplate: "suspicious unlock, maybe Unlock was intended?",
- WhereExpr: ir.FilterExpr{
- Line: 57,
- Op: ir.FilterEqOp,
- Src: "m[\"mu1\"].Text == m[\"mu2\"].Text",
- Args: []ir.FilterExpr{
- {Line: 57, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"},
- {Line: 57, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"},
- },
- },
- LocationVar: "mu2",
- },
- {
- Line: 61,
- SyntaxPatterns: []ir.PatternString{{Line: 61, Value: "$mu1.RLock(); defer $mu2.Unlock()"}},
- ReportTemplate: "suspicious unlock, maybe RUnlock was intended?",
- WhereExpr: ir.FilterExpr{
- Line: 62,
- Op: ir.FilterEqOp,
- Src: "m[\"mu1\"].Text == m[\"mu2\"].Text",
- Args: []ir.FilterExpr{
- {Line: 62, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"},
- {Line: 62, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"},
- },
- },
- LocationVar: "mu2",
- },
- {
- Line: 67,
- SyntaxPatterns: []ir.PatternString{{Line: 67, Value: "$mu1.Lock(); defer $mu2.Lock()"}},
- ReportTemplate: "maybe defer $mu1.Unlock() was intended?",
- WhereExpr: ir.FilterExpr{
- Line: 68,
- Op: ir.FilterEqOp,
- Src: "m[\"mu1\"].Text == m[\"mu2\"].Text",
- Args: []ir.FilterExpr{
- {Line: 68, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"},
- {Line: 68, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"},
- },
- },
- LocationVar: "mu2",
- },
- {
- Line: 72,
- SyntaxPatterns: []ir.PatternString{{Line: 72, Value: "$mu1.RLock(); defer $mu2.RLock()"}},
- ReportTemplate: "maybe defer $mu1.RUnlock() was intended?",
- WhereExpr: ir.FilterExpr{
- Line: 73,
- Op: ir.FilterEqOp,
- Src: "m[\"mu1\"].Text == m[\"mu2\"].Text",
- Args: []ir.FilterExpr{
- {Line: 73, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"},
- {Line: 73, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"},
- },
- },
- LocationVar: "mu2",
- },
- },
- },
- {
- Line: 82,
- Name: "httpNoBody",
- MatcherName: "m",
- DocTags: []string{"style", "experimental"},
- DocSummary: "Detects nil usages in http.NewRequest calls, suggesting http.NoBody as an alternative",
- DocBefore: "http.NewRequest(\"GET\", url, nil)",
- DocAfter: "http.NewRequest(\"GET\", url, http.NoBody)",
- Rules: []ir.Rule{
- {
- Line: 83,
- SyntaxPatterns: []ir.PatternString{{Line: 83, Value: "http.NewRequest($method, $url, $nil)"}},
- ReportTemplate: "http.NoBody should be preferred to the nil request body",
- SuggestTemplate: "http.NewRequest($method, $url, http.NoBody)",
- WhereExpr: ir.FilterExpr{
- Line: 84,
- Op: ir.FilterEqOp,
- Src: "m[\"nil\"].Text == \"nil\"",
- Args: []ir.FilterExpr{
- {Line: 84, Op: ir.FilterVarTextOp, Src: "m[\"nil\"].Text", Value: "nil"},
- {Line: 84, Op: ir.FilterStringOp, Src: "\"nil\"", Value: "nil"},
- },
- },
- },
- {
- Line: 88,
- SyntaxPatterns: []ir.PatternString{{Line: 88, Value: "http.NewRequestWithContext($ctx, $method, $url, $nil)"}},
- ReportTemplate: "http.NoBody should be preferred to the nil request body",
- SuggestTemplate: "http.NewRequestWithContext($ctx, $method, $url, http.NoBody)",
- WhereExpr: ir.FilterExpr{
- Line: 89,
- Op: ir.FilterEqOp,
- Src: "m[\"nil\"].Text == \"nil\"",
- Args: []ir.FilterExpr{
- {Line: 89, Op: ir.FilterVarTextOp, Src: "m[\"nil\"].Text", Value: "nil"},
- {Line: 89, Op: ir.FilterStringOp, Src: "\"nil\"", Value: "nil"},
- },
- },
- },
- {
- Line: 93,
- SyntaxPatterns: []ir.PatternString{{Line: 93, Value: "httptest.NewRequest($method, $url, $nil)"}},
- ReportTemplate: "http.NoBody should be preferred to the nil request body",
- SuggestTemplate: "httptest.NewRequest($method, $url, http.NoBody)",
- WhereExpr: ir.FilterExpr{
- Line: 94,
- Op: ir.FilterEqOp,
- Src: "m[\"nil\"].Text == \"nil\"",
- Args: []ir.FilterExpr{
- {Line: 94, Op: ir.FilterVarTextOp, Src: "m[\"nil\"].Text", Value: "nil"},
- {Line: 94, Op: ir.FilterStringOp, Src: "\"nil\"", Value: "nil"},
- },
- },
- },
- },
- },
- {
- Line: 104,
- Name: "preferDecodeRune",
- MatcherName: "m",
- DocTags: []string{"performance", "experimental"},
- DocSummary: "Detects expressions like []rune(s)[0] that may cause unwanted rune slice allocation",
- DocBefore: "r := []rune(s)[0]",
- DocAfter: "r, _ := utf8.DecodeRuneInString(s)",
- DocNote: "See Go issue for details: https://github.com/golang/go/issues/45260",
- Rules: []ir.Rule{{
- Line: 105,
- SyntaxPatterns: []ir.PatternString{{Line: 105, Value: "[]rune($s)[0]"}},
- ReportTemplate: "consider replacing $$ with utf8.DecodeRuneInString($s)",
- WhereExpr: ir.FilterExpr{
- Line: 106,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"s\"].Type.Is(`string`)",
- Value: "s",
- Args: []ir.FilterExpr{{Line: 106, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
- },
- }},
- },
- {
- Line: 114,
- Name: "sloppyLen",
- MatcherName: "m",
- DocTags: []string{"diagnostic"},
- DocSummary: "Detects usage of `len` when result is obvious or doesn't make sense",
- DocBefore: "len(arr) <= 0",
- DocAfter: "len(arr) == 0",
- Rules: []ir.Rule{
- {
- Line: 115,
- SyntaxPatterns: []ir.PatternString{{Line: 115, Value: "len($_) >= 0"}},
- ReportTemplate: "$$ is always true",
- },
- {
- Line: 116,
- SyntaxPatterns: []ir.PatternString{{Line: 116, Value: "len($_) < 0"}},
- ReportTemplate: "$$ is always false",
- },
- {
- Line: 117,
- SyntaxPatterns: []ir.PatternString{{Line: 117, Value: "len($x) <= 0"}},
- ReportTemplate: "$$ can be len($x) == 0",
- },
- },
- },
- {
- Line: 124,
- Name: "valSwap",
- MatcherName: "m",
- DocTags: []string{"style"},
- DocSummary: "Detects value swapping code that are not using parallel assignment",
- DocBefore: "*tmp = *x; *x = *y; *y = *tmp",
- DocAfter: "*x, *y = *y, *x",
- Rules: []ir.Rule{{
- Line: 125,
- SyntaxPatterns: []ir.PatternString{{Line: 125, Value: "$tmp := $y; $y = $x; $x = $tmp"}},
- ReportTemplate: "can re-write as `$y, $x = $x, $y`",
- }},
- },
- {
- Line: 133,
- Name: "switchTrue",
- MatcherName: "m",
- DocTags: []string{"style"},
- DocSummary: "Detects switch-over-bool statements that use explicit `true` tag value",
- DocBefore: "switch true {...}",
- DocAfter: "switch {...}",
- Rules: []ir.Rule{
- {
- Line: 134,
- SyntaxPatterns: []ir.PatternString{{Line: 134, Value: "switch true { $*_ }"}},
- ReportTemplate: "replace 'switch true {}' with 'switch {}'",
- },
- {
- Line: 136,
- SyntaxPatterns: []ir.PatternString{{Line: 136, Value: "switch $x; true { $*_ }"}},
- ReportTemplate: "replace 'switch $x; true {}' with 'switch $x; {}'",
- },
- },
- },
- {
- Line: 144,
- Name: "flagDeref",
- MatcherName: "m",
- DocTags: []string{"diagnostic"},
- DocSummary: "Detects immediate dereferencing of `flag` package pointers",
- DocBefore: "b := *flag.Bool(\"b\", false, \"b docs\")",
- DocAfter: "var b bool; flag.BoolVar(&b, \"b\", false, \"b docs\")",
- Rules: []ir.Rule{
- {
- Line: 145,
- SyntaxPatterns: []ir.PatternString{{Line: 145, Value: "*flag.Bool($*_)"}},
- ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.BoolVar",
- },
- {
- Line: 146,
- SyntaxPatterns: []ir.PatternString{{Line: 146, Value: "*flag.Duration($*_)"}},
- ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.DurationVar",
- },
- {
- Line: 147,
- SyntaxPatterns: []ir.PatternString{{Line: 147, Value: "*flag.Float64($*_)"}},
- ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.Float64Var",
- },
- {
- Line: 148,
- SyntaxPatterns: []ir.PatternString{{Line: 148, Value: "*flag.Int($*_)"}},
- ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.IntVar",
- },
- {
- Line: 149,
- SyntaxPatterns: []ir.PatternString{{Line: 149, Value: "*flag.Int64($*_)"}},
- ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.Int64Var",
- },
- {
- Line: 150,
- SyntaxPatterns: []ir.PatternString{{Line: 150, Value: "*flag.String($*_)"}},
- ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.StringVar",
- },
- {
- Line: 151,
- SyntaxPatterns: []ir.PatternString{{Line: 151, Value: "*flag.Uint($*_)"}},
- ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.UintVar",
- },
- {
- Line: 152,
- SyntaxPatterns: []ir.PatternString{{Line: 152, Value: "*flag.Uint64($*_)"}},
- ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.Uint64Var",
- },
- },
- },
- {
- Line: 159,
- Name: "emptyStringTest",
- MatcherName: "m",
- DocTags: []string{"style", "experimental"},
- DocSummary: "Detects empty string checks that can be written more idiomatically",
- DocBefore: "len(s) == 0",
- DocAfter: "s == \"\"",
- Rules: []ir.Rule{
- {
- Line: 160,
- SyntaxPatterns: []ir.PatternString{{Line: 160, Value: "len($s) != 0"}},
- ReportTemplate: "replace `$$` with `$s != \"\"`",
- WhereExpr: ir.FilterExpr{
- Line: 161,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"s\"].Type.Is(`string`)",
- Value: "s",
- Args: []ir.FilterExpr{{Line: 161, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
- },
- },
- {
- Line: 163,
- SyntaxPatterns: []ir.PatternString{{Line: 163, Value: "len($s) > 0"}},
- ReportTemplate: "replace `$$` with `$s != \"\"`",
- WhereExpr: ir.FilterExpr{
- Line: 164,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"s\"].Type.Is(`string`)",
- Value: "s",
- Args: []ir.FilterExpr{{Line: 164, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
- },
- },
- {
- Line: 167,
- SyntaxPatterns: []ir.PatternString{{Line: 167, Value: "len($s) == 0"}},
- ReportTemplate: "replace `$$` with `$s == \"\"`",
- WhereExpr: ir.FilterExpr{
- Line: 168,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"s\"].Type.Is(`string`)",
- Value: "s",
- Args: []ir.FilterExpr{{Line: 168, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
- },
- },
- {
- Line: 170,
- SyntaxPatterns: []ir.PatternString{{Line: 170, Value: "len($s) <= 0"}},
- ReportTemplate: "replace `$$` with `$s == \"\"`",
- WhereExpr: ir.FilterExpr{
- Line: 171,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"s\"].Type.Is(`string`)",
- Value: "s",
- Args: []ir.FilterExpr{{Line: 171, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
- },
- },
- },
- },
- {
- Line: 179,
- Name: "stringXbytes",
- MatcherName: "m",
- DocTags: []string{"performance"},
- DocSummary: "Detects redundant conversions between string and []byte",
- DocBefore: "copy(b, []byte(s))",
- DocAfter: "copy(b, s)",
- Rules: []ir.Rule{
- {
- Line: 180,
- SyntaxPatterns: []ir.PatternString{{Line: 180, Value: "copy($_, []byte($s))"}},
- ReportTemplate: "can simplify `[]byte($s)` to `$s`",
- },
- {
- Line: 182,
- SyntaxPatterns: []ir.PatternString{{Line: 182, Value: "string($b) == \"\""}},
- ReportTemplate: "suggestion: len($b) == 0",
- SuggestTemplate: "len($b) == 0",
- WhereExpr: ir.FilterExpr{
- Line: 182,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"b\"].Type.Is(`[]byte`)",
- Value: "b",
- Args: []ir.FilterExpr{{Line: 182, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
- },
- },
- {
- Line: 183,
- SyntaxPatterns: []ir.PatternString{{Line: 183, Value: "string($b) != \"\""}},
- ReportTemplate: "suggestion: len($b) != 0",
- SuggestTemplate: "len($b) != 0",
- WhereExpr: ir.FilterExpr{
- Line: 183,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"b\"].Type.Is(`[]byte`)",
- Value: "b",
- Args: []ir.FilterExpr{{Line: 183, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
- },
- },
- {
- Line: 185,
- SyntaxPatterns: []ir.PatternString{{Line: 185, Value: "len(string($b))"}},
- ReportTemplate: "suggestion: len($b)",
- SuggestTemplate: "len($b)",
- WhereExpr: ir.FilterExpr{
- Line: 185,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"b\"].Type.Is(`[]byte`)",
- Value: "b",
- Args: []ir.FilterExpr{{Line: 185, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
- },
- },
- {
- Line: 187,
- SyntaxPatterns: []ir.PatternString{{Line: 187, Value: "string($x) == string($y)"}},
- ReportTemplate: "suggestion: bytes.Equal($x, $y)",
- SuggestTemplate: "bytes.Equal($x, $y)",
- WhereExpr: ir.FilterExpr{
- Line: 188,
- Op: ir.FilterAndOp,
- Src: "m[\"x\"].Type.Is(`[]byte`) && m[\"y\"].Type.Is(`[]byte`)",
- Args: []ir.FilterExpr{
- {
- Line: 188,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"x\"].Type.Is(`[]byte`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 188, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
- },
- {
- Line: 188,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"y\"].Type.Is(`[]byte`)",
- Value: "y",
- Args: []ir.FilterExpr{{Line: 188, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
- },
- },
- },
- },
- {
- Line: 191,
- SyntaxPatterns: []ir.PatternString{{Line: 191, Value: "string($x) != string($y)"}},
- ReportTemplate: "suggestion: !bytes.Equal($x, $y)",
- SuggestTemplate: "!bytes.Equal($x, $y)",
- WhereExpr: ir.FilterExpr{
- Line: 192,
- Op: ir.FilterAndOp,
- Src: "m[\"x\"].Type.Is(`[]byte`) && m[\"y\"].Type.Is(`[]byte`)",
- Args: []ir.FilterExpr{
- {
- Line: 192,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"x\"].Type.Is(`[]byte`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 192, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
- },
- {
- Line: 192,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"y\"].Type.Is(`[]byte`)",
- Value: "y",
- Args: []ir.FilterExpr{{Line: 192, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
- },
- },
- },
- },
- {
- Line: 195,
- SyntaxPatterns: []ir.PatternString{{Line: 195, Value: "$re.Match([]byte($s))"}},
- ReportTemplate: "suggestion: $re.MatchString($s)",
- SuggestTemplate: "$re.MatchString($s)",
- WhereExpr: ir.FilterExpr{
- Line: 196,
- Op: ir.FilterAndOp,
- Src: "m[\"re\"].Type.Is(`*regexp.Regexp`) && m[\"s\"].Type.Is(`string`)",
- Args: []ir.FilterExpr{
- {
- Line: 196,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"re\"].Type.Is(`*regexp.Regexp`)",
- Value: "re",
- Args: []ir.FilterExpr{{Line: 196, Op: ir.FilterStringOp, Src: "`*regexp.Regexp`", Value: "*regexp.Regexp"}},
- },
- {
- Line: 196,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"s\"].Type.Is(`string`)",
- Value: "s",
- Args: []ir.FilterExpr{{Line: 196, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
- },
- },
- },
- },
- {
- Line: 199,
- SyntaxPatterns: []ir.PatternString{{Line: 199, Value: "$re.FindIndex([]byte($s))"}},
- ReportTemplate: "suggestion: $re.FindStringIndex($s)",
- SuggestTemplate: "$re.FindStringIndex($s)",
- WhereExpr: ir.FilterExpr{
- Line: 200,
- Op: ir.FilterAndOp,
- Src: "m[\"re\"].Type.Is(`*regexp.Regexp`) && m[\"s\"].Type.Is(`string`)",
- Args: []ir.FilterExpr{
- {
- Line: 200,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"re\"].Type.Is(`*regexp.Regexp`)",
- Value: "re",
- Args: []ir.FilterExpr{{Line: 200, Op: ir.FilterStringOp, Src: "`*regexp.Regexp`", Value: "*regexp.Regexp"}},
- },
- {
- Line: 200,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"s\"].Type.Is(`string`)",
- Value: "s",
- Args: []ir.FilterExpr{{Line: 200, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
- },
- },
- },
- },
- {
- Line: 203,
- SyntaxPatterns: []ir.PatternString{{Line: 203, Value: "$re.FindAllIndex([]byte($s), $n)"}},
- ReportTemplate: "suggestion: $re.FindAllStringIndex($s, $n)",
- SuggestTemplate: "$re.FindAllStringIndex($s, $n)",
- WhereExpr: ir.FilterExpr{
- Line: 204,
- Op: ir.FilterAndOp,
- Src: "m[\"re\"].Type.Is(`*regexp.Regexp`) && m[\"s\"].Type.Is(`string`)",
- Args: []ir.FilterExpr{
- {
- Line: 204,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"re\"].Type.Is(`*regexp.Regexp`)",
- Value: "re",
- Args: []ir.FilterExpr{{Line: 204, Op: ir.FilterStringOp, Src: "`*regexp.Regexp`", Value: "*regexp.Regexp"}},
- },
- {
- Line: 204,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"s\"].Type.Is(`string`)",
- Value: "s",
- Args: []ir.FilterExpr{{Line: 204, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
- },
- },
- },
- },
- },
- },
- {
- Line: 213,
- Name: "indexAlloc",
- MatcherName: "m",
- DocTags: []string{"performance"},
- DocSummary: "Detects strings.Index calls that may cause unwanted allocs",
- DocBefore: "strings.Index(string(x), y)",
- DocAfter: "bytes.Index(x, []byte(y))",
- DocNote: "See Go issue for details: https://github.com/golang/go/issues/25864",
- Rules: []ir.Rule{{
- Line: 214,
- SyntaxPatterns: []ir.PatternString{{Line: 214, Value: "strings.Index(string($x), $y)"}},
- ReportTemplate: "consider replacing $$ with bytes.Index($x, []byte($y))",
- WhereExpr: ir.FilterExpr{
- Line: 215,
- Op: ir.FilterAndOp,
- Src: "m[\"x\"].Pure && m[\"y\"].Pure",
- Args: []ir.FilterExpr{
- {Line: 215, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- {Line: 215, Op: ir.FilterVarPureOp, Src: "m[\"y\"].Pure", Value: "y"},
- },
- },
- }},
- },
- {
- Line: 223,
- Name: "wrapperFunc",
- MatcherName: "m",
- DocTags: []string{"style"},
- DocSummary: "Detects function calls that can be replaced with convenience wrappers",
- DocBefore: "wg.Add(-1)",
- DocAfter: "wg.Done()",
- Rules: []ir.Rule{
- {
- Line: 224,
- SyntaxPatterns: []ir.PatternString{{Line: 224, Value: "$wg.Add(-1)"}},
- ReportTemplate: "use WaitGroup.Done method in `$$`",
- WhereExpr: ir.FilterExpr{
- Line: 225,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"wg\"].Type.Is(`sync.WaitGroup`)",
- Value: "wg",
- Args: []ir.FilterExpr{{Line: 225, Op: ir.FilterStringOp, Src: "`sync.WaitGroup`", Value: "sync.WaitGroup"}},
- },
- },
- {
- Line: 228,
- SyntaxPatterns: []ir.PatternString{{Line: 228, Value: "$buf.Truncate(0)"}},
- ReportTemplate: "use Buffer.Reset method in `$$`",
- WhereExpr: ir.FilterExpr{
- Line: 229,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"buf\"].Type.Is(`bytes.Buffer`)",
- Value: "buf",
- Args: []ir.FilterExpr{{Line: 229, Op: ir.FilterStringOp, Src: "`bytes.Buffer`", Value: "bytes.Buffer"}},
- },
- },
- {
- Line: 232,
- SyntaxPatterns: []ir.PatternString{{Line: 232, Value: "http.HandlerFunc(http.NotFound)"}},
- ReportTemplate: "use http.NotFoundHandler method in `$$`",
- },
- {
- Line: 234,
- SyntaxPatterns: []ir.PatternString{{Line: 234, Value: "strings.SplitN($_, $_, -1)"}},
- ReportTemplate: "use strings.Split method in `$$`",
- },
- {
- Line: 235,
- SyntaxPatterns: []ir.PatternString{{Line: 235, Value: "strings.Replace($_, $_, $_, -1)"}},
- ReportTemplate: "use strings.ReplaceAll method in `$$`",
- },
- {
- Line: 236,
- SyntaxPatterns: []ir.PatternString{{Line: 236, Value: "strings.Map(unicode.ToTitle, $_)"}},
- ReportTemplate: "use strings.ToTitle method in `$$`",
- },
- {
- Line: 237,
- SyntaxPatterns: []ir.PatternString{
- {Line: 237, Value: "strings.Index($s1, $s2) >= 0"},
- {Line: 237, Value: "strings.Index($s1, $s2) != -1"},
- },
- ReportTemplate: "suggestion: strings.Contains($s1, $s2)",
- SuggestTemplate: "strings.Contains($s1, $s2)",
- },
- {
- Line: 238,
- SyntaxPatterns: []ir.PatternString{
- {Line: 238, Value: "strings.IndexAny($s1, $s2) >= 0"},
- {Line: 238, Value: "strings.IndexAny($s1, $s2) != -1"},
- },
- ReportTemplate: "suggestion: strings.ContainsAny($s1, $s2)",
- SuggestTemplate: "strings.ContainsAny($s1, $s2)",
- },
- {
- Line: 239,
- SyntaxPatterns: []ir.PatternString{
- {Line: 239, Value: "strings.IndexRune($s1, $s2) >= 0"},
- {Line: 239, Value: "strings.IndexRune($s1, $s2) != -1"},
- },
- ReportTemplate: "suggestion: strings.ContainsRune($s1, $s2)",
- SuggestTemplate: "strings.ContainsRune($s1, $s2)",
- },
- {
- Line: 241,
- SyntaxPatterns: []ir.PatternString{
- {Line: 241, Value: "$i := strings.Index($s, $sep); $*_; $x, $y = $s[:$i], $s[$i+1:]"},
- {Line: 242, Value: "$i := strings.Index($s, $sep); $*_; $x = $s[:$i]; $*_; $y = $s[$i+1:]"},
- },
- ReportTemplate: "suggestion: $x, $y, _ = strings.Cut($s, $sep)",
- SuggestTemplate: "$x, $y, _ = strings.Cut($s, $sep)",
- WhereExpr: ir.FilterExpr{
- Line: 243,
- Op: ir.FilterGoVersionGreaterEqThanOp,
- Src: "m.GoVersion().GreaterEqThan(\"1.18\")",
- Value: "1.18",
- },
- },
- {
- Line: 246,
- SyntaxPatterns: []ir.PatternString{
- {Line: 247, Value: "if $i := strings.Index($s, $sep); $i != -1 { $*_; $x, $y = $s[:$i], $s[$i+1:]; $*_ }"},
- {Line: 248, Value: "if $i := strings.Index($s, $sep); $i != -1 { $*_; $x = $s[:$i]; $*_; $y = $s[$i+1:]; $*_ }"},
- {Line: 249, Value: "if $i := strings.Index($s, $sep); $i >= 0 { $*_; $x, $y = $s[:$i], $s[$i+1:]; $*_ }"},
- {Line: 250, Value: "if $i := strings.Index($s, $sep); $i >= 0 { $*_; $x = $s[:$i]; $*_; $y = $s[$i+1:]; $*_ }"},
- },
- ReportTemplate: "suggestion: if $x, $y, ok = strings.Cut($s, $sep); ok { ... }",
- SuggestTemplate: "if $x, $y, ok = strings.Cut($s, $sep); ok { ... }",
- WhereExpr: ir.FilterExpr{
- Line: 251,
- Op: ir.FilterGoVersionGreaterEqThanOp,
- Src: "m.GoVersion().GreaterEqThan(\"1.18\")",
- Value: "1.18",
- },
- },
- {
- Line: 254,
- SyntaxPatterns: []ir.PatternString{{Line: 254, Value: "bytes.SplitN(b, []byte(\".\"), -1)"}},
- ReportTemplate: "use bytes.Split method in `$$`",
- },
- {
- Line: 255,
- SyntaxPatterns: []ir.PatternString{{Line: 255, Value: "bytes.Replace($_, $_, $_, -1)"}},
- ReportTemplate: "use bytes.ReplaceAll method in `$$`",
- },
- {
- Line: 256,
- SyntaxPatterns: []ir.PatternString{{Line: 256, Value: "bytes.Map(unicode.ToUpper, $_)"}},
- ReportTemplate: "use bytes.ToUpper method in `$$`",
- },
- {
- Line: 257,
- SyntaxPatterns: []ir.PatternString{{Line: 257, Value: "bytes.Map(unicode.ToLower, $_)"}},
- ReportTemplate: "use bytes.ToLower method in `$$`",
- },
- {
- Line: 258,
- SyntaxPatterns: []ir.PatternString{{Line: 258, Value: "bytes.Map(unicode.ToTitle, $_)"}},
- ReportTemplate: "use bytes.ToTitle method in `$$`",
- },
- {
- Line: 259,
- SyntaxPatterns: []ir.PatternString{
- {Line: 259, Value: "bytes.Index($b1, $b2) >= 0"},
- {Line: 259, Value: "bytes.Index($b1, $b2) != -1"},
- },
- ReportTemplate: "suggestion: bytes.Contains($b1, $b2)",
- SuggestTemplate: "bytes.Contains($b1, $b2)",
- },
- {
- Line: 260,
- SyntaxPatterns: []ir.PatternString{
- {Line: 260, Value: "bytes.IndexAny($b1, $b2) >= 0"},
- {Line: 260, Value: "bytes.IndexAny($b1, $b2) != -1"},
- },
- ReportTemplate: "suggestion: bytes.ContainsAny($b1, $b2)",
- SuggestTemplate: "bytes.ContainsAny($b1, $b2)",
- },
- {
- Line: 261,
- SyntaxPatterns: []ir.PatternString{
- {Line: 261, Value: "bytes.IndexRune($b1, $b2) >= 0"},
- {Line: 261, Value: "bytes.IndexRune($b1, $b2) != -1"},
- },
- ReportTemplate: "suggestion: bytes.ContainsRune($b1, $b2)",
- SuggestTemplate: "bytes.ContainsRune($b1, $b2)",
- },
- {
- Line: 263,
- SyntaxPatterns: []ir.PatternString{{Line: 263, Value: "draw.DrawMask($_, $_, $_, $_, nil, image.Point{}, $_)"}},
- ReportTemplate: "use draw.Draw method in `$$`",
- },
- },
- },
- {
- Line: 271,
- Name: "regexpMust",
- MatcherName: "m",
- DocTags: []string{"style"},
- DocSummary: "Detects `regexp.Compile*` that can be replaced with `regexp.MustCompile*`",
- DocBefore: "re, _ := regexp.Compile(\"const pattern\")",
- DocAfter: "re := regexp.MustCompile(\"const pattern\")",
- Rules: []ir.Rule{
- {
- Line: 272,
- SyntaxPatterns: []ir.PatternString{{Line: 272, Value: "regexp.Compile($pat)"}},
- ReportTemplate: "for const patterns like $pat, use regexp.MustCompile",
- WhereExpr: ir.FilterExpr{
- Line: 273,
- Op: ir.FilterVarConstOp,
- Src: "m[\"pat\"].Const",
- Value: "pat",
- },
- },
- {
- Line: 276,
- SyntaxPatterns: []ir.PatternString{{Line: 276, Value: "regexp.CompilePOSIX($pat)"}},
- ReportTemplate: "for const patterns like $pat, use regexp.MustCompilePOSIX",
- WhereExpr: ir.FilterExpr{
- Line: 277,
- Op: ir.FilterVarConstOp,
- Src: "m[\"pat\"].Const",
- Value: "pat",
- },
- },
- },
- },
- {
- Line: 285,
- Name: "badCall",
- MatcherName: "m",
- DocTags: []string{"diagnostic"},
- DocSummary: "Detects suspicious function calls",
- DocBefore: "strings.Replace(s, from, to, 0)",
- DocAfter: "strings.Replace(s, from, to, -1)",
- Rules: []ir.Rule{
- {
- Line: 286,
- SyntaxPatterns: []ir.PatternString{{Line: 286, Value: "strings.Replace($_, $_, $_, $zero)"}},
- ReportTemplate: "suspicious arg 0, probably meant -1",
- WhereExpr: ir.FilterExpr{
- Line: 287,
- Op: ir.FilterEqOp,
- Src: "m[\"zero\"].Value.Int() == 0",
- Args: []ir.FilterExpr{
- {
- Line: 287,
- Op: ir.FilterVarValueIntOp,
- Src: "m[\"zero\"].Value.Int()",
- Value: "zero",
- },
- {
- Line: 287,
- Op: ir.FilterIntOp,
- Src: "0",
- Value: int64(0),
- },
- },
- },
- LocationVar: "zero",
- },
- {
- Line: 289,
- SyntaxPatterns: []ir.PatternString{{Line: 289, Value: "bytes.Replace($_, $_, $_, $zero)"}},
- ReportTemplate: "suspicious arg 0, probably meant -1",
- WhereExpr: ir.FilterExpr{
- Line: 290,
- Op: ir.FilterEqOp,
- Src: "m[\"zero\"].Value.Int() == 0",
- Args: []ir.FilterExpr{
- {
- Line: 290,
- Op: ir.FilterVarValueIntOp,
- Src: "m[\"zero\"].Value.Int()",
- Value: "zero",
- },
- {
- Line: 290,
- Op: ir.FilterIntOp,
- Src: "0",
- Value: int64(0),
- },
- },
- },
- LocationVar: "zero",
- },
- {
- Line: 293,
- SyntaxPatterns: []ir.PatternString{{Line: 293, Value: "strings.SplitN($_, $_, $zero)"}},
- ReportTemplate: "suspicious arg 0, probably meant -1",
- WhereExpr: ir.FilterExpr{
- Line: 294,
- Op: ir.FilterEqOp,
- Src: "m[\"zero\"].Value.Int() == 0",
- Args: []ir.FilterExpr{
- {
- Line: 294,
- Op: ir.FilterVarValueIntOp,
- Src: "m[\"zero\"].Value.Int()",
- Value: "zero",
- },
- {
- Line: 294,
- Op: ir.FilterIntOp,
- Src: "0",
- Value: int64(0),
- },
- },
- },
- LocationVar: "zero",
- },
- {
- Line: 296,
- SyntaxPatterns: []ir.PatternString{{Line: 296, Value: "bytes.SplitN($_, $_, $zero)"}},
- ReportTemplate: "suspicious arg 0, probably meant -1",
- WhereExpr: ir.FilterExpr{
- Line: 297,
- Op: ir.FilterEqOp,
- Src: "m[\"zero\"].Value.Int() == 0",
- Args: []ir.FilterExpr{
- {
- Line: 297,
- Op: ir.FilterVarValueIntOp,
- Src: "m[\"zero\"].Value.Int()",
- Value: "zero",
- },
- {
- Line: 297,
- Op: ir.FilterIntOp,
- Src: "0",
- Value: int64(0),
- },
- },
- },
- LocationVar: "zero",
- },
- {
- Line: 300,
- SyntaxPatterns: []ir.PatternString{{Line: 300, Value: "append($_)"}},
- ReportTemplate: "no-op append call, probably missing arguments",
- },
- {
- Line: 302,
- SyntaxPatterns: []ir.PatternString{{Line: 302, Value: "filepath.Join($_)"}},
- ReportTemplate: "suspicious Join on 1 argument",
- },
- },
- },
- {
- Line: 309,
- Name: "assignOp",
- MatcherName: "m",
- DocTags: []string{"style"},
- DocSummary: "Detects assignments that can be simplified by using assignment operators",
- DocBefore: "x = x * 2",
- DocAfter: "x *= 2",
- Rules: []ir.Rule{
- {
- Line: 310,
- SyntaxPatterns: []ir.PatternString{{Line: 310, Value: "$x = $x + 1"}},
- ReportTemplate: "replace `$$` with `$x++`",
- WhereExpr: ir.FilterExpr{Line: 310, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- {
- Line: 311,
- SyntaxPatterns: []ir.PatternString{{Line: 311, Value: "$x = $x - 1"}},
- ReportTemplate: "replace `$$` with `$x--`",
- WhereExpr: ir.FilterExpr{Line: 311, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- {
- Line: 313,
- SyntaxPatterns: []ir.PatternString{{Line: 313, Value: "$x = $x + $y"}},
- ReportTemplate: "replace `$$` with `$x += $y`",
- WhereExpr: ir.FilterExpr{Line: 313, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- {
- Line: 314,
- SyntaxPatterns: []ir.PatternString{{Line: 314, Value: "$x = $x - $y"}},
- ReportTemplate: "replace `$$` with `$x -= $y`",
- WhereExpr: ir.FilterExpr{Line: 314, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- {
- Line: 316,
- SyntaxPatterns: []ir.PatternString{{Line: 316, Value: "$x = $x * $y"}},
- ReportTemplate: "replace `$$` with `$x *= $y`",
- WhereExpr: ir.FilterExpr{Line: 316, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- {
- Line: 317,
- SyntaxPatterns: []ir.PatternString{{Line: 317, Value: "$x = $x / $y"}},
- ReportTemplate: "replace `$$` with `$x /= $y`",
- WhereExpr: ir.FilterExpr{Line: 317, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- {
- Line: 318,
- SyntaxPatterns: []ir.PatternString{{Line: 318, Value: "$x = $x % $y"}},
- ReportTemplate: "replace `$$` with `$x %= $y`",
- WhereExpr: ir.FilterExpr{Line: 318, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- {
- Line: 319,
- SyntaxPatterns: []ir.PatternString{{Line: 319, Value: "$x = $x & $y"}},
- ReportTemplate: "replace `$$` with `$x &= $y`",
- WhereExpr: ir.FilterExpr{Line: 319, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- {
- Line: 320,
- SyntaxPatterns: []ir.PatternString{{Line: 320, Value: "$x = $x | $y"}},
- ReportTemplate: "replace `$$` with `$x |= $y`",
- WhereExpr: ir.FilterExpr{Line: 320, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- {
- Line: 321,
- SyntaxPatterns: []ir.PatternString{{Line: 321, Value: "$x = $x ^ $y"}},
- ReportTemplate: "replace `$$` with `$x ^= $y`",
- WhereExpr: ir.FilterExpr{Line: 321, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- {
- Line: 322,
- SyntaxPatterns: []ir.PatternString{{Line: 322, Value: "$x = $x << $y"}},
- ReportTemplate: "replace `$$` with `$x <<= $y`",
- WhereExpr: ir.FilterExpr{Line: 322, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- {
- Line: 323,
- SyntaxPatterns: []ir.PatternString{{Line: 323, Value: "$x = $x >> $y"}},
- ReportTemplate: "replace `$$` with `$x >>= $y`",
- WhereExpr: ir.FilterExpr{Line: 323, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- {
- Line: 324,
- SyntaxPatterns: []ir.PatternString{{Line: 324, Value: "$x = $x &^ $y"}},
- ReportTemplate: "replace `$$` with `$x &^= $y`",
- WhereExpr: ir.FilterExpr{Line: 324, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- },
- },
- {
- Line: 331,
- Name: "preferWriteByte",
- MatcherName: "m",
- DocTags: []string{"performance", "experimental", "opinionated"},
- DocSummary: "Detects WriteRune calls with rune literal argument that is single byte and reports to use WriteByte instead",
- DocBefore: "w.WriteRune('\\n')",
- DocAfter: "w.WriteByte('\\n')",
- Rules: []ir.Rule{{
- Line: 335,
- SyntaxPatterns: []ir.PatternString{{Line: 335, Value: "$w.WriteRune($c)"}},
- ReportTemplate: "consider writing single byte rune $c with $w.WriteByte($c)",
- WhereExpr: ir.FilterExpr{
- Line: 336,
- Op: ir.FilterAndOp,
- Src: "m[\"w\"].Type.Implements(\"io.ByteWriter\") && (m[\"c\"].Const && m[\"c\"].Value.Int() < runeSelf)",
- Args: []ir.FilterExpr{
- {
- Line: 336,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"w\"].Type.Implements(\"io.ByteWriter\")",
- Value: "w",
- Args: []ir.FilterExpr{{Line: 336, Op: ir.FilterStringOp, Src: "\"io.ByteWriter\"", Value: "io.ByteWriter"}},
- },
- {
- Line: 336,
- Op: ir.FilterAndOp,
- Src: "(m[\"c\"].Const && m[\"c\"].Value.Int() < runeSelf)",
- Args: []ir.FilterExpr{
- {
- Line: 336,
- Op: ir.FilterVarConstOp,
- Src: "m[\"c\"].Const",
- Value: "c",
- },
- {
- Line: 336,
- Op: ir.FilterLtOp,
- Src: "m[\"c\"].Value.Int() < runeSelf",
- Args: []ir.FilterExpr{
- {
- Line: 336,
- Op: ir.FilterVarValueIntOp,
- Src: "m[\"c\"].Value.Int()",
- Value: "c",
- },
- {
- Line: 336,
- Op: ir.FilterIntOp,
- Src: "runeSelf",
- Value: int64(128),
- },
- },
- },
- },
- },
- },
- },
- }},
- },
- {
- Line: 344,
- Name: "preferFprint",
- MatcherName: "m",
- DocTags: []string{"performance", "experimental"},
- DocSummary: "Detects fmt.Sprint(f/ln) calls which can be replaced with fmt.Fprint(f/ln)",
- DocBefore: "w.Write([]byte(fmt.Sprintf(\"%x\", 10)))",
- DocAfter: "fmt.Fprintf(w, \"%x\", 10)",
- Rules: []ir.Rule{
- {
- Line: 345,
- SyntaxPatterns: []ir.PatternString{{Line: 345, Value: "$w.Write([]byte(fmt.Sprint($*args)))"}},
- ReportTemplate: "fmt.Fprint($w, $args) should be preferred to the $$",
- SuggestTemplate: "fmt.Fprint($w, $args)",
- WhereExpr: ir.FilterExpr{
- Line: 346,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"w\"].Type.Implements(\"io.Writer\")",
- Value: "w",
- Args: []ir.FilterExpr{{Line: 346, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}},
- },
- },
- {
- Line: 350,
- SyntaxPatterns: []ir.PatternString{{Line: 350, Value: "$w.Write([]byte(fmt.Sprintf($*args)))"}},
- ReportTemplate: "fmt.Fprintf($w, $args) should be preferred to the $$",
- SuggestTemplate: "fmt.Fprintf($w, $args)",
- WhereExpr: ir.FilterExpr{
- Line: 351,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"w\"].Type.Implements(\"io.Writer\")",
- Value: "w",
- Args: []ir.FilterExpr{{Line: 351, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}},
- },
- },
- {
- Line: 355,
- SyntaxPatterns: []ir.PatternString{{Line: 355, Value: "$w.Write([]byte(fmt.Sprintln($*args)))"}},
- ReportTemplate: "fmt.Fprintln($w, $args) should be preferred to the $$",
- SuggestTemplate: "fmt.Fprintln($w, $args)",
- WhereExpr: ir.FilterExpr{
- Line: 356,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"w\"].Type.Implements(\"io.Writer\")",
- Value: "w",
- Args: []ir.FilterExpr{{Line: 356, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}},
- },
- },
- {
- Line: 360,
- SyntaxPatterns: []ir.PatternString{{Line: 360, Value: "io.WriteString($w, fmt.Sprint($*args))"}},
- ReportTemplate: "suggestion: fmt.Fprint($w, $args)",
- SuggestTemplate: "fmt.Fprint($w, $args)",
- },
- {
- Line: 361,
- SyntaxPatterns: []ir.PatternString{{Line: 361, Value: "io.WriteString($w, fmt.Sprintf($*args))"}},
- ReportTemplate: "suggestion: fmt.Fprintf($w, $args)",
- SuggestTemplate: "fmt.Fprintf($w, $args)",
- },
- {
- Line: 362,
- SyntaxPatterns: []ir.PatternString{{Line: 362, Value: "io.WriteString($w, fmt.Sprintln($*args))"}},
- ReportTemplate: "suggestion: fmt.Fprintln($w, $args)",
- SuggestTemplate: "fmt.Fprintln($w, $args)",
- },
- {
- Line: 364,
- SyntaxPatterns: []ir.PatternString{{Line: 364, Value: "$w.WriteString(fmt.Sprint($*args))"}},
- ReportTemplate: "suggestion: fmt.Fprint($w, $args)",
- SuggestTemplate: "fmt.Fprint($w, $args)",
- WhereExpr: ir.FilterExpr{
- Line: 365,
- Op: ir.FilterAndOp,
- Src: "m[\"w\"].Type.Implements(\"io.Writer\") && m[\"w\"].Type.Implements(\"io.StringWriter\")",
- Args: []ir.FilterExpr{
- {
- Line: 365,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"w\"].Type.Implements(\"io.Writer\")",
- Value: "w",
- Args: []ir.FilterExpr{{Line: 365, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}},
- },
- {
- Line: 365,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"w\"].Type.Implements(\"io.StringWriter\")",
- Value: "w",
- Args: []ir.FilterExpr{{Line: 365, Op: ir.FilterStringOp, Src: "\"io.StringWriter\"", Value: "io.StringWriter"}},
- },
- },
- },
- },
- {
- Line: 367,
- SyntaxPatterns: []ir.PatternString{{Line: 367, Value: "$w.WriteString(fmt.Sprintf($*args))"}},
- ReportTemplate: "suggestion: fmt.Fprintf($w, $args)",
- SuggestTemplate: "fmt.Fprintf($w, $args)",
- WhereExpr: ir.FilterExpr{
- Line: 368,
- Op: ir.FilterAndOp,
- Src: "m[\"w\"].Type.Implements(\"io.Writer\") && m[\"w\"].Type.Implements(\"io.StringWriter\")",
- Args: []ir.FilterExpr{
- {
- Line: 368,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"w\"].Type.Implements(\"io.Writer\")",
- Value: "w",
- Args: []ir.FilterExpr{{Line: 368, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}},
- },
- {
- Line: 368,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"w\"].Type.Implements(\"io.StringWriter\")",
- Value: "w",
- Args: []ir.FilterExpr{{Line: 368, Op: ir.FilterStringOp, Src: "\"io.StringWriter\"", Value: "io.StringWriter"}},
- },
- },
- },
- },
- {
- Line: 370,
- SyntaxPatterns: []ir.PatternString{{Line: 370, Value: "$w.WriteString(fmt.Sprintln($*args))"}},
- ReportTemplate: "suggestion: fmt.Fprintln($w, $args)",
- SuggestTemplate: "fmt.Fprintln($w, $args)",
- WhereExpr: ir.FilterExpr{
- Line: 371,
- Op: ir.FilterAndOp,
- Src: "m[\"w\"].Type.Implements(\"io.Writer\") && m[\"w\"].Type.Implements(\"io.StringWriter\")",
- Args: []ir.FilterExpr{
- {
- Line: 371,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"w\"].Type.Implements(\"io.Writer\")",
- Value: "w",
- Args: []ir.FilterExpr{{Line: 371, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}},
- },
- {
- Line: 371,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"w\"].Type.Implements(\"io.StringWriter\")",
- Value: "w",
- Args: []ir.FilterExpr{{Line: 371, Op: ir.FilterStringOp, Src: "\"io.StringWriter\"", Value: "io.StringWriter"}},
- },
- },
- },
- },
- },
- },
- {
- Line: 379,
- Name: "dupArg",
- MatcherName: "m",
- DocTags: []string{"diagnostic"},
- DocSummary: "Detects suspicious duplicated arguments",
- DocBefore: "copy(dst, dst)",
- DocAfter: "copy(dst, src)",
- Rules: []ir.Rule{
- {
- Line: 380,
- SyntaxPatterns: []ir.PatternString{
- {Line: 380, Value: "$x.Equal($x)"},
- {Line: 380, Value: "$x.Equals($x)"},
- {Line: 380, Value: "$x.Compare($x)"},
- {Line: 380, Value: "$x.Cmp($x)"},
- },
- ReportTemplate: "suspicious method call with the same argument and receiver",
- WhereExpr: ir.FilterExpr{Line: 381, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- {
- Line: 384,
- SyntaxPatterns: []ir.PatternString{
- {Line: 384, Value: "copy($x, $x)"},
- {Line: 385, Value: "math.Max($x, $x)"},
- {Line: 386, Value: "math.Min($x, $x)"},
- {Line: 387, Value: "reflect.Copy($x, $x)"},
- {Line: 388, Value: "reflect.DeepEqual($x, $x)"},
- {Line: 389, Value: "strings.Contains($x, $x)"},
- {Line: 390, Value: "strings.Compare($x, $x)"},
- {Line: 391, Value: "strings.EqualFold($x, $x)"},
- {Line: 392, Value: "strings.HasPrefix($x, $x)"},
- {Line: 393, Value: "strings.HasSuffix($x, $x)"},
- {Line: 394, Value: "strings.Index($x, $x)"},
- {Line: 395, Value: "strings.LastIndex($x, $x)"},
- {Line: 396, Value: "strings.Split($x, $x)"},
- {Line: 397, Value: "strings.SplitAfter($x, $x)"},
- {Line: 398, Value: "strings.SplitAfterN($x, $x, $_)"},
- {Line: 399, Value: "strings.SplitN($x, $x, $_)"},
- {Line: 400, Value: "strings.Replace($_, $x, $x, $_)"},
- {Line: 401, Value: "strings.ReplaceAll($_, $x, $x)"},
- {Line: 402, Value: "bytes.Contains($x, $x)"},
- {Line: 403, Value: "bytes.Compare($x, $x)"},
- {Line: 404, Value: "bytes.Equal($x, $x)"},
- {Line: 405, Value: "bytes.EqualFold($x, $x)"},
- {Line: 406, Value: "bytes.HasPrefix($x, $x)"},
- {Line: 407, Value: "bytes.HasSuffix($x, $x)"},
- {Line: 408, Value: "bytes.Index($x, $x)"},
- {Line: 409, Value: "bytes.LastIndex($x, $x)"},
- {Line: 410, Value: "bytes.Split($x, $x)"},
- {Line: 411, Value: "bytes.SplitAfter($x, $x)"},
- {Line: 412, Value: "bytes.SplitAfterN($x, $x, $_)"},
- {Line: 413, Value: "bytes.SplitN($x, $x, $_)"},
- {Line: 414, Value: "bytes.Replace($_, $x, $x, $_)"},
- {Line: 415, Value: "bytes.ReplaceAll($_, $x, $x)"},
- {Line: 416, Value: "types.Identical($x, $x)"},
- {Line: 417, Value: "types.IdenticalIgnoreTags($x, $x)"},
- {Line: 418, Value: "draw.Draw($x, $_, $x, $_, $_)"},
- },
- ReportTemplate: "suspicious duplicated args in $$",
- WhereExpr: ir.FilterExpr{Line: 419, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- },
- },
- },
- {
- Line: 427,
- Name: "returnAfterHttpError",
- MatcherName: "m",
- DocTags: []string{"diagnostic", "experimental"},
- DocSummary: "Detects suspicious http.Error call without following return",
- DocBefore: "if err != nil { http.Error(...); }",
- DocAfter: "if err != nil { http.Error(...); return; }",
- Rules: []ir.Rule{{
- Line: 428,
- SyntaxPatterns: []ir.PatternString{{Line: 428, Value: "if $_ { $*_; http.Error($w, $err, $code) }"}},
- ReportTemplate: "Possibly return is missed after the http.Error call",
- LocationVar: "w",
- }},
- },
- {
- Line: 437,
- Name: "preferFilepathJoin",
- MatcherName: "m",
- DocTags: []string{"style", "experimental"},
- DocSummary: "Detects concatenation with os.PathSeparator which can be replaced with filepath.Join",
- DocBefore: "x + string(os.PathSeparator) + y",
- DocAfter: "filepath.Join(x, y)",
- Rules: []ir.Rule{{
- Line: 438,
- SyntaxPatterns: []ir.PatternString{{Line: 438, Value: "$x + string(os.PathSeparator) + $y"}},
- ReportTemplate: "filepath.Join($x, $y) should be preferred to the $$",
- SuggestTemplate: "filepath.Join($x, $y)",
- WhereExpr: ir.FilterExpr{
- Line: 439,
- Op: ir.FilterAndOp,
- Src: "m[\"x\"].Type.Is(`string`) && m[\"y\"].Type.Is(`string`)",
- Args: []ir.FilterExpr{
- {
- Line: 439,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"x\"].Type.Is(`string`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 439, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
- },
- {
- Line: 439,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"y\"].Type.Is(`string`)",
- Value: "y",
- Args: []ir.FilterExpr{{Line: 439, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
- },
- },
- },
- }},
- },
- {
- Line: 448,
- Name: "preferStringWriter",
- MatcherName: "m",
- DocTags: []string{"performance", "experimental"},
- DocSummary: "Detects w.Write or io.WriteString calls which can be replaced with w.WriteString",
- DocBefore: "w.Write([]byte(\"foo\"))",
- DocAfter: "w.WriteString(\"foo\")",
- Rules: []ir.Rule{
- {
- Line: 449,
- SyntaxPatterns: []ir.PatternString{{Line: 449, Value: "$w.Write([]byte($s))"}},
- ReportTemplate: "$w.WriteString($s) should be preferred to the $$",
- SuggestTemplate: "$w.WriteString($s)",
- WhereExpr: ir.FilterExpr{
- Line: 450,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"w\"].Type.Implements(\"io.StringWriter\")",
- Value: "w",
- Args: []ir.FilterExpr{{Line: 450, Op: ir.FilterStringOp, Src: "\"io.StringWriter\"", Value: "io.StringWriter"}},
- },
- },
- {
- Line: 454,
- SyntaxPatterns: []ir.PatternString{{Line: 454, Value: "io.WriteString($w, $s)"}},
- ReportTemplate: "$w.WriteString($s) should be preferred to the $$",
- SuggestTemplate: "$w.WriteString($s)",
- WhereExpr: ir.FilterExpr{
- Line: 455,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"w\"].Type.Implements(\"io.StringWriter\")",
- Value: "w",
- Args: []ir.FilterExpr{{Line: 455, Op: ir.FilterStringOp, Src: "\"io.StringWriter\"", Value: "io.StringWriter"}},
- },
- },
- },
- },
- {
- Line: 464,
- Name: "sliceClear",
- MatcherName: "m",
- DocTags: []string{"performance", "experimental"},
- DocSummary: "Detects slice clear loops, suggests an idiom that is recognized by the Go compiler",
- DocBefore: "for i := 0; i < len(buf); i++ { buf[i] = 0 }",
- DocAfter: "for i := range buf { buf[i] = 0 }",
- Rules: []ir.Rule{{
- Line: 465,
- SyntaxPatterns: []ir.PatternString{{Line: 465, Value: "for $i := 0; $i < len($xs); $i++ { $xs[$i] = $zero }"}},
- ReportTemplate: "rewrite as for-range so compiler can recognize this pattern",
- WhereExpr: ir.FilterExpr{
- Line: 466,
- Op: ir.FilterEqOp,
- Src: "m[\"zero\"].Value.Int() == 0",
- Args: []ir.FilterExpr{
- {
- Line: 466,
- Op: ir.FilterVarValueIntOp,
- Src: "m[\"zero\"].Value.Int()",
- Value: "zero",
- },
- {
- Line: 466,
- Op: ir.FilterIntOp,
- Src: "0",
- Value: int64(0),
- },
- },
- },
- }},
- },
- {
- Line: 474,
- Name: "syncMapLoadAndDelete",
- MatcherName: "m",
- DocTags: []string{"diagnostic", "experimental"},
- DocSummary: "Detects sync.Map load+delete operations that can be replaced with LoadAndDelete",
- DocBefore: "v, ok := m.Load(k); if ok { m.Delete($k); f(v); }",
- DocAfter: "v, deleted := m.LoadAndDelete(k); if deleted { f(v) }",
- Rules: []ir.Rule{{
- Line: 475,
- SyntaxPatterns: []ir.PatternString{{Line: 475, Value: "$_, $ok := $m.Load($k); if $ok { $m.Delete($k); $*_ }"}},
- ReportTemplate: "use $m.LoadAndDelete to perform load+delete operations atomically",
- WhereExpr: ir.FilterExpr{
- Line: 476,
- Op: ir.FilterAndOp,
- Src: "m.GoVersion().GreaterEqThan(\"1.15\") &&\n\tm[\"m\"].Type.Is(`*sync.Map`)",
- Args: []ir.FilterExpr{
- {
- Line: 476,
- Op: ir.FilterGoVersionGreaterEqThanOp,
- Src: "m.GoVersion().GreaterEqThan(\"1.15\")",
- Value: "1.15",
- },
- {
- Line: 477,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"m\"].Type.Is(`*sync.Map`)",
- Value: "m",
- Args: []ir.FilterExpr{{Line: 477, Op: ir.FilterStringOp, Src: "`*sync.Map`", Value: "*sync.Map"}},
- },
- },
- },
- }},
- },
- {
- Line: 485,
- Name: "sprintfQuotedString",
- MatcherName: "m",
- DocTags: []string{"diagnostic", "experimental"},
- DocSummary: "Detects \"%s\" formatting directives that can be replaced with %q",
- DocBefore: "fmt.Sprintf(`\"%s\"`, s)",
- DocAfter: "fmt.Sprintf(`%q`, s)",
- Rules: []ir.Rule{{
- Line: 486,
- SyntaxPatterns: []ir.PatternString{{Line: 486, Value: "fmt.Sprintf($s, $*_)"}},
- ReportTemplate: "use %q instead of \"%s\" for quoted strings",
- WhereExpr: ir.FilterExpr{
- Line: 487,
- Op: ir.FilterOrOp,
- Src: "m[\"s\"].Text.Matches(\"^`.*\\\"%s\\\".*`$\") ||\n\tm[\"s\"].Text.Matches(`^\".*\\\\\"%s\\\\\".*\"$`)",
- Args: []ir.FilterExpr{
- {
- Line: 487,
- Op: ir.FilterVarTextMatchesOp,
- Src: "m[\"s\"].Text.Matches(\"^`.*\\\"%s\\\".*`$\")",
- Value: "s",
- Args: []ir.FilterExpr{{Line: 487, Op: ir.FilterStringOp, Src: "\"^`.*\\\"%s\\\".*`$\"", Value: "^`.*\"%s\".*`$"}},
- },
- {
- Line: 488,
- Op: ir.FilterVarTextMatchesOp,
- Src: "m[\"s\"].Text.Matches(`^\".*\\\\\"%s\\\\\".*\"$`)",
- Value: "s",
- Args: []ir.FilterExpr{{Line: 488, Op: ir.FilterStringOp, Src: "`^\".*\\\\\"%s\\\\\".*\"$`", Value: "^\".*\\\\\"%s\\\\\".*\"$"}},
- },
- },
- },
- }},
- },
- {
- Line: 496,
- Name: "offBy1",
- MatcherName: "m",
- DocTags: []string{"diagnostic"},
- DocSummary: "Detects various off-by-one kind of errors",
- DocBefore: "xs[len(xs)]",
- DocAfter: "xs[len(xs)-1]",
- Rules: []ir.Rule{
- {
- Line: 497,
- SyntaxPatterns: []ir.PatternString{{Line: 497, Value: "$x[len($x)]"}},
- ReportTemplate: "index expr always panics; maybe you wanted $x[len($x)-1]?",
- SuggestTemplate: "$x[len($x)-1]",
- WhereExpr: ir.FilterExpr{
- Line: 498,
- Op: ir.FilterAndOp,
- Src: "m[\"x\"].Pure && m[\"x\"].Type.Is(`[]$_`)",
- Args: []ir.FilterExpr{
- {Line: 498, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- {
- Line: 498,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"x\"].Type.Is(`[]$_`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 498, Op: ir.FilterStringOp, Src: "`[]$_`", Value: "[]$_"}},
- },
- },
- },
- },
- {
- Line: 505,
- SyntaxPatterns: []ir.PatternString{
- {Line: 506, Value: "$i := strings.Index($s, $_); $_ := $slicing[$i:]"},
- {Line: 507, Value: "$i := strings.Index($s, $_); $_ = $slicing[$i:]"},
- {Line: 508, Value: "$i := bytes.Index($s, $_); $_ := $slicing[$i:]"},
- {Line: 509, Value: "$i := bytes.Index($s, $_); $_ = $slicing[$i:]"},
- },
- ReportTemplate: "Index() can return -1; maybe you wanted to do $s[$i+1:]",
- WhereExpr: ir.FilterExpr{
- Line: 510,
- Op: ir.FilterEqOp,
- Src: "m[\"s\"].Text == m[\"slicing\"].Text",
- Args: []ir.FilterExpr{
- {Line: 510, Op: ir.FilterVarTextOp, Src: "m[\"s\"].Text", Value: "s"},
- {Line: 510, Op: ir.FilterVarTextOp, Src: "m[\"slicing\"].Text", Value: "slicing"},
- },
- },
- LocationVar: "slicing",
- },
- {
- Line: 514,
- SyntaxPatterns: []ir.PatternString{
- {Line: 515, Value: "$i := strings.Index($s, $_); $_ := $slicing[:$i]"},
- {Line: 516, Value: "$i := strings.Index($s, $_); $_ = $slicing[:$i]"},
- {Line: 517, Value: "$i := bytes.Index($s, $_); $_ := $slicing[:$i]"},
- {Line: 518, Value: "$i := bytes.Index($s, $_); $_ = $slicing[:$i]"},
- },
- ReportTemplate: "Index() can return -1; maybe you wanted to do $s[:$i+1]",
- WhereExpr: ir.FilterExpr{
- Line: 519,
- Op: ir.FilterEqOp,
- Src: "m[\"s\"].Text == m[\"slicing\"].Text",
- Args: []ir.FilterExpr{
- {Line: 519, Op: ir.FilterVarTextOp, Src: "m[\"s\"].Text", Value: "s"},
- {Line: 519, Op: ir.FilterVarTextOp, Src: "m[\"slicing\"].Text", Value: "slicing"},
- },
- },
- LocationVar: "slicing",
- },
- {
- Line: 523,
- SyntaxPatterns: []ir.PatternString{
- {Line: 524, Value: "$s[strings.Index($s, $_):]"},
- {Line: 525, Value: "$s[:strings.Index($s, $_)]"},
- {Line: 526, Value: "$s[bytes.Index($s, $_):]"},
- {Line: 527, Value: "$s[:bytes.Index($s, $_)]"},
- },
- ReportTemplate: "Index() can return -1; maybe you wanted to do Index()+1",
- },
- },
- },
- {
- Line: 535,
- Name: "unslice",
- MatcherName: "m",
- DocTags: []string{"style"},
- DocSummary: "Detects slice expressions that can be simplified to sliced expression itself",
- DocBefore: "copy(b[:], values...)",
- DocAfter: "copy(b, values...)",
- Rules: []ir.Rule{{
- Line: 536,
- SyntaxPatterns: []ir.PatternString{{Line: 536, Value: "$s[:]"}},
- ReportTemplate: "could simplify $$ to $s",
- SuggestTemplate: "$s",
- WhereExpr: ir.FilterExpr{
- Line: 537,
- Op: ir.FilterOrOp,
- Src: "m[\"s\"].Type.Is(`string`) || m[\"s\"].Type.Is(`[]$_`)",
- Args: []ir.FilterExpr{
- {
- Line: 537,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"s\"].Type.Is(`string`)",
- Value: "s",
- Args: []ir.FilterExpr{{Line: 537, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
- },
- {
- Line: 537,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"s\"].Type.Is(`[]$_`)",
- Value: "s",
- Args: []ir.FilterExpr{{Line: 537, Op: ir.FilterStringOp, Src: "`[]$_`", Value: "[]$_"}},
- },
- },
- },
- }},
- },
- {
- Line: 546,
- Name: "yodaStyleExpr",
- MatcherName: "m",
- DocTags: []string{"style", "experimental"},
- DocSummary: "Detects Yoda style expressions and suggests to replace them",
- DocBefore: "return nil != ptr",
- DocAfter: "return ptr != nil",
- Rules: []ir.Rule{
- {
- Line: 547,
- SyntaxPatterns: []ir.PatternString{{Line: 547, Value: "$constval != $x"}},
- ReportTemplate: "consider to change order in expression to $x != $constval",
- WhereExpr: ir.FilterExpr{
- Line: 547,
- Op: ir.FilterAndOp,
- Src: "m[\"constval\"].Node.Is(`BasicLit`) && !m[\"x\"].Node.Is(`BasicLit`)",
- Args: []ir.FilterExpr{
- {
- Line: 547,
- Op: ir.FilterVarNodeIsOp,
- Src: "m[\"constval\"].Node.Is(`BasicLit`)",
- Value: "constval",
- Args: []ir.FilterExpr{{Line: 547, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}},
- },
- {
- Line: 547,
- Op: ir.FilterNotOp,
- Src: "!m[\"x\"].Node.Is(`BasicLit`)",
- Args: []ir.FilterExpr{{
- Line: 547,
- Op: ir.FilterVarNodeIsOp,
- Src: "m[\"x\"].Node.Is(`BasicLit`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 547, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}},
- }},
- },
- },
- },
- },
- {
- Line: 549,
- SyntaxPatterns: []ir.PatternString{{Line: 549, Value: "$constval == $x"}},
- ReportTemplate: "consider to change order in expression to $x == $constval",
- WhereExpr: ir.FilterExpr{
- Line: 549,
- Op: ir.FilterAndOp,
- Src: "m[\"constval\"].Node.Is(`BasicLit`) && !m[\"x\"].Node.Is(`BasicLit`)",
- Args: []ir.FilterExpr{
- {
- Line: 549,
- Op: ir.FilterVarNodeIsOp,
- Src: "m[\"constval\"].Node.Is(`BasicLit`)",
- Value: "constval",
- Args: []ir.FilterExpr{{Line: 549, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}},
- },
- {
- Line: 549,
- Op: ir.FilterNotOp,
- Src: "!m[\"x\"].Node.Is(`BasicLit`)",
- Args: []ir.FilterExpr{{
- Line: 549,
- Op: ir.FilterVarNodeIsOp,
- Src: "m[\"x\"].Node.Is(`BasicLit`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 549, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}},
- }},
- },
- },
- },
- },
- {
- Line: 552,
- SyntaxPatterns: []ir.PatternString{{Line: 552, Value: "nil != $x"}},
- ReportTemplate: "consider to change order in expression to $x != nil",
- WhereExpr: ir.FilterExpr{
- Line: 552,
- Op: ir.FilterNotOp,
- Src: "!m[\"x\"].Node.Is(`BasicLit`)",
- Args: []ir.FilterExpr{{
- Line: 552,
- Op: ir.FilterVarNodeIsOp,
- Src: "m[\"x\"].Node.Is(`BasicLit`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 552, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}},
- }},
- },
- },
- {
- Line: 554,
- SyntaxPatterns: []ir.PatternString{{Line: 554, Value: "nil == $x"}},
- ReportTemplate: "consider to change order in expression to $x == nil",
- WhereExpr: ir.FilterExpr{
- Line: 554,
- Op: ir.FilterNotOp,
- Src: "!m[\"x\"].Node.Is(`BasicLit`)",
- Args: []ir.FilterExpr{{
- Line: 554,
- Op: ir.FilterVarNodeIsOp,
- Src: "m[\"x\"].Node.Is(`BasicLit`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 554, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}},
- }},
- },
- },
- },
- },
- {
- Line: 562,
- Name: "equalFold",
- MatcherName: "m",
- DocTags: []string{"performance", "experimental"},
- DocSummary: "Detects unoptimal strings/bytes case-insensitive comparison",
- DocBefore: "strings.ToLower(x) == strings.ToLower(y)",
- DocAfter: "strings.EqualFold(x, y)",
- Rules: []ir.Rule{
- {
- Line: 571,
- SyntaxPatterns: []ir.PatternString{
- {Line: 572, Value: "strings.ToLower($x) == $y"},
- {Line: 573, Value: "strings.ToLower($x) == strings.ToLower($y)"},
- {Line: 574, Value: "$x == strings.ToLower($y)"},
- {Line: 575, Value: "strings.ToUpper($x) == $y"},
- {Line: 576, Value: "strings.ToUpper($x) == strings.ToUpper($y)"},
- {Line: 577, Value: "$x == strings.ToUpper($y)"},
- },
- ReportTemplate: "consider replacing with strings.EqualFold($x, $y)",
- SuggestTemplate: "strings.EqualFold($x, $y)",
- WhereExpr: ir.FilterExpr{
- Line: 578,
- Op: ir.FilterAndOp,
- Src: "m[\"x\"].Pure && m[\"y\"].Pure && m[\"x\"].Text != m[\"y\"].Text",
- Args: []ir.FilterExpr{
- {
- Line: 578,
- Op: ir.FilterAndOp,
- Src: "m[\"x\"].Pure && m[\"y\"].Pure",
- Args: []ir.FilterExpr{
- {Line: 578, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- {Line: 578, Op: ir.FilterVarPureOp, Src: "m[\"y\"].Pure", Value: "y"},
- },
- },
- {
- Line: 578,
- Op: ir.FilterNeqOp,
- Src: "m[\"x\"].Text != m[\"y\"].Text",
- Args: []ir.FilterExpr{
- {Line: 578, Op: ir.FilterVarTextOp, Src: "m[\"x\"].Text", Value: "x"},
- {Line: 578, Op: ir.FilterVarTextOp, Src: "m[\"y\"].Text", Value: "y"},
- },
- },
- },
- },
- },
- {
- Line: 583,
- SyntaxPatterns: []ir.PatternString{
- {Line: 584, Value: "strings.ToLower($x) != $y"},
- {Line: 585, Value: "strings.ToLower($x) != strings.ToLower($y)"},
- {Line: 586, Value: "$x != strings.ToLower($y)"},
- {Line: 587, Value: "strings.ToUpper($x) != $y"},
- {Line: 588, Value: "strings.ToUpper($x) != strings.ToUpper($y)"},
- {Line: 589, Value: "$x != strings.ToUpper($y)"},
- },
- ReportTemplate: "consider replacing with !strings.EqualFold($x, $y)",
- SuggestTemplate: "!strings.EqualFold($x, $y)",
- WhereExpr: ir.FilterExpr{
- Line: 590,
- Op: ir.FilterAndOp,
- Src: "m[\"x\"].Pure && m[\"y\"].Pure && m[\"x\"].Text != m[\"y\"].Text",
- Args: []ir.FilterExpr{
- {
- Line: 590,
- Op: ir.FilterAndOp,
- Src: "m[\"x\"].Pure && m[\"y\"].Pure",
- Args: []ir.FilterExpr{
- {Line: 590, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- {Line: 590, Op: ir.FilterVarPureOp, Src: "m[\"y\"].Pure", Value: "y"},
- },
- },
- {
- Line: 590,
- Op: ir.FilterNeqOp,
- Src: "m[\"x\"].Text != m[\"y\"].Text",
- Args: []ir.FilterExpr{
- {Line: 590, Op: ir.FilterVarTextOp, Src: "m[\"x\"].Text", Value: "x"},
- {Line: 590, Op: ir.FilterVarTextOp, Src: "m[\"y\"].Text", Value: "y"},
- },
- },
- },
- },
- },
- {
- Line: 595,
- SyntaxPatterns: []ir.PatternString{
- {Line: 596, Value: "bytes.Equal(bytes.ToLower($x), $y)"},
- {Line: 597, Value: "bytes.Equal(bytes.ToLower($x), bytes.ToLower($y))"},
- {Line: 598, Value: "bytes.Equal($x, bytes.ToLower($y))"},
- {Line: 599, Value: "bytes.Equal(bytes.ToUpper($x), $y)"},
- {Line: 600, Value: "bytes.Equal(bytes.ToUpper($x), bytes.ToUpper($y))"},
- {Line: 601, Value: "bytes.Equal($x, bytes.ToUpper($y))"},
- },
- ReportTemplate: "consider replacing with bytes.EqualFold($x, $y)",
- SuggestTemplate: "bytes.EqualFold($x, $y)",
- WhereExpr: ir.FilterExpr{
- Line: 602,
- Op: ir.FilterAndOp,
- Src: "m[\"x\"].Pure && m[\"y\"].Pure && m[\"x\"].Text != m[\"y\"].Text",
- Args: []ir.FilterExpr{
- {
- Line: 602,
- Op: ir.FilterAndOp,
- Src: "m[\"x\"].Pure && m[\"y\"].Pure",
- Args: []ir.FilterExpr{
- {Line: 602, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
- {Line: 602, Op: ir.FilterVarPureOp, Src: "m[\"y\"].Pure", Value: "y"},
- },
- },
- {
- Line: 602,
- Op: ir.FilterNeqOp,
- Src: "m[\"x\"].Text != m[\"y\"].Text",
- Args: []ir.FilterExpr{
- {Line: 602, Op: ir.FilterVarTextOp, Src: "m[\"x\"].Text", Value: "x"},
- {Line: 602, Op: ir.FilterVarTextOp, Src: "m[\"y\"].Text", Value: "y"},
- },
- },
- },
- },
- },
- },
- },
- {
- Line: 611,
- Name: "argOrder",
- MatcherName: "m",
- DocTags: []string{"diagnostic"},
- DocSummary: "Detects suspicious arguments order",
- DocBefore: "strings.HasPrefix(\"#\", userpass)",
- DocAfter: "strings.HasPrefix(userpass, \"#\")",
- Rules: []ir.Rule{{
- Line: 612,
- SyntaxPatterns: []ir.PatternString{
- {Line: 613, Value: "strings.HasPrefix($lit, $s)"},
- {Line: 614, Value: "bytes.HasPrefix($lit, $s)"},
- {Line: 615, Value: "strings.HasSuffix($lit, $s)"},
- {Line: 616, Value: "bytes.HasSuffix($lit, $s)"},
- {Line: 617, Value: "strings.Contains($lit, $s)"},
- {Line: 618, Value: "bytes.Contains($lit, $s)"},
- {Line: 619, Value: "strings.TrimPrefix($lit, $s)"},
- {Line: 620, Value: "bytes.TrimPrefix($lit, $s)"},
- {Line: 621, Value: "strings.TrimSuffix($lit, $s)"},
- {Line: 622, Value: "bytes.TrimSuffix($lit, $s)"},
- {Line: 623, Value: "strings.Split($lit, $s)"},
- {Line: 624, Value: "bytes.Split($lit, $s)"},
- },
- ReportTemplate: "$lit and $s arguments order looks reversed",
- WhereExpr: ir.FilterExpr{
- Line: 625,
- Op: ir.FilterAndOp,
- Src: "(m[\"lit\"].Const || m[\"lit\"].ConstSlice) &&\n\t!(m[\"s\"].Const || m[\"s\"].ConstSlice) &&\n\t!m[\"lit\"].Node.Is(`Ident`)",
- Args: []ir.FilterExpr{
- {
- Line: 625,
- Op: ir.FilterAndOp,
- Src: "(m[\"lit\"].Const || m[\"lit\"].ConstSlice) &&\n\t!(m[\"s\"].Const || m[\"s\"].ConstSlice)",
- Args: []ir.FilterExpr{
- {
- Line: 625,
- Op: ir.FilterOrOp,
- Src: "(m[\"lit\"].Const || m[\"lit\"].ConstSlice)",
- Args: []ir.FilterExpr{
- {
- Line: 625,
- Op: ir.FilterVarConstOp,
- Src: "m[\"lit\"].Const",
- Value: "lit",
- },
- {
- Line: 625,
- Op: ir.FilterVarConstSliceOp,
- Src: "m[\"lit\"].ConstSlice",
- Value: "lit",
- },
- },
- },
- {
- Line: 626,
- Op: ir.FilterNotOp,
- Src: "!(m[\"s\"].Const || m[\"s\"].ConstSlice)",
- Args: []ir.FilterExpr{{
- Line: 626,
- Op: ir.FilterOrOp,
- Src: "(m[\"s\"].Const || m[\"s\"].ConstSlice)",
- Args: []ir.FilterExpr{
- {
- Line: 626,
- Op: ir.FilterVarConstOp,
- Src: "m[\"s\"].Const",
- Value: "s",
- },
- {
- Line: 626,
- Op: ir.FilterVarConstSliceOp,
- Src: "m[\"s\"].ConstSlice",
- Value: "s",
- },
- },
- }},
- },
- },
- },
- {
- Line: 627,
- Op: ir.FilterNotOp,
- Src: "!m[\"lit\"].Node.Is(`Ident`)",
- Args: []ir.FilterExpr{{
- Line: 627,
- Op: ir.FilterVarNodeIsOp,
- Src: "m[\"lit\"].Node.Is(`Ident`)",
- Value: "lit",
- Args: []ir.FilterExpr{{Line: 627, Op: ir.FilterStringOp, Src: "`Ident`", Value: "Ident"}},
- }},
- },
- },
- },
- }},
- },
- {
- Line: 635,
- Name: "stringConcatSimplify",
- MatcherName: "m",
- DocTags: []string{"style", "experimental"},
- DocSummary: "Detects string concat operations that can be simplified",
- DocBefore: "strings.Join([]string{x, y}, \"_\")",
- DocAfter: "x + \"_\" + y",
- Rules: []ir.Rule{
- {
- Line: 636,
- SyntaxPatterns: []ir.PatternString{{Line: 636, Value: "strings.Join([]string{$x, $y}, \"\")"}},
- ReportTemplate: "suggestion: $x + $y",
- SuggestTemplate: "$x + $y",
- },
- {
- Line: 637,
- SyntaxPatterns: []ir.PatternString{{Line: 637, Value: "strings.Join([]string{$x, $y, $z}, \"\")"}},
- ReportTemplate: "suggestion: $x + $y + $z",
- SuggestTemplate: "$x + $y + $z",
- },
- {
- Line: 638,
- SyntaxPatterns: []ir.PatternString{{Line: 638, Value: "strings.Join([]string{$x, $y}, $glue)"}},
- ReportTemplate: "suggestion: $x + $glue + $y",
- SuggestTemplate: "$x + $glue + $y",
- },
- },
- },
- {
- Line: 645,
- Name: "timeExprSimplify",
- MatcherName: "m",
- DocTags: []string{"style", "experimental"},
- DocSummary: "Detects manual conversion to milli- or microseconds",
- DocBefore: "t.Unix() / 1000",
- DocAfter: "t.UnixMilli()",
- Rules: []ir.Rule{
- {
- Line: 650,
- SyntaxPatterns: []ir.PatternString{{Line: 650, Value: "$t.Unix() / 1000"}},
- ReportTemplate: "use $t.UnixMilli() instead of $$",
- SuggestTemplate: "$t.UnixMilli()",
- WhereExpr: ir.FilterExpr{
- Line: 651,
- Op: ir.FilterAndOp,
- Src: "m.GoVersion().GreaterEqThan(\"1.17\") && isTime(m[\"t\"])",
- Args: []ir.FilterExpr{
- {
- Line: 651,
- Op: ir.FilterGoVersionGreaterEqThanOp,
- Src: "m.GoVersion().GreaterEqThan(\"1.17\")",
- Value: "1.17",
- },
- {
- Line: 651,
- Op: ir.FilterOrOp,
- Src: "isTime(m[\"t\"])",
- Args: []ir.FilterExpr{
- {
- Line: 651,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"t\"].Type.Is(`time.Time`)",
- Value: "t",
- Args: []ir.FilterExpr{{Line: 647, Op: ir.FilterStringOp, Src: "`time.Time`", Value: "time.Time"}},
- },
- {
- Line: 651,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"t\"].Type.Is(`*time.Time`)",
- Value: "t",
- Args: []ir.FilterExpr{{Line: 647, Op: ir.FilterStringOp, Src: "`*time.Time`", Value: "*time.Time"}},
- },
- },
- },
- },
- },
- },
- {
- Line: 655,
- SyntaxPatterns: []ir.PatternString{{Line: 655, Value: "$t.UnixNano() * 1000"}},
- ReportTemplate: "use $t.UnixMicro() instead of $$",
- SuggestTemplate: "$t.UnixMicro()",
- WhereExpr: ir.FilterExpr{
- Line: 656,
- Op: ir.FilterAndOp,
- Src: "m.GoVersion().GreaterEqThan(\"1.17\") && isTime(m[\"t\"])",
- Args: []ir.FilterExpr{
- {
- Line: 656,
- Op: ir.FilterGoVersionGreaterEqThanOp,
- Src: "m.GoVersion().GreaterEqThan(\"1.17\")",
- Value: "1.17",
- },
- {
- Line: 656,
- Op: ir.FilterOrOp,
- Src: "isTime(m[\"t\"])",
- Args: []ir.FilterExpr{
- {
- Line: 656,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"t\"].Type.Is(`time.Time`)",
- Value: "t",
- Args: []ir.FilterExpr{{Line: 647, Op: ir.FilterStringOp, Src: "`time.Time`", Value: "time.Time"}},
- },
- {
- Line: 656,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"t\"].Type.Is(`*time.Time`)",
- Value: "t",
- Args: []ir.FilterExpr{{Line: 647, Op: ir.FilterStringOp, Src: "`*time.Time`", Value: "*time.Time"}},
- },
- },
- },
- },
- },
- },
- },
- },
- {
- Line: 665,
- Name: "exposedSyncMutex",
- MatcherName: "m",
- DocTags: []string{"style", "experimental"},
- DocSummary: "Detects exposed methods from sync.Mutex and sync.RWMutex",
- DocBefore: "type Foo struct{ ...; sync.Mutex; ... }",
- DocAfter: "type Foo struct{ ...; mu sync.Mutex; ... }",
- Rules: []ir.Rule{
- {
- Line: 670,
- SyntaxPatterns: []ir.PatternString{{Line: 670, Value: "type $x struct { $*_; sync.Mutex; $*_ }"}},
- ReportTemplate: "don't embed sync.Mutex",
- WhereExpr: ir.FilterExpr{
- Line: 671,
- Op: ir.FilterVarTextMatchesOp,
- Src: "isExported(m[\"x\"])",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 667, Op: ir.FilterStringOp, Src: "`^\\p{Lu}`", Value: "^\\p{Lu}"}},
- },
- },
- {
- Line: 674,
- SyntaxPatterns: []ir.PatternString{{Line: 674, Value: "type $x struct { $*_; *sync.Mutex; $*_ }"}},
- ReportTemplate: "don't embed *sync.Mutex",
- WhereExpr: ir.FilterExpr{
- Line: 675,
- Op: ir.FilterVarTextMatchesOp,
- Src: "isExported(m[\"x\"])",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 667, Op: ir.FilterStringOp, Src: "`^\\p{Lu}`", Value: "^\\p{Lu}"}},
- },
- },
- {
- Line: 678,
- SyntaxPatterns: []ir.PatternString{{Line: 678, Value: "type $x struct { $*_; sync.RWMutex; $*_ }"}},
- ReportTemplate: "don't embed sync.RWMutex",
- WhereExpr: ir.FilterExpr{
- Line: 679,
- Op: ir.FilterVarTextMatchesOp,
- Src: "isExported(m[\"x\"])",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 667, Op: ir.FilterStringOp, Src: "`^\\p{Lu}`", Value: "^\\p{Lu}"}},
- },
- },
- {
- Line: 682,
- SyntaxPatterns: []ir.PatternString{{Line: 682, Value: "type $x struct { $*_; *sync.RWMutex; $*_ }"}},
- ReportTemplate: "don't embed *sync.RWMutex",
- WhereExpr: ir.FilterExpr{
- Line: 683,
- Op: ir.FilterVarTextMatchesOp,
- Src: "isExported(m[\"x\"])",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 667, Op: ir.FilterStringOp, Src: "`^\\p{Lu}`", Value: "^\\p{Lu}"}},
- },
- },
- },
- },
- {
- Line: 691,
- Name: "badSorting",
- MatcherName: "m",
- DocTags: []string{"diagnostic", "experimental"},
- DocSummary: "Detects bad usage of sort package",
- DocBefore: "xs = sort.StringSlice(xs)",
- DocAfter: "sort.Strings(xs)",
- Rules: []ir.Rule{
- {
- Line: 692,
- SyntaxPatterns: []ir.PatternString{{Line: 692, Value: "$x = sort.IntSlice($x)"}},
- ReportTemplate: "suspicious sort.IntSlice usage, maybe sort.Ints was intended?",
- SuggestTemplate: "sort.Ints($x)",
- WhereExpr: ir.FilterExpr{
- Line: 693,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"x\"].Type.Is(`[]int`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 693, Op: ir.FilterStringOp, Src: "`[]int`", Value: "[]int"}},
- },
- },
- {
- Line: 697,
- SyntaxPatterns: []ir.PatternString{{Line: 697, Value: "$x = sort.Float64Slice($x)"}},
- ReportTemplate: "suspicious sort.Float64s usage, maybe sort.Float64s was intended?",
- SuggestTemplate: "sort.Float64s($x)",
- WhereExpr: ir.FilterExpr{
- Line: 698,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"x\"].Type.Is(`[]float64`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 698, Op: ir.FilterStringOp, Src: "`[]float64`", Value: "[]float64"}},
- },
- },
- {
- Line: 702,
- SyntaxPatterns: []ir.PatternString{{Line: 702, Value: "$x = sort.StringSlice($x)"}},
- ReportTemplate: "suspicious sort.StringSlice usage, maybe sort.Strings was intended?",
- SuggestTemplate: "sort.Strings($x)",
- WhereExpr: ir.FilterExpr{
- Line: 703,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"x\"].Type.Is(`[]string`)",
- Value: "x",
- Args: []ir.FilterExpr{{Line: 703, Op: ir.FilterStringOp, Src: "`[]string`", Value: "[]string"}},
- },
- },
- },
- },
- {
- Line: 712,
- Name: "externalErrorReassign",
- MatcherName: "m",
- DocTags: []string{"diagnostic", "experimental"},
- DocSummary: "Detects suspicious reassignment of error from another package",
- DocBefore: "io.EOF = nil",
- DocAfter: "/* don't do it */",
- Rules: []ir.Rule{{
- Line: 713,
- SyntaxPatterns: []ir.PatternString{{Line: 713, Value: "$pkg.$err = $x"}},
- ReportTemplate: "suspicious reassignment of error from another package",
- WhereExpr: ir.FilterExpr{
- Line: 714,
- Op: ir.FilterAndOp,
- Src: "m[\"err\"].Type.Is(`error`) && m[\"pkg\"].Object.Is(`PkgName`)",
- Args: []ir.FilterExpr{
- {
- Line: 714,
- Op: ir.FilterVarTypeIsOp,
- Src: "m[\"err\"].Type.Is(`error`)",
- Value: "err",
- Args: []ir.FilterExpr{{Line: 714, Op: ir.FilterStringOp, Src: "`error`", Value: "error"}},
- },
- {
- Line: 714,
- Op: ir.FilterVarObjectIsOp,
- Src: "m[\"pkg\"].Object.Is(`PkgName`)",
- Value: "pkg",
- Args: []ir.FilterExpr{{Line: 714, Op: ir.FilterStringOp, Src: "`PkgName`", Value: "PkgName"}},
- },
- },
- },
- }},
- },
- {
- Line: 722,
- Name: "emptyDecl",
- MatcherName: "m",
- DocTags: []string{"diagnostic", "experimental"},
- DocSummary: "Detects suspicious empty declarations blocks",
- DocBefore: "var()",
- DocAfter: "/* nothing */",
- Rules: []ir.Rule{
- {
- Line: 723,
- SyntaxPatterns: []ir.PatternString{{Line: 723, Value: "var()"}},
- ReportTemplate: "empty var() block",
- },
- {
- Line: 724,
- SyntaxPatterns: []ir.PatternString{{Line: 724, Value: "const()"}},
- ReportTemplate: "empty const() block",
- },
- {
- Line: 725,
- SyntaxPatterns: []ir.PatternString{{Line: 725, Value: "type()"}},
- ReportTemplate: "empty type() block",
- },
- },
- },
- {
- Line: 732,
- Name: "dynamicFmtString",
- MatcherName: "m",
- DocTags: []string{"diagnostic", "experimental"},
- DocSummary: "Detects suspicious formatting strings usage",
- DocBefore: "fmt.Errorf(msg)",
- DocAfter: "fmt.Errorf(\"%s\", msg)",
- Rules: []ir.Rule{
- {
- Line: 733,
- SyntaxPatterns: []ir.PatternString{{Line: 733, Value: "fmt.Errorf($f)"}},
- ReportTemplate: "use errors.New($f) or fmt.Errorf(\"%s\", $f) instead",
- SuggestTemplate: "errors.New($f)",
- WhereExpr: ir.FilterExpr{
- Line: 734,
- Op: ir.FilterNotOp,
- Src: "!m[\"f\"].Const",
- Args: []ir.FilterExpr{{
- Line: 734,
- Op: ir.FilterVarConstOp,
- Src: "m[\"f\"].Const",
- Value: "f",
- }},
- },
- },
- {
- Line: 738,
- SyntaxPatterns: []ir.PatternString{{Line: 738, Value: "fmt.Errorf($f($*args))"}},
- ReportTemplate: "use errors.New($f($*args)) or fmt.Errorf(\"%s\", $f($*args)) instead",
- SuggestTemplate: "errors.New($f($*args))",
- },
- },
- },
- {
- Line: 747,
- Name: "stringsCompare",
- MatcherName: "m",
- DocTags: []string{"style", "experimental"},
- DocSummary: "Detects strings.Compare usage",
- DocBefore: "strings.Compare(x, y)",
- DocAfter: "x < y",
- Rules: []ir.Rule{
- {
- Line: 748,
- SyntaxPatterns: []ir.PatternString{{Line: 748, Value: "strings.Compare($s1, $s2) == 0"}},
- ReportTemplate: "suggestion: $s1 == $s2",
- SuggestTemplate: "$s1 == $s2",
- },
- {
- Line: 751,
- SyntaxPatterns: []ir.PatternString{
- {Line: 751, Value: "strings.Compare($s1, $s2) == -1"},
- {Line: 752, Value: "strings.Compare($s1, $s2) < 0"},
- },
- ReportTemplate: "suggestion: $s1 < $s2",
- SuggestTemplate: "$s1 < $s2",
- },
- {
- Line: 755,
- SyntaxPatterns: []ir.PatternString{
- {Line: 755, Value: "strings.Compare($s1, $s2) == 1"},
- {Line: 756, Value: "strings.Compare($s1, $s2) > 0"},
- },
- ReportTemplate: "suggestion: $s1 > $s2",
- SuggestTemplate: "$s1 > $s2",
- },
- },
- },
- {
- Line: 764,
- Name: "uncheckedInlineErr",
- MatcherName: "m",
- DocTags: []string{"diagnostic", "experimental"},
- DocSummary: "Detects unchecked errors in if statements",
- DocBefore: "if err := expr(); err2 != nil { /*...*/ }",
- DocAfter: "if err := expr(); err != nil { /*...*/ }",
- Rules: []ir.Rule{{
- Line: 765,
- SyntaxPatterns: []ir.PatternString{
- {Line: 766, Value: "if $err := $_($*_); $err2 != nil { $*_ }"},
- {Line: 767, Value: "if $err = $_($*_); $err2 != nil { $*_ }"},
- {Line: 768, Value: "if $*_, $err := $_($*_); $err2 != nil { $*_ }"},
- {Line: 769, Value: "if $*_, $err = $_($*_); $err2 != nil { $*_ }"},
- },
- ReportTemplate: "$err error is unchecked, maybe intended to check it instead of $err2",
- WhereExpr: ir.FilterExpr{
- Line: 770,
- Op: ir.FilterAndOp,
- Src: "m[\"err\"].Type.Implements(\"error\") && m[\"err2\"].Type.Implements(\"error\") &&\n\tm[\"err\"].Text != m[\"err2\"].Text",
- Args: []ir.FilterExpr{
- {
- Line: 770,
- Op: ir.FilterAndOp,
- Src: "m[\"err\"].Type.Implements(\"error\") && m[\"err2\"].Type.Implements(\"error\")",
- Args: []ir.FilterExpr{
- {
- Line: 770,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"err\"].Type.Implements(\"error\")",
- Value: "err",
- Args: []ir.FilterExpr{{Line: 770, Op: ir.FilterStringOp, Src: "\"error\"", Value: "error"}},
- },
- {
- Line: 770,
- Op: ir.FilterVarTypeImplementsOp,
- Src: "m[\"err2\"].Type.Implements(\"error\")",
- Value: "err2",
- Args: []ir.FilterExpr{{Line: 770, Op: ir.FilterStringOp, Src: "\"error\"", Value: "error"}},
- },
- },
- },
- {
- Line: 771,
- Op: ir.FilterNeqOp,
- Src: "m[\"err\"].Text != m[\"err2\"].Text",
- Args: []ir.FilterExpr{
- {Line: 771, Op: ir.FilterVarTextOp, Src: "m[\"err\"].Text", Value: "err"},
- {Line: 771, Op: ir.FilterVarTextOp, Src: "m[\"err2\"].Text", Value: "err2"},
- },
- },
- },
- },
- LocationVar: "err",
- }},
- },
- {
- Line: 780,
- Name: "badSyncOnceFunc",
- MatcherName: "m",
- DocTags: []string{"diagnostic", "experimental"},
- DocSummary: "Detects bad usage of sync.OnceFunc",
- DocBefore: "sync.OnceFunc(foo)()",
- DocAfter: "fooOnce := sync.OnceFunc(foo); ...; fooOnce()",
- Rules: []ir.Rule{
- {
- Line: 781,
- SyntaxPatterns: []ir.PatternString{{Line: 781, Value: "$*_; sync.OnceFunc($x); $*_;"}},
- ReportTemplate: "possible sync.OnceFunc misuse, sync.OnceFunc($x) result is not used",
- WhereExpr: ir.FilterExpr{
- Line: 783,
- Op: ir.FilterGoVersionGreaterEqThanOp,
- Src: "m.GoVersion().GreaterEqThan(\"1.21\")",
- Value: "1.21",
- },
- },
- {
- Line: 785,
- SyntaxPatterns: []ir.PatternString{{Line: 785, Value: "sync.OnceFunc($x)()"}},
- ReportTemplate: "possible sync.OnceFunc misuse, consider to assign sync.OnceFunc($x) to a variable",
- WhereExpr: ir.FilterExpr{
- Line: 787,
- Op: ir.FilterGoVersionGreaterEqThanOp,
- Src: "m.GoVersion().GreaterEqThan(\"1.21\")",
- Value: "1.21",
- },
- },
- },
- },
- },
-}
-
diff --git a/vendor/github.com/go-critic/go-critic/checkers/singleCaseSwitch_checker.go b/vendor/github.com/go-critic/go-critic/checkers/singleCaseSwitch_checker.go
deleted file mode 100644
index a1a399fda..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/singleCaseSwitch_checker.go
+++ /dev/null
@@ -1,85 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "golang.org/x/tools/go/ast/astutil"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "singleCaseSwitch"
- info.Tags = []string{linter.StyleTag}
- info.Summary = "Detects switch statements that could be better written as if statement"
- info.Before = `
-switch x := x.(type) {
-case int:
- body()
-}`
- info.After = `
-if x, ok := x.(int); ok {
- body()
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&singleCaseSwitchChecker{ctx: ctx}), nil
- })
-}
-
-type singleCaseSwitchChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *singleCaseSwitchChecker) VisitStmt(stmt ast.Stmt) {
- switch stmt := stmt.(type) {
- case *ast.SwitchStmt:
- c.checkSwitchStmt(stmt, stmt.Body)
- case *ast.TypeSwitchStmt:
- c.checkSwitchStmt(stmt, stmt.Body)
- }
-}
-
-func (c *singleCaseSwitchChecker) checkSwitchStmt(stmt ast.Stmt, body *ast.BlockStmt) {
- if len(body.List) != 1 {
- return
- }
- cc := body.List[0].(*ast.CaseClause)
- if c.hasBreak(cc) {
- return
- }
- switch {
- case cc.List == nil:
- c.warnDefault(stmt)
- case len(cc.List) == 1:
- c.warn(stmt)
- }
-}
-
-func (c *singleCaseSwitchChecker) hasBreak(stmt ast.Stmt) bool {
- found := false
- astutil.Apply(stmt, func(cur *astutil.Cursor) bool {
- switch n := cur.Node().(type) {
- case *ast.BranchStmt:
- if n.Tok == token.BREAK {
- found = true
- }
- case *ast.ForStmt, *ast.RangeStmt, *ast.SelectStmt, *ast.SwitchStmt:
- return false
- }
- return true
- }, nil)
- return found
-}
-
-func (c *singleCaseSwitchChecker) warn(stmt ast.Stmt) {
- c.ctx.Warn(stmt, "should rewrite switch statement to if statement")
-}
-
-func (c *singleCaseSwitchChecker) warnDefault(stmt ast.Stmt) {
- c.ctx.Warn(stmt, "found switch with default case only")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/sloppyReassign_checker.go b/vendor/github.com/go-critic/go-critic/checkers/sloppyReassign_checker.go
deleted file mode 100644
index d83d7fd5a..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/sloppyReassign_checker.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "github.com/go-toolsmith/astcopy"
- "github.com/go-toolsmith/astequal"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "sloppyReassign"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects suspicious/confusing re-assignments"
- info.Before = `if err = f(); err != nil { return err }`
- info.After = `if err := f(); err != nil { return err }`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&sloppyReassignChecker{ctx: ctx}), nil
- })
-}
-
-type sloppyReassignChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *sloppyReassignChecker) VisitStmt(stmt ast.Stmt) {
- // Right now only check assignments in if statements init.
- ifStmt := astcast.ToIfStmt(stmt)
- assign := astcast.ToAssignStmt(ifStmt.Init)
- if assign.Tok != token.ASSIGN {
- return
- }
-
- // TODO(quasilyte): is handling of multi-value assignments worthwhile?
- if len(assign.Lhs) != 1 || len(assign.Rhs) != 1 {
- return
- }
-
- // TODO(quasilyte): handle not only the simplest, return-only case.
- body := ifStmt.Body.List
- if len(body) != 1 {
- return
- }
-
- // Variable that is being re-assigned.
- reAssigned := astcast.ToIdent(assign.Lhs[0])
- if reAssigned.Name == "" {
- return
- }
-
- // TODO(quasilyte): handle not only nil comparisons.
- eqToNil := &ast.BinaryExpr{
- Op: token.NEQ,
- X: reAssigned,
- Y: &ast.Ident{Name: "nil"},
- }
- if !astequal.Expr(ifStmt.Cond, eqToNil) {
- return
- }
-
- results := astcast.ToReturnStmt(body[0]).Results
- for _, res := range results {
- if astequal.Expr(reAssigned, res) {
- c.warnAssignToDefine(assign, reAssigned.Name)
- break
- }
- }
-}
-
-func (c *sloppyReassignChecker) warnAssignToDefine(assign *ast.AssignStmt, name string) {
- suggest := astcopy.AssignStmt(assign)
- suggest.Tok = token.DEFINE
- c.ctx.Warn(assign, "re-assignment to `%s` can be replaced with `%s`", name, suggest)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/sloppyTypeAssert_checker.go b/vendor/github.com/go-critic/go-critic/checkers/sloppyTypeAssert_checker.go
deleted file mode 100644
index 454ab78b1..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/sloppyTypeAssert_checker.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "sloppyTypeAssert"
- info.Tags = []string{linter.DiagnosticTag}
- info.Summary = "Detects redundant type assertions"
- info.Before = `
-func f(r io.Reader) interface{} {
- return r.(interface{})
-}
-`
- info.After = `
-func f(r io.Reader) interface{} {
- return r
-}
-`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForExpr(&sloppyTypeAssertChecker{ctx: ctx}), nil
- })
-}
-
-type sloppyTypeAssertChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *sloppyTypeAssertChecker) VisitExpr(expr ast.Expr) {
- assert := astcast.ToTypeAssertExpr(expr)
- if assert.Type == nil {
- return
- }
-
- toType := c.ctx.TypeOf(expr)
- fromType := c.ctx.TypeOf(assert.X)
-
- if types.Identical(toType, fromType) {
- c.warnIdentical(expr)
- return
- }
-}
-
-func (c *sloppyTypeAssertChecker) warnIdentical(cause ast.Expr) {
- c.ctx.Warn(cause, "type assertion from/to types are identical")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/sortSlice_checker.go b/vendor/github.com/go-critic/go-critic/checkers/sortSlice_checker.go
deleted file mode 100644
index 22ef3b16a..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/sortSlice_checker.go
+++ /dev/null
@@ -1,136 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/checkers/internal/lintutil"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "github.com/go-toolsmith/astequal"
- "github.com/go-toolsmith/typep"
- "golang.org/x/tools/go/ast/astutil"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "sortSlice"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects suspicious sort.Slice calls"
- info.Before = `sort.Slice(xs, func(i, j) bool { return keys[i] < keys[j] })`
- info.After = `sort.Slice(kv, func(i, j) bool { return kv[i].key < kv[j].key })`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForExpr(&sortSliceChecker{ctx: ctx}), nil
- })
-}
-
-type sortSliceChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *sortSliceChecker) VisitExpr(expr ast.Expr) {
- call := astcast.ToCallExpr(expr)
- if len(call.Args) != 2 {
- return
- }
- switch qualifiedName(call.Fun) {
- case "sort.Slice", "sort.SliceStable":
- // OK.
- default:
- return
- }
-
- slice := c.unwrapSlice(call.Args[0])
- lessFunc, ok := call.Args[1].(*ast.FuncLit)
- if !ok {
- return
- }
- if !typep.SideEffectFree(c.ctx.TypesInfo, slice) {
- return // Don't check unpredictable slice values
- }
-
- ivar, jvar := c.paramIdents(lessFunc.Type)
- if ivar == nil || jvar == nil {
- return
- }
-
- if len(lessFunc.Body.List) != 1 {
- return
- }
- ret, ok := lessFunc.Body.List[0].(*ast.ReturnStmt)
- if !ok {
- return
- }
- cmp := astcast.ToBinaryExpr(astutil.Unparen(ret.Results[0]))
- if !typep.SideEffectFree(c.ctx.TypesInfo, cmp) {
- return
- }
- switch cmp.Op {
- case token.LSS, token.LEQ, token.GTR, token.GEQ:
- // Both cmp.X and cmp.Y are expected to be some expressions
- // over the `slice` expression. In the simplest case,
- // it's a `slice[i] <op> slice[j]`.
- if !c.containsSlice(cmp.X, slice) && !c.containsSlice(cmp.Y, slice) {
- c.warnSlice(cmp, slice)
- }
-
- // This one is more about the style, but can reveal potential issue
- // or misprint in sorting condition.
- // We give a warn if X contains indexing with `i` index and Y
- // contains indexing with `j`.
- if c.containsIndex(cmp.X, jvar) && c.containsIndex(cmp.Y, ivar) {
- c.warnIndex(cmp, ivar, jvar)
- }
- }
-}
-
-func (c *sortSliceChecker) paramIdents(e *ast.FuncType) (ivar, jvar *ast.Ident) {
- // Covers both `i, j int` and `i int, j int`.
- idents := make([]*ast.Ident, 0, 2)
- for _, field := range e.Params.List {
- idents = append(idents, field.Names...)
- }
- if len(idents) == 2 {
- return idents[0], idents[1]
- }
- return nil, nil
-}
-
-func (c *sortSliceChecker) unwrapSlice(e ast.Expr) ast.Expr {
- switch e := e.(type) {
- case *ast.ParenExpr:
- return c.unwrapSlice(e.X)
- case *ast.SliceExpr:
- return e.X
- default:
- return e
- }
-}
-
-func (c *sortSliceChecker) containsIndex(e, index ast.Expr) bool {
- return lintutil.ContainsNode(e, func(n ast.Node) bool {
- indexing, ok := n.(*ast.IndexExpr)
- if !ok {
- return false
- }
- return astequal.Expr(indexing.Index, index)
- })
-}
-
-func (c *sortSliceChecker) containsSlice(e, slice ast.Expr) bool {
- return lintutil.ContainsNode(e, func(n ast.Node) bool {
- return astequal.Node(n, slice)
- })
-}
-
-func (c *sortSliceChecker) warnSlice(cause ast.Node, slice ast.Expr) {
- c.ctx.Warn(cause, "cmp func must use %s slice in comparison", slice)
-}
-
-func (c *sortSliceChecker) warnIndex(cause ast.Node, ivar, jvar *ast.Ident) {
- c.ctx.Warn(cause, "unusual order of {%s,%s} params in comparison", ivar, jvar)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/sqlQuery_checker.go b/vendor/github.com/go-critic/go-critic/checkers/sqlQuery_checker.go
deleted file mode 100644
index 8a132b586..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/sqlQuery_checker.go
+++ /dev/null
@@ -1,168 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "sqlQuery"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects issue in Query() and Exec() calls"
- info.Before = `_, err := db.Query("UPDATE ...")`
- info.After = `_, err := db.Exec("UPDATE ...")`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&sqlQueryChecker{ctx: ctx}), nil
- })
-}
-
-type sqlQueryChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *sqlQueryChecker) VisitStmt(stmt ast.Stmt) {
- assign := astcast.ToAssignStmt(stmt)
- if len(assign.Lhs) != 2 { // Query() has 2 return values.
- return
- }
- if len(assign.Rhs) != 1 {
- return
- }
-
- // If Query() is called, but first return value is ignored,
- // there is no way to close/read the returned rows.
- // This can cause a connection leak.
- if id, ok := assign.Lhs[0].(*ast.Ident); ok && id.Name != "_" {
- return
- }
-
- call := astcast.ToCallExpr(assign.Rhs[0])
- funcExpr := astcast.ToSelectorExpr(call.Fun)
- if !c.funcIsQuery(funcExpr) {
- return
- }
-
- if c.typeHasExecMethod(c.ctx.TypeOf(funcExpr.X)) {
- c.warnAndSuggestExec(funcExpr)
- } else {
- c.warnRowsIgnored(funcExpr)
- }
-}
-
-func (c *sqlQueryChecker) funcIsQuery(funcExpr *ast.SelectorExpr) bool {
- if funcExpr.Sel == nil {
- return false
- }
- switch funcExpr.Sel.Name {
- case "Query", "QueryContext":
- // Stdlib and friends.
- case "Queryx", "QueryxContext":
- // sqlx.
- default:
- return false
- }
-
- // To avoid false positives (unrelated types can have Query method)
- // check that the 1st returned type has Row-like name.
- typ, ok := c.ctx.TypeOf(funcExpr).Underlying().(*types.Signature)
- if !ok || typ.Results() == nil || typ.Results().Len() != 2 {
- return false
- }
- if !c.typeIsRowsLike(typ.Results().At(0).Type()) {
- return false
- }
-
- return true
-}
-
-func (c *sqlQueryChecker) typeIsRowsLike(typ types.Type) bool {
- switch typ := typ.(type) {
- case *types.Pointer:
- return c.typeIsRowsLike(typ.Elem())
- case *types.Named:
- return typ.Obj().Name() == "Rows"
- default:
- return false
- }
-}
-
-func (c *sqlQueryChecker) funcIsExec(fn *types.Func) bool {
- if fn.Name() != "Exec" {
- return false
- }
-
- // Expect exactly 2 results.
- sig := fn.Type().(*types.Signature)
- if sig.Results() == nil || sig.Results().Len() != 2 {
- return false
- }
-
- // Expect at least 1 param and it should be a string (query).
- params := sig.Params()
- if params == nil || params.Len() == 0 {
- return false
- }
- if typ, ok := params.At(0).Type().(*types.Basic); !ok || typ.Kind() != types.String {
- return false
- }
-
- return true
-}
-
-func (c *sqlQueryChecker) typeHasExecMethod(typ types.Type) bool {
- switch typ := typ.(type) {
- case *types.Struct:
- for i := 0; i < typ.NumFields(); i++ {
- if c.typeHasExecMethod(typ.Field(i).Type()) {
- return true
- }
- }
- case *types.Interface:
- for i := 0; i < typ.NumMethods(); i++ {
- if c.funcIsExec(typ.Method(i)) {
- return true
- }
- }
- case *types.Pointer:
- return c.typeHasExecMethod(typ.Elem())
- case *types.Named:
- for i := 0; i < typ.NumMethods(); i++ {
- if c.funcIsExec(typ.Method(i)) {
- return true
- }
- }
- switch ut := typ.Underlying().(type) {
- case *types.Interface:
- return c.typeHasExecMethod(ut)
- case *types.Struct:
- // Check embedded types.
- for i := 0; i < ut.NumFields(); i++ {
- field := ut.Field(i)
- if !field.Embedded() {
- continue
- }
- if c.typeHasExecMethod(field.Type()) {
- return true
- }
- }
- }
- }
-
- return false
-}
-
-func (c *sqlQueryChecker) warnAndSuggestExec(funcExpr *ast.SelectorExpr) {
- c.ctx.Warn(funcExpr, "use %s.Exec() if returned result is not needed", funcExpr.X)
-}
-
-func (c *sqlQueryChecker) warnRowsIgnored(funcExpr *ast.SelectorExpr) {
- c.ctx.Warn(funcExpr, "ignoring Query() rows result may lead to a connection leak")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/todoCommentWithoutDetail_checker.go b/vendor/github.com/go-critic/go-critic/checkers/todoCommentWithoutDetail_checker.go
deleted file mode 100644
index f8e4b9b3c..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/todoCommentWithoutDetail_checker.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "regexp"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "todoCommentWithoutDetail"
- info.Tags = []string{linter.StyleTag, linter.OpinionatedTag, linter.ExperimentalTag}
- info.Summary = "Detects TODO comments without detail/assignee"
- info.Before = `
-// TODO
-fiiWithCtx(nil, a, b)
-`
- info.After = `
-// TODO(admin): pass context.TODO() instead of nil
-fiiWithCtx(nil, a, b)
-`
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- visitor := &todoCommentWithoutCodeChecker{
- ctx: ctx,
- regex: regexp.MustCompile(`^(//|/\*)?\s*(TODO|FIX|FIXME|BUG)\s*(\*/)?$`),
- }
- return astwalk.WalkerForComment(visitor), nil
- })
-}
-
-type todoCommentWithoutCodeChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
- regex *regexp.Regexp
-}
-
-func (c *todoCommentWithoutCodeChecker) VisitComment(cg *ast.CommentGroup) {
- for _, comment := range cg.List {
- if c.regex.MatchString(comment.Text) {
- c.warn(cg)
- break
- }
- }
-}
-
-func (c *todoCommentWithoutCodeChecker) warn(cause ast.Node) {
- c.ctx.Warn(cause, "may want to add detail/assignee to this TODO/FIXME/BUG comment")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/tooManyResults_checker.go b/vendor/github.com/go-critic/go-critic/checkers/tooManyResults_checker.go
deleted file mode 100644
index 57411ba24..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/tooManyResults_checker.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "tooManyResultsChecker"
- info.Tags = []string{linter.StyleTag, linter.OpinionatedTag, linter.ExperimentalTag}
- info.Params = linter.CheckerParams{
- "maxResults": {
- Value: 5,
- Usage: "maximum number of results",
- },
- }
- info.Summary = "Detects function with too many results"
- info.Before = `func fn() (a, b, c, d float32, _ int, _ bool)`
- info.After = `func fn() (resultStruct, bool)`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- c := astwalk.WalkerForFuncDecl(&tooManyResultsChecker{
- ctx: ctx,
- maxParams: info.Params.Int("maxResults"),
- })
- return c, nil
- })
-}
-
-type tooManyResultsChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
- maxParams int
-}
-
-func (c *tooManyResultsChecker) VisitFuncDecl(decl *ast.FuncDecl) {
- typ := c.ctx.TypeOf(decl.Name)
- sig, ok := typ.(*types.Signature)
- if !ok {
- return
- }
-
- if count := sig.Results().Len(); count > c.maxParams {
- c.warn(decl)
- }
-}
-
-func (c *tooManyResultsChecker) warn(n ast.Node) {
- c.ctx.Warn(n, "function has more than %d results, consider to simplify the function", c.maxParams)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/truncateCmp_checker.go b/vendor/github.com/go-critic/go-critic/checkers/truncateCmp_checker.go
deleted file mode 100644
index b36902526..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/truncateCmp_checker.go
+++ /dev/null
@@ -1,124 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "github.com/go-toolsmith/astp"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "truncateCmp"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Params = linter.CheckerParams{
- "skipArchDependent": {
- Value: true,
- Usage: "whether to skip int/uint/uintptr types",
- },
- }
- info.Summary = "Detects potential truncation issues when comparing ints of different sizes"
- info.Before = `
-func f(x int32, y int16) bool {
- return int16(x) < y
-}`
- info.After = `
-func f(x int32, int16) bool {
- return x < int32(y)
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- c := &truncateCmpChecker{ctx: ctx}
- c.skipArchDependent = info.Params.Bool("skipArchDependent")
- return astwalk.WalkerForExpr(c), nil
- })
-}
-
-type truncateCmpChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- skipArchDependent bool
-}
-
-func (c *truncateCmpChecker) VisitExpr(expr ast.Expr) {
- cmp := astcast.ToBinaryExpr(expr)
- switch cmp.Op {
- case token.LSS, token.GTR, token.LEQ, token.GEQ, token.EQL, token.NEQ:
- if astp.IsBasicLit(cmp.X) || astp.IsBasicLit(cmp.Y) {
- return // Don't bother about untyped consts
- }
- leftCast := c.isTruncCast(cmp.X)
- rightCast := c.isTruncCast(cmp.Y)
- switch {
- case leftCast && rightCast:
- return
- case leftCast:
- c.checkCmp(cmp.X, cmp.Y)
- case rightCast:
- c.checkCmp(cmp.Y, cmp.X)
- }
- default:
- return
- }
-}
-
-func (c *truncateCmpChecker) isTruncCast(x ast.Expr) bool {
- switch astcast.ToIdent(astcast.ToCallExpr(x).Fun).Name {
- case "int8", "int16", "int32", "uint8", "uint16", "uint32":
- return true
- default:
- return false
- }
-}
-
-func (c *truncateCmpChecker) checkCmp(cmpX, cmpY ast.Expr) {
- // Check if we have a cast to a type that can truncate.
- xcast := astcast.ToCallExpr(cmpX)
- if len(xcast.Args) != 1 {
- return // Just in case of the shadowed builtin
- }
-
- x := xcast.Args[0]
- y := cmpY
-
- // Check that both x and y are signed or unsigned int-typed.
- xtyp, ok := c.ctx.TypeOf(x).Underlying().(*types.Basic)
- if !ok || xtyp.Info()&types.IsInteger == 0 {
- return
- }
- ytyp, ok := c.ctx.TypeOf(y).Underlying().(*types.Basic)
- if !ok || xtyp.Info() != ytyp.Info() {
- return
- }
-
- xsize, ok := c.ctx.SizeOf(xtyp)
- if !ok {
- return
- }
- ysize, ok := c.ctx.SizeOf(ytyp)
- if !ok {
- return
- }
- if xsize <= ysize {
- return
- }
-
- if c.skipArchDependent {
- switch xtyp.Kind() {
- case types.Int, types.Uint, types.Uintptr:
- return
- }
- }
-
- c.warn(xcast, xsize*8, ysize*8, xtyp.String())
-}
-
-func (c *truncateCmpChecker) warn(cause ast.Expr, xsize, ysize int64, suggest string) {
- c.ctx.Warn(cause, "truncation in comparison %d->%d bit; cast the other operand to %s instead", xsize, ysize, suggest)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/typeAssertChain_checker.go b/vendor/github.com/go-critic/go-critic/checkers/typeAssertChain_checker.go
deleted file mode 100644
index e0d20fd4c..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/typeAssertChain_checker.go
+++ /dev/null
@@ -1,133 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/checkers/internal/lintutil"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "github.com/go-toolsmith/astequal"
- "github.com/go-toolsmith/astp"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "typeAssertChain"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag}
- info.Summary = "Detects repeated type assertions and suggests to replace them with type switch statement"
- info.Before = `
-if x, ok := v.(T1); ok {
- // Code A, uses x.
-} else if x, ok := v.(T2); ok {
- // Code B, uses x.
-} else if x, ok := v.(T3); ok {
- // Code C, uses x.
-}`
- info.After = `
-switch x := v.(T1) {
-case cond1:
- // Code A, uses x.
-case cond2:
- // Code B, uses x.
-default:
- // Code C, uses x.
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&typeAssertChainChecker{ctx: ctx}), nil
- })
-}
-
-type typeAssertChainChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- cause *ast.IfStmt
- visited map[*ast.IfStmt]bool
- typeSet lintutil.AstSet
-}
-
-func (c *typeAssertChainChecker) EnterFunc(fn *ast.FuncDecl) bool {
- if fn.Body == nil {
- return false
- }
- c.visited = make(map[*ast.IfStmt]bool)
- return true
-}
-
-func (c *typeAssertChainChecker) VisitStmt(stmt ast.Stmt) {
- ifstmt, ok := stmt.(*ast.IfStmt)
- if !ok || c.visited[ifstmt] || ifstmt.Init == nil {
- return
- }
- assertion := c.getTypeAssert(ifstmt)
- if assertion == nil {
- return
- }
- c.cause = ifstmt
- c.checkIfStmt(ifstmt, assertion)
-}
-
-func (c *typeAssertChainChecker) getTypeAssert(ifstmt *ast.IfStmt) *ast.TypeAssertExpr {
- assign := astcast.ToAssignStmt(ifstmt.Init)
- if len(assign.Lhs) != 2 || len(assign.Rhs) != 1 {
- return nil
- }
- if !astp.IsIdent(assign.Lhs[0]) || assign.Tok != token.DEFINE {
- return nil
- }
- if !astequal.Expr(assign.Lhs[1], ifstmt.Cond) {
- return nil
- }
-
- assertion, ok := assign.Rhs[0].(*ast.TypeAssertExpr)
- if !ok {
- return nil
- }
- return assertion
-}
-
-func (c *typeAssertChainChecker) checkIfStmt(stmt *ast.IfStmt, assertion *ast.TypeAssertExpr) {
- if c.countTypeAssertions(stmt, assertion) >= 2 {
- c.warn()
- }
-}
-
-func (c *typeAssertChainChecker) countTypeAssertions(stmt *ast.IfStmt, assertion *ast.TypeAssertExpr) int {
- c.typeSet.Clear()
-
- count := 1
- x := assertion.X
- c.typeSet.Insert(assertion.Type)
- for {
- e, ok := stmt.Else.(*ast.IfStmt)
- if !ok {
- return count
- }
- assertion = c.getTypeAssert(e)
- if assertion == nil {
- return count
- }
- if !c.typeSet.Insert(assertion.Type) {
- // Asserted type is duplicated.
- // Type switch does not permit duplicate cases,
- // so give up.
- return 0
- }
- if !astequal.Expr(x, assertion.X) {
- // Mixed type asserting chain.
- // Can't be easily translated to a type switch.
- return 0
- }
- stmt = e
- count++
- c.visited[e] = true
- }
-}
-
-func (c *typeAssertChainChecker) warn() {
- c.ctx.Warn(c.cause, "rewrite if-else to type switch statement")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/typeDefFirst_checker.go b/vendor/github.com/go-critic/go-critic/checkers/typeDefFirst_checker.go
deleted file mode 100644
index 11381c401..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/typeDefFirst_checker.go
+++ /dev/null
@@ -1,92 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "typeDefFirst"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag}
- info.Summary = "Detects method declarations preceding the type definition itself"
- info.Before = `
-func (r rec) Method() {}
-type rec struct{}
-`
- info.After = `
-type rec struct{}
-func (r rec) Method() {}
-`
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return &typeDefFirstChecker{
- ctx: ctx,
- }, nil
- })
-}
-
-type typeDefFirstChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
- trackedTypes map[string]bool
-}
-
-func (c *typeDefFirstChecker) WalkFile(f *ast.File) {
- if len(f.Decls) == 0 {
- return
- }
-
- c.trackedTypes = make(map[string]bool)
- for _, decl := range f.Decls {
- c.walkDecl(decl)
- }
-}
-
-func (c *typeDefFirstChecker) walkDecl(decl ast.Decl) {
- switch decl := decl.(type) {
- case *ast.FuncDecl:
- if decl.Recv == nil {
- return
- }
- receiver := decl.Recv.List[0]
- typeName := c.receiverType(receiver.Type)
- c.trackedTypes[typeName] = true
-
- case *ast.GenDecl:
- if decl.Tok != token.TYPE {
- return
- }
- for _, spec := range decl.Specs {
- spec, ok := spec.(*ast.TypeSpec)
- if !ok {
- return
- }
- typeName := spec.Name.Name
- if val, ok := c.trackedTypes[typeName]; ok && val {
- c.warn(decl, typeName)
- }
- }
- }
-}
-
-func (c *typeDefFirstChecker) receiverType(e ast.Expr) string {
- switch e := e.(type) {
- case *ast.StarExpr:
- return c.receiverType(e.X)
- case *ast.Ident:
- return e.Name
- case *ast.IndexExpr:
- return c.receiverType(e.X)
- case *ast.IndexListExpr:
- return c.receiverType(e.X)
- default:
- panic("unreachable")
- }
-}
-
-func (c *typeDefFirstChecker) warn(cause ast.Node, typeName string) {
- c.ctx.Warn(cause, "definition of type '%s' should appear before its methods", typeName)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/typeSwitchVar_checker.go b/vendor/github.com/go-critic/go-critic/checkers/typeSwitchVar_checker.go
deleted file mode 100644
index 4b27b1792..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/typeSwitchVar_checker.go
+++ /dev/null
@@ -1,98 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/checkers/internal/lintutil"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astequal"
- "github.com/go-toolsmith/astp"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "typeSwitchVar"
- info.Tags = []string{linter.StyleTag}
- info.Summary = "Detects type switches that can benefit from type guard clause with variable"
- info.Before = `
-switch v.(type) {
-case int:
- return v.(int)
-case point:
- return v.(point).x + v.(point).y
-default:
- return 0
-}`
- info.After = `
-switch v := v.(type) {
-case int:
- return v
-case point:
- return v.x + v.y
-default:
- return 0
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&typeSwitchVarChecker{ctx: ctx}), nil
- })
-}
-
-type typeSwitchVarChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
- count int
-}
-
-func (c *typeSwitchVarChecker) VisitStmt(stmt ast.Stmt) {
- if stmt, ok := stmt.(*ast.TypeSwitchStmt); ok {
- c.count = 0
- c.checkTypeSwitch(stmt)
- }
-}
-
-func (c *typeSwitchVarChecker) checkTypeSwitch(root *ast.TypeSwitchStmt) {
- if astp.IsAssignStmt(root.Assign) {
- return // Already with type guard
- }
- // Must be a *ast.ExprStmt then.
- expr := root.Assign.(*ast.ExprStmt).X.(*ast.TypeAssertExpr).X
- object := c.ctx.TypesInfo.ObjectOf(identOf(expr))
- if object == nil {
- return // Give up: can't handle shadowing without object
- }
-
- for _, clause := range root.Body.List {
- clause := clause.(*ast.CaseClause)
- // Multiple types in a list mean that assert.X will have
- // a type of interface{} inside clause body.
- // We are looking for precise type case.
- if len(clause.List) != 1 {
- continue
- }
- // Create artificial node just for matching.
- assert1 := ast.TypeAssertExpr{X: expr, Type: clause.List[0]}
- for _, stmt := range clause.Body {
- assert2 := lintutil.FindNode(stmt, nil, func(x ast.Node) bool {
- return astequal.Node(&assert1, x)
- })
- if object == c.ctx.TypesInfo.ObjectOf(identOf(assert2)) {
- c.count++
- break
- }
- }
- }
- if c.count > 0 {
- c.warn(root)
- }
-}
-
-func (c *typeSwitchVarChecker) warn(n ast.Node) {
- msg := "case"
- if c.count > 1 {
- msg = "cases"
- }
- c.ctx.Warn(n, "%d "+msg+" can benefit from type switch with assignment", c.count)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/typeUnparen_checker.go b/vendor/github.com/go-critic/go-critic/checkers/typeUnparen_checker.go
deleted file mode 100644
index e2e225ebf..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/typeUnparen_checker.go
+++ /dev/null
@@ -1,96 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcopy"
- "github.com/go-toolsmith/astequal"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "typeUnparen"
- info.Tags = []string{linter.StyleTag, linter.OpinionatedTag}
- info.Summary = "Detects unneeded parenthesis inside type expressions and suggests to remove them"
- info.Before = `type foo [](func([](func())))`
- info.After = `type foo []func([]func())`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForTypeExpr(&typeUnparenChecker{ctx: ctx}, ctx.TypesInfo), nil
- })
-}
-
-type typeUnparenChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *typeUnparenChecker) VisitTypeExpr(e ast.Expr) {
- switch e := e.(type) {
- case *ast.ParenExpr:
- switch e.X.(type) {
- case *ast.StructType:
- c.ctx.Warn(e, "could simplify (struct{...}) to struct{...}")
- case *ast.InterfaceType:
- c.ctx.Warn(e, "could simplify (interface{...}) to interface{...}")
- default:
- c.checkType(e)
- }
- case *ast.StructType, *ast.InterfaceType:
- // Only nested fields are to be reported.
- default:
- c.checkType(e)
- }
-}
-
-func (c *typeUnparenChecker) checkType(e ast.Expr) {
- noParens := c.removeRedundantParens(astcopy.Expr(e))
- if !astequal.Expr(e, noParens) {
- c.warn(e, noParens)
- }
- c.SkipChilds = true
-}
-
-func (c *typeUnparenChecker) removeRedundantParens(e ast.Expr) ast.Expr {
- switch e := e.(type) {
- case *ast.ParenExpr:
- return c.removeRedundantParens(e.X)
- case *ast.ArrayType:
- e.Elt = c.removeRedundantParens(e.Elt)
- case *ast.StarExpr:
- e.X = c.removeRedundantParens(e.X)
- case *ast.TypeAssertExpr:
- e.Type = c.removeRedundantParens(e.Type)
- case *ast.FuncType:
- for _, field := range e.Params.List {
- field.Type = c.removeRedundantParens(field.Type)
- }
- if e.Results != nil {
- for _, field := range e.Results.List {
- field.Type = c.removeRedundantParens(field.Type)
- }
- }
- case *ast.MapType:
- e.Key = c.removeRedundantParens(e.Key)
- e.Value = c.removeRedundantParens(e.Value)
- case *ast.ChanType:
- if valueWithParens, ok := e.Value.(*ast.ParenExpr); ok {
- if nestedChan, ok := valueWithParens.X.(*ast.ChanType); ok {
- const anyDir = ast.SEND | ast.RECV
- if nestedChan.Dir != anyDir || e.Dir != anyDir {
- valueWithParens.X = c.removeRedundantParens(valueWithParens.X)
- return e
- }
- }
- }
- e.Value = c.removeRedundantParens(e.Value)
- }
- return e
-}
-
-func (c *typeUnparenChecker) warn(cause, noParens ast.Expr) {
- c.ctx.Warn(cause, "could simplify %s to %s", cause, noParens)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/underef_checker.go b/vendor/github.com/go-critic/go-critic/checkers/underef_checker.go
deleted file mode 100644
index 0ce2c89ba..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/underef_checker.go
+++ /dev/null
@@ -1,128 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "github.com/go-toolsmith/astp"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "underef"
- info.Tags = []string{linter.StyleTag}
- info.Params = linter.CheckerParams{
- "skipRecvDeref": {
- Value: true,
- Usage: "whether to skip (*x).method() calls where x is a pointer receiver",
- },
- }
- info.Summary = "Detects dereference expressions that can be omitted"
- info.Before = `
-(*k).field = 5
-v := (*a)[5] // only if a is array`
- info.After = `
-k.field = 5
-v := a[5]`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- c := &underefChecker{ctx: ctx}
- c.skipRecvDeref = info.Params.Bool("skipRecvDeref")
- return astwalk.WalkerForExpr(c), nil
- })
-}
-
-type underefChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- skipRecvDeref bool
-}
-
-func (c *underefChecker) VisitExpr(expr ast.Expr) {
- switch n := expr.(type) {
- case *ast.SelectorExpr:
- expr := astcast.ToParenExpr(n.X)
- if c.skipRecvDeref && c.isPtrRecvMethodCall(n.Sel) {
- return
- }
-
- if expr, ok := expr.X.(*ast.StarExpr); ok {
- if c.checkStarExpr(expr) {
- c.warnSelect(n)
- }
- }
- case *ast.IndexExpr:
- expr := astcast.ToParenExpr(n.X)
- if expr, ok := expr.X.(*ast.StarExpr); ok {
- if !c.checkStarExpr(expr) {
- return
- }
- if c.checkArray(expr) {
- c.warnArray(n)
- }
- }
- }
-}
-
-func (c *underefChecker) isPtrRecvMethodCall(fn *ast.Ident) bool {
- typ, ok := c.ctx.TypeOf(fn).(*types.Signature)
- if ok && typ != nil && typ.Recv() != nil {
- _, ok := typ.Recv().Type().(*types.Pointer)
- return ok
- }
- return false
-}
-
-func (c *underefChecker) underef(x *ast.ParenExpr) ast.Expr {
- // If there is only 1 deref, can remove parenthesis,
- // otherwise can remove StarExpr only.
- dereferenced := x.X.(*ast.StarExpr).X
- if astp.IsStarExpr(dereferenced) {
- return &ast.ParenExpr{X: dereferenced}
- }
- return dereferenced
-}
-
-func (c *underefChecker) warnSelect(expr *ast.SelectorExpr) {
- // TODO: add () to function output.
- c.ctx.Warn(expr, "could simplify %s to %s.%s",
- expr,
- c.underef(expr.X.(*ast.ParenExpr)),
- expr.Sel.Name)
-}
-
-func (c *underefChecker) warnArray(expr *ast.IndexExpr) {
- c.ctx.Warn(expr, "could simplify %s to %s[%s]",
- expr,
- c.underef(expr.X.(*ast.ParenExpr)),
- expr.Index)
-}
-
-// checkStarExpr checks if ast.StarExpr could be simplified.
-func (c *underefChecker) checkStarExpr(expr *ast.StarExpr) bool {
- typ, ok := c.ctx.TypeOf(expr.X).Underlying().(*types.Pointer)
- if !ok {
- return false
- }
-
- switch typ.Elem().Underlying().(type) {
- case *types.Pointer, *types.Interface:
- return false
- default:
- return true
- }
-}
-
-func (c *underefChecker) checkArray(expr *ast.StarExpr) bool {
- typ, ok := c.ctx.TypeOf(expr.X).(*types.Pointer)
- if !ok {
- return false
- }
- _, ok = typ.Elem().(*types.Array)
- return ok
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/unlabelStmt_checker.go b/vendor/github.com/go-critic/go-critic/checkers/unlabelStmt_checker.go
deleted file mode 100644
index d0e83f3c2..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/unlabelStmt_checker.go
+++ /dev/null
@@ -1,181 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/checkers/internal/lintutil"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "unlabelStmt"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag}
- info.Summary = "Detects redundant statement labels"
- info.Before = `
-derp:
-for x := range xs {
- if x == 0 {
- break derp
- }
-}`
- info.After = `
-for x := range xs {
- if x == 0 {
- break
- }
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmt(&unlabelStmtChecker{ctx: ctx}), nil
- })
-}
-
-type unlabelStmtChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *unlabelStmtChecker) EnterFunc(fn *ast.FuncDecl) bool {
- if fn.Body == nil {
- return false
- }
- // TODO(quasilyte): should not do additional traversal here.
- // For now, skip all functions that contain goto statement.
- return !lintutil.ContainsNode(fn.Body, func(n ast.Node) bool {
- br, ok := n.(*ast.BranchStmt)
- return ok && br.Tok == token.GOTO
- })
-}
-
-func (c *unlabelStmtChecker) VisitStmt(stmt ast.Stmt) {
- labeled, ok := stmt.(*ast.LabeledStmt)
- if !ok || !c.canBreakFrom(labeled.Stmt) {
- return
- }
-
- // We have a labeled statement from that have labeled continue/break.
- // This is an invariant, since unused label is a compile-time error
- // and we're currently skipping functions containing goto.
- //
- // Also note that Go labels are function-scoped and there
- // can be no re-definitions. This means that we don't
- // need to care about label shadowing or things like that.
- //
- // The task is to find cases where labeled branch (continue/break)
- // is redundant and can be re-written, decreasing the label usages
- // and potentially leading to its redundancy,
- // or finding the redundant labels right away.
-
- name := labeled.Label.Name
-
- // Simplest case that can prove that label is redundant.
- //
- // If labeled branch is somewhere inside the statement block itself
- // and none of the nested break'able statements refer to that label,
- // the label can be removed.
- matchUsage := func(n ast.Node) bool {
- return c.canBreakFrom(n) && c.usesLabel(c.blockStmtOf(n), name)
- }
- if !lintutil.ContainsNode(c.blockStmtOf(labeled.Stmt), matchUsage) {
- c.warnRedundant(labeled)
- return
- }
-
- // Only for loops: if last stmt in list is a loop
- // that contains labeled "continue" to the outer loop label,
- // it can be refactored to use "break" instead.
- // Exceptions: select statements with a labeled "continue" are ignored.
- if c.isLoop(labeled.Stmt) {
- body := c.blockStmtOf(labeled.Stmt)
- if len(body.List) == 0 {
- return
- }
- last := body.List[len(body.List)-1]
- if !c.isLoop(last) {
- return
- }
- br := lintutil.FindNode(c.blockStmtOf(last),
- func(n ast.Node) bool {
- switch n.(type) {
- case *ast.SelectStmt:
- return false
- default:
- return true
- }
- },
- func(n ast.Node) bool {
- br, ok := n.(*ast.BranchStmt)
- return ok && br.Label != nil &&
- br.Label.Name == name && br.Tok == token.CONTINUE
- })
-
- if br != nil {
- c.warnLabeledContinue(br, name)
- }
- }
-}
-
-// isLoop reports whether n is a loop of some kind.
-// In other words, it tells whether n body can contain "continue"
-// associated with n.
-func (c *unlabelStmtChecker) isLoop(n ast.Node) bool {
- switch n.(type) {
- case *ast.ForStmt, *ast.RangeStmt:
- return true
- default:
- return false
- }
-}
-
-// canBreakFrom reports whether it is possible to "break" or "continue" from n body.
-func (c *unlabelStmtChecker) canBreakFrom(n ast.Node) bool {
- switch n.(type) {
- case *ast.RangeStmt, *ast.ForStmt, *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt:
- return true
- default:
- return false
- }
-}
-
-// blockStmtOf returns body of specified node.
-//
-// TODO(quasilyte): handle other statements and see if it can be useful
-// in other checkers.
-func (c *unlabelStmtChecker) blockStmtOf(n ast.Node) *ast.BlockStmt {
- switch n := n.(type) {
- case *ast.RangeStmt:
- return n.Body
- case *ast.ForStmt:
- return n.Body
- case *ast.SwitchStmt:
- return n.Body
- case *ast.TypeSwitchStmt:
- return n.Body
- case *ast.SelectStmt:
- return n.Body
-
- default:
- return nil
- }
-}
-
-// usesLabel reports whether n contains a usage of label.
-func (c *unlabelStmtChecker) usesLabel(n *ast.BlockStmt, label string) bool {
- return lintutil.ContainsNode(n, func(n ast.Node) bool {
- branch, ok := n.(*ast.BranchStmt)
- return ok && branch.Label != nil &&
- branch.Label.Name == label &&
- (branch.Tok == token.CONTINUE || branch.Tok == token.BREAK)
- })
-}
-
-func (c *unlabelStmtChecker) warnRedundant(cause *ast.LabeledStmt) {
- c.ctx.Warn(cause, "label %s is redundant", cause.Label)
-}
-
-func (c *unlabelStmtChecker) warnLabeledContinue(cause ast.Node, label string) {
- c.ctx.Warn(cause, "change `continue %s` to `break`", label)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/unlambda_checker.go b/vendor/github.com/go-critic/go-critic/checkers/unlambda_checker.go
deleted file mode 100644
index 0401bf5d3..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/unlambda_checker.go
+++ /dev/null
@@ -1,118 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/checkers/internal/lintutil"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "github.com/go-toolsmith/astequal"
- "github.com/go-toolsmith/typep"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "unlambda"
- info.Tags = []string{linter.StyleTag}
- info.Summary = "Detects function literals that can be simplified"
- info.Before = `func(x int) int { return fn(x) }`
- info.After = `fn`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForExpr(&unlambdaChecker{ctx: ctx}), nil
- })
-}
-
-type unlambdaChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *unlambdaChecker) VisitExpr(x ast.Expr) {
- fn, ok := x.(*ast.FuncLit)
- if !ok || len(fn.Body.List) != 1 {
- return
- }
-
- ret, ok := fn.Body.List[0].(*ast.ReturnStmt)
- if !ok || len(ret.Results) != 1 {
- return
- }
-
- result := astcast.ToCallExpr(ret.Results[0])
- callable := qualifiedName(result.Fun)
- if callable == "" {
- return // Skip tricky cases; only handle simple calls
- }
- if isBuiltin(callable) {
- return // See #762
- }
- hasVars := lintutil.ContainsNode(result.Fun, func(n ast.Node) bool {
- id, ok := n.(*ast.Ident)
- if !ok {
- return false
- }
- obj, ok := c.ctx.TypesInfo.ObjectOf(id).(*types.Var)
- if !ok {
- return false
- }
- // Permit only non-pointer struct method values.
- return !typep.IsStruct(obj.Type().Underlying())
- })
- if hasVars {
- return // See #888 #1007
- }
-
- fnType := c.ctx.TypeOf(fn)
- resultType := c.ctx.TypeOf(result.Fun)
- if !types.Identical(fnType, resultType) {
- return
- }
- // Now check that all arguments match the parameters.
- n := 0
- for _, params := range fn.Type.Params.List {
- if _, ok := params.Type.(*ast.Ellipsis); ok {
- if result.Ellipsis == token.NoPos {
- return
- }
- n++
- continue
- }
-
- for _, id := range params.Names {
- if !astequal.Expr(id, result.Args[n]) {
- return
- }
- n++
- }
- }
-
- if c.lenArgs(result.Args) == n {
- c.warn(fn, callable)
- }
-}
-
-func (c *unlambdaChecker) warn(cause ast.Node, suggestion string) {
- c.ctx.Warn(cause, "replace `%s` with `%s`", cause, suggestion)
-}
-
-func (c *unlambdaChecker) lenArgs(args []ast.Expr) int {
- lenArgs := len(args)
-
- for _, arg := range args {
- callExp, ok := arg.(*ast.CallExpr)
- if !ok {
- continue
- }
-
- // Don't count function call. only args.
- lenArgs--
- lenArgs += c.lenArgs(callExp.Args)
- }
-
- return lenArgs
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/unnamedResult_checker.go b/vendor/github.com/go-critic/go-critic/checkers/unnamedResult_checker.go
deleted file mode 100644
index 0d40addf7..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/unnamedResult_checker.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/types"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "unnamedResult"
- info.Tags = []string{linter.StyleTag, linter.OpinionatedTag, linter.ExperimentalTag}
- info.Params = linter.CheckerParams{
- "checkExported": {
- Value: false,
- Usage: "whether to check exported functions",
- },
- }
- info.Summary = "Detects unnamed results that may benefit from names"
- info.Before = `func f() (float64, float64)`
- info.After = `func f() (x, y float64)`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- c := &unnamedResultChecker{ctx: ctx}
- c.checkExported = info.Params.Bool("checkExported")
- return astwalk.WalkerForFuncDecl(c), nil
- })
-}
-
-type unnamedResultChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-
- checkExported bool
-}
-
-func (c *unnamedResultChecker) VisitFuncDecl(decl *ast.FuncDecl) {
- if c.checkExported && !ast.IsExported(decl.Name.Name) {
- return
- }
- results := decl.Type.Results
- switch {
- case results == nil:
- return // Function has no results
- case len(results.List) != 0 && results.List[0].Names != nil:
- return // Skip named results
- }
-
- typeName := func(x ast.Expr) string { return c.typeName(c.ctx.TypeOf(x)) }
- isError := func(x ast.Expr) bool { return qualifiedName(x) == "error" }
- isBool := func(x ast.Expr) bool { return qualifiedName(x) == "bool" }
-
- // Main difference with case of len=2 is that we permit any
- // typ1 as long as second type is either error or bool.
- if results.NumFields() == 2 {
- typ1, typ2 := results.List[0].Type, results.List[1].Type
- name1, name2 := typeName(typ1), typeName(typ2)
- cond := (name1 != name2 && name2 != "") ||
- (!isError(typ1) && isError(typ2)) ||
- (!isBool(typ1) && isBool(typ2))
- if !cond {
- c.warn(decl)
- }
- return
- }
-
- seen := make(map[string]bool, len(results.List))
- for i := range results.List {
- typ := results.List[i].Type
- name := typeName(typ)
- isLast := i == len(results.List)-1
-
- cond := !seen[name] ||
- (isLast && (isError(typ) || isBool(typ)))
- if !cond {
- c.warn(decl)
- return
- }
-
- seen[name] = true
- }
-}
-
-func (c *unnamedResultChecker) typeName(typ types.Type) string {
- switch typ := typ.(type) {
- case *types.Array:
- return c.typeName(typ.Elem())
- case *types.Pointer:
- return c.typeName(typ.Elem())
- case *types.Slice:
- return c.typeName(typ.Elem())
- case *types.Named:
- return typ.Obj().Name()
- default:
- return ""
- }
-}
-
-func (c *unnamedResultChecker) warn(n ast.Node) {
- c.ctx.Warn(n, "consider giving a name to these results")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/unnecessaryBlock_checker.go b/vendor/github.com/go-critic/go-critic/checkers/unnecessaryBlock_checker.go
deleted file mode 100644
index b577ff421..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/unnecessaryBlock_checker.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astp"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "unnecessaryBlock"
- info.Tags = []string{linter.StyleTag, linter.OpinionatedTag, linter.ExperimentalTag}
- info.Summary = "Detects unnecessary braced statement blocks"
- info.Before = `
-x := 1
-{
- print(x)
-}`
- info.After = `
-x := 1
-print(x)`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForStmtList(&unnecessaryBlockChecker{ctx: ctx}), nil
- })
-}
-
-type unnecessaryBlockChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *unnecessaryBlockChecker) VisitStmtList(x ast.Node, statements []ast.Stmt) {
- // Using StmtListVisitor instead of StmtVisitor makes it easier to avoid
- // false positives on IfStmt, RangeStmt, ForStmt and alike.
- // We only inspect BlockStmt inside statement lists, so this method is not
- // called for IfStmt itself, for example.
-
- if (astp.IsCaseClause(x) || astp.IsCommClause(x)) && len(statements) == 1 {
- if _, ok := statements[0].(*ast.BlockStmt); ok {
- c.ctx.Warn(statements[0], "case statement doesn't require a block statement")
- return
- }
- }
-
- for _, stmt := range statements {
- stmt, ok := stmt.(*ast.BlockStmt)
- if ok && !c.hasDefinitions(stmt) {
- c.warn(stmt)
- }
- }
-}
-
-func (c *unnecessaryBlockChecker) hasDefinitions(stmt *ast.BlockStmt) bool {
- for _, bs := range stmt.List {
- switch stmt := bs.(type) {
- case *ast.AssignStmt:
- if stmt.Tok == token.DEFINE {
- return true
- }
- case *ast.DeclStmt:
- decl := stmt.Decl.(*ast.GenDecl)
- if len(decl.Specs) != 0 {
- return true
- }
- }
- }
-
- return false
-}
-
-func (c *unnecessaryBlockChecker) warn(expr ast.Stmt) {
- c.ctx.Warn(expr, "block doesn't have definitions, can be simply deleted")
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/unnecessaryDefer_checker.go b/vendor/github.com/go-critic/go-critic/checkers/unnecessaryDefer_checker.go
deleted file mode 100644
index 4c1ed41f6..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/unnecessaryDefer_checker.go
+++ /dev/null
@@ -1,112 +0,0 @@
-package checkers
-
-import (
- "go/ast"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astfmt"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "unnecessaryDefer"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects redundantly deferred calls"
- info.Before = `
-func() {
- defer os.Remove(filename)
-}`
- info.After = `
-func() {
- os.Remove(filename)
-}`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForFuncDecl(&unnecessaryDeferChecker{ctx: ctx}), nil
- })
-}
-
-type unnecessaryDeferChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
- isFunc bool
-}
-
-// Visit implements the ast.Visitor. This visitor keeps track of the block
-// statement belongs to a function or any other block. If the block is not a
-// function and ends with a defer statement that should be OK since it's
-// deferring the outer function.
-func (c *unnecessaryDeferChecker) Visit(node ast.Node) ast.Visitor {
- switch n := node.(type) {
- case *ast.FuncDecl, *ast.FuncLit:
- c.isFunc = true
- case *ast.BlockStmt:
- c.checkDeferBeforeReturn(n)
- default:
- c.isFunc = false
- }
-
- return c
-}
-
-func (c *unnecessaryDeferChecker) VisitFuncDecl(funcDecl *ast.FuncDecl) {
- // We always start as a function (*ast.FuncDecl.Body passed)
- c.isFunc = true
-
- ast.Walk(c, funcDecl.Body)
-}
-
-func (c *unnecessaryDeferChecker) checkDeferBeforeReturn(funcDecl *ast.BlockStmt) {
- // Check if we have an explicit return or if it's just the end of the scope.
- explicitReturn := false
- retIndex := len(funcDecl.List)
- for i, stmt := range funcDecl.List {
- retStmt, ok := stmt.(*ast.ReturnStmt)
- if !ok {
- continue
- }
- explicitReturn = true
- if !c.isTrivialReturn(retStmt) {
- continue
- }
- retIndex = i
- break
- }
- if retIndex == 0 {
- return
- }
-
- if deferStmt, ok := funcDecl.List[retIndex-1].(*ast.DeferStmt); ok {
- // If the block is a function and ending with return or if we have an
- // explicit return in any other block we should warn about
- // unnecessary defer.
- if c.isFunc || explicitReturn {
- c.warn(deferStmt)
- }
- }
-}
-
-func (c *unnecessaryDeferChecker) isTrivialReturn(ret *ast.ReturnStmt) bool {
- for _, e := range ret.Results {
- if !c.isConstExpr(e) {
- return false
- }
- }
- return true
-}
-
-func (c *unnecessaryDeferChecker) isConstExpr(e ast.Expr) bool {
- return c.ctx.TypesInfo.Types[e].Value != nil
-}
-
-func (c *unnecessaryDeferChecker) warn(deferStmt *ast.DeferStmt) {
- s := astfmt.Sprint(deferStmt)
- if fnlit, ok := deferStmt.Call.Fun.(*ast.FuncLit); ok {
- // To avoid long and multi-line warning messages,
- // collapse the function literals.
- s = "defer " + astfmt.Sprint(fnlit.Type) + "{...}(...)"
- }
- c.ctx.Warn(deferStmt, "%s is placed just before return", s)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/utils.go b/vendor/github.com/go-critic/go-critic/checkers/utils.go
deleted file mode 100644
index 6e12cf9b3..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/utils.go
+++ /dev/null
@@ -1,311 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/types"
- "strings"
-
- "github.com/go-critic/go-critic/linter"
-)
-
-// goStdlib contains `go list std` command output list.
-// Used to detect packages that belong to standard Go packages distribution.
-var goStdlib = map[string]bool{
- "archive/tar": true,
- "archive/zip": true,
- "bufio": true,
- "bytes": true,
- "compress/bzip2": true,
- "compress/flate": true,
- "compress/gzip": true,
- "compress/lzw": true,
- "compress/zlib": true,
- "container/heap": true,
- "container/list": true,
- "container/ring": true,
- "context": true,
- "crypto": true,
- "crypto/aes": true,
- "crypto/cipher": true,
- "crypto/des": true,
- "crypto/dsa": true,
- "crypto/ecdsa": true,
- "crypto/elliptic": true,
- "crypto/hmac": true,
- "crypto/internal/randutil": true,
- "crypto/internal/subtle": true,
- "crypto/md5": true,
- "crypto/rand": true,
- "crypto/rc4": true,
- "crypto/rsa": true,
- "crypto/sha1": true,
- "crypto/sha256": true,
- "crypto/sha512": true,
- "crypto/subtle": true,
- "crypto/tls": true,
- "crypto/x509": true,
- "crypto/x509/pkix": true,
- "database/sql": true,
- "database/sql/driver": true,
- "debug/dwarf": true,
- "debug/elf": true,
- "debug/gosym": true,
- "debug/macho": true,
- "debug/pe": true,
- "debug/plan9obj": true,
- "encoding": true,
- "encoding/ascii85": true,
- "encoding/asn1": true,
- "encoding/base32": true,
- "encoding/base64": true,
- "encoding/binary": true,
- "encoding/csv": true,
- "encoding/gob": true,
- "encoding/hex": true,
- "encoding/json": true,
- "encoding/pem": true,
- "encoding/xml": true,
- "errors": true,
- "expvar": true,
- "flag": true,
- "fmt": true,
- "go/ast": true,
- "go/build": true,
- "go/constant": true,
- "go/doc": true,
- "go/format": true,
- "go/importer": true,
- "go/internal/gccgoimporter": true,
- "go/internal/gcimporter": true,
- "go/internal/srcimporter": true,
- "go/parser": true,
- "go/printer": true,
- "go/scanner": true,
- "go/token": true,
- "go/types": true,
- "hash": true,
- "hash/adler32": true,
- "hash/crc32": true,
- "hash/crc64": true,
- "hash/fnv": true,
- "html": true,
- "html/template": true,
- "image": true,
- "image/color": true,
- "image/color/palette": true,
- "image/draw": true,
- "image/gif": true,
- "image/internal/imageutil": true,
- "image/jpeg": true,
- "image/png": true,
- "index/suffixarray": true,
- "internal/bytealg": true,
- "internal/cpu": true,
- "internal/nettrace": true,
- "internal/poll": true,
- "internal/race": true,
- "internal/singleflight": true,
- "internal/syscall/unix": true,
- "internal/syscall/windows": true,
- "internal/syscall/windows/registry": true,
- "internal/syscall/windows/sysdll": true,
- "internal/testenv": true,
- "internal/testlog": true,
- "internal/trace": true,
- "io": true,
- "io/ioutil": true,
- "log": true,
- "log/syslog": true,
- "math": true,
- "math/big": true,
- "math/bits": true,
- "math/cmplx": true,
- "math/rand": true,
- "mime": true,
- "mime/multipart": true,
- "mime/quotedprintable": true,
- "net": true,
- "net/http": true,
- "net/http/cgi": true,
- "net/http/cookiejar": true,
- "net/http/fcgi": true,
- "net/http/httptest": true,
- "net/http/httptrace": true,
- "net/http/httputil": true,
- "net/http/internal": true,
- "net/http/pprof": true,
- "net/internal/socktest": true,
- "net/mail": true,
- "net/rpc": true,
- "net/rpc/jsonrpc": true,
- "net/smtp": true,
- "net/textproto": true,
- "net/url": true,
- "os": true,
- "os/exec": true,
- "os/signal": true,
- "os/signal/internal/pty": true,
- "os/user": true,
- "path": true,
- "path/filepath": true,
- "plugin": true,
- "reflect": true,
- "regexp": true,
- "regexp/syntax": true,
- "runtime": true,
- "runtime/cgo": true,
- "runtime/debug": true,
- "runtime/internal/atomic": true,
- "runtime/internal/sys": true,
- "runtime/pprof": true,
- "runtime/pprof/internal/profile": true,
- "runtime/race": true,
- "runtime/trace": true,
- "sort": true,
- "strconv": true,
- "strings": true,
- "sync": true,
- "sync/atomic": true,
- "syscall": true,
- "testing": true,
- "testing/internal/testdeps": true,
- "testing/iotest": true,
- "testing/quick": true,
- "text/scanner": true,
- "text/tabwriter": true,
- "text/template": true,
- "text/template/parse": true,
- "time": true,
- "unicode": true,
- "unicode/utf16": true,
- "unicode/utf8": true,
- "unsafe": true,
-}
-
-var goBuiltins = map[string]bool{
- // Types
- "bool": true,
- "byte": true,
- "complex64": true,
- "complex128": true,
- "error": true,
- "float32": true,
- "float64": true,
- "int": true,
- "int8": true,
- "int16": true,
- "int32": true,
- "int64": true,
- "rune": true,
- "string": true,
- "uint": true,
- "uint8": true,
- "uint16": true,
- "uint32": true,
- "uint64": true,
- "uintptr": true,
-
- // Constants
- "true": true,
- "false": true,
- "iota": true,
-
- // Zero value
- "nil": true,
-
- // Functions
- "append": true,
- "cap": true,
- "close": true,
- "complex": true,
- "copy": true,
- "delete": true,
- "imag": true,
- "len": true,
- "make": true,
- "min": true,
- "max": true,
- "new": true,
- "panic": true,
- "print": true,
- "println": true,
- "real": true,
- "recover": true,
-}
-
-// isBuiltin reports whether sym belongs to a predefined identifier set.
-func isBuiltin(sym string) bool {
- return goBuiltins[sym]
-}
-
-// isStdlibPkg reports whether pkg is a package from the Go standard library.
-func isStdlibPkg(pkg *types.Package) bool {
- return pkg != nil && goStdlib[pkg.Path()]
-}
-
-// isExampleTestFunc reports whether FuncDecl looks like a testable example function.
-func isExampleTestFunc(fn *ast.FuncDecl) bool {
- return len(fn.Type.Params.List) == 0 && strings.HasPrefix(fn.Name.String(), "Example")
-}
-
-// isUnitTestFunc reports whether FuncDecl declares testing function.
-func isUnitTestFunc(ctx *linter.CheckerContext, fn *ast.FuncDecl) bool {
- if !strings.HasPrefix(fn.Name.Name, "Test") {
- return false
- }
- typ := ctx.TypesInfo.TypeOf(fn.Name)
- if sig, ok := typ.(*types.Signature); ok {
- return sig.Results().Len() == 0 &&
- sig.Params().Len() == 1 &&
- sig.Params().At(0).Type().String() == "*testing.T"
- }
- return false
-}
-
-// qualifiedName returns called expr fully-qualified name.
-//
-// It works for simple identifiers like f => "f" and identifiers
-// from other package like pkg.f => "pkg.f".
-//
-// For all unexpected expressions returns empty string.
-func qualifiedName(x ast.Expr) string {
- switch x := x.(type) {
- case *ast.SelectorExpr:
- pkg, ok := x.X.(*ast.Ident)
- if !ok {
- return ""
- }
- return pkg.Name + "." + x.Sel.Name
- case *ast.Ident:
- return x.Name
- default:
- return ""
- }
-}
-
-// identOf returns identifier for x that can be used to obtain associated types.Object.
-// Returns nil for expressions that yield temporary results, like `f().field`.
-func identOf(x ast.Node) *ast.Ident {
- switch x := x.(type) {
- case *ast.Ident:
- return x
- case *ast.SelectorExpr:
- return identOf(x.Sel)
- case *ast.TypeAssertExpr:
- // x.(type) - x may contain ident.
- return identOf(x.X)
- case *ast.IndexExpr:
- // x[i] - x may contain ident.
- return identOf(x.X)
- case *ast.StarExpr:
- // *x - x may contain ident.
- return identOf(x.X)
- case *ast.SliceExpr:
- // x[:] - x may contain ident.
- return identOf(x.X)
-
- default:
- // Note that this function is not comprehensive.
- return nil
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/weakCond_checker.go b/vendor/github.com/go-critic/go-critic/checkers/weakCond_checker.go
deleted file mode 100644
index 3d7c9c122..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/weakCond_checker.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "go/token"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/checkers/internal/lintutil"
- "github.com/go-critic/go-critic/linter"
-
- "github.com/go-toolsmith/astcast"
- "github.com/go-toolsmith/astequal"
- "github.com/go-toolsmith/typep"
- "golang.org/x/tools/go/ast/astutil"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "weakCond"
- info.Tags = []string{linter.DiagnosticTag, linter.ExperimentalTag}
- info.Summary = "Detects conditions that are unsafe due to not being exhaustive"
- info.Before = `xs != nil && xs[0] != nil`
- info.After = `len(xs) != 0 && xs[0] != nil`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForExpr(&weakCondChecker{ctx: ctx}), nil
- })
-}
-
-type weakCondChecker struct {
- astwalk.WalkHandler
- ctx *linter.CheckerContext
-}
-
-func (c *weakCondChecker) VisitExpr(expr ast.Expr) {
- // TODO(Quasilyte): more patterns.
- // TODO(Quasilyte): analyze and fix false positives.
-
- cond := astcast.ToBinaryExpr(expr)
- lhs := astcast.ToBinaryExpr(astutil.Unparen(cond.X))
- rhs := astutil.Unparen(cond.Y)
-
- // Pattern 1.
- // `x != nil && usageOf(x[i])`
- // Pattern 2.
- // `x == nil || usageOf(x[i])`
-
- // lhs is `x <op> nil`
- x := lhs.X
- if !typep.IsSlice(c.ctx.TypeOf(x)) {
- return
- }
- if astcast.ToIdent(lhs.Y).Name != "nil" {
- return
- }
-
- pat1prefix := cond.Op == token.LAND && lhs.Op == token.NEQ
- pat2prefix := cond.Op == token.LOR && lhs.Op == token.EQL
- if !pat1prefix && !pat2prefix {
- return
- }
-
- if c.isIndexed(rhs, x) {
- c.warn(expr, "nil check may not be enough, check for len")
- }
-}
-
-// isIndexed reports whether x is indexed inside given expr tree.
-func (c *weakCondChecker) isIndexed(tree, x ast.Expr) bool {
- return lintutil.ContainsNode(tree, func(n ast.Node) bool {
- indexing := astcast.ToIndexExpr(n)
- return astequal.Expr(x, indexing.X)
- })
-}
-
-func (c *weakCondChecker) warn(cause ast.Node, suggest string) {
- c.ctx.Warn(cause, "suspicious `%s`; %s", cause, suggest)
-}
diff --git a/vendor/github.com/go-critic/go-critic/checkers/whyNoLint_checker.go b/vendor/github.com/go-critic/go-critic/checkers/whyNoLint_checker.go
deleted file mode 100644
index eaa53e5d5..000000000
--- a/vendor/github.com/go-critic/go-critic/checkers/whyNoLint_checker.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package checkers
-
-import (
- "go/ast"
- "regexp"
- "strings"
-
- "github.com/go-critic/go-critic/checkers/internal/astwalk"
- "github.com/go-critic/go-critic/linter"
-)
-
-func init() {
- var info linter.CheckerInfo
- info.Name = "whyNoLint"
- info.Tags = []string{linter.StyleTag, linter.ExperimentalTag}
- info.Summary = "Ensures that `//nolint` comments include an explanation"
- info.Before = `//nolint`
- info.After = `//nolint // reason`
-
- collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
- return astwalk.WalkerForComment(&whyNoLintChecker{
- ctx: ctx,
- re: regexp.MustCompile(`^// *nolint(?::[^ ]+)? *(.*)$`),
- }), nil
- })
-}
-
-type whyNoLintChecker struct {
- astwalk.WalkHandler
-
- ctx *linter.CheckerContext
- re *regexp.Regexp
-}
-
-func (c whyNoLintChecker) VisitComment(cg *ast.CommentGroup) {
- if strings.HasPrefix(cg.List[0].Text, "/*") {
- return
- }
- for _, comment := range cg.List {
- sl := c.re.FindStringSubmatch(comment.Text)
- if len(sl) < 2 {
- continue
- }
-
- if s := sl[1]; !strings.HasPrefix(s, "//") || strings.TrimPrefix(s, "//") == "" {
- c.ctx.Warn(cg, "include an explanation for nolint directive")
- return
- }
- }
-}
diff --git a/vendor/github.com/go-critic/go-critic/linter/go_version.go b/vendor/github.com/go-critic/go-critic/linter/go_version.go
deleted file mode 100644
index b5ef2f75f..000000000
--- a/vendor/github.com/go-critic/go-critic/linter/go_version.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package linter
-
-import (
- "fmt"
- "strconv"
- "strings"
-)
-
-type GoVersion struct {
- Major int
- Minor int
-}
-
-// GreaterOrEqual performs $v >= $other operation.
-//
-// In other words, it reports whether $v version constraint can use
-// a feature from the $other Go version.
-//
-// As a special case, Major=0 covers all versions.
-func (v GoVersion) GreaterOrEqual(other GoVersion) bool {
- switch {
- case v.Major == 0:
- return true
- case v.Major == other.Major:
- return v.Minor >= other.Minor
- default:
- return v.Major >= other.Major
- }
-}
-
-func ParseGoVersion(version string) (GoVersion, error) {
- var result GoVersion
- version = strings.TrimPrefix(version, "go")
- if version == "" {
- return result, nil
- }
- parts := strings.Split(version, ".")
- if len(parts) != 2 {
- return result, fmt.Errorf("invalid Go version format: %s", version)
- }
- major, err := strconv.Atoi(parts[0])
- if err != nil {
- return result, fmt.Errorf("invalid major version part: %s: %w", parts[0], err)
- }
- minor, err := strconv.Atoi(parts[1])
- if err != nil {
- return result, fmt.Errorf("invalid minor version part: %s: %w", parts[1], err)
- }
- result.Major = major
- result.Minor = minor
- return result, nil
-}
diff --git a/vendor/github.com/go-critic/go-critic/linter/helpers.go b/vendor/github.com/go-critic/go-critic/linter/helpers.go
deleted file mode 100644
index d5110df64..000000000
--- a/vendor/github.com/go-critic/go-critic/linter/helpers.go
+++ /dev/null
@@ -1,136 +0,0 @@
-package linter
-
-import (
- "fmt"
- "regexp"
- "sort"
- "strings"
-
- "github.com/go-toolsmith/astfmt"
-)
-
-type checkerProto struct {
- info *CheckerInfo
- constructor func(*Context) (*Checker, error)
-}
-
-// prototypes is a set of registered checkers that are not yet instantiated.
-// Registration should be done with AddChecker function.
-// Initialized checkers can be obtained with NewChecker function.
-var prototypes = make(map[string]checkerProto)
-
-func getCheckersInfo() []*CheckerInfo {
- infoList := make([]*CheckerInfo, 0, len(prototypes))
- for _, proto := range prototypes {
- infoCopy := *proto.info
- infoList = append(infoList, &infoCopy)
- }
- sort.Slice(infoList, func(i, j int) bool {
- return infoList[i].Name < infoList[j].Name
- })
- return infoList
-}
-
-func addChecker(info *CheckerInfo, constructor func(*CheckerContext) (FileWalker, error)) {
- if _, ok := prototypes[info.Name]; ok {
- panic(fmt.Sprintf("checker with name %q already registered", info.Name))
- }
-
- // Validate param value type.
- for pname, param := range info.Params {
- switch param.Value.(type) {
- case string, int, bool:
- // OK.
- default:
- panic(fmt.Sprintf("unsupported %q param type value: %T",
- pname, param.Value))
- }
- }
-
- trimDocumentation := func(info *CheckerInfo) {
- fields := []*string{
- &info.Summary,
- &info.Details,
- &info.Before,
- &info.After,
- &info.Note,
- }
- for _, f := range fields {
- *f = strings.TrimSpace(*f)
- }
- }
-
- trimDocumentation(info)
-
- if err := validateCheckerInfo(info); err != nil {
- panic(err)
- }
-
- proto := checkerProto{
- info: info,
- constructor: func(ctx *Context) (*Checker, error) {
- var c Checker
- c.Info = info
- c.ctx = CheckerContext{
- Context: ctx,
- printer: astfmt.NewPrinter(ctx.FileSet),
- }
- var err error
- c.fileWalker, err = constructor(&c.ctx)
- return &c, err
- },
- }
-
- prototypes[info.Name] = proto
-}
-
-func newChecker(ctx *Context, info *CheckerInfo) (*Checker, error) {
- proto, ok := prototypes[info.Name]
- if !ok {
- panic(fmt.Sprintf("checker with name %q not registered", info.Name))
- }
- return proto.constructor(ctx)
-}
-
-func validateCheckerInfo(info *CheckerInfo) error {
- steps := []func(*CheckerInfo) error{
- validateCheckerName,
- validateCheckerDocumentation,
- validateCheckerTags,
- }
-
- for _, step := range steps {
- if err := step(info); err != nil {
- return fmt.Errorf("%q validation error: %v", info.Name, err)
- }
- }
- return nil
-}
-
-var validIdentRE = regexp.MustCompile(`^\w+$`)
-
-func validateCheckerName(info *CheckerInfo) error {
- if !validIdentRE.MatchString(info.Name) {
- return fmt.Errorf("checker name contains illegal chars")
- }
- return nil
-}
-
-func validateCheckerDocumentation(_ *CheckerInfo) error {
- // TODO(quasilyte): validate documentation.
- return nil
-}
-
-func validateCheckerTags(info *CheckerInfo) error {
- tagSet := make(map[string]bool)
- for _, tag := range info.Tags {
- if tagSet[tag] {
- return fmt.Errorf("duplicated tag %q", tag)
- }
- if !validIdentRE.MatchString(tag) {
- return fmt.Errorf("checker tag %q contains illegal chars", tag)
- }
- tagSet[tag] = true
- }
- return nil
-}
diff --git a/vendor/github.com/go-critic/go-critic/linter/linter.go b/vendor/github.com/go-critic/go-critic/linter/linter.go
deleted file mode 100644
index d4bc17536..000000000
--- a/vendor/github.com/go-critic/go-critic/linter/linter.go
+++ /dev/null
@@ -1,401 +0,0 @@
-package linter
-
-import (
- "go/ast"
- "go/token"
- "go/types"
- "strconv"
- "strings"
-
- "github.com/go-toolsmith/astfmt"
-)
-
-const (
- DiagnosticTag = "diagnostic"
- ExperimentalTag = "experimental"
- OpinionatedTag = "opinionated"
- PerformanceTag = "performance"
- SecurityTag = "security"
- StyleTag = "style"
-)
-
-// UnknownType is a special sentinel value that is returned from the CheckerContext.TypeOf
-// method instead of the nil type.
-var UnknownType types.Type = types.Typ[types.Invalid]
-
-// FileWalker is an interface every checker should implement.
-//
-// The WalkFile method is executed for every Go file inside the
-// package that is being checked.
-type FileWalker interface {
- WalkFile(*ast.File)
-}
-
-// CheckerCollection provides additional information for a group of checkers.
-type CheckerCollection struct {
- // URL is a link for a main source of information on the collection.
- URL string
-}
-
-// AddChecker registers a new checker into a checkers pool.
-// Constructor is used to create a new checker instance.
-// Checker name (defined in CheckerInfo.Name) must be unique.
-//
-// CheckerInfo.Collection is automatically set to the coll (the receiver).
-//
-// If checker is never needed, for example if it is disabled,
-// constructor will not be called.
-func (coll *CheckerCollection) AddChecker(info *CheckerInfo, constructor func(*CheckerContext) (FileWalker, error)) {
- if coll == nil {
- panic("adding checker to a nil collection")
- }
- info.Collection = coll
- addChecker(info, constructor)
-}
-
-// CheckerParam describes a single checker customizable parameter.
-type CheckerParam struct {
- // Value holds parameter bound value.
- // It might be overwritten by the integrating linter.
- //
- // Permitted types include:
- // - int
- // - bool
- // - string
- Value interface{}
-
- // Usage gives an overview about what parameter does.
- Usage string
-}
-
-// CheckerParams holds all checker-specific parameters.
-//
-// Provides convenient access to the loosely typed underlying map.
-type CheckerParams map[string]*CheckerParam
-
-// Int lookups pname key in underlying map and type-asserts it to int.
-func (params CheckerParams) Int(pname string) int { return params[pname].Value.(int) }
-
-// Bool lookups pname key in underlying map and type-asserts it to bool.
-func (params CheckerParams) Bool(pname string) bool { return params[pname].Value.(bool) }
-
-// String lookups pname key in underlying map and type-asserts it to string.
-func (params CheckerParams) String(pname string) string { return params[pname].Value.(string) }
-
-// CheckerInfo holds checker metadata and structured documentation.
-type CheckerInfo struct {
- // Name is a checker name.
- Name string
-
- // Tags is a list of labels that can be used to enable or disable checker.
- // Common tags are "experimental" and "performance".
- Tags []string
-
- // Params declares checker-specific parameters. Optional.
- Params CheckerParams
-
- // Summary is a short one sentence description.
- // Should not end with a period.
- Summary string
-
- // Details extends summary with additional info. Optional.
- Details string
-
- // Before is a code snippet of code that will violate rule.
- Before string
-
- // After is a code snippet of fixed code that complies to the rule.
- After string
-
- // Note is an optional caution message or advice.
- Note string
-
- // EmbeddedRuleguard tells whether this checker is auto-generated
- // from the embedded ruleguard rules.
- EmbeddedRuleguard bool
-
- // Collection establishes a checker-to-collection relationship.
- Collection *CheckerCollection
-}
-
-// GetCheckersInfo returns a checkers info list for all registered checkers.
-// The slice is sorted by a checker name.
-//
-// Info objects can be used to instantiate checkers with NewChecker function.
-func GetCheckersInfo() []*CheckerInfo {
- return getCheckersInfo()
-}
-
-// HasTag reports whether checker described by the info has specified tag.
-func (info *CheckerInfo) HasTag(tag string) bool {
- for i := range info.Tags {
- if info.Tags[i] == tag {
- return true
- }
- }
- return false
-}
-
-// Checker is an implementation of a check that is described by the associated info.
-type Checker struct {
- // Info is an info object that was used to instantiate this checker.
- Info *CheckerInfo
-
- ctx CheckerContext
-
- fileWalker FileWalker
-}
-
-// NewChecker returns initialized checker identified by an info.
-// info must be non-nil.
-// Returns an error if info describes a checker that was not properly registered,
-// or if checker fails to initialize.
-func NewChecker(ctx *Context, info *CheckerInfo) (*Checker, error) {
- return newChecker(ctx, info)
-}
-
-// Check runs rule checker over file f.
-func (c *Checker) Check(f *ast.File) []Warning {
- c.ctx.warnings = c.ctx.warnings[:0]
- c.fileWalker.WalkFile(f)
- return c.ctx.warnings
-}
-
-// QuickFix is our analysis.TextEdit; we're using it here to avoid
-// direct analysis package dependency for now.
-type QuickFix struct {
- From token.Pos
- To token.Pos
- Replacement []byte
-}
-
-// Warning represents issue that is found by checker.
-type Warning struct {
- Pos token.Pos
-
- // Text is warning message without source location info.
- Text string
-
- // Suggestion is a quick fix for a given problem.
- // QuickFix is analysis.TextEdit and can be used to
- // construct an analysis.SuggestedFix object.
- //
- // For convenience, there is Warning.HasQuickFix() method
- // that reports whether Suggestion has something meaningful.
- Suggestion QuickFix
-}
-
-// HasQuickFix reports whether this warning has a suggested fix.
-func (warn Warning) HasQuickFix() bool {
- return warn.Suggestion.Replacement != nil
-}
-
-// Context is a readonly state shared among every checker.
-type Context struct {
- // TypesInfo carries parsed packages types information.
- TypesInfo *types.Info
-
- // SizesInfo carries alignment and type size information.
- // Arch-dependent.
- SizesInfo types.Sizes
-
- // GoVersion is a target Go version.
- GoVersion GoVersion
-
- // FileSet is a file set that was used during the program loading.
- FileSet *token.FileSet
-
- // Pkg describes package that is being checked.
- Pkg *types.Package
-
- // Filename is a currently checked file name.
- Filename string
-
- // Require records what optional resources are required
- // by the checkers set that use this context.
- //
- // Every require fields makes associated context field
- // to be properly initialized.
- // For example, Context.require.PkgObjects => Context.PkgObjects.
- Require struct {
- PkgObjects bool
- PkgRenames bool
- }
-
- // PkgObjects stores all imported packages and their local names.
- PkgObjects map[*types.PkgName]string
-
- // PkgRenames maps package path to its local renaming.
- // Contains no entries for packages that were imported without
- // explicit local names.
- PkgRenames map[string]string
-}
-
-// NewContext returns new shared context to be used by every checker.
-//
-// All data carried by the context is readonly for checkers,
-// but can be modified by the integrating application.
-func NewContext(fset *token.FileSet, sizes types.Sizes) *Context {
- return &Context{
- FileSet: fset,
- SizesInfo: sizes,
- TypesInfo: &types.Info{},
- }
-}
-
-// SetGoVersion adjust the target Go language version.
-//
-// The format is like "1.5", "1.8", etc.
-// It's permitted to have "go" prefix (e.g. "go1.5").
-//
-// Empty string (the default) means that we make no
-// Go version assumptions and (like gocritic does) behave
-// like all features are available. To make gocritic
-// more conservative, the upper Go version level should be adjusted.
-func (c *Context) SetGoVersion(version string) {
- v, err := ParseGoVersion(version)
- if err != nil {
- panic(err)
- }
- c.GoVersion = v
-}
-
-// SetPackageInfo sets package-related metadata.
-//
-// Must be called for every package being checked.
-func (c *Context) SetPackageInfo(info *types.Info, pkg *types.Package) {
- if info != nil {
- // We do this kind of assignment to avoid
- // changing c.typesInfo field address after
- // every re-assignment.
- *c.TypesInfo = *info
- }
- c.Pkg = pkg
-}
-
-// SetFileInfo sets file-related metadata.
-//
-// Must be called for every source code file being checked.
-func (c *Context) SetFileInfo(name string, f *ast.File) {
- c.Filename = name
- if c.Require.PkgObjects {
- resolvePkgObjects(c, f)
- }
- if c.Require.PkgRenames {
- resolvePkgRenames(c, f)
- }
-}
-
-// CheckerContext is checker-local context copy.
-// Fields that are not from Context itself are writeable.
-type CheckerContext struct {
- *Context
-
- // printer used to format warning text.
- printer *astfmt.Printer
-
- warnings []Warning
-}
-
-// Warn adds a Warning to checker output.
-func (ctx *CheckerContext) Warn(node ast.Node, format string, args ...interface{}) {
- ctx.WarnWithPos(node.Pos(), format, args...)
-}
-
-// WarnFixable emits a warning with a fix suggestion provided by the caller.
-func (ctx *CheckerContext) WarnFixable(node ast.Node, fix QuickFix, format string, args ...interface{}) {
- ctx.WarnFixableWithPos(node.Pos(), fix, format, args...)
-}
-
-// WarnWithPos adds a Warning to checker output. Useful for ruleguard's Report func.
-func (ctx *CheckerContext) WarnWithPos(pos token.Pos, format string, args ...interface{}) {
- ctx.warnings = append(ctx.warnings, Warning{
- Text: ctx.printer.Sprintf(format, args...),
- Pos: pos,
- })
-}
-
-// WarnFixableWithPos adds a Warning to checker output. Useful for ruleguard's Report func.
-func (ctx *CheckerContext) WarnFixableWithPos(pos token.Pos, fix QuickFix, format string, args ...interface{}) {
- ctx.warnings = append(ctx.warnings, Warning{
- Text: ctx.printer.Sprintf(format, args...),
- Pos: pos,
- Suggestion: fix,
- })
-}
-
-// TypeOf returns the type of expression x.
-//
-// Unlike TypesInfo.TypeOf, it never returns nil.
-// Instead, it returns the Invalid type as a sentinel UnknownType value.
-func (ctx *CheckerContext) TypeOf(x ast.Expr) types.Type {
- typ := ctx.TypesInfo.TypeOf(x)
- if typ != nil {
- return typ
- }
- // Usually it means that some incorrect type info was loaded
- // or the analyzed package was only partially (?) correct.
- // To avoid nil pointer panics we can return a sentinel value
- // that will fail most type assertions as well as kind checks
- // (if the call side expects a *types.Basic).
- return UnknownType
-}
-
-// SizeOf returns the size of the typ in bytes.
-//
-// Unlike SizesInfo.SizeOf, it will not panic on generic types.
-func (ctx *CheckerContext) SizeOf(typ types.Type) (int64, bool) {
- if _, ok := typ.(*types.TypeParam); ok {
- return 0, false
- }
- if named, ok := typ.(*types.Named); ok && named.TypeParams() != nil {
- return 0, false
- }
- return ctx.safeSizesInfoSizeof(typ)
-}
-
-// safeSizesInfoSizeof unlike SizesInfo.Sizeof will not panic on struct with generic fields.
-// it will catch a panic and recover from it, see https://github.com/go-critic/go-critic/issues/1354
-func (ctx *CheckerContext) safeSizesInfoSizeof(typ types.Type) (size int64, ok bool) {
- ok = true
- defer func() {
- if r := recover(); r != nil {
- if strings.Contains(r.(string), "assertion failed") {
- size, ok = 0, false
- } else {
- panic(r)
- }
- }
- }()
-
- size = ctx.SizesInfo.Sizeof(typ)
- return size, ok
-}
-
-func resolvePkgObjects(ctx *Context, f *ast.File) {
- ctx.PkgObjects = make(map[*types.PkgName]string, len(f.Imports))
-
- for _, spec := range f.Imports {
- if spec.Name != nil {
- obj := ctx.TypesInfo.ObjectOf(spec.Name)
- ctx.PkgObjects[obj.(*types.PkgName)] = spec.Name.Name
- } else {
- obj := ctx.TypesInfo.Implicits[spec]
- ctx.PkgObjects[obj.(*types.PkgName)] = obj.Name()
- }
- }
-}
-
-func resolvePkgRenames(ctx *Context, f *ast.File) {
- ctx.PkgRenames = make(map[string]string)
-
- for _, spec := range f.Imports {
- if spec.Name != nil {
- path, err := strconv.Unquote(spec.Path.Value)
- if err != nil {
- panic(err)
- }
- ctx.PkgRenames[path] = spec.Name.Name
- }
- }
-}