aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/nunnatsa
diff options
context:
space:
mode:
authordependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>2024-03-04 17:40:11 +0000
committerTaras Madan <tarasmadan@google.com>2024-03-04 18:34:55 +0000
commit5fc5366972c874b919f93165bb4ed4e2bcb7c350 (patch)
tree287c3361a0dee0c72af80d9a1a66714a06e98a62 /vendor/github.com/nunnatsa
parent1be5ce38a9059c356eb193a8c34d60d61c9fc31f (diff)
mod: bump github.com/golangci/golangci-lint from 1.55.2 to 1.56.2
Bumps [github.com/golangci/golangci-lint](https://github.com/golangci/golangci-lint) from 1.55.2 to 1.56.2. - [Release notes](https://github.com/golangci/golangci-lint/releases) - [Changelog](https://github.com/golangci/golangci-lint/blob/master/CHANGELOG.md) - [Commits](https://github.com/golangci/golangci-lint/compare/v1.55.2...v1.56.2) --- updated-dependencies: - dependency-name: github.com/golangci/golangci-lint dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Diffstat (limited to 'vendor/github.com/nunnatsa')
-rw-r--r--vendor/github.com/nunnatsa/ginkgolinter/Makefile5
-rw-r--r--vendor/github.com/nunnatsa/ginkgolinter/README.md32
-rw-r--r--vendor/github.com/nunnatsa/ginkgolinter/ginkgo_linter.go153
-rw-r--r--vendor/github.com/nunnatsa/ginkgolinter/gomegahandler/handler.go6
-rw-r--r--vendor/github.com/nunnatsa/ginkgolinter/interfaces/interfaces.go76
5 files changed, 253 insertions, 19 deletions
diff --git a/vendor/github.com/nunnatsa/ginkgolinter/Makefile b/vendor/github.com/nunnatsa/ginkgolinter/Makefile
index e8efae583..586633006 100644
--- a/vendor/github.com/nunnatsa/ginkgolinter/Makefile
+++ b/vendor/github.com/nunnatsa/ginkgolinter/Makefile
@@ -5,9 +5,12 @@ HASH_FLAG := -X github.com/nunnatsa/ginkgolinter/version.gitHash=$(COMMIT_HASH)
BUILD_ARGS := -ldflags "$(VERSION_FLAG) $(HASH_FLAG)"
-build:
+build: unit-test
go build $(BUILD_ARGS) -o ginkgolinter ./cmd/ginkgolinter
+unit-test:
+ go test ./...
+
build-for-windows:
GOOS=windows GOARCH=amd64 go build $(BUILD_ARGS) -o bin/ginkgolinter-amd64.exe ./cmd/ginkgolinter
diff --git a/vendor/github.com/nunnatsa/ginkgolinter/README.md b/vendor/github.com/nunnatsa/ginkgolinter/README.md
index 6c95917d2..3832f610d 100644
--- a/vendor/github.com/nunnatsa/ginkgolinter/README.md
+++ b/vendor/github.com/nunnatsa/ginkgolinter/README.md
@@ -44,7 +44,7 @@ It is not enabled by default, though. There are two ways to run ginkgolinter wit
enable:
- ginkgolinter
```
-## Linter Checks
+## Linter Rules
The linter checks the ginkgo and gomega assertions in golang test code. Gomega may be used together with ginkgo tests,
For example:
```go
@@ -177,7 +177,8 @@ var _ = Describe("checking something", Focus, func() {
})
```
-These container, or the `Focus` spec, must not be part of the final source code, and should only be used locally by the developer.
+These container, or the `Focus` spec, must not be part of the final source code, and should only be used locally by the
+developer.
***This rule is disabled by default***. Use the `--forbid-focus-container=true` command line flag to enable it.
@@ -205,8 +206,30 @@ To suppress this warning entirely, use the `--suppress-type-compare-assertion=tr
To suppress a specific file or line, use the `// ginkgo-linter:ignore-type-compare-warning` comment (see [below](#suppress-warning-from-the-code))
+### Wrong Usage of the `MatchError` gomega Matcher [BUG]
+The `MatchError` gomega matcher asserts an error value (and if it's not nil).
+There are four valid formats for using this Matcher:
+* error value; e.g. `Expect(err).To(MatchError(anotherErr))`
+* string, to be equal to the output of the `Error()` method; e.g. `Expect(err).To(MatchError("Not Found"))`
+* A gomega matcher that asserts strings; e.g. `Expect(err).To(MatchError(ContainSubstring("Found")))`
+* [from v0.29.0] a function that receive a single error parameter and returns a single boolean value.
+ In this format, an additional single string parameter, with the function description, is also required; e.g.
+ `Expect(err).To(MatchError(isNotFound, "is the error is a not found error"))`
+
+These four format are checked on runtime, but sometimes it's too late. ginkgolinter performs a static analysis and so it
+will find these issues on build time.
+
+ginkgolinter checks the following:
+* Is the first parameter is one of the four options above.
+* That there are no additional parameters passed to the matcher; e.g.
+ `MatchError(isNotFoundFunc, "a valid description" , "not used string")`. In this case, the matcher won't fail on run
+ time, but the additional parameters are not in use and ignored.
+* If the first parameter is a function with the format of `func(error)bool`, ginkgolinter makes sure that the second
+ parameter exists and its type is string.
+
### Wrong Length Assertion [STYLE]
-The linter finds assertion of the golang built-in `len` function, with all kind of matchers, while there are already gomega matchers for these usecases; We want to assert the item, rather than its length.
+The linter finds assertion of the golang built-in `len` function, with all kind of matchers, while there are already
+gomega matchers for these usecases; We want to assert the item, rather than its length.
There are several wrong patterns:
```go
@@ -240,7 +263,8 @@ The output of the linter,when finding issues, looks like this:
The linter will also warn about the `HaveLen(0)` matcher, and will suggest to replace it with `BeEmpty()`
### Wrong `nil` Assertion [STYLE]
-The linter finds assertion of the comparison to nil, with all kind of matchers, instead of using the existing `BeNil()` matcher; We want to assert the item, rather than a comparison result.
+The linter finds assertion of the comparison to nil, with all kind of matchers, instead of using the existing `BeNil()`
+matcher; We want to assert the item, rather than a comparison result.
There are several wrong patterns:
diff --git a/vendor/github.com/nunnatsa/ginkgolinter/ginkgo_linter.go b/vendor/github.com/nunnatsa/ginkgolinter/ginkgo_linter.go
index d1e5164fa..a0aff1612 100644
--- a/vendor/github.com/nunnatsa/ginkgolinter/ginkgo_linter.go
+++ b/vendor/github.com/nunnatsa/ginkgolinter/ginkgo_linter.go
@@ -16,6 +16,7 @@ import (
"github.com/nunnatsa/ginkgolinter/ginkgohandler"
"github.com/nunnatsa/ginkgolinter/gomegahandler"
+ "github.com/nunnatsa/ginkgolinter/interfaces"
"github.com/nunnatsa/ginkgolinter/reverseassertion"
"github.com/nunnatsa/ginkgolinter/types"
"github.com/nunnatsa/ginkgolinter/version"
@@ -40,8 +41,13 @@ const (
focusContainerFound = linterName + ": Focus container found. This is used only for local debug and should not be part of the actual source code, consider to replace with %q"
focusSpecFound = linterName + ": Focus spec found. This is used only for local debug and should not be part of the actual source code, consider to remove it"
compareDifferentTypes = linterName + ": use %[1]s with different types: Comparing %[2]s with %[3]s; either change the expected value type if possible, or use the BeEquivalentTo() matcher, instead of %[1]s()"
- compareInterfaces = linterName + ": be careful comparing interfaces. This can fail in runtime, if the actual implementing types are different"
+ matchErrorArgWrongType = linterName + ": the MatchError matcher used to assert a non error type (%s)"
+ matchErrorWrongTypeAssertion = linterName + ": MatchError first parameter (%s) must be error, string, GomegaMatcher or func(error)bool are allowed"
+ matchErrorMissingDescription = linterName + ": missing function description as second parameter of MatchError"
+ matchErrorRedundantArg = linterName + ": redundant MatchError arguments; consider removing them; consider using `%s` instead"
+ matchErrorNoFuncDescription = linterName + ": The second parameter of MatchError must be the function description (string)"
)
+
const ( // gomega matchers
beEmpty = "BeEmpty"
beEquivalentTo = "BeEquivalentTo"
@@ -61,6 +67,7 @@ const ( // gomega matchers
and = "And"
or = "Or"
withTransform = "WithTransform"
+ matchError = "MatchError"
)
const ( // gomega actuals
@@ -133,6 +140,8 @@ currently, the linter searches for following:
* trigger a warning when a ginkgo focus container (FDescribe, FContext, FWhen or FIt) is found. [Bug]
+* validate the MatchError gomega matcher [Bug]
+
* trigger a warning when using the Equal or the BeIdentical matcher with two different types, as these matchers will
fail in runtime.
@@ -179,6 +188,8 @@ func (l *ginkgoLinter) run(pass *analysis.Pass) (interface{}, error) {
continue
}
+ //gomegaMatcher = getMatcherInterface(pass, file)
+
ast.Inspect(file, func(n ast.Node) bool {
if ginkgoHndlr != nil && fileConfig.ForbidFocus {
spec, ok := n.(*ast.ValueSpec)
@@ -304,6 +315,8 @@ func checkExpression(pass *analysis.Pass, config types.Config, assertionExp *ast
}
return bool(config.SuppressCompare) || checkComparison(expr, pass, matcher, handler, first, second, op, oldExpr)
+ } else if checkMatchError(pass, assertionExp, actualArg, handler, oldExpr) {
+ return false
} else if isExprError(pass, actualArg) {
return bool(config.SuppressErr) || checkNilError(pass, expr, handler, actualArg, oldExpr)
@@ -318,6 +331,130 @@ func checkExpression(pass *analysis.Pass, config types.Config, assertionExp *ast
return true
}
+func checkMatchError(pass *analysis.Pass, origExp *ast.CallExpr, actualArg ast.Expr, handler gomegahandler.Handler, oldExpr string) bool {
+ matcher, ok := origExp.Args[0].(*ast.CallExpr)
+ if !ok {
+ return false
+ }
+
+ return doCheckMatchError(pass, origExp, matcher, actualArg, handler, oldExpr)
+}
+
+func doCheckMatchError(pass *analysis.Pass, origExp *ast.CallExpr, matcher *ast.CallExpr, actualArg ast.Expr, handler gomegahandler.Handler, oldExpr string) bool {
+ name, ok := handler.GetActualFuncName(matcher)
+ if !ok {
+ return false
+ }
+ switch name {
+ case matchError:
+ case not:
+ nested, ok := matcher.Args[0].(*ast.CallExpr)
+ if !ok {
+ return false
+ }
+
+ return doCheckMatchError(pass, origExp, nested, actualArg, handler, oldExpr)
+ case and, or:
+ res := true
+ for _, arg := range matcher.Args {
+ if nested, ok := arg.(*ast.CallExpr); ok {
+ if !doCheckMatchError(pass, origExp, nested, actualArg, handler, oldExpr) {
+ res = false
+ }
+ }
+ }
+ return res
+ default:
+ return false
+ }
+
+ if !isExprError(pass, actualArg) {
+ reportNoFix(pass, origExp.Pos(), matchErrorArgWrongType, goFmt(pass.Fset, actualArg))
+ }
+
+ expr := astcopy.CallExpr(matcher)
+
+ validAssertion, requiredParams := checkMatchErrorAssertion(pass, matcher)
+ if !validAssertion {
+ reportNoFix(pass, expr.Pos(), matchErrorWrongTypeAssertion, goFmt(pass.Fset, matcher.Args[0]))
+ return false
+ }
+
+ numParams := len(matcher.Args)
+ if numParams == requiredParams {
+ if numParams == 2 {
+ t := pass.TypesInfo.TypeOf(matcher.Args[1])
+ if !gotypes.Identical(t, gotypes.Typ[gotypes.String]) {
+ pass.Reportf(expr.Pos(), matchErrorNoFuncDescription)
+ return false
+ }
+ }
+ return true
+ }
+
+ if requiredParams == 2 && numParams == 1 {
+ reportNoFix(pass, expr.Pos(), matchErrorMissingDescription)
+ return false
+ }
+
+ var newArgsSuggestion = []ast.Expr{expr.Args[0]}
+ if requiredParams == 2 {
+ newArgsSuggestion = append(newArgsSuggestion, expr.Args[1])
+ }
+ expr.Args = newArgsSuggestion
+ report(pass, expr, matchErrorRedundantArg, oldExpr)
+ return false
+}
+
+func checkMatchErrorAssertion(pass *analysis.Pass, matcher *ast.CallExpr) (bool, int) {
+ if isErrorMatcherValidArg(pass, matcher.Args[0]) {
+ return true, 1
+ }
+
+ t1 := pass.TypesInfo.TypeOf(matcher.Args[0])
+ if isFuncErrBool(t1) {
+ return true, 2
+ }
+
+ return false, 0
+}
+
+// isFuncErrBool checks if a function is with the signature `func(error) bool`
+func isFuncErrBool(t gotypes.Type) bool {
+ sig, ok := t.(*gotypes.Signature)
+ if !ok {
+ return false
+ }
+ if sig.Params().Len() != 1 || sig.Results().Len() != 1 {
+ return false
+ }
+
+ if !interfaces.ImplementsError(sig.Params().At(0).Type()) {
+ return false
+ }
+
+ b, ok := sig.Results().At(0).Type().(*gotypes.Basic)
+ if ok && b.Name() == "bool" && b.Info() == gotypes.IsBoolean && b.Kind() == gotypes.Bool {
+ return true
+ }
+
+ return false
+}
+
+func isErrorMatcherValidArg(pass *analysis.Pass, arg ast.Expr) bool {
+ if isExprError(pass, arg) {
+ return true
+ }
+
+ if t, ok := pass.TypesInfo.TypeOf(arg).(*gotypes.Basic); ok && t.Kind() == gotypes.String {
+ return true
+ }
+
+ t := pass.TypesInfo.TypeOf(arg)
+
+ return interfaces.ImplementsGomegaMatcher(t)
+}
+
func checkEqualWrongType(pass *analysis.Pass, origExp *ast.CallExpr, actualArg ast.Expr, handler gomegahandler.Handler, old string) bool {
matcher, ok := origExp.Args[0].(*ast.CallExpr)
if !ok {
@@ -1297,28 +1434,18 @@ func goFmt(fset *token.FileSet, x ast.Expr) string {
return b.String()
}
-var errorType *gotypes.Interface
-
-func init() {
- errorType = gotypes.Universe.Lookup("error").Type().Underlying().(*gotypes.Interface)
-}
-
-func isError(t gotypes.Type) bool {
- return gotypes.Implements(t, errorType)
-}
-
func isExprError(pass *analysis.Pass, expr ast.Expr) bool {
actualArgType := pass.TypesInfo.TypeOf(expr)
switch t := actualArgType.(type) {
case *gotypes.Named:
- if isError(actualArgType) {
+ if interfaces.ImplementsError(actualArgType) {
return true
}
case *gotypes.Tuple:
if t.Len() > 0 {
switch t0 := t.At(0).Type().(type) {
case *gotypes.Named, *gotypes.Pointer:
- if isError(t0) {
+ if interfaces.ImplementsError(t0) {
return true
}
}
diff --git a/vendor/github.com/nunnatsa/ginkgolinter/gomegahandler/handler.go b/vendor/github.com/nunnatsa/ginkgolinter/gomegahandler/handler.go
index 0c34cb7c1..419145b75 100644
--- a/vendor/github.com/nunnatsa/ginkgolinter/gomegahandler/handler.go
+++ b/vendor/github.com/nunnatsa/ginkgolinter/gomegahandler/handler.go
@@ -5,6 +5,10 @@ import (
"go/token"
)
+const (
+ importPath = `"github.com/onsi/gomega"`
+)
+
// Handler provide different handling, depend on the way gomega was imported, whether
// in imported with "." name, custom name or without any name.
type Handler interface {
@@ -23,7 +27,7 @@ type Handler interface {
// GetGomegaHandler returns a gomegar handler according to the way gomega was imported in the specific file
func GetGomegaHandler(file *ast.File) Handler {
for _, imp := range file.Imports {
- if imp.Path.Value != `"github.com/onsi/gomega"` {
+ if imp.Path.Value != importPath {
continue
}
diff --git a/vendor/github.com/nunnatsa/ginkgolinter/interfaces/interfaces.go b/vendor/github.com/nunnatsa/ginkgolinter/interfaces/interfaces.go
new file mode 100644
index 000000000..dafeacd4f
--- /dev/null
+++ b/vendor/github.com/nunnatsa/ginkgolinter/interfaces/interfaces.go
@@ -0,0 +1,76 @@
+package interfaces
+
+import (
+ "go/token"
+ gotypes "go/types"
+)
+
+var (
+ errorType *gotypes.Interface
+ gomegaMatcherType *gotypes.Interface
+)
+
+func init() {
+ errorType = gotypes.Universe.Lookup("error").Type().Underlying().(*gotypes.Interface)
+ gomegaMatcherType = generateTheGomegaMatcherInfType()
+}
+
+// generateTheGomegaMatcherInfType generates a types.Interface instance that represents the
+// GomegaMatcher interface.
+// The original code is (copied from https://github.com/nunnatsa/ginkgolinter/blob/8fdd05eee922578d4699f49d267001c01e0b9f1e/testdata/src/a/vendor/github.com/onsi/gomega/types/types.go)
+//
+// type GomegaMatcher interface {
+// Match(actual interface{}) (success bool, err error)
+// FailureMessage(actual interface{}) (message string)
+// NegatedFailureMessage(actual interface{}) (message string)
+// }
+func generateTheGomegaMatcherInfType() *gotypes.Interface {
+ err := gotypes.Universe.Lookup("error").Type()
+ bl := gotypes.Typ[gotypes.Bool]
+ str := gotypes.Typ[gotypes.String]
+ anyType := gotypes.Universe.Lookup("any").Type()
+
+ return gotypes.NewInterfaceType([]*gotypes.Func{
+ // Match(actual interface{}) (success bool, err error)
+ gotypes.NewFunc(token.NoPos, nil, "Match", gotypes.NewSignatureType(
+ nil, nil, nil,
+ gotypes.NewTuple(
+ gotypes.NewVar(token.NoPos, nil, "actual", anyType),
+ ),
+ gotypes.NewTuple(
+ gotypes.NewVar(token.NoPos, nil, "", bl),
+ gotypes.NewVar(token.NoPos, nil, "", err),
+ ), false),
+ ),
+ // FailureMessage(actual interface{}) (message string)
+ gotypes.NewFunc(token.NoPos, nil, "FailureMessage", gotypes.NewSignatureType(
+ nil, nil, nil,
+ gotypes.NewTuple(
+ gotypes.NewVar(token.NoPos, nil, "", anyType),
+ ),
+ gotypes.NewTuple(
+ gotypes.NewVar(token.NoPos, nil, "", str),
+ ),
+ false),
+ ),
+ //NegatedFailureMessage(actual interface{}) (message string)
+ gotypes.NewFunc(token.NoPos, nil, "NegatedFailureMessage", gotypes.NewSignatureType(
+ nil, nil, nil,
+ gotypes.NewTuple(
+ gotypes.NewVar(token.NoPos, nil, "", anyType),
+ ),
+ gotypes.NewTuple(
+ gotypes.NewVar(token.NoPos, nil, "", str),
+ ),
+ false),
+ ),
+ }, nil)
+}
+
+func ImplementsError(t gotypes.Type) bool {
+ return gotypes.Implements(t, errorType)
+}
+
+func ImplementsGomegaMatcher(t gotypes.Type) bool {
+ return gotypes.Implements(t, gomegaMatcherType)
+}