aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/GaijinEntertainment
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2024-09-10 12:16:33 +0200
committerTaras Madan <tarasmadan@google.com>2024-09-10 14:05:26 +0000
commitc97c816133b42257d0bcf1ee4bd178bb2a7a2b9e (patch)
tree0bcbc2e540bbf8f62f6c17887cdd53b8c2cee637 /vendor/github.com/GaijinEntertainment
parent54e657429ab892ad06c90cd7c1a4eb33ba93a3dc (diff)
vendor: update
Diffstat (limited to 'vendor/github.com/GaijinEntertainment')
-rw-r--r--vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer/analyzer.go45
1 files changed, 36 insertions, 9 deletions
diff --git a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer/analyzer.go b/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer/analyzer.go
index b490f1c64..ec75fd409 100644
--- a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer/analyzer.go
+++ b/vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer/analyzer.go
@@ -100,12 +100,9 @@ func (a *analyzer) newVisitor(pass *analysis.Pass) func(n ast.Node, push bool, s
if len(lit.Elts) == 0 {
if ret, ok := stackParentIsReturn(stack); ok {
- if returnContainsNonNilError(pass, ret) {
+ if returnContainsNonNilError(pass, ret, n) {
// it is okay to return uninitialized structure in case struct's direct parent is
// a return statement containing non-nil error
- //
- // we're unable to check if returned error is custom, but at least we're able to
- // cover str [error] type.
return true
}
}
@@ -184,17 +181,47 @@ func getStructType(pass *analysis.Pass, lit *ast.CompositeLit) (*types.Struct, *
func stackParentIsReturn(stack []ast.Node) (*ast.ReturnStmt, bool) {
// it is safe to skip boundary check, since stack always has at least one element
- // - whole file.
- ret, ok := stack[len(stack)-2].(*ast.ReturnStmt)
+ // we also have no reason to check the first element, since it is always a file
+ for i := len(stack) - 2; i > 0; i-- {
+ switch st := stack[i].(type) {
+ case *ast.ReturnStmt:
+ return st, true
- return ret, ok
+ case *ast.UnaryExpr:
+ // in case we're dealing with pointers - it is still viable to check pointer's
+ // parent for return statement
+ continue
+
+ default:
+ return nil, false
+ }
+ }
+
+ return nil, false
}
-func returnContainsNonNilError(pass *analysis.Pass, ret *ast.ReturnStmt) bool {
+// errorIface is a type that represents [error] interface and all types will be
+// compared against.
+var errorIface = types.Universe.Lookup("error").Type().Underlying().(*types.Interface)
+
+func returnContainsNonNilError(pass *analysis.Pass, ret *ast.ReturnStmt, except ast.Node) bool {
// errors are mostly located at the end of return statement, so we're starting
// from the end.
for i := len(ret.Results) - 1; i >= 0; i-- {
- if pass.TypesInfo.TypeOf(ret.Results[i]).String() == "error" {
+ ri := ret.Results[i]
+
+ // skip current node
+ if ri == except {
+ continue
+ }
+
+ if un, ok := ri.(*ast.UnaryExpr); ok {
+ if un.X == except {
+ continue
+ }
+ }
+
+ if types.Implements(pass.TypesInfo.TypeOf(ri), errorIface) {
return true
}
}