diff options
| author | Taras Madan <tarasmadan@google.com> | 2024-09-10 12:16:33 +0200 |
|---|---|---|
| committer | Taras Madan <tarasmadan@google.com> | 2024-09-10 14:05:26 +0000 |
| commit | c97c816133b42257d0bcf1ee4bd178bb2a7a2b9e (patch) | |
| tree | 0bcbc2e540bbf8f62f6c17887cdd53b8c2cee637 /vendor/github.com/GaijinEntertainment | |
| parent | 54e657429ab892ad06c90cd7c1a4eb33ba93a3dc (diff) | |
vendor: update
Diffstat (limited to 'vendor/github.com/GaijinEntertainment')
| -rw-r--r-- | vendor/github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer/analyzer.go | 45 |
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 } } |
