aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/Antonboom
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2024-11-11 11:41:38 +0100
committerTaras Madan <tarasmadan@google.com>2024-11-11 11:10:48 +0000
commit27e76fae2ee2d84dc7db63af1d9ed7358ba35b7a (patch)
treeed19c0e35e272b3c4cc5a2f2c595e035b2428337 /vendor/github.com/Antonboom
parent621e84e063b0e15b23e17780338627c509e1b9e8 (diff)
vendor: update
Diffstat (limited to 'vendor/github.com/Antonboom')
-rw-r--r--vendor/github.com/Antonboom/errname/pkg/analyzer/analyzer.go131
-rw-r--r--vendor/github.com/Antonboom/errname/pkg/analyzer/facts.go199
-rw-r--r--vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go33
-rw-r--r--vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go4
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/analysisutil/encoded.go46
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/analysisutil/file.go8
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/blank_import.go2
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/bool_compare.go18
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/checkers_registry.go3
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/compares.go9
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/contains.go71
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/empty.go34
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/encoded_compare.go101
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/error_is_as.go16
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/error_nil.go15
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/expected_actual.go2
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/float_compare.go2
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/formatter.go81
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/go_require.go10
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_basic_type.go81
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_diagnostic.go101
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_encoded.go40
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_error.go20
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_format.go35
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_interface.go5
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_pkg_func.go59
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/len.go17
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/negative_positive.go (renamed from vendor/github.com/Antonboom/testifylint/internal/checkers/negative_postive.go)10
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/nil_compare.go5
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/printf/printf.go6
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/regexp.go44
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/require_error.go7
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/suite_broken_parallel.go2
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/suite_dont_use_pkg.go2
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/suite_extra_assert_call.go4
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/suite_subtest_run.go2
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/suite_thelper.go4
-rw-r--r--vendor/github.com/Antonboom/testifylint/internal/checkers/useless_assert.go87
38 files changed, 853 insertions, 463 deletions
diff --git a/vendor/github.com/Antonboom/errname/pkg/analyzer/analyzer.go b/vendor/github.com/Antonboom/errname/pkg/analyzer/analyzer.go
index aa8522510..2b8794dc2 100644
--- a/vendor/github.com/Antonboom/errname/pkg/analyzer/analyzer.go
+++ b/vendor/github.com/Antonboom/errname/pkg/analyzer/analyzer.go
@@ -1,11 +1,9 @@
package analyzer
import (
- "fmt"
"go/ast"
"go/token"
- "strconv"
- "strings"
+ "go/types"
"unicode"
"golang.org/x/tools/go/analysis"
@@ -23,86 +21,61 @@ func New() *analysis.Analyzer {
}
}
-type stringSet = map[string]struct{}
-
-var (
- importNodes = []ast.Node{(*ast.ImportSpec)(nil)}
- typeNodes = []ast.Node{(*ast.TypeSpec)(nil)}
- funcNodes = []ast.Node{(*ast.FuncDecl)(nil)}
-)
-
func run(pass *analysis.Pass) (interface{}, error) {
insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
- pkgAliases := map[string]string{}
- insp.Preorder(importNodes, func(node ast.Node) {
- i := node.(*ast.ImportSpec)
- if n := i.Name; n != nil && i.Path != nil {
- if path, err := strconv.Unquote(i.Path.Value); err == nil {
- pkgAliases[n.Name] = getPkgFromPath(path)
- }
- }
- })
-
- allTypes := stringSet{}
- typesSpecs := map[string]*ast.TypeSpec{}
- insp.Preorder(typeNodes, func(node ast.Node) {
- t := node.(*ast.TypeSpec)
- allTypes[t.Name.Name] = struct{}{}
- typesSpecs[t.Name.Name] = t
- })
-
- errorTypes := stringSet{}
- insp.Preorder(funcNodes, func(node ast.Node) {
- f := node.(*ast.FuncDecl)
- t, ok := isMethodError(f)
- if !ok {
- return
- }
- errorTypes[t] = struct{}{}
-
- tSpec, ok := typesSpecs[t]
- if !ok {
- panic(fmt.Sprintf("no specification for type %q", t))
- }
-
- if _, ok := tSpec.Type.(*ast.ArrayType); ok {
- if !isValidErrorArrayTypeName(t) {
- reportAboutErrorType(pass, tSpec.Pos(), t, true)
- }
- } else if !isValidErrorTypeName(t) {
- reportAboutErrorType(pass, tSpec.Pos(), t, false)
- }
- })
-
- errorFuncs := stringSet{}
- insp.Preorder(funcNodes, func(node ast.Node) {
- f := node.(*ast.FuncDecl)
- if isFuncReturningErr(f.Type, allTypes, errorTypes) {
- errorFuncs[f.Name.Name] = struct{}{}
+ insp.Nodes([]ast.Node{
+ (*ast.TypeSpec)(nil),
+ (*ast.ValueSpec)(nil),
+ (*ast.FuncDecl)(nil),
+ }, func(node ast.Node, push bool) bool {
+ if !push {
+ return false
}
- })
- inspectPkgLevelVarsOnly := func(node ast.Node) bool {
switch v := node.(type) {
case *ast.FuncDecl:
return false
case *ast.ValueSpec:
- if name, ok := isSentinelError(v, pkgAliases, allTypes, errorTypes, errorFuncs); ok && !isValidErrorVarName(name) {
- reportAboutErrorVar(pass, v.Pos(), name)
+ if len(v.Names) != 1 {
+ return false
+ }
+ ident := v.Names[0]
+
+ if exprImplementsError(pass, ident) && !isValidErrorVarName(ident.Name) {
+ reportAboutSentinelError(pass, v.Pos(), ident.Name)
+ }
+ return false
+
+ case *ast.TypeSpec:
+ tt := pass.TypesInfo.TypeOf(v.Name)
+ if tt == nil {
+ return false
+ }
+ // NOTE(a.telyshev): Pointer is the hack against Error() method with pointer receiver.
+ if !typeImplementsError(types.NewPointer(tt)) {
+ return false
}
+
+ name := v.Name.Name
+ if _, ok := v.Type.(*ast.ArrayType); ok {
+ if !isValidErrorArrayTypeName(name) {
+ reportAboutArrayErrorType(pass, v.Pos(), name)
+ }
+ } else if !isValidErrorTypeName(name) {
+ reportAboutErrorType(pass, v.Pos(), name)
+ }
+ return false
}
+
return true
- }
- for _, f := range pass.Files {
- ast.Inspect(f, inspectPkgLevelVarsOnly)
- }
+ })
return nil, nil //nolint:nilnil
}
-func reportAboutErrorType(pass *analysis.Pass, typePos token.Pos, typeName string, isArrayType bool) {
+func reportAboutErrorType(pass *analysis.Pass, typePos token.Pos, typeName string) {
var form string
if unicode.IsLower([]rune(typeName)[0]) {
form = "xxxError"
@@ -110,26 +83,26 @@ func reportAboutErrorType(pass *analysis.Pass, typePos token.Pos, typeName strin
form = "XxxError"
}
- if isArrayType {
- form += "s"
+ pass.Reportf(typePos, "the error type name `%s` should conform to the `%s` format", typeName, form)
+}
+
+func reportAboutArrayErrorType(pass *analysis.Pass, typePos token.Pos, typeName string) {
+ var forms string
+ if unicode.IsLower([]rune(typeName)[0]) {
+ forms = "`xxxErrors` or `xxxError`"
+ } else {
+ forms = "`XxxErrors` or `XxxError`"
}
- pass.Reportf(typePos, "the type name `%s` should conform to the `%s` format", typeName, form)
+
+ pass.Reportf(typePos, "the error type name `%s` should conform to the %s format", typeName, forms)
}
-func reportAboutErrorVar(pass *analysis.Pass, pos token.Pos, varName string) {
+func reportAboutSentinelError(pass *analysis.Pass, pos token.Pos, varName string) {
var form string
if unicode.IsLower([]rune(varName)[0]) {
form = "errXxx"
} else {
form = "ErrXxx"
}
- pass.Reportf(pos, "the variable name `%s` should conform to the `%s` format", varName, form)
-}
-
-func getPkgFromPath(p string) string {
- idx := strings.LastIndex(p, "/")
- if idx == -1 {
- return p
- }
- return p[idx+1:]
+ pass.Reportf(pos, "the sentinel error name `%s` should conform to the `%s` format", varName, form)
}
diff --git a/vendor/github.com/Antonboom/errname/pkg/analyzer/facts.go b/vendor/github.com/Antonboom/errname/pkg/analyzer/facts.go
index 06f8d61d8..04e14fb68 100644
--- a/vendor/github.com/Antonboom/errname/pkg/analyzer/facts.go
+++ b/vendor/github.com/Antonboom/errname/pkg/analyzer/facts.go
@@ -1,58 +1,22 @@
package analyzer
import (
- "fmt"
"go/ast"
- "go/token"
"go/types"
"strings"
"unicode"
-)
-
-func isMethodError(f *ast.FuncDecl) (typeName string, ok bool) {
- if f.Recv == nil || len(f.Recv.List) != 1 {
- return "", false
- }
- if f.Name == nil || f.Name.Name != "Error" {
- return "", false
- }
- if f.Type == nil || f.Type.Results == nil || len(f.Type.Results.List) != 1 {
- return "", false
- }
-
- returnType, ok := f.Type.Results.List[0].Type.(*ast.Ident)
- if !ok {
- return "", false
- }
-
- var receiverType string
-
- unwrapIdentName := func(e ast.Expr) string {
- switch v := e.(type) {
- case *ast.Ident:
- return v.Name
- case *ast.IndexExpr:
- if i, ok := v.X.(*ast.Ident); ok {
- return i.Name
- }
- case *ast.IndexListExpr:
- if i, ok := v.X.(*ast.Ident); ok {
- return i.Name
- }
- }
- panic(fmt.Errorf("unsupported Error() receiver type %q", types.ExprString(e)))
- }
+ "golang.org/x/tools/go/analysis"
+)
- switch rt := f.Recv.List[0].Type; v := rt.(type) {
- case *ast.Ident, *ast.IndexExpr, *ast.IndexListExpr: // SomeError, SomeError[T], SomeError[T1, T2, ...]
- receiverType = unwrapIdentName(rt)
+var errorIface = types.Universe.Lookup("error").Type().Underlying().(*types.Interface)
- case *ast.StarExpr: // *SomeError, *SomeError[T], *SomeError[T1, T2, ...]
- receiverType = unwrapIdentName(v.X)
- }
+func exprImplementsError(pass *analysis.Pass, e ast.Expr) bool {
+ return typeImplementsError(pass.TypesInfo.TypeOf(e))
+}
- return receiverType, returnType.Name == "string"
+func typeImplementsError(t types.Type) bool {
+ return t != nil && types.Implements(t, errorIface)
}
func isValidErrorTypeName(s string) bool {
@@ -77,153 +41,12 @@ func isValidErrorArrayTypeName(s string) bool {
words := split(s)
wordsCnt := wordsCount(words)
- if wordsCnt["errors"] != 1 {
- return false
- }
- return words[len(words)-1] == "errors"
-}
-
-func isFuncReturningErr(fType *ast.FuncType, allTypes, errorTypes stringSet) bool {
- if fType == nil || fType.Results == nil || len(fType.Results.List) != 1 {
+ if wordsCnt["errors"] != 1 && wordsCnt["error"] != 1 {
return false
}
- var returnTypeName string
- switch rt := fType.Results.List[0].Type.(type) {
- case *ast.Ident:
- returnTypeName = rt.Name
- case *ast.StarExpr:
- if i, ok := rt.X.(*ast.Ident); ok {
- returnTypeName = i.Name
- }
- }
-
- return isErrorType(returnTypeName, allTypes, errorTypes)
-}
-
-func isErrorType(tName string, allTypes, errorTypes stringSet) bool {
- _, isUserType := allTypes[tName]
- _, isErrType := errorTypes[tName]
- return isErrType || (tName == "error" && !isUserType)
-}
-
-var knownErrConstructors = stringSet{
- "fmt.Errorf": {},
- "errors.Errorf": {},
- "errors.New": {},
- "errors.Newf": {},
- "errors.NewWithDepth": {},
- "errors.NewWithDepthf": {},
- "errors.NewAssertionErrorWithWrappedErrf": {},
-}
-
-func isSentinelError( //nolint:gocognit,gocyclo
- v *ast.ValueSpec,
- pkgAliases map[string]string,
- allTypes, errorTypes, errorFuncs stringSet,
-) (varName string, ok bool) {
- if len(v.Names) != 1 {
- return "", false
- }
- varName = v.Names[0].Name
-
- switch vv := v.Type.(type) {
- // var ErrEndOfFile error
- // var ErrEndOfFile SomeErrType
- case *ast.Ident:
- if isErrorType(vv.Name, allTypes, errorTypes) {
- return varName, true
- }
-
- // var ErrEndOfFile *SomeErrType
- case *ast.StarExpr:
- if i, ok := vv.X.(*ast.Ident); ok && isErrorType(i.Name, allTypes, errorTypes) {
- return varName, true
- }
- }
-
- if len(v.Values) != 1 {
- return "", false
- }
-
- switch vv := v.Values[0].(type) {
- case *ast.CallExpr:
- switch fun := vv.Fun.(type) {
- // var ErrEndOfFile = errors.New("end of file")
- case *ast.SelectorExpr:
- pkg, ok := fun.X.(*ast.Ident)
- if !ok {
- return "", false
- }
- pkgFun := fun.Sel
-
- pkgName := pkg.Name
- if a, ok := pkgAliases[pkgName]; ok {
- pkgName = a
- }
-
- _, ok = knownErrConstructors[pkgName+"."+pkgFun.Name]
- return varName, ok
-
- // var ErrEndOfFile = newErrEndOfFile()
- // var ErrEndOfFile = new(EndOfFileError)
- // const ErrEndOfFile = constError("end of file")
- // var statusCodeError = new(SomePtrError[string])
- case *ast.Ident:
- if isErrorType(fun.Name, allTypes, errorTypes) {
- return varName, true
- }
-
- if _, ok := errorFuncs[fun.Name]; ok {
- return varName, true
- }
-
- if fun.Name == "new" && len(vv.Args) == 1 {
- switch i := vv.Args[0].(type) {
- case *ast.Ident:
- return varName, isErrorType(i.Name, allTypes, errorTypes)
- case *ast.IndexExpr:
- if ii, ok := i.X.(*ast.Ident); ok {
- return varName, isErrorType(ii.Name, allTypes, errorTypes)
- }
- }
- }
-
- // var ErrEndOfFile = func() error { ... }
- case *ast.FuncLit:
- return varName, isFuncReturningErr(fun.Type, allTypes, errorTypes)
- }
-
- // var ErrEndOfFile = &EndOfFileError{}
- // var ErrOK = &SomePtrError[string]{Code: "200 OK"}
- case *ast.UnaryExpr:
- if vv.Op == token.AND { // &
- if lit, ok := vv.X.(*ast.CompositeLit); ok {
- switch i := lit.Type.(type) {
- case *ast.Ident:
- return varName, isErrorType(i.Name, allTypes, errorTypes)
- case *ast.IndexExpr:
- if ii, ok := i.X.(*ast.Ident); ok {
- return varName, isErrorType(ii.Name, allTypes, errorTypes)
- }
- }
- }
- }
-
- // var ErrEndOfFile = EndOfFileError{}
- // var ErrNotFound = SomeError[string]{Code: "Not Found"}
- case *ast.CompositeLit:
- switch i := vv.Type.(type) {
- case *ast.Ident:
- return varName, isErrorType(i.Name, allTypes, errorTypes)
- case *ast.IndexExpr:
- if ii, ok := i.X.(*ast.Ident); ok {
- return varName, isErrorType(ii.Name, allTypes, errorTypes)
- }
- }
- }
-
- return "", false
+ lastWord := words[len(words)-1]
+ return lastWord == "errors" || lastWord == "error"
}
func isValidErrorVarName(s string) bool {
diff --git a/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go
index 5646ee909..5507d9546 100644
--- a/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go
+++ b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go
@@ -15,7 +15,8 @@ const (
name = "nilnil"
doc = "Checks that there is no simultaneous return of `nil` error and an invalid value."
- reportMsg = "return both the `nil` error and invalid value: use a sentinel error instead"
+ nilNilReportMsg = "return both a `nil` error and an invalid value: use a sentinel error instead"
+ notNilNotNilReportMsg = "return both a non-nil error and a valid value: use separate returns instead"
)
// New returns new nilnil analyzer.
@@ -28,18 +29,22 @@ func New() *analysis.Analyzer {
Run: n.run,
Requires: []*analysis.Analyzer{inspect.Analyzer},
}
- a.Flags.Var(&n.checkedTypes, "checked-types", "coma separated list")
+ a.Flags.Var(&n.checkedTypes, "checked-types", "comma separated list of return types to check")
+ a.Flags.BoolVar(&n.detectOpposite, "detect-opposite", false,
+ "in addition, detect opposite situation (simultaneous return of non-nil error and valid value)")
return a
}
type nilNil struct {
- checkedTypes checkedTypes
+ checkedTypes checkedTypes
+ detectOpposite bool
}
func newNilNil() *nilNil {
return &nilNil{
- checkedTypes: newDefaultCheckedTypes(),
+ checkedTypes: newDefaultCheckedTypes(),
+ detectOpposite: false,
}
}
@@ -87,22 +92,22 @@ func (n *nilNil) run(pass *analysis.Pass) (interface{}, error) {
}
ok, zv := n.isDangerNilType(fRes1Type)
- if !(ok && isErrorType(fRes2Type)) {
+ if !(ok && implementsError(fRes2Type)) {
return false
}
retVal, retErr := v.Results[0], v.Results[1]
- var needWarn bool
- switch zv {
- case zeroValueNil:
- needWarn = isNil(pass, retVal) && isNil(pass, retErr)
- case zeroValueZero:
- needWarn = isZero(retVal) && isNil(pass, retErr)
+ if ((zv == zeroValueNil) && isNil(pass, retVal) && isNil(pass, retErr)) ||
+ ((zv == zeroValueZero) && isZero(retVal) && isNil(pass, retErr)) {
+ pass.Reportf(v.Pos(), nilNilReportMsg)
+ return false
}
- if needWarn {
- pass.Reportf(v.Pos(), reportMsg)
+ if n.detectOpposite && (((zv == zeroValueNil) && !isNil(pass, retVal) && !isNil(pass, retErr)) ||
+ ((zv == zeroValueZero) && !isZero(retVal) && !isNil(pass, retErr))) {
+ pass.Reportf(v.Pos(), notNilNotNilReportMsg)
+ return false
}
}
@@ -152,7 +157,7 @@ func (n *nilNil) isDangerNilType(t types.Type) (bool, zeroValue) {
var errorIface = types.Universe.Lookup("error").Type().Underlying().(*types.Interface)
-func isErrorType(t types.Type) bool {
+func implementsError(t types.Type) bool {
_, ok := t.Underlying().(*types.Interface)
return ok && types.Implements(t, errorIface)
}
diff --git a/vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go
index c9b8e3eed..90ae548f3 100644
--- a/vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go
+++ b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go
@@ -8,11 +8,11 @@ import (
func newDefaultCheckedTypes() checkedTypes {
return checkedTypes{
- ptrType: {},
+ chanType: {},
funcType: {},
ifaceType: {},
mapType: {},
- chanType: {},
+ ptrType: {},
uintptrType: {},
unsafeptrType: {},
}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/analysisutil/encoded.go b/vendor/github.com/Antonboom/testifylint/internal/analysisutil/encoded.go
new file mode 100644
index 000000000..cafc283e6
--- /dev/null
+++ b/vendor/github.com/Antonboom/testifylint/internal/analysisutil/encoded.go
@@ -0,0 +1,46 @@
+package analysisutil
+
+import "strings"
+
+var whitespaceRemover = strings.NewReplacer("\n", "", "\\n", "", "\t", "", "\\t", "", " ", "")
+
+// IsJSONLike returns true if the string has JSON format features.
+// A positive result can be returned for invalid JSON as well.
+func IsJSONLike(s string) bool {
+ s = whitespaceRemover.Replace(unescape(s))
+
+ var startMatch bool
+ for _, prefix := range []string{
+ `{{`, `{[`, `{"`,
+ `[{{`, `[{[`, `[{"`,
+ } {
+ if strings.HasPrefix(s, prefix) {
+ startMatch = true
+ break
+ }
+ }
+ if !startMatch {
+ return false
+ }
+
+ for _, keyValue := range []string{`":{`, `":[`, `":"`} {
+ if strings.Contains(s, keyValue) {
+ return true
+ }
+ }
+ return false
+
+ // NOTE(a.telyshev): We do not check the end of the string, because this is usually a field for typos.
+ // And one of the reasons for using JSON-specific assertions is to catch typos like this.
+}
+
+func unescape(s string) string {
+ s = strings.ReplaceAll(s, `\"`, `"`)
+ s = unquote(s, `"`)
+ s = unquote(s, "`")
+ return s
+}
+
+func unquote(s string, q string) string {
+ return strings.TrimLeft(strings.TrimRight(s, q), q)
+}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/analysisutil/file.go b/vendor/github.com/Antonboom/testifylint/internal/analysisutil/file.go
index 3fc1f42b8..d55260918 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/analysisutil/file.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/analysisutil/file.go
@@ -2,6 +2,7 @@ package analysisutil
import (
"go/ast"
+ "slices"
"strconv"
)
@@ -17,11 +18,8 @@ func Imports(file *ast.File, pkgs ...string) bool {
if err != nil {
continue
}
- // NOTE(a.telyshev): Don't use `slices.Contains` to keep the minimum module version 1.20.
- for _, pkg := range pkgs { // Small O(n).
- if pkg == path {
- return true
- }
+ if slices.Contains(pkgs, path) { // Small O(n).
+ return true
}
}
return false
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/blank_import.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/blank_import.go
index 403691e27..56cd64e07 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/blank_import.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/blank_import.go
@@ -53,7 +53,7 @@ func (checker BlankImport) Check(pass *analysis.Pass, _ *inspector.Inspector) (d
}
msg := fmt.Sprintf("avoid blank import of %s as it does nothing", pkg)
- diagnostics = append(diagnostics, *newDiagnostic(checker.Name(), imp, msg, nil))
+ diagnostics = append(diagnostics, *newDiagnostic(checker.Name(), imp, msg))
}
}
return diagnostics
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/bool_compare.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/bool_compare.go
index d125c43f9..67959b633 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/bool_compare.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/bool_compare.go
@@ -49,13 +49,11 @@ func (checker BoolCompare) Check(pass *analysis.Pass, call *CallMeta) *analysis.
}
survivingArg = newBoolCast(survivingArg)
}
- return newUseFunctionDiagnostic(checker.Name(), call, proposed,
- newSuggestedFuncReplacement(call, proposed, analysis.TextEdit{
- Pos: replaceStart,
- End: replaceEnd,
- NewText: analysisutil.NodeBytes(pass.Fset, survivingArg),
- }),
- )
+ return newUseFunctionDiagnostic(checker.Name(), call, proposed, analysis.TextEdit{
+ Pos: replaceStart,
+ End: replaceEnd,
+ NewText: analysisutil.NodeBytes(pass.Fset, survivingArg),
+ })
}
newUseTrueDiagnostic := func(survivingArg ast.Expr, replaceStart, replaceEnd token.Pos) *analysis.Diagnostic {
@@ -74,7 +72,7 @@ func (checker BoolCompare) Check(pass *analysis.Pass, call *CallMeta) *analysis.
survivingArg = newBoolCast(survivingArg)
}
return newDiagnostic(checker.Name(), call, "need to simplify the assertion",
- &analysis.SuggestedFix{
+ analysis.SuggestedFix{
Message: "Simplify the assertion",
TextEdits: []analysis.TextEdit{{
Pos: replaceStart,
@@ -106,7 +104,7 @@ func (checker BoolCompare) Check(pass *analysis.Pass, call *CallMeta) *analysis.
case xor(t1, t2):
survivingArg, _ := anyVal([]bool{t1, t2}, arg2, arg1)
if call.Fn.NameFTrimmed == "Exactly" && !isBuiltinBool(pass, survivingArg) {
- // NOTE(a.telyshev): `Exactly` assumes no type casting.
+ // NOTE(a.telyshev): `Exactly` assumes no type conversion.
return nil
}
return newUseTrueDiagnostic(survivingArg, arg1.Pos(), arg2.End())
@@ -114,7 +112,7 @@ func (checker BoolCompare) Check(pass *analysis.Pass, call *CallMeta) *analysis.
case xor(f1, f2):
survivingArg, _ := anyVal([]bool{f1, f2}, arg2, arg1)
if call.Fn.NameFTrimmed == "Exactly" && !isBuiltinBool(pass, survivingArg) {
- // NOTE(a.telyshev): `Exactly` assumes no type casting.
+ // NOTE(a.telyshev): `Exactly` assumes no type conversion.
return nil
}
return newUseFalseDiagnostic(survivingArg, arg1.Pos(), arg2.End())
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/checkers_registry.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/checkers_registry.go
index 17c7d14ee..f881be4f2 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/checkers_registry.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/checkers_registry.go
@@ -13,10 +13,13 @@ var registry = checkersRegistry{
{factory: asCheckerFactory(NewLen), enabledByDefault: true},
{factory: asCheckerFactory(NewNegativePositive), enabledByDefault: true},
{factory: asCheckerFactory(NewCompares), enabledByDefault: true},
+ {factory: asCheckerFactory(NewContains), enabledByDefault: true},
{factory: asCheckerFactory(NewErrorNil), enabledByDefault: true},
{factory: asCheckerFactory(NewNilCompare), enabledByDefault: true},
{factory: asCheckerFactory(NewErrorIsAs), enabledByDefault: true},
+ {factory: asCheckerFactory(NewEncodedCompare), enabledByDefault: true},
{factory: asCheckerFactory(NewExpectedActual), enabledByDefault: true},
+ {factory: asCheckerFactory(NewRegexp), enabledByDefault: true},
{factory: asCheckerFactory(NewSuiteExtraAssertCall), enabledByDefault: true},
{factory: asCheckerFactory(NewSuiteDontUsePkg), enabledByDefault: true},
{factory: asCheckerFactory(NewUselessAssert), enabledByDefault: true},
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/compares.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/compares.go
index bdde03d95..f0c4013f1 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/compares.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/compares.go
@@ -61,7 +61,9 @@ func (checker Compares) Check(pass *analysis.Pass, call *CallMeta) *analysis.Dia
return nil
}
- if isPointer(pass, be.X) && isPointer(pass, be.Y) {
+ _, xp := isPointer(pass, be.X)
+ _, yp := isPointer(pass, be.Y)
+ if xp && yp {
switch proposedFn {
case "Equal":
proposedFn = "Same"
@@ -72,12 +74,11 @@ func (checker Compares) Check(pass *analysis.Pass, call *CallMeta) *analysis.Dia
a, b := be.X, be.Y
return newUseFunctionDiagnostic(checker.Name(), call, proposedFn,
- newSuggestedFuncReplacement(call, proposedFn, analysis.TextEdit{
+ analysis.TextEdit{
Pos: be.X.Pos(),
End: be.Y.End(),
NewText: formatAsCallArgs(pass, a, b),
- }),
- )
+ })
}
var tokenToProposedFnInsteadOfTrue = map[token.Token]string{
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/contains.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/contains.go
new file mode 100644
index 000000000..07f76c6e4
--- /dev/null
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/contains.go
@@ -0,0 +1,71 @@
+package checkers
+
+import (
+ "go/ast"
+
+ "golang.org/x/tools/go/analysis"
+)
+
+// Contains detects situations like
+//
+// assert.True(t, strings.Contains(a, "abc123"))
+// assert.False(t, !strings.Contains(a, "abc123"))
+//
+// assert.False(t, strings.Contains(a, "abc123"))
+// assert.True(t, !strings.Contains(a, "abc123"))
+//
+// and requires
+//
+// assert.Contains(t, a, "abc123")
+// assert.NotContains(t, a, "abc123")
+type Contains struct{}
+
+// NewContains constructs Contains checker.
+func NewContains() Contains { return Contains{} }
+func (Contains) Name() string { return "contains" }
+
+func (checker Contains) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
+ if len(call.Args) < 1 {
+ return nil
+ }
+
+ expr := call.Args[0]
+ unpacked, isNeg := isNegation(expr)
+ if isNeg {
+ expr = unpacked
+ }
+
+ ce, ok := expr.(*ast.CallExpr)
+ if !ok || len(ce.Args) != 2 {
+ return nil
+ }
+
+ if !isStringsContainsCall(pass, ce) {
+ return nil
+ }
+
+ var proposed string
+ switch call.Fn.NameFTrimmed {
+ default:
+ return nil
+
+ case "True":
+ proposed = "Contains"
+ if isNeg {
+ proposed = "NotContains"
+ }
+
+ case "False":
+ proposed = "NotContains"
+ if isNeg {
+ proposed = "Contains"
+ }
+ }
+
+ return newUseFunctionDiagnostic(checker.Name(), call, proposed,
+ analysis.TextEdit{
+ Pos: call.Args[0].Pos(),
+ End: call.Args[0].End(),
+ NewText: formatAsCallArgs(pass, ce.Args[0], ce.Args[1]),
+ })
+}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/empty.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/empty.go
index eafecb678..71657fe11 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/empty.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/empty.go
@@ -53,25 +53,28 @@ func (checker Empty) checkEmpty(pass *analysis.Pass, call *CallMeta) *analysis.D
newUseEmptyDiagnostic := func(replaceStart, replaceEnd token.Pos, replaceWith ast.Expr) *analysis.Diagnostic {
const proposed = "Empty"
return newUseFunctionDiagnostic(checker.Name(), call, proposed,
- newSuggestedFuncReplacement(call, proposed, analysis.TextEdit{
+ analysis.TextEdit{
Pos: replaceStart,
End: replaceEnd,
NewText: analysisutil.NodeBytes(pass.Fset, replaceWith),
- }),
- )
+ })
}
if len(call.Args) == 0 {
return nil
}
-
a := call.Args[0]
+
switch call.Fn.NameFTrimmed {
- case "Zero", "Empty":
- lenArg, ok := isBuiltinLenCall(pass, a)
- if ok {
+ case "Zero":
+ if lenArg, ok := isBuiltinLenCall(pass, a); ok {
return newUseEmptyDiagnostic(a.Pos(), a.End(), lenArg)
}
+
+ case "Empty":
+ if lenArg, ok := isBuiltinLenCall(pass, a); ok {
+ return newRemoveLenDiagnostic(pass, checker.Name(), call, a, lenArg)
+ }
}
if len(call.Args) < 2 {
@@ -120,25 +123,28 @@ func (checker Empty) checkNotEmpty(pass *analysis.Pass, call *CallMeta) *analysi
newUseNotEmptyDiagnostic := func(replaceStart, replaceEnd token.Pos, replaceWith ast.Expr) *analysis.Diagnostic {
const proposed = "NotEmpty"
return newUseFunctionDiagnostic(checker.Name(), call, proposed,
- newSuggestedFuncReplacement(call, proposed, analysis.TextEdit{
+ analysis.TextEdit{
Pos: replaceStart,
End: replaceEnd,
NewText: analysisutil.NodeBytes(pass.Fset, replaceWith),
- }),
- )
+ })
}
if len(call.Args) == 0 {
return nil
}
-
a := call.Args[0]
+
switch call.Fn.NameFTrimmed {
- case "NotZero", "NotEmpty", "Positive":
- lenArg, ok := isBuiltinLenCall(pass, a)
- if ok {
+ case "NotZero", "Positive":
+ if lenArg, ok := isBuiltinLenCall(pass, a); ok {
return newUseNotEmptyDiagnostic(a.Pos(), a.End(), lenArg)
}
+
+ case "NotEmpty":
+ if lenArg, ok := isBuiltinLenCall(pass, a); ok {
+ return newRemoveLenDiagnostic(pass, checker.Name(), call, a, lenArg)
+ }
}
if len(call.Args) < 2 {
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/encoded_compare.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/encoded_compare.go
new file mode 100644
index 000000000..53c74ac45
--- /dev/null
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/encoded_compare.go
@@ -0,0 +1,101 @@
+package checkers
+
+import (
+ "go/ast"
+
+ "golang.org/x/tools/go/analysis"
+)
+
+// EncodedCompare detects situations like
+//
+// assert.Equal(t, `{"foo": "bar"}`, body)
+// assert.EqualValues(t, `{"foo": "bar"}`, body)
+// assert.Exactly(t, `{"foo": "bar"}`, body)
+// assert.Equal(t, expectedJSON, resultJSON)
+// assert.Equal(t, expBodyConst, w.Body.String())
+// assert.Equal(t, fmt.Sprintf(`{"value":"%s"}`, hexString), result)
+// assert.Equal(t, "{}", json.RawMessage(resp))
+// assert.Equal(t, expJSON, strings.Trim(string(resultJSONBytes), "\n")) // + Replace, ReplaceAll, TrimSpace
+//
+// assert.Equal(t, expectedYML, conf)
+//
+// and requires
+//
+// assert.JSONEq(t, `{"foo": "bar"}`, body)
+// assert.YAMLEq(t, expectedYML, conf)
+type EncodedCompare struct{}
+
+// NewEncodedCompare constructs EncodedCompare checker.
+func NewEncodedCompare() EncodedCompare { return EncodedCompare{} }
+func (EncodedCompare) Name() string { return "encoded-compare" }
+
+func (checker EncodedCompare) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
+ switch call.Fn.NameFTrimmed {
+ case "Equal", "EqualValues", "Exactly":
+ default:
+ return nil
+ }
+
+ if len(call.Args) < 2 {
+ return nil
+ }
+ lhs, rhs := call.Args[0], call.Args[1]
+
+ a, aIsExplicitJSON := checker.unwrap(pass, call.Args[0])
+ b, bIsExplicitJSON := checker.unwrap(pass, call.Args[1])
+
+ var proposed string
+ switch {
+ case aIsExplicitJSON, bIsExplicitJSON, isJSONStyleExpr(pass, a), isJSONStyleExpr(pass, b):
+ proposed = "JSONEq"
+ case isYAMLStyleExpr(a), isYAMLStyleExpr(b):
+ proposed = "YAMLEq"
+ }
+
+ if proposed != "" {
+ return newUseFunctionDiagnostic(checker.Name(), call, proposed,
+ analysis.TextEdit{
+ Pos: lhs.Pos(),
+ End: lhs.End(),
+ NewText: formatWithStringCastForBytes(pass, a),
+ },
+ analysis.TextEdit{
+ Pos: rhs.Pos(),
+ End: rhs.End(),
+ NewText: formatWithStringCastForBytes(pass, b),
+ },
+ )
+ }
+ return nil
+}
+
+// unwrap unwraps expression from string, []byte, strings.Replace(All), strings.Trim(Space) and json.RawMessage conversions.
+// Returns true in the second argument, if json.RawMessage was in the chain.
+func (checker EncodedCompare) unwrap(pass *analysis.Pass, e ast.Expr) (ast.Expr, bool) {
+ ce, ok := e.(*ast.CallExpr)
+ if !ok {
+ return e, false
+ }
+ if len(ce.Args) == 0 {
+ return e, false
+ }
+
+ if isJSONRawMessageCast(pass, ce) {
+ if isNil(ce.Args[0]) { // NOTE(a.telyshev): Ignore json.RawMessage(nil) case.
+ return checker.unwrap(pass, ce.Args[0])
+ }
+
+ v, _ := checker.unwrap(pass, ce.Args[0])
+ return v, true
+ }
+
+ if isIdentWithName("string", ce.Fun) ||
+ isByteArray(ce.Fun) ||
+ isStringsReplaceCall(pass, ce) ||
+ isStringsReplaceAllCall(pass, ce) ||
+ isStringsTrimCall(pass, ce) ||
+ isStringsTrimSpaceCall(pass, ce) {
+ return checker.unwrap(pass, ce.Args[0])
+ }
+ return e, false
+}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/error_is_as.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/error_is_as.go
index ab92c2ec0..f2812c939 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/error_is_as.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/error_is_as.go
@@ -67,12 +67,11 @@ func (checker ErrorIsAs) Check(pass *analysis.Pass, call *CallMeta) *analysis.Di
}
if proposed != "" {
return newUseFunctionDiagnostic(checker.Name(), call, proposed,
- newSuggestedFuncReplacement(call, proposed, analysis.TextEdit{
+ analysis.TextEdit{
Pos: ce.Pos(),
End: ce.End(),
NewText: formatAsCallArgs(pass, ce.Args[0], ce.Args[1]),
- }),
- )
+ })
}
case "False":
@@ -91,12 +90,11 @@ func (checker ErrorIsAs) Check(pass *analysis.Pass, call *CallMeta) *analysis.Di
if isErrorsIsCall(pass, ce) {
const proposed = "NotErrorIs"
return newUseFunctionDiagnostic(checker.Name(), call, proposed,
- newSuggestedFuncReplacement(call, proposed, analysis.TextEdit{
+ analysis.TextEdit{
Pos: ce.Pos(),
End: ce.End(),
NewText: formatAsCallArgs(pass, ce.Args[0], ce.Args[1]),
- }),
- )
+ })
}
case "ErrorAs":
@@ -127,15 +125,15 @@ func (checker ErrorIsAs) Check(pass *analysis.Pass, call *CallMeta) *analysis.Di
pt, ok := tv.Type.Underlying().(*types.Pointer)
if !ok {
- return newDiagnostic(checker.Name(), call, defaultReport, nil)
+ return newDiagnostic(checker.Name(), call, defaultReport)
}
if pt.Elem() == errorType {
- return newDiagnostic(checker.Name(), call, errorPtrReport, nil)
+ return newDiagnostic(checker.Name(), call, errorPtrReport)
}
_, isInterface := pt.Elem().Underlying().(*types.Interface)
if !isInterface && !types.Implements(pt.Elem(), errorIface) {
- return newDiagnostic(checker.Name(), call, defaultReport, nil)
+ return newDiagnostic(checker.Name(), call, defaultReport)
}
}
return nil
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/error_nil.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/error_nil.go
index 1e56d222a..b9f28df21 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/error_nil.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/error_nil.go
@@ -12,12 +12,16 @@ import (
// ErrorNil detects situations like
//
// assert.Nil(t, err)
-// assert.NotNil(t, err)
+// assert.Empty(t, err)
+// assert.Zero(t, err)
// assert.Equal(t, nil, err)
// assert.EqualValues(t, nil, err)
// assert.Exactly(t, nil, err)
// assert.ErrorIs(t, err, nil)
//
+// assert.NotNil(t, err)
+// assert.NotEmpty(t, err)
+// assert.NotZero(t, err)
// assert.NotEqual(t, nil, err)
// assert.NotEqualValues(t, nil, err)
// assert.NotErrorIs(t, err, nil)
@@ -40,12 +44,12 @@ func (checker ErrorNil) Check(pass *analysis.Pass, call *CallMeta) *analysis.Dia
proposedFn, survivingArg, replacementEndPos := func() (string, ast.Expr, token.Pos) {
switch call.Fn.NameFTrimmed {
- case "Nil":
+ case "Nil", "Empty", "Zero":
if len(call.Args) >= 1 && isError(pass, call.Args[0]) {
return noErrorFn, call.Args[0], call.Args[0].End()
}
- case "NotNil":
+ case "NotNil", "NotEmpty", "NotZero":
if len(call.Args) >= 1 && isError(pass, call.Args[0]) {
return errorFn, call.Args[0], call.Args[0].End()
}
@@ -81,12 +85,11 @@ func (checker ErrorNil) Check(pass *analysis.Pass, call *CallMeta) *analysis.Dia
if proposedFn != "" {
return newUseFunctionDiagnostic(checker.Name(), call, proposedFn,
- newSuggestedFuncReplacement(call, proposedFn, analysis.TextEdit{
+ analysis.TextEdit{
Pos: call.Args[0].Pos(),
End: replacementEndPos,
NewText: analysisutil.NodeBytes(pass.Fset, survivingArg),
- }),
- )
+ })
}
return nil
}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/expected_actual.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/expected_actual.go
index 77784dc7b..351d675ce 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/expected_actual.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/expected_actual.go
@@ -87,7 +87,7 @@ func (checker ExpectedActual) Check(pass *analysis.Pass, call *CallMeta) *analys
first, second := call.Args[0], call.Args[1]
if checker.isWrongExpectedActualOrder(pass, first, second) {
- return newDiagnostic(checker.Name(), call, "need to reverse actual and expected values", &analysis.SuggestedFix{
+ return newDiagnostic(checker.Name(), call, "need to reverse actual and expected values", analysis.SuggestedFix{
Message: "Reverse actual and expected values",
TextEdits: []analysis.TextEdit{
{
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/float_compare.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/float_compare.go
index 7436f9ca1..6bc22cd02 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/float_compare.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/float_compare.go
@@ -44,7 +44,7 @@ func (checker FloatCompare) Check(pass *analysis.Pass, call *CallMeta) *analysis
if call.Fn.IsFmt {
format = "use %s.InEpsilonf (or InDeltaf)"
}
- return newDiagnostic(checker.Name(), call, fmt.Sprintf(format, call.SelectorXStr), nil)
+ return newDiagnostic(checker.Name(), call, fmt.Sprintf(format, call.SelectorXStr))
}
return nil
}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/formatter.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/formatter.go
index 3401bb097..896b6bf5f 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/formatter.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/formatter.go
@@ -1,8 +1,6 @@
package checkers
import (
- "fmt"
- "go/ast"
"go/types"
"strconv"
@@ -60,7 +58,7 @@ func (checker Formatter) Check(pass *analysis.Pass, call *CallMeta) (result *ana
}
func (checker Formatter) checkNotFmtAssertion(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
- msgAndArgsPos, ok := isPrintfLikeCall(pass, call, call.Fn.Signature)
+ msgAndArgsPos, ok := isPrintfLikeCall(pass, call)
if !ok {
return nil
}
@@ -71,21 +69,15 @@ func (checker Formatter) checkNotFmtAssertion(pass *analysis.Pass, call *CallMet
msgAndArgs := call.ArgsRaw[msgAndArgsPos]
if args, ok := isFmtSprintfCall(pass, msgAndArgs); ok {
if checker.requireFFuncs {
- msg := fmt.Sprintf("remove unnecessary fmt.Sprintf and use %s.%s", call.SelectorXStr, fFunc)
- return newDiagnostic(checker.Name(), call, msg,
- newSuggestedFuncReplacement(call, fFunc, analysis.TextEdit{
- Pos: msgAndArgs.Pos(),
- End: msgAndArgs.End(),
- NewText: formatAsCallArgs(pass, args...),
- }),
- )
+ return newRemoveFnAndUseDiagnostic(pass, checker.Name(), call, fFunc,
+ "fmt.Sprintf", msgAndArgs, args...)
}
return newRemoveSprintfDiagnostic(pass, checker.Name(), call, msgAndArgs, args)
}
}
if checker.requireFFuncs {
- return newUseFunctionDiagnostic(checker.Name(), call, fFunc, newSuggestedFuncReplacement(call, fFunc))
+ return newUseFunctionDiagnostic(checker.Name(), call, fFunc)
}
return nil
}
@@ -109,7 +101,7 @@ func (checker Formatter) checkFmtAssertion(pass *analysis.Pass, call *CallMeta)
defer func() { pass.Report = report }()
pass.Report = func(d analysis.Diagnostic) {
- result = newDiagnostic(checker.Name(), call, d.Message, nil)
+ result = newDiagnostic(checker.Name(), call, d.Message)
}
format, err := strconv.Unquote(analysisutil.NodeString(pass.Fset, msg))
@@ -121,21 +113,51 @@ func (checker Formatter) checkFmtAssertion(pass *analysis.Pass, call *CallMeta)
return result
}
-func isPrintfLikeCall(pass *analysis.Pass, call *CallMeta, sig *types.Signature) (int, bool) {
- msgAndArgsPos := getMsgAndArgsPosition(sig)
+func isPrintfLikeCall(pass *analysis.Pass, call *CallMeta) (int, bool) {
+ msgAndArgsPos := getMsgAndArgsPosition(call.Fn.Signature)
if msgAndArgsPos < 0 {
return -1, false
}
- fmtFn := analysisutil.ObjectOf(pass.Pkg, testify.AssertPkgPath, call.Fn.Name+"f")
- if fmtFn == nil {
- // NOTE(a.telyshev): No formatted analogue of assertion.
+ if !assertHasFormattedAnalogue(pass, call) {
return -1, false
}
return msgAndArgsPos, len(call.ArgsRaw) > msgAndArgsPos
}
+func assertHasFormattedAnalogue(pass *analysis.Pass, call *CallMeta) bool {
+ if fn := analysisutil.ObjectOf(pass.Pkg, testify.AssertPkgPath, call.Fn.Name+"f"); fn != nil {
+ return true
+ }
+
+ if fn := analysisutil.ObjectOf(pass.Pkg, testify.RequirePkgPath, call.Fn.Name+"f"); fn != nil {
+ return true
+ }
+
+ recv := call.Fn.Signature.Recv()
+ if recv == nil {
+ return false
+ }
+
+ recvT := recv.Type()
+ if ptr, ok := recv.Type().(*types.Pointer); ok {
+ recvT = ptr.Elem()
+ }
+
+ suite, ok := recvT.(*types.Named)
+ if !ok {
+ return false
+ }
+ for i := 0; i < suite.NumMethods(); i++ {
+ if suite.Method(i).Name() == call.Fn.Name+"f" {
+ return true
+ }
+ }
+
+ return false
+}
+
func getMsgAndArgsPosition(sig *types.Signature) int {
params := sig.Params()
if params.Len() < 1 {
@@ -162,26 +184,3 @@ func getMsgPosition(sig *types.Signature) int {
}
return -1
}
-
-func isFmtSprintfCall(pass *analysis.Pass, expr ast.Expr) ([]ast.Expr, bool) {
- ce, ok := expr.(*ast.CallExpr)
- if !ok {
- return nil, false
- }
-
- se, ok := ce.Fun.(*ast.SelectorExpr)
- if !ok {
- return nil, false
- }
-
- sprintfObj := analysisutil.ObjectOf(pass.Pkg, "fmt", "Sprintf")
- if sprintfObj == nil {
- return nil, false
- }
-
- if !analysisutil.IsObj(pass.TypesInfo, se.Sel, sprintfObj) {
- return nil, false
- }
-
- return ce.Args, true
-}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/go_require.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/go_require.go
index 060c96033..8b0d39999 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/go_require.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/go_require.go
@@ -142,11 +142,11 @@ func (checker GoRequire) Check(pass *analysis.Pass, inspector *inspector.Inspect
if testifyCall != nil {
switch checker.checkCall(testifyCall) {
case goRequireVerdictRequire:
- d := newDiagnostic(checker.Name(), testifyCall, fmt.Sprintf(goRequireCallReportFormat, "require"), nil)
+ d := newDiagnostic(checker.Name(), testifyCall, fmt.Sprintf(goRequireCallReportFormat, "require"))
diagnostics = append(diagnostics, *d)
case goRequireVerdictAssertFailNow:
- d := newDiagnostic(checker.Name(), testifyCall, fmt.Sprintf(goRequireCallReportFormat, testifyCall), nil)
+ d := newDiagnostic(checker.Name(), testifyCall, fmt.Sprintf(goRequireCallReportFormat, testifyCall))
diagnostics = append(diagnostics, *d)
case goRequireVerdictNoExit:
@@ -163,7 +163,7 @@ func (checker GoRequire) Check(pass *analysis.Pass, inspector *inspector.Inspect
if v := checker.checkFunc(pass, calledFd, testsDecls, processedFuncs); v != goRequireVerdictNoExit {
caller := analysisutil.NodeString(pass.Fset, ce.Fun)
- d := newDiagnostic(checker.Name(), ce, fmt.Sprintf(goRequireFnReportFormat, caller), nil)
+ d := newDiagnostic(checker.Name(), ce, fmt.Sprintf(goRequireFnReportFormat, caller))
diagnostics = append(diagnostics, *d)
}
}
@@ -198,11 +198,11 @@ func (checker GoRequire) checkHTTPHandlers(pass *analysis.Pass, insp *inspector.
switch checker.checkCall(testifyCall) {
case goRequireVerdictRequire:
- d := newDiagnostic(checker.Name(), testifyCall, fmt.Sprintf(goRequireHTTPHandlerReportFormat, "require"), nil)
+ d := newDiagnostic(checker.Name(), testifyCall, fmt.Sprintf(goRequireHTTPHandlerReportFormat, "require"))
diagnostics = append(diagnostics, *d)
case goRequireVerdictAssertFailNow:
- d := newDiagnostic(checker.Name(), testifyCall, fmt.Sprintf(goRequireHTTPHandlerReportFormat, testifyCall), nil)
+ d := newDiagnostic(checker.Name(), testifyCall, fmt.Sprintf(goRequireHTTPHandlerReportFormat, testifyCall))
diagnostics = append(diagnostics, *d)
case goRequireVerdictNoExit:
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_basic_type.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_basic_type.go
index 432a3032c..9b43e914c 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_basic_type.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_basic_type.go
@@ -1,10 +1,10 @@
package checkers
import (
- "fmt"
"go/ast"
"go/token"
"go/types"
+ "strconv"
"golang.org/x/tools/go/analysis"
)
@@ -56,9 +56,29 @@ func isTypedIntNumber(e ast.Expr, v int, types ...string) bool {
return false
}
-func isIntNumber(e ast.Expr, v int) bool {
+func isIntNumber(e ast.Expr, rhs int) bool {
+ lhs, ok := isIntBasicLit(e)
+ return ok && (lhs == rhs)
+}
+
+func isNegativeIntNumber(e ast.Expr) bool {
+ v, ok := isIntBasicLit(e)
+ return ok && v < 0
+}
+
+func isPositiveIntNumber(e ast.Expr) bool {
+ v, ok := isIntBasicLit(e)
+ return ok && v > 0
+}
+
+func isEmptyStringLit(e ast.Expr) bool {
+ bl, ok := e.(*ast.BasicLit)
+ return ok && bl.Kind == token.STRING && bl.Value == `""`
+}
+
+func isNotEmptyStringLit(e ast.Expr) bool {
bl, ok := e.(*ast.BasicLit)
- return ok && bl.Kind == token.INT && bl.Value == fmt.Sprintf("%d", v)
+ return ok && bl.Kind == token.STRING && bl.Value != `""`
}
func isBasicLit(e ast.Expr) bool {
@@ -66,9 +86,27 @@ func isBasicLit(e ast.Expr) bool {
return ok
}
-func isIntBasicLit(e ast.Expr) bool {
+func isIntBasicLit(e ast.Expr) (int, bool) {
+ if un, ok := e.(*ast.UnaryExpr); ok {
+ if un.Op == token.SUB {
+ v, ok := isIntBasicLit(un.X)
+ return -1 * v, ok
+ }
+ }
+
bl, ok := e.(*ast.BasicLit)
- return ok && bl.Kind == token.INT
+ if !ok {
+ return 0, false
+ }
+ if bl.Kind != token.INT {
+ return 0, false
+ }
+
+ v, err := strconv.Atoi(bl.Value)
+ if err != nil {
+ return 0, false
+ }
+ return v, true
}
func isUntypedConst(pass *analysis.Pass, e ast.Expr) bool {
@@ -98,12 +136,37 @@ func isUnderlying(pass *analysis.Pass, e ast.Expr, flag types.BasicInfo) bool {
return ok && (bt.Info()&flag > 0)
}
-func isPointer(pass *analysis.Pass, e ast.Expr) bool {
- _, ok := pass.TypesInfo.TypeOf(e).(*types.Pointer)
- return ok
+func isPointer(pass *analysis.Pass, e ast.Expr) (types.Type, bool) {
+ ptr, ok := pass.TypesInfo.TypeOf(e).(*types.Pointer)
+ if !ok {
+ return nil, false
+ }
+ return ptr.Elem(), true
+}
+
+// isByteArray returns true if expression is `[]byte` itself.
+func isByteArray(e ast.Expr) bool {
+ at, ok := e.(*ast.ArrayType)
+ return ok && isIdentWithName("byte", at.Elt)
+}
+
+// hasBytesType returns true if the expression is of `[]byte` type.
+func hasBytesType(pass *analysis.Pass, e ast.Expr) bool {
+ t := pass.TypesInfo.TypeOf(e)
+ if t == nil {
+ return false
+ }
+
+ sl, ok := t.(*types.Slice)
+ if !ok {
+ return false
+ }
+
+ el, ok := sl.Elem().(*types.Basic)
+ return ok && el.Kind() == types.Uint8
}
-// untype returns v from type(v) expression or v itself if there is no type cast.
+// untype returns v from type(v) expression or v itself if there is no type conversion.
func untype(e ast.Expr) ast.Expr {
ce, ok := e.(*ast.CallExpr)
if !ok || len(ce.Args) != 1 {
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_diagnostic.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_diagnostic.go
index 3ae88a560..f12d87aa3 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_diagnostic.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_diagnostic.go
@@ -7,11 +7,32 @@ import (
"golang.org/x/tools/go/analysis"
)
+func newRemoveFnAndUseDiagnostic(
+ pass *analysis.Pass,
+ checker string,
+ call *CallMeta,
+ proposedFn string,
+ removedFn string,
+ removedFnPos analysis.Range,
+ removedFnArgs ...ast.Expr,
+) *analysis.Diagnostic {
+ f := proposedFn
+ if call.Fn.IsFmt {
+ f += "f"
+ }
+ msg := fmt.Sprintf("remove unnecessary %s and use %s.%s", removedFn, call.SelectorXStr, f)
+
+ return newDiagnostic(checker, call, msg,
+ newSuggestedFuncRemoving(pass, removedFn, removedFnPos, removedFnArgs...),
+ newSuggestedFuncReplacement(call, proposedFn),
+ )
+}
+
func newUseFunctionDiagnostic(
checker string,
call *CallMeta,
proposedFn string,
- fix *analysis.SuggestedFix,
+ additionalEdits ...analysis.TextEdit,
) *analysis.Diagnostic {
f := proposedFn
if call.Fn.IsFmt {
@@ -19,33 +40,57 @@ func newUseFunctionDiagnostic(
}
msg := fmt.Sprintf("use %s.%s", call.SelectorXStr, f)
- return newDiagnostic(checker, call, msg, fix)
+ return newDiagnostic(checker, call, msg,
+ newSuggestedFuncReplacement(call, proposedFn, additionalEdits...))
+}
+
+func newRemoveLenDiagnostic(
+ pass *analysis.Pass,
+ checker string,
+ call *CallMeta,
+ fnPos analysis.Range,
+ fnArg ast.Expr,
+) *analysis.Diagnostic {
+ return newRemoveFnDiagnostic(pass, checker, call, "len", fnPos, fnArg)
+}
+
+func newRemoveMustCompileDiagnostic(
+ pass *analysis.Pass,
+ checker string,
+ call *CallMeta,
+ fnPos analysis.Range,
+ fnArg ast.Expr,
+) *analysis.Diagnostic {
+ return newRemoveFnDiagnostic(pass, checker, call, "regexp.MustCompile", fnPos, fnArg)
}
func newRemoveSprintfDiagnostic(
pass *analysis.Pass,
checker string,
call *CallMeta,
- sprintfPos analysis.Range,
- sprintfArgs []ast.Expr,
+ fnPos analysis.Range,
+ fnArgs []ast.Expr,
) *analysis.Diagnostic {
- return newDiagnostic(checker, call, "remove unnecessary fmt.Sprintf", &analysis.SuggestedFix{
- Message: "Remove `fmt.Sprintf`",
- TextEdits: []analysis.TextEdit{
- {
- Pos: sprintfPos.Pos(),
- End: sprintfPos.End(),
- NewText: formatAsCallArgs(pass, sprintfArgs...),
- },
- },
- })
+ return newRemoveFnDiagnostic(pass, checker, call, "fmt.Sprintf", fnPos, fnArgs...)
+}
+
+func newRemoveFnDiagnostic(
+ pass *analysis.Pass,
+ checker string,
+ call *CallMeta,
+ fnName string,
+ fnPos analysis.Range,
+ fnArgs ...ast.Expr,
+) *analysis.Diagnostic {
+ return newDiagnostic(checker, call, "remove unnecessary "+fnName,
+ newSuggestedFuncRemoving(pass, fnName, fnPos, fnArgs...))
}
func newDiagnostic(
checker string,
rng analysis.Range,
msg string,
- fix *analysis.SuggestedFix,
+ fixes ...analysis.SuggestedFix,
) *analysis.Diagnostic {
d := analysis.Diagnostic{
Pos: rng.Pos(),
@@ -53,21 +98,39 @@ func newDiagnostic(
Category: checker,
Message: checker + ": " + msg,
}
- if fix != nil {
- d.SuggestedFixes = []analysis.SuggestedFix{*fix}
+ if len(fixes) != 0 {
+ d.SuggestedFixes = fixes
}
return &d
}
+func newSuggestedFuncRemoving(
+ pass *analysis.Pass,
+ fnName string,
+ fnPos analysis.Range,
+ fnArgs ...ast.Expr,
+) analysis.SuggestedFix {
+ return analysis.SuggestedFix{
+ Message: fmt.Sprintf("Remove `%s`", fnName),
+ TextEdits: []analysis.TextEdit{
+ {
+ Pos: fnPos.Pos(),
+ End: fnPos.End(),
+ NewText: formatAsCallArgs(pass, fnArgs...),
+ },
+ },
+ }
+}
+
func newSuggestedFuncReplacement(
call *CallMeta,
proposedFn string,
additionalEdits ...analysis.TextEdit,
-) *analysis.SuggestedFix {
+) analysis.SuggestedFix {
if call.Fn.IsFmt {
proposedFn += "f"
}
- return &analysis.SuggestedFix{
+ return analysis.SuggestedFix{
Message: fmt.Sprintf("Replace `%s` with `%s`", call.Fn.Name, proposedFn),
TextEdits: append([]analysis.TextEdit{
{
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_encoded.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_encoded.go
new file mode 100644
index 000000000..35a497a72
--- /dev/null
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_encoded.go
@@ -0,0 +1,40 @@
+package checkers
+
+import (
+ "go/ast"
+ "go/token"
+ "regexp"
+
+ "golang.org/x/tools/go/analysis"
+
+ "github.com/Antonboom/testifylint/internal/analysisutil"
+)
+
+var (
+ jsonIdentRe = regexp.MustCompile(`json|JSON|Json`)
+ yamlIdentRe = regexp.MustCompile(`yaml|YAML|Yaml|yml|YML|Yml`)
+)
+
+func isJSONStyleExpr(pass *analysis.Pass, e ast.Expr) bool {
+ if isIdentNamedAfterPattern(jsonIdentRe, e) {
+ return true
+ }
+
+ if t, ok := pass.TypesInfo.Types[e]; ok && t.Value != nil {
+ return analysisutil.IsJSONLike(t.Value.String())
+ }
+
+ if bl, ok := e.(*ast.BasicLit); ok {
+ return bl.Kind == token.STRING && analysisutil.IsJSONLike(bl.Value)
+ }
+
+ if args, ok := isFmtSprintfCall(pass, e); ok {
+ return isJSONStyleExpr(pass, args[0])
+ }
+
+ return false
+}
+
+func isYAMLStyleExpr(e ast.Expr) bool {
+ return isIdentNamedAfterPattern(yamlIdentRe, e)
+}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_error.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_error.go
index 55cd5fd05..859a39ee8 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_error.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_error.go
@@ -5,8 +5,6 @@ import (
"go/types"
"golang.org/x/tools/go/analysis"
-
- "github.com/Antonboom/testifylint/internal/analysisutil"
)
var (
@@ -20,23 +18,9 @@ func isError(pass *analysis.Pass, expr ast.Expr) bool {
}
func isErrorsIsCall(pass *analysis.Pass, ce *ast.CallExpr) bool {
- return isErrorsPkgFnCall(pass, ce, "Is")
+ return isPkgFnCall(pass, ce, "errors", "Is")
}
func isErrorsAsCall(pass *analysis.Pass, ce *ast.CallExpr) bool {
- return isErrorsPkgFnCall(pass, ce, "As")
-}
-
-func isErrorsPkgFnCall(pass *analysis.Pass, ce *ast.CallExpr, fn string) bool {
- se, ok := ce.Fun.(*ast.SelectorExpr)
- if !ok {
- return false
- }
-
- errorsIsObj := analysisutil.ObjectOf(pass.Pkg, "errors", fn)
- if errorsIsObj == nil {
- return false
- }
-
- return analysisutil.IsObj(pass.TypesInfo, se.Sel, errorsIsObj)
+ return isPkgFnCall(pass, ce, "errors", "As")
}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_format.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_format.go
index 765fce527..d69c42860 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_format.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_format.go
@@ -3,6 +3,7 @@ package checkers
import (
"bytes"
"go/ast"
+ "strings"
"golang.org/x/tools/go/analysis"
@@ -24,3 +25,37 @@ func formatAsCallArgs(pass *analysis.Pass, args ...ast.Expr) []byte {
}
return buf.Bytes()
}
+
+func formatWithStringCastForBytes(pass *analysis.Pass, e ast.Expr) []byte {
+ if !hasBytesType(pass, e) {
+ return analysisutil.NodeBytes(pass.Fset, e)
+ }
+
+ if se, ok := isBufferBytesCall(pass, e); ok {
+ return []byte(analysisutil.NodeString(pass.Fset, se) + ".String()")
+ }
+ return []byte("string(" + analysisutil.NodeString(pass.Fset, e) + ")")
+}
+
+func isBufferBytesCall(pass *analysis.Pass, e ast.Expr) (ast.Node, bool) {
+ ce, ok := e.(*ast.CallExpr)
+ if !ok {
+ return nil, false
+ }
+
+ se, ok := ce.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return nil, false
+ }
+
+ if !isIdentWithName("Bytes", se.Sel) {
+ return nil, false
+ }
+ if t := pass.TypesInfo.TypeOf(se.X); t != nil {
+ // NOTE(a.telyshev): This is hack, because `bytes` package can be not imported,
+ // and we cannot do "true" comparison with `Buffer` object.
+ return se.X, strings.TrimPrefix(t.String(), "*") == "bytes.Buffer"
+ }
+
+ return nil, false
+}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_interface.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_interface.go
index b0c0d1302..ad39c72d7 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_interface.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_interface.go
@@ -15,8 +15,11 @@ func isEmptyInterface(pass *analysis.Pass, expr ast.Expr) bool {
if !ok {
return false
}
+ return isEmptyInterfaceType(t.Type)
+}
- iface, ok := t.Type.Underlying().(*types.Interface)
+func isEmptyInterfaceType(t types.Type) bool {
+ iface, ok := t.Underlying().(*types.Interface)
return ok && iface.NumMethods() == 0
}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_pkg_func.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_pkg_func.go
new file mode 100644
index 000000000..daf309339
--- /dev/null
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/helpers_pkg_func.go
@@ -0,0 +1,59 @@
+package checkers
+
+import (
+ "go/ast"
+
+ "golang.org/x/tools/go/analysis"
+
+ "github.com/Antonboom/testifylint/internal/analysisutil"
+)
+
+func isFmtSprintfCall(pass *analysis.Pass, e ast.Expr) ([]ast.Expr, bool) {
+ ce, ok := e.(*ast.CallExpr)
+ if !ok {
+ return nil, false
+ }
+ return ce.Args, isPkgFnCall(pass, ce, "fmt", "Sprintf")
+}
+
+func isJSONRawMessageCast(pass *analysis.Pass, ce *ast.CallExpr) bool {
+ return isPkgFnCall(pass, ce, "encoding/json", "RawMessage")
+}
+
+func isRegexpMustCompileCall(pass *analysis.Pass, ce *ast.CallExpr) bool {
+ return isPkgFnCall(pass, ce, "regexp", "MustCompile")
+}
+
+func isStringsContainsCall(pass *analysis.Pass, ce *ast.CallExpr) bool {
+ return isPkgFnCall(pass, ce, "strings", "Contains")
+}
+
+func isStringsReplaceCall(pass *analysis.Pass, ce *ast.CallExpr) bool {
+ return isPkgFnCall(pass, ce, "strings", "Replace")
+}
+
+func isStringsReplaceAllCall(pass *analysis.Pass, ce *ast.CallExpr) bool {
+ return isPkgFnCall(pass, ce, "strings", "ReplaceAll")
+}
+
+func isStringsTrimCall(pass *analysis.Pass, ce *ast.CallExpr) bool {
+ return isPkgFnCall(pass, ce, "strings", "Trim")
+}
+
+func isStringsTrimSpaceCall(pass *analysis.Pass, ce *ast.CallExpr) bool {
+ return isPkgFnCall(pass, ce, "strings", "TrimSpace")
+}
+
+func isPkgFnCall(pass *analysis.Pass, ce *ast.CallExpr, pkg, fn string) bool {
+ se, ok := ce.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return false
+ }
+
+ fnObj := analysisutil.ObjectOf(pass.Pkg, pkg, fn)
+ if fnObj == nil {
+ return false
+ }
+
+ return analysisutil.IsObj(pass.TypesInfo, se.Sel, fnObj)
+}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/len.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/len.go
index 47330568c..c240a6174 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/len.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/len.go
@@ -31,17 +31,16 @@ func (checker Len) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnost
a, b := call.Args[0], call.Args[1]
if lenArg, expectedLen, ok := xorLenCall(pass, a, b); ok {
- if expectedLen == b && !isIntBasicLit(expectedLen) {
+ if _, ok := isIntBasicLit(expectedLen); (expectedLen == b) && !ok {
// https://github.com/Antonboom/testifylint/issues/9
return nil
}
return newUseFunctionDiagnostic(checker.Name(), call, proposedFn,
- newSuggestedFuncReplacement(call, proposedFn, analysis.TextEdit{
+ analysis.TextEdit{
Pos: a.Pos(),
End: b.End(),
NewText: formatAsCallArgs(pass, lenArg, expectedLen),
- }),
- )
+ })
}
case "True":
@@ -50,14 +49,16 @@ func (checker Len) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnost
}
expr := call.Args[0]
- if lenArg, expectedLen, ok := isLenEquality(pass, expr); ok && isIntBasicLit(expectedLen) {
+ if lenArg, expectedLen, ok := isLenEquality(pass, expr); ok {
+ if _, ok := isIntBasicLit(expectedLen); !ok {
+ return nil
+ }
return newUseFunctionDiagnostic(checker.Name(), call, proposedFn,
- newSuggestedFuncReplacement(call, proposedFn, analysis.TextEdit{
+ analysis.TextEdit{
Pos: expr.Pos(),
End: expr.End(),
NewText: formatAsCallArgs(pass, lenArg, expectedLen),
- }),
- )
+ })
}
}
return nil
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/negative_postive.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/negative_positive.go
index 274021f67..a61bbdfcb 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/negative_postive.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/negative_positive.go
@@ -48,12 +48,11 @@ func (checker NegativePositive) checkNegative(pass *analysis.Pass, call *CallMet
newUseNegativeDiagnostic := func(replaceStart, replaceEnd token.Pos, replaceWith ast.Expr) *analysis.Diagnostic {
const proposed = "Negative"
return newUseFunctionDiagnostic(checker.Name(), call, proposed,
- newSuggestedFuncReplacement(call, proposed, analysis.TextEdit{
+ analysis.TextEdit{
Pos: replaceStart,
End: replaceEnd,
NewText: analysisutil.NodeBytes(pass.Fset, replaceWith),
- }),
- )
+ })
}
// NOTE(a.telyshev): We ignore uint-asserts as being no sense for assert.Negative.
@@ -114,12 +113,11 @@ func (checker NegativePositive) checkPositive(pass *analysis.Pass, call *CallMet
newUsePositiveDiagnostic := func(replaceStart, replaceEnd token.Pos, replaceWith ast.Expr) *analysis.Diagnostic {
const proposed = "Positive"
return newUseFunctionDiagnostic(checker.Name(), call, proposed,
- newSuggestedFuncReplacement(call, proposed, analysis.TextEdit{
+ analysis.TextEdit{
Pos: replaceStart,
End: replaceEnd,
NewText: analysisutil.NodeBytes(pass.Fset, replaceWith),
- }),
- )
+ })
}
switch call.Fn.NameFTrimmed {
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/nil_compare.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/nil_compare.go
index 47c4a7383..fc1adb7ea 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/nil_compare.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/nil_compare.go
@@ -47,10 +47,9 @@ func (checker NilCompare) Check(pass *analysis.Pass, call *CallMeta) *analysis.D
}
return newUseFunctionDiagnostic(checker.Name(), call, proposedFn,
- newSuggestedFuncReplacement(call, proposedFn, analysis.TextEdit{
+ analysis.TextEdit{
Pos: call.Args[0].Pos(),
End: call.Args[1].End(),
NewText: analysisutil.NodeBytes(pass.Fset, survivingArg),
- }),
- )
+ })
}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/printf/printf.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/printf/printf.go
index cfb47b542..4f6e3f9c4 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/printf/printf.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/printf/printf.go
@@ -213,9 +213,9 @@ func isFormatter(typ types.Type) bool {
types.Identical(sig.Params().At(1).Type(), types.Typ[types.Rune])
}
-// isTypeParam reports whether t is a type parameter.
+// isTypeParam reports whether t is a type parameter (or an alias of one).
func isTypeParam(t types.Type) bool {
- _, ok := t.(*types.TypeParam)
+ _, ok := types.Unalias(t).(*types.TypeParam)
return ok
}
@@ -224,7 +224,7 @@ func isTypeParam(t types.Type) bool {
// This function avoids allocating the concatenation of "pkg.Name",
// which is important for the performance of syntax matching.
func isNamedType(t types.Type, pkgPath string, names ...string) bool {
- n, ok := t.(*types.Named)
+ n, ok := types.Unalias(t).(*types.Named)
if !ok {
return false
}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/regexp.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/regexp.go
new file mode 100644
index 000000000..d634b74bd
--- /dev/null
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/regexp.go
@@ -0,0 +1,44 @@
+package checkers
+
+import (
+ "go/ast"
+
+ "golang.org/x/tools/go/analysis"
+)
+
+// Regexp detects situations like
+//
+// assert.Regexp(t, regexp.MustCompile(`\[.*\] DEBUG \(.*TestNew.*\): message`), out)
+// assert.NotRegexp(t, regexp.MustCompile(`\[.*\] TRACE message`), out)
+//
+// and requires
+//
+// assert.Regexp(t, `\[.*\] DEBUG \(.*TestNew.*\): message`, out)
+// assert.NotRegexp(t, `\[.*\] TRACE message`, out)
+type Regexp struct{}
+
+// NewRegexp constructs Regexp checker.
+func NewRegexp() Regexp { return Regexp{} }
+func (Regexp) Name() string { return "regexp" }
+
+func (checker Regexp) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
+ switch call.Fn.NameFTrimmed {
+ default:
+ return nil
+ case "Regexp", "NotRegexp":
+ }
+
+ if len(call.Args) < 1 {
+ return nil
+ }
+
+ ce, ok := call.Args[0].(*ast.CallExpr)
+ if !ok || len(ce.Args) != 1 {
+ return nil
+ }
+
+ if isRegexpMustCompileCall(pass, ce) {
+ return newRemoveMustCompileDiagnostic(pass, checker.Name(), call, ce, ce.Args[0])
+ }
+ return nil
+}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/require_error.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/require_error.go
index 4303828fd..e4e30aaf4 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/require_error.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/require_error.go
@@ -134,7 +134,7 @@ func (checker RequireError) Check(pass *analysis.Pass, inspector *inspector.Insp
}
diagnostics = append(diagnostics,
- *newDiagnostic(checker.Name(), c.testifyCall, requireErrorReport, nil))
+ *newDiagnostic(checker.Name(), c.testifyCall, requireErrorReport))
}
}
@@ -197,11 +197,10 @@ func findRootIf(stack []ast.Node) *ast.IfStmt {
nearestIf, i := findNearestNodeWithIdx[*ast.IfStmt](stack)
for ; i > 0; i-- {
parent, ok := stack[i-1].(*ast.IfStmt)
- if ok {
- nearestIf = parent
- } else {
+ if !ok {
break
}
+ nearestIf = parent
}
return nearestIf
}
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_broken_parallel.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_broken_parallel.go
index f830fd2a5..4374c9359 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_broken_parallel.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_broken_parallel.go
@@ -68,7 +68,7 @@ func (checker SuiteBrokenParallel) Check(pass *analysis.Pass, insp *inspector.In
}
nextLine := pass.Fset.Position(ce.Pos()).Line + 1
- d := newDiagnostic(checker.Name(), ce, report, &analysis.SuggestedFix{
+ d := newDiagnostic(checker.Name(), ce, report, analysis.SuggestedFix{
Message: fmt.Sprintf("Remove `%s` call", analysisutil.NodeString(pass.Fset, ce)),
TextEdits: []analysis.TextEdit{
{
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_dont_use_pkg.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_dont_use_pkg.go
index 6150ae78d..4fbfbe7e0 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_dont_use_pkg.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_dont_use_pkg.go
@@ -60,7 +60,7 @@ func (checker SuiteDontUsePkg) Check(pass *analysis.Pass, call *CallMeta) *analy
}
msg := fmt.Sprintf("use %s.%s", newSelector, call.Fn.Name)
- return newDiagnostic(checker.Name(), call, msg, &analysis.SuggestedFix{
+ return newDiagnostic(checker.Name(), call, msg, analysis.SuggestedFix{
Message: fmt.Sprintf("Replace `%s` with `%s`", call.SelectorXStr, newSelector),
TextEdits: []analysis.TextEdit{
// Replace package function with suite method.
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_extra_assert_call.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_extra_assert_call.go
index 9adfe5190..fdea324fd 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_extra_assert_call.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_extra_assert_call.go
@@ -61,7 +61,7 @@ func (checker SuiteExtraAssertCall) Check(pass *analysis.Pass, call *CallMeta) *
}
msg := fmt.Sprintf("use an explicit %s.Assert().%s", analysisutil.NodeString(pass.Fset, x), call.Fn.Name)
- return newDiagnostic(checker.Name(), call, msg, &analysis.SuggestedFix{
+ return newDiagnostic(checker.Name(), call, msg, analysis.SuggestedFix{
Message: "Add `Assert()` call",
TextEdits: []analysis.TextEdit{{
Pos: x.End(),
@@ -85,7 +85,7 @@ func (checker SuiteExtraAssertCall) Check(pass *analysis.Pass, call *CallMeta) *
}
msg := fmt.Sprintf("need to simplify the assertion to %s.%s", analysisutil.NodeString(pass.Fset, se.X), call.Fn.Name)
- return newDiagnostic(checker.Name(), call, msg, &analysis.SuggestedFix{
+ return newDiagnostic(checker.Name(), call, msg, analysis.SuggestedFix{
Message: "Remove `Assert()` call",
TextEdits: []analysis.TextEdit{{
Pos: se.Sel.Pos(),
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_subtest_run.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_subtest_run.go
index 67d9c252b..525d5ffd8 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_subtest_run.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_subtest_run.go
@@ -53,7 +53,7 @@ func (checker SuiteSubtestRun) Check(pass *analysis.Pass, insp *inspector.Inspec
if implementsTestifySuite(pass, tCallSel.X) && implementsTestingT(pass, tCall) {
msg := fmt.Sprintf("use %s.Run to run subtest", analysisutil.NodeString(pass.Fset, tCallSel.X))
- diagnostics = append(diagnostics, *newDiagnostic(checker.Name(), ce, msg, nil))
+ diagnostics = append(diagnostics, *newDiagnostic(checker.Name(), ce, msg))
}
})
return diagnostics
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_thelper.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_thelper.go
index 59455290d..ef8d82132 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_thelper.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/suite_thelper.go
@@ -50,8 +50,8 @@ func (checker SuiteTHelper) Check(pass *analysis.Pass, inspector *inspector.Insp
return
}
- msg := fmt.Sprintf("suite helper method must start with " + helperCallStr)
- d := newDiagnostic(checker.Name(), fd, msg, &analysis.SuggestedFix{
+ msg := "suite helper method must start with " + helperCallStr
+ d := newDiagnostic(checker.Name(), fd, msg, analysis.SuggestedFix{
Message: fmt.Sprintf("Insert `%s`", helperCallStr),
TextEdits: []analysis.TextEdit{
{
diff --git a/vendor/github.com/Antonboom/testifylint/internal/checkers/useless_assert.go b/vendor/github.com/Antonboom/testifylint/internal/checkers/useless_assert.go
index 6f206d095..045706e5d 100644
--- a/vendor/github.com/Antonboom/testifylint/internal/checkers/useless_assert.go
+++ b/vendor/github.com/Antonboom/testifylint/internal/checkers/useless_assert.go
@@ -10,15 +10,40 @@ import (
// UselessAssert detects useless asserts like
//
-// 1) Asserting of the same variable
-//
+// assert.Contains(t, tt.value, tt.value)
+// assert.ElementsMatch(t, tt.value, tt.value)
// assert.Equal(t, tt.value, tt.value)
-// assert.ElementsMatch(t, users, users)
+// assert.EqualExportedValues(t, tt.value, tt.value)
// ...
+//
// assert.True(t, num > num)
+// assert.True(t, num < num)
+// assert.True(t, num >= num)
+// assert.True(t, num <= num)
+// assert.True(t, num == num)
+// assert.True(t, num != num)
+//
+// assert.False(t, num > num)
+// assert.False(t, num < num)
+// assert.False(t, num >= num)
+// assert.False(t, num <= num)
// assert.False(t, num == num)
+// assert.False(t, num != num)
//
-// 2) Open for contribution...
+// assert.Empty(t, "")
+// assert.False(t, false)
+// assert.Implements(t, (*any)(nil), new(Conn))
+// assert.Negative(t, -42)
+// assert.Nil(t, nil)
+// assert.NoError(t, nil)
+// assert.NotEmpty(t, "value")
+// assert.NotZero(t, 42)
+// assert.NotZero(t, "value")
+// assert.Positive(t, 42)
+// assert.True(t, true)
+// assert.Zero(t, 0)
+// assert.Zero(t, "")
+// assert.Zero(t, nil)
type UselessAssert struct{}
// NewUselessAssert constructs UselessAssert checker.
@@ -26,6 +51,58 @@ func NewUselessAssert() UselessAssert { return UselessAssert{} }
func (UselessAssert) Name() string { return "useless-assert" }
func (checker UselessAssert) Check(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
+ if d := checker.checkSameVars(pass, call); d != nil {
+ return d
+ }
+
+ var isMeaningless bool
+ switch call.Fn.NameFTrimmed {
+ case "Empty":
+ isMeaningless = (len(call.Args) >= 1) && isEmptyStringLit(call.Args[0])
+
+ case "False":
+ isMeaningless = (len(call.Args) >= 1) && isUntypedFalse(pass, call.Args[0])
+
+ case "Implements":
+ if len(call.Args) < 2 {
+ return nil
+ }
+
+ elem, ok := isPointer(pass, call.Args[0])
+ isMeaningless = ok && isEmptyInterfaceType(elem)
+
+ case "Negative":
+ isMeaningless = (len(call.Args) >= 1) && isNegativeIntNumber(call.Args[0])
+
+ case "Nil", "NoError":
+ isMeaningless = (len(call.Args) >= 1) && isNil(call.Args[0])
+
+ case "NotEmpty":
+ isMeaningless = (len(call.Args) >= 1) && isNotEmptyStringLit(call.Args[0])
+
+ case "NotZero":
+ isMeaningless = (len(call.Args) >= 1) &&
+ (isNotEmptyStringLit(call.Args[0]) ||
+ isNegativeIntNumber(call.Args[0]) || isPositiveIntNumber(call.Args[0]))
+
+ case "Positive":
+ isMeaningless = (len(call.Args) >= 1) && isPositiveIntNumber(call.Args[0])
+
+ case "True":
+ isMeaningless = (len(call.Args) >= 1) && isUntypedTrue(pass, call.Args[0])
+
+ case "Zero":
+ isMeaningless = (len(call.Args) >= 1) &&
+ (isZero(call.Args[0]) || isEmptyStringLit(call.Args[0]) || isNil(call.Args[0]))
+ }
+
+ if isMeaningless {
+ return newDiagnostic(checker.Name(), call, "meaningless assertion")
+ }
+ return nil
+}
+
+func (checker UselessAssert) checkSameVars(pass *analysis.Pass, call *CallMeta) *analysis.Diagnostic {
var first, second ast.Node
switch call.Fn.NameFTrimmed {
@@ -82,7 +159,7 @@ func (checker UselessAssert) Check(pass *analysis.Pass, call *CallMeta) *analysi
}
if analysisutil.NodeString(pass.Fset, first) == analysisutil.NodeString(pass.Fset, second) {
- return newDiagnostic(checker.Name(), call, "asserting of the same variable", nil)
+ return newDiagnostic(checker.Name(), call, "asserting of the same variable")
}
return nil
}