diff options
| author | Taras Madan <tarasmadan@google.com> | 2025-01-22 16:07:17 +0100 |
|---|---|---|
| committer | Taras Madan <tarasmadan@google.com> | 2025-01-23 10:42:36 +0000 |
| commit | 7b4377ad9d8a7205416df8d6217ef2b010f89481 (patch) | |
| tree | e6fec4fd12ff807a16d847923f501075bf71d16c /vendor/github.com/kisielk/errcheck | |
| parent | 475a4c203afb8b7d3af51c4fd32bb170ff32a45e (diff) | |
vendor: delete
Diffstat (limited to 'vendor/github.com/kisielk/errcheck')
9 files changed, 0 insertions, 1066 deletions
diff --git a/vendor/github.com/kisielk/errcheck/LICENSE b/vendor/github.com/kisielk/errcheck/LICENSE deleted file mode 100644 index a2b16b5bd..000000000 --- a/vendor/github.com/kisielk/errcheck/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2013 Kamil Kisiel - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/kisielk/errcheck/errcheck/analyzer.go b/vendor/github.com/kisielk/errcheck/errcheck/analyzer.go deleted file mode 100644 index 82ab6298a..000000000 --- a/vendor/github.com/kisielk/errcheck/errcheck/analyzer.go +++ /dev/null @@ -1,77 +0,0 @@ -package errcheck - -import ( - "fmt" - "go/ast" - "reflect" - "regexp" - - "golang.org/x/tools/go/analysis" -) - -var Analyzer = &analysis.Analyzer{ - Name: "errcheck", - Doc: "check for unchecked errors", - Run: runAnalyzer, - ResultType: reflect.TypeOf(Result{}), -} - -var ( - argBlank bool - argAsserts bool - argExcludeFile string - argExcludeOnly bool -) - -func init() { - Analyzer.Flags.BoolVar(&argBlank, "blank", false, "if true, check for errors assigned to blank identifier") - Analyzer.Flags.BoolVar(&argAsserts, "assert", false, "if true, check for ignored type assertion results") - Analyzer.Flags.StringVar(&argExcludeFile, "exclude", "", "Path to a file containing a list of functions to exclude from checking") - Analyzer.Flags.BoolVar(&argExcludeOnly, "excludeonly", false, "Use only excludes from exclude file") -} - -func runAnalyzer(pass *analysis.Pass) (interface{}, error) { - exclude := map[string]bool{} - if !argExcludeOnly { - for _, name := range DefaultExcludedSymbols { - exclude[name] = true - } - } - if argExcludeFile != "" { - excludes, err := ReadExcludes(argExcludeFile) - if err != nil { - return nil, fmt.Errorf("Could not read exclude file: %v\n", err) - } - for _, name := range excludes { - exclude[name] = true - } - } - - var allErrors []UncheckedError - for _, f := range pass.Files { - v := &visitor{ - typesInfo: pass.TypesInfo, - fset: pass.Fset, - blank: argBlank, - asserts: argAsserts, - exclude: exclude, - ignore: map[string]*regexp.Regexp{}, // deprecated & not used - lines: make(map[string][]string), - errors: nil, - } - - ast.Walk(v, f) - - for _, err := range v.errors { - pass.Report(analysis.Diagnostic{ - Pos: pass.Fset.File(f.Pos()).Pos(err.Pos.Offset), - Message: "unchecked error", - Category: "errcheck", - }) - } - - allErrors = append(allErrors, v.errors...) - } - - return Result{UncheckedErrors: allErrors}, nil -} diff --git a/vendor/github.com/kisielk/errcheck/errcheck/embedded_walker.go b/vendor/github.com/kisielk/errcheck/errcheck/embedded_walker.go deleted file mode 100644 index 98f28e9a6..000000000 --- a/vendor/github.com/kisielk/errcheck/errcheck/embedded_walker.go +++ /dev/null @@ -1,144 +0,0 @@ -package errcheck - -import ( - "fmt" - "go/types" -) - -// walkThroughEmbeddedInterfaces returns a slice of Interfaces that -// we need to walk through in order to reach the actual definition, -// in an Interface, of the method selected by the given selection. -// -// false will be returned in the second return value if: -// - the right side of the selection is not a function -// - the actual definition of the function is not in an Interface -// -// The returned slice will contain all the interface types that need -// to be walked through to reach the actual definition. -// -// For example, say we have: -// -// type Inner interface {Method()} -// type Middle interface {Inner} -// type Outer interface {Middle} -// type T struct {Outer} -// type U struct {T} -// type V struct {U} -// -// And then the selector: -// -// V.Method -// -// We'll return [Outer, Middle, Inner] by first walking through the embedded structs -// until we reach the Outer interface, then descending through the embedded interfaces -// until we find the one that actually explicitly defines Method. -func walkThroughEmbeddedInterfaces(sel *types.Selection) ([]types.Type, bool) { - fn, ok := sel.Obj().(*types.Func) - if !ok { - return nil, false - } - - // Start off at the receiver. - currentT := sel.Recv() - - // First, we can walk through any Struct fields provided - // by the selection Index() method. We ignore the last - // index because it would give the method itself. - indexes := sel.Index() - for _, fieldIndex := range indexes[:len(indexes)-1] { - currentT = getTypeAtFieldIndex(currentT, fieldIndex) - } - - // Now currentT is either a type implementing the actual function, - // an Invalid type (if the receiver is a package), or an interface. - // - // If it's not an Interface, then we're done, as this function - // only cares about Interface-defined functions. - // - // If it is an Interface, we potentially need to continue digging until - // we find the Interface that actually explicitly defines the function. - interfaceT, ok := maybeUnname(currentT).(*types.Interface) - if !ok { - return nil, false - } - - // The first interface we pass through is this one we've found. We return the possibly - // wrapping types.Named because it is more useful to work with for callers. - result := []types.Type{currentT} - - // If this interface itself explicitly defines the given method - // then we're done digging. - for !explicitlyDefinesMethod(interfaceT, fn) { - // Otherwise, we find which of the embedded interfaces _does_ - // define the method, add it to our list, and loop. - namedInterfaceT, ok := getEmbeddedInterfaceDefiningMethod(interfaceT, fn) - if !ok { - // Returned a nil interface, we are done. - break - } - result = append(result, namedInterfaceT) - interfaceT = namedInterfaceT.Underlying().(*types.Interface) - } - - return result, true -} - -func getTypeAtFieldIndex(startingAt types.Type, fieldIndex int) types.Type { - t := maybeDereference(maybeUnalias(startingAt)) - t = maybeUnname(maybeUnalias(t)) - s, ok := t.(*types.Struct) - if !ok { - panic(fmt.Sprintf("cannot get Field of a type that is not a struct, got a %T", t)) - } - - return s.Field(fieldIndex).Type() -} - -// getEmbeddedInterfaceDefiningMethod searches through any embedded interfaces of the -// passed interface searching for one that defines the given function. If found, the -// types.Named wrapping that interface will be returned along with true in the second value. -// -// If no such embedded interface is found, nil and false are returned. -func getEmbeddedInterfaceDefiningMethod(interfaceT *types.Interface, fn *types.Func) (*types.Named, bool) { - for i := 0; i < interfaceT.NumEmbeddeds(); i++ { - embedded := interfaceT.Embedded(i) - if embedded != nil && definesMethod(embedded.Underlying().(*types.Interface), fn) { - return embedded, true - } - } - return nil, false -} - -func explicitlyDefinesMethod(interfaceT *types.Interface, fn *types.Func) bool { - for i := 0; i < interfaceT.NumExplicitMethods(); i++ { - if interfaceT.ExplicitMethod(i) == fn { - return true - } - } - return false -} - -func definesMethod(interfaceT *types.Interface, fn *types.Func) bool { - for i := 0; i < interfaceT.NumMethods(); i++ { - if interfaceT.Method(i) == fn { - return true - } - } - return false -} - -func maybeDereference(t types.Type) types.Type { - p, ok := t.(*types.Pointer) - if ok { - return p.Elem() - } - return t -} - -func maybeUnname(t types.Type) types.Type { - n, ok := t.(*types.Named) - if ok { - return n.Underlying() - } - return t -} diff --git a/vendor/github.com/kisielk/errcheck/errcheck/embedded_walker_121.go b/vendor/github.com/kisielk/errcheck/errcheck/embedded_walker_121.go deleted file mode 100644 index f2df6849b..000000000 --- a/vendor/github.com/kisielk/errcheck/errcheck/embedded_walker_121.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !go1.22 -// +build !go1.22 - -package errcheck - -import "go/types" - -func maybeUnalias(t types.Type) types.Type { - return t -} diff --git a/vendor/github.com/kisielk/errcheck/errcheck/embedded_walker_122.go b/vendor/github.com/kisielk/errcheck/errcheck/embedded_walker_122.go deleted file mode 100644 index cbff3cd43..000000000 --- a/vendor/github.com/kisielk/errcheck/errcheck/embedded_walker_122.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build go1.22 -// +build go1.22 - -package errcheck - -import "go/types" - -func maybeUnalias(t types.Type) types.Type { - return types.Unalias(t) -} diff --git a/vendor/github.com/kisielk/errcheck/errcheck/errcheck.go b/vendor/github.com/kisielk/errcheck/errcheck/errcheck.go deleted file mode 100644 index a7a2a30bf..000000000 --- a/vendor/github.com/kisielk/errcheck/errcheck/errcheck.go +++ /dev/null @@ -1,694 +0,0 @@ -// Package errcheck is the library used to implement the errcheck command-line tool. -package errcheck - -import ( - "bufio" - "errors" - "fmt" - "go/ast" - "go/token" - "go/types" - "os" - "regexp" - "sort" - "strings" - - "golang.org/x/tools/go/packages" -) - -var errorType *types.Interface - -func init() { - errorType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface) -} - -var ( - // ErrNoGoFiles is returned when CheckPackage is run on a package with no Go source files - ErrNoGoFiles = errors.New("package contains no go source files") -) - -// UncheckedError indicates the position of an unchecked error return. -type UncheckedError struct { - Pos token.Position - Line string - FuncName string - SelectorName string -} - -// Result is returned from the CheckPackage function, and holds all the errors -// that were found to be unchecked in a package. -// -// Aggregation can be done using the Append method for users that want to -// combine results from multiple packages. -type Result struct { - // UncheckedErrors is a list of all the unchecked errors in the package. - // Printing an error reports its position within the file and the contents of the line. - UncheckedErrors []UncheckedError -} - -type byName []UncheckedError - -// Less reports whether the element with index i should sort before the element with index j. -func (b byName) Less(i, j int) bool { - ei, ej := b[i], b[j] - - pi, pj := ei.Pos, ej.Pos - - if pi.Filename != pj.Filename { - return pi.Filename < pj.Filename - } - if pi.Line != pj.Line { - return pi.Line < pj.Line - } - if pi.Column != pj.Column { - return pi.Column < pj.Column - } - - return ei.Line < ej.Line -} - -func (b byName) Swap(i, j int) { - b[i], b[j] = b[j], b[i] -} - -func (b byName) Len() int { - return len(b) -} - -// Append appends errors to e. Append does not do any duplicate checking. -func (r *Result) Append(other Result) { - r.UncheckedErrors = append(r.UncheckedErrors, other.UncheckedErrors...) -} - -// Unique returns the unique errors that have been accumulated. Duplicates may occur -// when a file containing an unchecked error belongs to > 1 package. -// -// The method receiver remains unmodified after the call to Unique. -func (r Result) Unique() Result { - result := make([]UncheckedError, len(r.UncheckedErrors)) - copy(result, r.UncheckedErrors) - sort.Sort((byName)(result)) - uniq := result[:0] // compact in-place - for i, err := range result { - if i == 0 || err != result[i-1] { - uniq = append(uniq, err) - } - } - return Result{UncheckedErrors: uniq} -} - -// Exclusions define symbols and language elements that will be not checked -type Exclusions struct { - - // Packages lists paths of excluded packages. - Packages []string - - // SymbolRegexpsByPackage maps individual package paths to regular - // expressions that match symbols to be excluded. - // - // Packages whose paths appear both here and in Packages list will - // be excluded entirely. - // - // This is a legacy input that will be deprecated in errcheck version 2 and - // should not be used. - SymbolRegexpsByPackage map[string]*regexp.Regexp - - // Symbols lists patterns that exclude individual package symbols. - // - // For example: - // - // "fmt.Errorf" // function - // "fmt.Fprintf(os.Stderr)" // function with set argument value - // "(hash.Hash).Write" // method - // - Symbols []string - - // TestFiles excludes _test.go files. - TestFiles bool - - // GeneratedFiles excludes generated source files. - // - // Source file is assumed to be generated if its contents - // match the following regular expression: - // - // ^// Code generated .* DO NOT EDIT\\.$ - // - GeneratedFiles bool - - // BlankAssignments ignores assignments to blank identifier. - BlankAssignments bool - - // TypeAssertions ignores unchecked type assertions. - TypeAssertions bool -} - -// Checker checks that you checked errors. -type Checker struct { - // Exclusions defines code packages, symbols, and other elements that will not be checked. - Exclusions Exclusions - - // Tags are a list of build tags to use. - Tags []string - - // The mod flag for go build. - Mod string -} - -// loadPackages is used for testing. -var loadPackages = func(cfg *packages.Config, paths ...string) ([]*packages.Package, error) { - return packages.Load(cfg, paths...) -} - -// LoadPackages loads all the packages in all the paths provided. It uses the -// exclusions and build tags provided to by the user when loading the packages. -func (c *Checker) LoadPackages(paths ...string) ([]*packages.Package, error) { - buildFlags := []string{fmtTags(c.Tags)} - if c.Mod != "" { - buildFlags = append(buildFlags, fmt.Sprintf("-mod=%s", c.Mod)) - } - cfg := &packages.Config{ - Mode: packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo, - Tests: !c.Exclusions.TestFiles, - BuildFlags: buildFlags, - } - return loadPackages(cfg, paths...) -} - -var generatedCodeRegexp = regexp.MustCompile("^// Code generated .* DO NOT EDIT\\.$") -var dotStar = regexp.MustCompile(".*") - -func (c *Checker) shouldSkipFile(file *ast.File) bool { - if !c.Exclusions.GeneratedFiles { - return false - } - - for _, cg := range file.Comments { - for _, comment := range cg.List { - if generatedCodeRegexp.MatchString(comment.Text) { - return true - } - } - } - - return false -} - -// CheckPackage checks packages for errors that have not been checked. -// -// It will exclude specific errors from analysis if the user has configured -// exclusions. -func (c *Checker) CheckPackage(pkg *packages.Package) Result { - excludedSymbols := map[string]bool{} - for _, sym := range c.Exclusions.Symbols { - excludedSymbols[sym] = true - } - - ignore := map[string]*regexp.Regexp{} - // Apply SymbolRegexpsByPackage first so that if the same path appears in - // Packages, a more narrow regexp will be superseded by dotStar below. - if regexps := c.Exclusions.SymbolRegexpsByPackage; regexps != nil { - for pkg, re := range regexps { - // TODO warn if previous entry overwritten? - ignore[nonVendoredPkgPath(pkg)] = re - } - } - for _, pkg := range c.Exclusions.Packages { - // TODO warn if previous entry overwritten? - ignore[nonVendoredPkgPath(pkg)] = dotStar - } - - v := &visitor{ - typesInfo: pkg.TypesInfo, - fset: pkg.Fset, - ignore: ignore, - blank: !c.Exclusions.BlankAssignments, - asserts: !c.Exclusions.TypeAssertions, - lines: make(map[string][]string), - exclude: excludedSymbols, - errors: []UncheckedError{}, - } - - for _, astFile := range pkg.Syntax { - if c.shouldSkipFile(astFile) { - continue - } - ast.Walk(v, astFile) - } - return Result{UncheckedErrors: v.errors} -} - -// visitor implements the errcheck algorithm -type visitor struct { - typesInfo *types.Info - fset *token.FileSet - ignore map[string]*regexp.Regexp - blank bool - asserts bool - lines map[string][]string - exclude map[string]bool - - errors []UncheckedError -} - -// selectorAndFunc tries to get the selector and function from call expression. -// For example, given the call expression representing "a.b()", the selector -// is "a.b" and the function is "b" itself. -// -// The final return value will be true if it is able to do extract a selector -// from the call and look up the function object it refers to. -// -// If the call does not include a selector (like if it is a plain "f()" function call) -// then the final return value will be false. -func (v *visitor) selectorAndFunc(call *ast.CallExpr) (*ast.SelectorExpr, *types.Func, bool) { - sel, ok := call.Fun.(*ast.SelectorExpr) - if !ok { - return nil, nil, false - } - - fn, ok := v.typesInfo.ObjectOf(sel.Sel).(*types.Func) - if !ok { - // Shouldn't happen, but be paranoid - return nil, nil, false - } - - return sel, fn, true - -} - -// fullName will return a package / receiver-type qualified name for a called function -// if the function is the result of a selector. Otherwise it will return -// the empty string. -// -// The name is fully qualified by the import path, possible type, -// function/method name and pointer receiver. -// -// For example, -// - for "fmt.Printf(...)" it will return "fmt.Printf" -// - for "base64.StdEncoding.Decode(...)" it will return "(*encoding/base64.Encoding).Decode" -// - for "myFunc()" it will return "" -func (v *visitor) fullName(call *ast.CallExpr) string { - _, fn, ok := v.selectorAndFunc(call) - if !ok { - return "" - } - - // TODO(dh): vendored packages will have /vendor/ in their name, - // thus not matching vendored standard library packages. If we - // want to support vendored stdlib packages, we need to implement - // FullName with our own logic. - return fn.FullName() -} - -func getSelectorName(sel *ast.SelectorExpr) string { - if ident, ok := sel.X.(*ast.Ident); ok { - return fmt.Sprintf("%s.%s", ident.Name, sel.Sel.Name) - } - if s, ok := sel.X.(*ast.SelectorExpr); ok { - return fmt.Sprintf("%s.%s", getSelectorName(s), sel.Sel.Name) - } - - return "" -} - -// selectorName will return a name for a called function -// if the function is the result of a selector. Otherwise it will return -// the empty string. -// -// The name is fully qualified by the import path, possible type, -// function/method name and pointer receiver. -// -// For example, -// - for "fmt.Printf(...)" it will return "fmt.Printf" -// - for "base64.StdEncoding.Decode(...)" it will return "base64.StdEncoding.Decode" -// - for "myFunc()" it will return "" -func (v *visitor) selectorName(call *ast.CallExpr) string { - sel, _, ok := v.selectorAndFunc(call) - if !ok { - return "" - } - - return getSelectorName(sel) -} - -// namesForExcludeCheck will return a list of fully-qualified function names -// from a function call that can be used to check against the exclusion list. -// -// If a function call is against a local function (like "myFunc()") then no -// names are returned. If the function is package-qualified (like "fmt.Printf()") -// then just that function's fullName is returned. -// -// Otherwise, we walk through all the potentially embedded interfaces of the receiver -// to collect a list of type-qualified function names that we will check. -func (v *visitor) namesForExcludeCheck(call *ast.CallExpr) []string { - sel, fn, ok := v.selectorAndFunc(call) - if !ok { - return nil - } - - name := v.fullName(call) - if name == "" { - return nil - } - - // This will be missing for functions without a receiver (like fmt.Printf), - // so just fall back to the function's fullName in that case. - selection, ok := v.typesInfo.Selections[sel] - if !ok { - return []string{name} - } - - // This will return with ok false if the function isn't defined - // on an interface, so just fall back to the fullName. - ts, ok := walkThroughEmbeddedInterfaces(selection) - if !ok { - return []string{name} - } - - result := make([]string, len(ts)) - for i, t := range ts { - // Like in fullName, vendored packages will have /vendor/ in their name, - // thus not matching vendored standard library packages. If we - // want to support vendored stdlib packages, we need to implement - // additional logic here. - result[i] = fmt.Sprintf("(%s).%s", t.String(), fn.Name()) - } - return result -} - -// isBufferType checks if the expression type is a known in-memory buffer type. -func (v *visitor) argName(expr ast.Expr) string { - // Special-case literal "os.Stdout" and "os.Stderr" - if sel, ok := expr.(*ast.SelectorExpr); ok { - if obj := v.typesInfo.ObjectOf(sel.Sel); obj != nil { - vr, ok := obj.(*types.Var) - if ok && vr.Pkg() != nil && vr.Pkg().Name() == "os" && (vr.Name() == "Stderr" || vr.Name() == "Stdout") { - return "os." + vr.Name() - } - } - } - t := v.typesInfo.TypeOf(expr) - if t == nil { - return "" - } - return t.String() -} - -func (v *visitor) excludeCall(call *ast.CallExpr) bool { - var arg0 string - if len(call.Args) > 0 { - arg0 = v.argName(call.Args[0]) - } - for _, name := range v.namesForExcludeCheck(call) { - if v.exclude[name] { - return true - } - if arg0 != "" && v.exclude[name+"("+arg0+")"] { - return true - } - } - return false -} - -func (v *visitor) ignoreCall(call *ast.CallExpr) bool { - if v.excludeCall(call) { - return true - } - - // Try to get an identifier. - // Currently only supports simple expressions: - // 1. f() - // 2. x.y.f() - var id *ast.Ident - switch exp := call.Fun.(type) { - case *ast.Ident: - id = exp - case *ast.SelectorExpr: - id = exp.Sel - default: - // eg: *ast.SliceExpr, *ast.IndexExpr - } - - if id == nil { - return false - } - - // If we got an identifier for the function, see if it is ignored - if re, ok := v.ignore[""]; ok && re.MatchString(id.Name) { - return true - } - - if obj := v.typesInfo.Uses[id]; obj != nil { - if pkg := obj.Pkg(); pkg != nil { - if re, ok := v.ignore[nonVendoredPkgPath(pkg.Path())]; ok { - return re.MatchString(id.Name) - } - } - } - - return false -} - -// nonVendoredPkgPath returns the unvendored version of the provided package -// path (or returns the provided path if it does not represent a vendored -// path). -func nonVendoredPkgPath(pkgPath string) string { - lastVendorIndex := strings.LastIndex(pkgPath, "/vendor/") - if lastVendorIndex == -1 { - return pkgPath - } - return pkgPath[lastVendorIndex+len("/vendor/"):] -} - -// errorsByArg returns a slice s such that -// len(s) == number of return types of call -// s[i] == true iff return type at position i from left is an error type -func (v *visitor) errorsByArg(call *ast.CallExpr) []bool { - switch t := v.typesInfo.Types[call].Type.(type) { - case *types.Named: - // Single return - return []bool{isErrorType(t)} - case *types.Pointer: - // Single return via pointer - return []bool{isErrorType(t)} - case *types.Tuple: - // Multiple returns - s := make([]bool, t.Len()) - for i := 0; i < t.Len(); i++ { - switch et := t.At(i).Type().(type) { - case *types.Named: - // Single return - s[i] = isErrorType(et) - case *types.Pointer: - // Single return via pointer - s[i] = isErrorType(et) - default: - s[i] = false - } - } - return s - } - return []bool{false} -} - -func (v *visitor) callReturnsError(call *ast.CallExpr) bool { - if v.isRecover(call) { - return true - } - for _, isError := range v.errorsByArg(call) { - if isError { - return true - } - } - return false -} - -// isRecover returns true if the given CallExpr is a call to the built-in recover() function. -func (v *visitor) isRecover(call *ast.CallExpr) bool { - if fun, ok := call.Fun.(*ast.Ident); ok { - if _, ok := v.typesInfo.Uses[fun].(*types.Builtin); ok { - return fun.Name == "recover" - } - } - return false -} - -// TODO (dtcaciuc) collect token.Pos and then convert them to UncheckedErrors -// after visitor is done running. This will allow to integrate more cleanly -// with analyzer so that we don't have to convert Position back to Pos. -func (v *visitor) addErrorAtPosition(position token.Pos, call *ast.CallExpr) { - pos := v.fset.Position(position) - lines, ok := v.lines[pos.Filename] - if !ok { - lines = readfile(pos.Filename) - v.lines[pos.Filename] = lines - } - - line := "??" - if pos.Line-1 < len(lines) { - line = strings.TrimSpace(lines[pos.Line-1]) - } - - var name string - var sel string - if call != nil { - name = v.fullName(call) - sel = v.selectorName(call) - } - - v.errors = append(v.errors, UncheckedError{pos, line, name, sel}) -} - -func readfile(filename string) []string { - var f, err = os.Open(filename) - if err != nil { - return nil - } - defer f.Close() - - var lines []string - var scanner = bufio.NewScanner(f) - for scanner.Scan() { - lines = append(lines, scanner.Text()) - } - return lines -} - -func (v *visitor) Visit(node ast.Node) ast.Visitor { - switch stmt := node.(type) { - case *ast.ExprStmt: - if call, ok := stmt.X.(*ast.CallExpr); ok { - if !v.ignoreCall(call) && v.callReturnsError(call) { - v.addErrorAtPosition(call.Lparen, call) - } - } - case *ast.GoStmt: - if !v.ignoreCall(stmt.Call) && v.callReturnsError(stmt.Call) { - v.addErrorAtPosition(stmt.Call.Lparen, stmt.Call) - } - case *ast.DeferStmt: - if !v.ignoreCall(stmt.Call) && v.callReturnsError(stmt.Call) { - v.addErrorAtPosition(stmt.Call.Lparen, stmt.Call) - } - case *ast.GenDecl: - if stmt.Tok != token.VAR { - break - } - - for _, spec := range stmt.Specs { - vspec := spec.(*ast.ValueSpec) - - if len(vspec.Values) == 0 { - // ignore declarations w/o assignments - continue - } - - var lhs []ast.Expr - for _, name := range vspec.Names { - lhs = append(lhs, ast.Expr(name)) - } - followed := v.checkAssignment(lhs, vspec.Values) - if !followed { - return nil - } - } - - case *ast.AssignStmt: - followed := v.checkAssignment(stmt.Lhs, stmt.Rhs) - if !followed { - return nil - } - - case *ast.TypeAssertExpr: - v.checkAssertExpr(stmt) - return nil - - default: - } - return v -} - -// checkAssignment checks the assignment statement and returns a boolean value -// indicating whether to continue checking the substructure in AssignStmt or not -func (v *visitor) checkAssignment(lhs, rhs []ast.Expr) (followed bool) { - if len(rhs) == 1 { - // single value on rhs; check against lhs identifiers - if call, ok := rhs[0].(*ast.CallExpr); ok { - if !v.blank { - return true - } - if v.ignoreCall(call) { - return true - } - isError := v.errorsByArg(call) - for i := 0; i < len(lhs); i++ { - if id, ok := lhs[i].(*ast.Ident); ok { - // We shortcut calls to recover() because errorsByArg can't - // check its return types for errors since it returns interface{}. - if id.Name == "_" && (v.isRecover(call) || isError[i]) { - v.addErrorAtPosition(id.NamePos, call) - } - } - } - } else if assert, ok := rhs[0].(*ast.TypeAssertExpr); ok { - if !v.asserts { - return false - } - if assert.Type == nil { - // type switch - return false - } - if len(lhs) < 2 { - // assertion result not read - v.addErrorAtPosition(rhs[0].Pos(), nil) - } else if id, ok := lhs[1].(*ast.Ident); ok && v.blank && id.Name == "_" { - // assertion result ignored - v.addErrorAtPosition(id.NamePos, nil) - } - return false - } - } else { - // multiple value on rhs; in this case a call can't return - // multiple values. Assume len(lhs) == len(rhs) - for i := 0; i < len(lhs); i++ { - if id, ok := lhs[i].(*ast.Ident); ok { - if call, ok := rhs[i].(*ast.CallExpr); ok { - if !v.blank { - continue - } - if v.ignoreCall(call) { - continue - } - if id.Name == "_" && v.callReturnsError(call) { - v.addErrorAtPosition(id.NamePos, call) - } - } else if assert, ok := rhs[i].(*ast.TypeAssertExpr); ok { - if !v.asserts { - continue - } - if assert.Type == nil { - // Shouldn't happen anyway, no multi assignment in type switches - continue - } - v.addErrorAtPosition(id.NamePos, nil) - } - } - } - } - - return true -} - -func (v *visitor) checkAssertExpr(expr *ast.TypeAssertExpr) { - if !v.asserts { - return - } - if expr.Type == nil { - // type switch - return - } - v.addErrorAtPosition(expr.Pos(), nil) -} - -func isErrorType(t types.Type) bool { - return types.Implements(t, errorType) -} diff --git a/vendor/github.com/kisielk/errcheck/errcheck/excludes.go b/vendor/github.com/kisielk/errcheck/errcheck/excludes.go deleted file mode 100644 index 450b798e4..000000000 --- a/vendor/github.com/kisielk/errcheck/errcheck/excludes.go +++ /dev/null @@ -1,84 +0,0 @@ -package errcheck - -import ( - "bufio" - "bytes" - "os" - "strings" -) - -// DefaultExcludedSymbols is a list of symbol names that are usually excluded from checks by default. -// -// Note, that they still need to be explicitly copied to Checker.Exclusions.Symbols -var DefaultExcludedSymbols = []string{ - // bytes - "(*bytes.Buffer).Write", - "(*bytes.Buffer).WriteByte", - "(*bytes.Buffer).WriteRune", - "(*bytes.Buffer).WriteString", - - // fmt - "fmt.Print", - "fmt.Printf", - "fmt.Println", - "fmt.Fprint(*bytes.Buffer)", - "fmt.Fprintf(*bytes.Buffer)", - "fmt.Fprintln(*bytes.Buffer)", - "fmt.Fprint(*strings.Builder)", - "fmt.Fprintf(*strings.Builder)", - "fmt.Fprintln(*strings.Builder)", - "fmt.Fprint(os.Stderr)", - "fmt.Fprintf(os.Stderr)", - "fmt.Fprintln(os.Stderr)", - - // io - "(*io.PipeReader).CloseWithError", - "(*io.PipeWriter).CloseWithError", - - // math/rand - "math/rand.Read", - "(*math/rand.Rand).Read", - - // strings - "(*strings.Builder).Write", - "(*strings.Builder).WriteByte", - "(*strings.Builder).WriteRune", - "(*strings.Builder).WriteString", - - // hash - "(hash.Hash).Write", - - // hash/maphash - "(*hash/maphash.Hash).Write", - "(*hash/maphash.Hash).WriteByte", - "(*hash/maphash.Hash).WriteString", -} - -// ReadExcludes reads an excludes file, a newline delimited file that lists -// patterns for which to allow unchecked errors. -// -// Lines that start with two forward slashes are considered comments and are ignored. -func ReadExcludes(path string) ([]string, error) { - var excludes []string - - buf, err := os.ReadFile(path) - if err != nil { - return nil, err - } - - scanner := bufio.NewScanner(bytes.NewReader(buf)) - - for scanner.Scan() { - name := scanner.Text() - // Skip comments and empty lines. - if strings.HasPrefix(name, "//") || name == "" { - continue - } - excludes = append(excludes, name) - } - if err := scanner.Err(); err != nil { - return nil, err - } - - return excludes, nil -} diff --git a/vendor/github.com/kisielk/errcheck/errcheck/tags.go b/vendor/github.com/kisielk/errcheck/errcheck/tags.go deleted file mode 100644 index 7b423ca69..000000000 --- a/vendor/github.com/kisielk/errcheck/errcheck/tags.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build go1.13 - -package errcheck - -import ( - "fmt" - "strings" -) - -func fmtTags(tags []string) string { - return fmt.Sprintf("-tags=%s", strings.Join(tags, ",")) -} diff --git a/vendor/github.com/kisielk/errcheck/errcheck/tags_compat.go b/vendor/github.com/kisielk/errcheck/errcheck/tags_compat.go deleted file mode 100644 index 2f534f40a..000000000 --- a/vendor/github.com/kisielk/errcheck/errcheck/tags_compat.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build go1.11 -// +build !go1.13 - -package errcheck - -import ( - "fmt" - "strings" -) - -func fmtTags(tags []string) string { - return fmt.Sprintf("-tags=%s", strings.Join(tags, " ")) -} |
