You've already forked postgres_exporter
mirror of
https://github.com/prometheus-community/postgres_exporter.git
synced 2025-08-08 04:42:07 +03:00
Add self-contained gometalinter build tooling.
This commit is contained in:
22
tools/vendor/github.com/kisielk/errcheck/LICENSE
generated
vendored
Normal file
22
tools/vendor/github.com/kisielk/errcheck/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
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.
|
122
tools/vendor/github.com/kisielk/errcheck/README.md
generated
vendored
Normal file
122
tools/vendor/github.com/kisielk/errcheck/README.md
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
# errcheck
|
||||
|
||||
errcheck is a program for checking for unchecked errors in go programs.
|
||||
|
||||
[](https://travis-ci.org/kisielk/errcheck)
|
||||
|
||||
## Install
|
||||
|
||||
go get -u github.com/kisielk/errcheck
|
||||
|
||||
errcheck requires Go 1.6 or newer and depends on the package go/loader from the golang.org/x/tools repository.
|
||||
|
||||
## Use
|
||||
|
||||
For basic usage, just give the package path of interest as the first argument:
|
||||
|
||||
errcheck github.com/kisielk/errcheck/testdata
|
||||
|
||||
To check all packages beneath the current directory:
|
||||
|
||||
errcheck ./...
|
||||
|
||||
Or check all packages in your $GOPATH and $GOROOT:
|
||||
|
||||
errcheck all
|
||||
|
||||
errcheck also recognizes the following command-line options:
|
||||
|
||||
The `-tags` flag takes a space-separated list of build tags, just like `go
|
||||
build`. If you are using any custom build tags in your code base, you may need
|
||||
to specify the relevant tags here.
|
||||
|
||||
The `-asserts` flag enables checking for ignored type assertion results. It
|
||||
takes no arguments.
|
||||
|
||||
The `-blank` flag enables checking for assignments of errors to the
|
||||
blank identifier. It takes no arguments.
|
||||
|
||||
|
||||
## Excluding functions
|
||||
|
||||
Use the `-exclude` flag to specify a path to a file containing a list of functions to
|
||||
be excluded.
|
||||
|
||||
errcheck -exclude errcheck_excludes.txt path/to/package
|
||||
|
||||
The file should contain one function signature per line. The format for function signatures is
|
||||
`package.FunctionName` while for methods it's `(package.Receiver).MethodName` for value receivers
|
||||
and `(*package.Receiver).MethodName` for pointer receivers.
|
||||
|
||||
An example of an exclude file is:
|
||||
|
||||
io/ioutil.ReadFile
|
||||
(*net/http.Client).Do
|
||||
|
||||
The exclude list is combined with an internal list for functions in the Go standard library that
|
||||
have an error return type but are documented to never return an error.
|
||||
|
||||
|
||||
### The deprecated method
|
||||
|
||||
The `-ignore` flag takes a comma-separated list of pairs of the form package:regex.
|
||||
For each package, the regex describes which functions to ignore within that package.
|
||||
The package may be omitted to have the regex apply to all packages.
|
||||
|
||||
For example, you may wish to ignore common operations like Read and Write:
|
||||
|
||||
errcheck -ignore '[rR]ead|[wW]rite' path/to/package
|
||||
|
||||
or you may wish to ignore common functions like the `print` variants in `fmt`:
|
||||
|
||||
errcheck -ignore 'fmt:[FS]?[Pp]rint*' path/to/package
|
||||
|
||||
The `-ignorepkg` flag takes a comma-separated list of package import paths
|
||||
to ignore:
|
||||
|
||||
errcheck -ignorepkg 'fmt,encoding/binary' path/to/package
|
||||
|
||||
Note that this is equivalent to:
|
||||
|
||||
errcheck -ignore 'fmt:.*,encoding/binary:.*' path/to/package
|
||||
|
||||
If a regex is provided for a package `pkg` via `-ignore`, and `pkg` also appears
|
||||
in the list of packages passed to `-ignorepkg`, the latter takes precedence;
|
||||
that is, all functions within `pkg` will be ignored.
|
||||
|
||||
Note that by default the `fmt` package is ignored entirely, unless a regex is
|
||||
specified for it. To disable this, specify a regex that matches nothing:
|
||||
|
||||
errcheck -ignore 'fmt:a^' path/to/package
|
||||
|
||||
The `-ignoretests` flag disables checking of `_test.go` files. It takes
|
||||
no arguments.
|
||||
|
||||
## Cgo
|
||||
|
||||
Currently errcheck is unable to check packages that `import "C"` due to limitations
|
||||
in the importer.
|
||||
|
||||
However, you can use errcheck on packages that depend on those which use cgo. In
|
||||
order for this to work you need to `go install` the cgo dependencies before running
|
||||
errcheck on the dependant packages.
|
||||
|
||||
See https://github.com/kisielk/errcheck/issues/16 for more details.
|
||||
|
||||
## Exit Codes
|
||||
|
||||
errcheck returns 1 if any problems were found in the checked files.
|
||||
It returns 2 if there were any other failures.
|
||||
|
||||
# Editor Integration
|
||||
|
||||
## Emacs
|
||||
|
||||
[go-errcheck.el](https://github.com/dominikh/go-errcheck.el)
|
||||
integrates errcheck with Emacs by providing a `go-errcheck` command
|
||||
and customizable variables to automatically pass flags to errcheck.
|
||||
|
||||
## Vim
|
||||
|
||||
[vim-go](https://github.com/fatih/vim-go) can run errcheck via both its `:GoErrCheck`
|
||||
and `:GoMetaLinter` commands.
|
481
tools/vendor/github.com/kisielk/errcheck/internal/errcheck/errcheck.go
generated
vendored
Normal file
481
tools/vendor/github.com/kisielk/errcheck/internal/errcheck/errcheck.go
generated
vendored
Normal file
@@ -0,0 +1,481 @@
|
||||
// Package errcheck is the library used to implement the errcheck command-line tool.
|
||||
//
|
||||
// Note: The API of this package has not been finalized and may change at any point.
|
||||
package errcheck
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/tools/go/loader"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// UncheckedErrors is returned from the CheckPackage function if the package contains
|
||||
// any unchecked errors.
|
||||
// Errors should be appended using the Append method, which is safe to use concurrently.
|
||||
type UncheckedErrors struct {
|
||||
mu sync.Mutex
|
||||
|
||||
// Errors 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.
|
||||
Errors []UncheckedError
|
||||
}
|
||||
|
||||
func (e *UncheckedErrors) Append(errors ...UncheckedError) {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
e.Errors = append(e.Errors, errors...)
|
||||
}
|
||||
|
||||
func (e *UncheckedErrors) Error() string {
|
||||
return fmt.Sprintf("%d unchecked errors", len(e.Errors))
|
||||
}
|
||||
|
||||
// Len is the number of elements in the collection.
|
||||
func (e *UncheckedErrors) Len() int { return len(e.Errors) }
|
||||
|
||||
// Swap swaps the elements with indexes i and j.
|
||||
func (e *UncheckedErrors) Swap(i, j int) { e.Errors[i], e.Errors[j] = e.Errors[j], e.Errors[i] }
|
||||
|
||||
type byName struct{ *UncheckedErrors }
|
||||
|
||||
// Less reports whether the element with index i should sort before the element with index j.
|
||||
func (e byName) Less(i, j int) bool {
|
||||
ei, ej := e.Errors[i], e.Errors[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
|
||||
}
|
||||
|
||||
type Checker struct {
|
||||
// ignore is a map of package names to regular expressions. Identifiers from a package are
|
||||
// checked against its regular expressions and if any of the expressions match the call
|
||||
// is not checked.
|
||||
Ignore map[string]*regexp.Regexp
|
||||
|
||||
// If blank is true then assignments to the blank identifier are also considered to be
|
||||
// ignored errors.
|
||||
Blank bool
|
||||
|
||||
// If asserts is true then ignored type assertion results are also checked
|
||||
Asserts bool
|
||||
|
||||
// build tags
|
||||
Tags []string
|
||||
|
||||
Verbose bool
|
||||
|
||||
// If true, checking of of _test.go files is disabled
|
||||
WithoutTests bool
|
||||
|
||||
exclude map[string]bool
|
||||
}
|
||||
|
||||
func NewChecker() *Checker {
|
||||
c := Checker{}
|
||||
c.SetExclude(map[string]bool{})
|
||||
return &c
|
||||
}
|
||||
|
||||
func (c *Checker) SetExclude(l map[string]bool) {
|
||||
// Default exclude for stdlib functions
|
||||
c.exclude = map[string]bool{
|
||||
"math/rand.Read": true,
|
||||
"(*math/rand.Rand).Read": true,
|
||||
|
||||
"(*bytes.Buffer).Write": true,
|
||||
"(*bytes.Buffer).WriteByte": true,
|
||||
"(*bytes.Buffer).WriteRune": true,
|
||||
"(*bytes.Buffer).WriteString": true,
|
||||
}
|
||||
for k := range l {
|
||||
c.exclude[k] = true
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Checker) logf(msg string, args ...interface{}) {
|
||||
if c.Verbose {
|
||||
fmt.Fprintf(os.Stderr, msg+"\n", args...)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Checker) load(paths ...string) (*loader.Program, error) {
|
||||
ctx := build.Default
|
||||
for _, tag := range c.Tags {
|
||||
ctx.BuildTags = append(ctx.BuildTags, tag)
|
||||
}
|
||||
loadcfg := loader.Config{
|
||||
Build: &ctx,
|
||||
}
|
||||
rest, err := loadcfg.FromArgs(paths, !c.WithoutTests)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse arguments: %s", err)
|
||||
}
|
||||
if len(rest) > 0 {
|
||||
return nil, fmt.Errorf("unhandled extra arguments: %v", rest)
|
||||
}
|
||||
|
||||
return loadcfg.Load()
|
||||
}
|
||||
|
||||
// CheckPackages checks packages for errors.
|
||||
func (c *Checker) CheckPackages(paths ...string) error {
|
||||
program, err := c.load(paths...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not type check: %s", err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
u := &UncheckedErrors{}
|
||||
for _, pkgInfo := range program.InitialPackages() {
|
||||
if pkgInfo.Pkg.Path() == "unsafe" { // not a real package
|
||||
continue
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
|
||||
go func(pkgInfo *loader.PackageInfo) {
|
||||
defer wg.Done()
|
||||
c.logf("Checking %s", pkgInfo.Pkg.Path())
|
||||
|
||||
v := &visitor{
|
||||
prog: program,
|
||||
pkg: pkgInfo,
|
||||
ignore: c.Ignore,
|
||||
blank: c.Blank,
|
||||
asserts: c.Asserts,
|
||||
lines: make(map[string][]string),
|
||||
exclude: c.exclude,
|
||||
errors: []UncheckedError{},
|
||||
}
|
||||
|
||||
for _, astFile := range v.pkg.Files {
|
||||
ast.Walk(v, astFile)
|
||||
}
|
||||
u.Append(v.errors...)
|
||||
}(pkgInfo)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
if u.Len() > 0 {
|
||||
sort.Sort(byName{u})
|
||||
return u
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// visitor implements the errcheck algorithm
|
||||
type visitor struct {
|
||||
prog *loader.Program
|
||||
pkg *loader.PackageInfo
|
||||
ignore map[string]*regexp.Regexp
|
||||
blank bool
|
||||
asserts bool
|
||||
lines map[string][]string
|
||||
exclude map[string]bool
|
||||
|
||||
errors []UncheckedError
|
||||
}
|
||||
|
||||
func (v *visitor) fullName(call *ast.CallExpr) (string, bool) {
|
||||
sel, ok := call.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
fn, ok := v.pkg.ObjectOf(sel.Sel).(*types.Func)
|
||||
if !ok {
|
||||
// Shouldn't happen, but be paranoid
|
||||
return "", false
|
||||
}
|
||||
// The name is fully qualified by the import path, possible type,
|
||||
// function/method name and pointer receiver.
|
||||
//
|
||||
// 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(), true
|
||||
}
|
||||
|
||||
func (v *visitor) excludeCall(call *ast.CallExpr) bool {
|
||||
if name, ok := v.fullName(call); ok {
|
||||
return v.exclude[name]
|
||||
}
|
||||
|
||||
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.pkg.Uses[id]; obj != nil {
|
||||
if pkg := obj.Pkg(); pkg != nil {
|
||||
if re, ok := v.ignore[pkg.Path()]; ok {
|
||||
return re.MatchString(id.Name)
|
||||
}
|
||||
|
||||
// if current package being considered is vendored, check to see if it should be ignored based
|
||||
// on the unvendored path.
|
||||
if nonVendoredPkg, ok := nonVendoredPkgPath(pkg.Path()); ok {
|
||||
if re, ok := v.ignore[nonVendoredPkg]; 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). The second return value is true if the provided package was vendored, false
|
||||
// otherwise.
|
||||
func nonVendoredPkgPath(pkgPath string) (string, bool) {
|
||||
lastVendorIndex := strings.LastIndex(pkgPath, "/vendor/")
|
||||
if lastVendorIndex == -1 {
|
||||
return pkgPath, false
|
||||
}
|
||||
return pkgPath[lastVendorIndex+len("/vendor/"):], true
|
||||
}
|
||||
|
||||
// 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.pkg.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.pkg.Uses[fun].(*types.Builtin); ok {
|
||||
return fun.Name == "recover"
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (v *visitor) addErrorAtPosition(position token.Pos, call *ast.CallExpr) {
|
||||
pos := v.prog.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
|
||||
if call != nil {
|
||||
name, _ = v.fullName(call)
|
||||
}
|
||||
|
||||
v.errors = append(v.errors, UncheckedError{pos, line, name})
|
||||
}
|
||||
|
||||
func readfile(filename string) []string {
|
||||
var f, err = os.Open(filename)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
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.AssignStmt:
|
||||
if len(stmt.Rhs) == 1 {
|
||||
// single value on rhs; check against lhs identifiers
|
||||
if call, ok := stmt.Rhs[0].(*ast.CallExpr); ok {
|
||||
if !v.blank {
|
||||
break
|
||||
}
|
||||
if v.ignoreCall(call) {
|
||||
break
|
||||
}
|
||||
isError := v.errorsByArg(call)
|
||||
for i := 0; i < len(stmt.Lhs); i++ {
|
||||
if id, ok := stmt.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 := stmt.Rhs[0].(*ast.TypeAssertExpr); ok {
|
||||
if !v.asserts {
|
||||
break
|
||||
}
|
||||
if assert.Type == nil {
|
||||
// type switch
|
||||
break
|
||||
}
|
||||
if len(stmt.Lhs) < 2 {
|
||||
// assertion result not read
|
||||
v.addErrorAtPosition(stmt.Rhs[0].Pos(), nil)
|
||||
} else if id, ok := stmt.Lhs[1].(*ast.Ident); ok && v.blank && id.Name == "_" {
|
||||
// assertion result ignored
|
||||
v.addErrorAtPosition(id.NamePos, nil)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// multiple value on rhs; in this case a call can't return
|
||||
// multiple values. Assume len(stmt.Lhs) == len(stmt.Rhs)
|
||||
for i := 0; i < len(stmt.Lhs); i++ {
|
||||
if id, ok := stmt.Lhs[i].(*ast.Ident); ok {
|
||||
if call, ok := stmt.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 := stmt.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func isErrorType(t types.Type) bool {
|
||||
return types.Implements(t, errorType)
|
||||
}
|
193
tools/vendor/github.com/kisielk/errcheck/main.go
generated
vendored
Normal file
193
tools/vendor/github.com/kisielk/errcheck/main.go
generated
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/kisielk/errcheck/internal/errcheck"
|
||||
"github.com/kisielk/gotool"
|
||||
)
|
||||
|
||||
const (
|
||||
exitCodeOk int = iota
|
||||
exitUncheckedError
|
||||
exitFatalError
|
||||
)
|
||||
|
||||
var abspath bool
|
||||
|
||||
type ignoreFlag map[string]*regexp.Regexp
|
||||
|
||||
func (f ignoreFlag) String() string {
|
||||
pairs := make([]string, 0, len(f))
|
||||
for pkg, re := range f {
|
||||
prefix := ""
|
||||
if pkg != "" {
|
||||
prefix = pkg + ":"
|
||||
}
|
||||
pairs = append(pairs, prefix+re.String())
|
||||
}
|
||||
return fmt.Sprintf("%q", strings.Join(pairs, ","))
|
||||
}
|
||||
|
||||
func (f ignoreFlag) Set(s string) error {
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
for _, pair := range strings.Split(s, ",") {
|
||||
colonIndex := strings.Index(pair, ":")
|
||||
var pkg, re string
|
||||
if colonIndex == -1 {
|
||||
pkg = ""
|
||||
re = pair
|
||||
} else {
|
||||
pkg = pair[:colonIndex]
|
||||
re = pair[colonIndex+1:]
|
||||
}
|
||||
regex, err := regexp.Compile(re)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f[pkg] = regex
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type tagsFlag []string
|
||||
|
||||
func (f *tagsFlag) String() string {
|
||||
return fmt.Sprintf("%q", strings.Join(*f, " "))
|
||||
}
|
||||
|
||||
func (f *tagsFlag) Set(s string) error {
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
tags := strings.Split(s, " ")
|
||||
if tags == nil {
|
||||
return nil
|
||||
}
|
||||
for _, tag := range tags {
|
||||
if tag != "" {
|
||||
*f = append(*f, tag)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var dotStar = regexp.MustCompile(".*")
|
||||
|
||||
func reportUncheckedErrors(e *errcheck.UncheckedErrors, verbose bool) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
wd = ""
|
||||
}
|
||||
for _, uncheckedError := range e.Errors {
|
||||
pos := uncheckedError.Pos.String()
|
||||
if !abspath {
|
||||
newPos, err := filepath.Rel(wd, pos)
|
||||
if err == nil {
|
||||
pos = newPos
|
||||
}
|
||||
}
|
||||
|
||||
if verbose && uncheckedError.FuncName != "" {
|
||||
fmt.Printf("%s:\t%s\t%s\n", pos, uncheckedError.FuncName, uncheckedError.Line)
|
||||
} else {
|
||||
fmt.Printf("%s:\t%s\n", pos, uncheckedError.Line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mainCmd(args []string) int {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
|
||||
checker := errcheck.NewChecker()
|
||||
paths, err := parseFlags(checker, args)
|
||||
if err != exitCodeOk {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checker.CheckPackages(paths...); err != nil {
|
||||
if e, ok := err.(*errcheck.UncheckedErrors); ok {
|
||||
reportUncheckedErrors(e, checker.Verbose)
|
||||
return exitUncheckedError
|
||||
} else if err == errcheck.ErrNoGoFiles {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return exitCodeOk
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "error: failed to check packages: %s\n", err)
|
||||
return exitFatalError
|
||||
}
|
||||
return exitCodeOk
|
||||
}
|
||||
|
||||
func parseFlags(checker *errcheck.Checker, args []string) ([]string, int) {
|
||||
flags := flag.NewFlagSet(args[0], flag.ContinueOnError)
|
||||
flags.BoolVar(&checker.Blank, "blank", false, "if true, check for errors assigned to blank identifier")
|
||||
flags.BoolVar(&checker.Asserts, "asserts", false, "if true, check for ignored type assertion results")
|
||||
flags.BoolVar(&checker.WithoutTests, "ignoretests", false, "if true, checking of _test.go files is disabled")
|
||||
flags.BoolVar(&checker.Verbose, "verbose", false, "produce more verbose logging")
|
||||
|
||||
flags.BoolVar(&abspath, "abspath", false, "print absolute paths to files")
|
||||
|
||||
tags := tagsFlag{}
|
||||
flags.Var(&tags, "tags", "space-separated list of build tags to include")
|
||||
ignorePkg := flags.String("ignorepkg", "", "comma-separated list of package paths to ignore")
|
||||
ignore := ignoreFlag(map[string]*regexp.Regexp{
|
||||
"fmt": dotStar,
|
||||
})
|
||||
flags.Var(ignore, "ignore", "[deprecated] comma-separated list of pairs of the form pkg:regex\n"+
|
||||
" the regex is used to ignore names within pkg.")
|
||||
|
||||
var excludeFile string
|
||||
flags.StringVar(&excludeFile, "exclude", "", "Path to a file containing a list of functions to exclude from checking")
|
||||
|
||||
if err := flags.Parse(args[1:]); err != nil {
|
||||
return nil, exitFatalError
|
||||
}
|
||||
|
||||
if excludeFile != "" {
|
||||
exclude := make(map[string]bool)
|
||||
fh, err := os.Open(excludeFile)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Could not read exclude file: %s\n", err)
|
||||
return nil, exitFatalError
|
||||
}
|
||||
scanner := bufio.NewScanner(fh)
|
||||
for scanner.Scan() {
|
||||
name := scanner.Text()
|
||||
exclude[name] = true
|
||||
|
||||
if checker.Verbose {
|
||||
fmt.Printf("Excluding %s\n", name)
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Could not read exclude file: %s\n", err)
|
||||
return nil, exitFatalError
|
||||
}
|
||||
checker.SetExclude(exclude)
|
||||
}
|
||||
|
||||
checker.Tags = tags
|
||||
for _, pkg := range strings.Split(*ignorePkg, ",") {
|
||||
if pkg != "" {
|
||||
ignore[pkg] = dotStar
|
||||
}
|
||||
}
|
||||
checker.Ignore = ignore
|
||||
|
||||
// ImportPaths normalizes paths and expands '...'
|
||||
return gotool.ImportPaths(flags.Args()), exitCodeOk
|
||||
}
|
||||
|
||||
func main() {
|
||||
os.Exit(mainCmd(os.Args))
|
||||
}
|
32
tools/vendor/github.com/kisielk/gotool/LEGAL
generated
vendored
Normal file
32
tools/vendor/github.com/kisielk/gotool/LEGAL
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
All the files in this distribution are covered under either the MIT
|
||||
license (see the file LICENSE) except some files mentioned below.
|
||||
|
||||
match.go, match_test.go:
|
||||
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
20
tools/vendor/github.com/kisielk/gotool/LICENSE
generated
vendored
Normal file
20
tools/vendor/github.com/kisielk/gotool/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2013 Kamil Kisiel <kamil@kamilkisiel.net>
|
||||
|
||||
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.
|
6
tools/vendor/github.com/kisielk/gotool/README.md
generated
vendored
Normal file
6
tools/vendor/github.com/kisielk/gotool/README.md
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
gotool
|
||||
======
|
||||
[](https://godoc.org/github.com/kisielk/gotool)
|
||||
[](https://travis-ci.org/kisielk/gotool)
|
||||
|
||||
Package gotool contains utility functions used to implement the standard "cmd/go" tool, provided as a convenience to developers who want to write tools with similar semantics.
|
15
tools/vendor/github.com/kisielk/gotool/go13.go
generated
vendored
Normal file
15
tools/vendor/github.com/kisielk/gotool/go13.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// +build !go1.4
|
||||
|
||||
package gotool
|
||||
|
||||
import (
|
||||
"go/build"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var gorootSrc = filepath.Join(runtime.GOROOT(), "src", "pkg")
|
||||
|
||||
func shouldIgnoreImport(p *build.Package) bool {
|
||||
return true
|
||||
}
|
15
tools/vendor/github.com/kisielk/gotool/go14-15.go
generated
vendored
Normal file
15
tools/vendor/github.com/kisielk/gotool/go14-15.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// +build go1.4,!go1.6
|
||||
|
||||
package gotool
|
||||
|
||||
import (
|
||||
"go/build"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var gorootSrc = filepath.Join(runtime.GOROOT(), "src")
|
||||
|
||||
func shouldIgnoreImport(p *build.Package) bool {
|
||||
return true
|
||||
}
|
15
tools/vendor/github.com/kisielk/gotool/go16.go
generated
vendored
Normal file
15
tools/vendor/github.com/kisielk/gotool/go16.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// +build go1.6
|
||||
|
||||
package gotool
|
||||
|
||||
import (
|
||||
"go/build"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var gorootSrc = filepath.Join(runtime.GOROOT(), "src")
|
||||
|
||||
func shouldIgnoreImport(p *build.Package) bool {
|
||||
return p == nil || len(p.InvalidGoFiles) == 0
|
||||
}
|
310
tools/vendor/github.com/kisielk/gotool/match.go
generated
vendored
Normal file
310
tools/vendor/github.com/kisielk/gotool/match.go
generated
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
// Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package gotool
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/build"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// This file contains code from the Go distribution.
|
||||
|
||||
// matchPattern(pattern)(name) reports whether
|
||||
// name matches pattern. Pattern is a limited glob
|
||||
// pattern in which '...' means 'any string' and there
|
||||
// is no other special syntax.
|
||||
func matchPattern(pattern string) func(name string) bool {
|
||||
re := regexp.QuoteMeta(pattern)
|
||||
re = strings.Replace(re, `\.\.\.`, `.*`, -1)
|
||||
// Special case: foo/... matches foo too.
|
||||
if strings.HasSuffix(re, `/.*`) {
|
||||
re = re[:len(re)-len(`/.*`)] + `(/.*)?`
|
||||
}
|
||||
reg := regexp.MustCompile(`^` + re + `$`)
|
||||
return reg.MatchString
|
||||
}
|
||||
|
||||
func (c *Context) matchPackages(pattern string) []string {
|
||||
match := func(string) bool { return true }
|
||||
treeCanMatch := func(string) bool { return true }
|
||||
if !isMetaPackage(pattern) {
|
||||
match = matchPattern(pattern)
|
||||
treeCanMatch = treeCanMatchPattern(pattern)
|
||||
}
|
||||
|
||||
have := map[string]bool{
|
||||
"builtin": true, // ignore pseudo-package that exists only for documentation
|
||||
}
|
||||
if !c.BuildContext.CgoEnabled {
|
||||
have["runtime/cgo"] = true // ignore during walk
|
||||
}
|
||||
var pkgs []string
|
||||
|
||||
for _, src := range c.BuildContext.SrcDirs() {
|
||||
if (pattern == "std" || pattern == "cmd") && src != gorootSrc {
|
||||
continue
|
||||
}
|
||||
src = filepath.Clean(src) + string(filepath.Separator)
|
||||
root := src
|
||||
if pattern == "cmd" {
|
||||
root += "cmd" + string(filepath.Separator)
|
||||
}
|
||||
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || !fi.IsDir() || path == src {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Avoid .foo, _foo, and testdata directory trees.
|
||||
_, elem := filepath.Split(path)
|
||||
if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
name := filepath.ToSlash(path[len(src):])
|
||||
if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") {
|
||||
// The name "std" is only the standard library.
|
||||
// If the name is cmd, it's the root of the command tree.
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if !treeCanMatch(name) {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if have[name] {
|
||||
return nil
|
||||
}
|
||||
have[name] = true
|
||||
if !match(name) {
|
||||
return nil
|
||||
}
|
||||
_, err = c.BuildContext.ImportDir(path, 0)
|
||||
if err != nil {
|
||||
if _, noGo := err.(*build.NoGoError); noGo {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
pkgs = append(pkgs, name)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// importPathsNoDotExpansion returns the import paths to use for the given
|
||||
// command line, but it does no ... expansion.
|
||||
func (c *Context) importPathsNoDotExpansion(args []string) []string {
|
||||
if len(args) == 0 {
|
||||
return []string{"."}
|
||||
}
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
// Arguments are supposed to be import paths, but
|
||||
// as a courtesy to Windows developers, rewrite \ to /
|
||||
// in command-line arguments. Handles .\... and so on.
|
||||
if filepath.Separator == '\\' {
|
||||
a = strings.Replace(a, `\`, `/`, -1)
|
||||
}
|
||||
|
||||
// Put argument in canonical form, but preserve leading ./.
|
||||
if strings.HasPrefix(a, "./") {
|
||||
a = "./" + path.Clean(a)
|
||||
if a == "./." {
|
||||
a = "."
|
||||
}
|
||||
} else {
|
||||
a = path.Clean(a)
|
||||
}
|
||||
if isMetaPackage(a) {
|
||||
out = append(out, c.allPackages(a)...)
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// importPaths returns the import paths to use for the given command line.
|
||||
func (c *Context) importPaths(args []string) []string {
|
||||
args = c.importPathsNoDotExpansion(args)
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
if strings.Contains(a, "...") {
|
||||
if build.IsLocalImport(a) {
|
||||
out = append(out, c.allPackagesInFS(a)...)
|
||||
} else {
|
||||
out = append(out, c.allPackages(a)...)
|
||||
}
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// allPackages returns all the packages that can be found
|
||||
// under the $GOPATH directories and $GOROOT matching pattern.
|
||||
// The pattern is either "all" (all packages), "std" (standard packages),
|
||||
// "cmd" (standard commands), or a path including "...".
|
||||
func (c *Context) allPackages(pattern string) []string {
|
||||
pkgs := c.matchPackages(pattern)
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// allPackagesInFS is like allPackages but is passed a pattern
|
||||
// beginning ./ or ../, meaning it should scan the tree rooted
|
||||
// at the given directory. There are ... in the pattern too.
|
||||
func (c *Context) allPackagesInFS(pattern string) []string {
|
||||
pkgs := c.matchPackagesInFS(pattern)
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
func (c *Context) matchPackagesInFS(pattern string) []string {
|
||||
// Find directory to begin the scan.
|
||||
// Could be smarter but this one optimization
|
||||
// is enough for now, since ... is usually at the
|
||||
// end of a path.
|
||||
i := strings.Index(pattern, "...")
|
||||
dir, _ := path.Split(pattern[:i])
|
||||
|
||||
// pattern begins with ./ or ../.
|
||||
// path.Clean will discard the ./ but not the ../.
|
||||
// We need to preserve the ./ for pattern matching
|
||||
// and in the returned import paths.
|
||||
prefix := ""
|
||||
if strings.HasPrefix(pattern, "./") {
|
||||
prefix = "./"
|
||||
}
|
||||
match := matchPattern(pattern)
|
||||
|
||||
var pkgs []string
|
||||
filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || !fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if path == dir {
|
||||
// filepath.Walk starts at dir and recurses. For the recursive case,
|
||||
// the path is the result of filepath.Join, which calls filepath.Clean.
|
||||
// The initial case is not Cleaned, though, so we do this explicitly.
|
||||
//
|
||||
// This converts a path like "./io/" to "io". Without this step, running
|
||||
// "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io
|
||||
// package, because prepending the prefix "./" to the unclean path would
|
||||
// result in "././io", and match("././io") returns false.
|
||||
path = filepath.Clean(path)
|
||||
}
|
||||
|
||||
// Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..".
|
||||
_, elem := filepath.Split(path)
|
||||
dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".."
|
||||
if dot || strings.HasPrefix(elem, "_") || elem == "testdata" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
name := prefix + filepath.ToSlash(path)
|
||||
if !match(name) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// We keep the directory if we can import it, or if we can't import it
|
||||
// due to invalid Go source files. This means that directories containing
|
||||
// parse errors will be built (and fail) instead of being silently skipped
|
||||
// as not matching the pattern. Go 1.5 and earlier skipped, but that
|
||||
// behavior means people miss serious mistakes.
|
||||
// See golang.org/issue/11407.
|
||||
if p, err := c.BuildContext.ImportDir(path, 0); err != nil && shouldIgnoreImport(p) {
|
||||
if _, noGo := err.(*build.NoGoError); !noGo {
|
||||
log.Print(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
pkgs = append(pkgs, name)
|
||||
return nil
|
||||
})
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// isMetaPackage checks if name is a reserved package name that expands to multiple packages
|
||||
func isMetaPackage(name string) bool {
|
||||
return name == "std" || name == "cmd" || name == "all"
|
||||
}
|
||||
|
||||
// isStandardImportPath reports whether $GOROOT/src/path should be considered
|
||||
// part of the standard distribution. For historical reasons we allow people to add
|
||||
// their own code to $GOROOT instead of using $GOPATH, but we assume that
|
||||
// code will start with a domain name (dot in the first element).
|
||||
func isStandardImportPath(path string) bool {
|
||||
i := strings.Index(path, "/")
|
||||
if i < 0 {
|
||||
i = len(path)
|
||||
}
|
||||
elem := path[:i]
|
||||
return !strings.Contains(elem, ".")
|
||||
}
|
||||
|
||||
// hasPathPrefix reports whether the path s begins with the
|
||||
// elements in prefix.
|
||||
func hasPathPrefix(s, prefix string) bool {
|
||||
switch {
|
||||
default:
|
||||
return false
|
||||
case len(s) == len(prefix):
|
||||
return s == prefix
|
||||
case len(s) > len(prefix):
|
||||
if prefix != "" && prefix[len(prefix)-1] == '/' {
|
||||
return strings.HasPrefix(s, prefix)
|
||||
}
|
||||
return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
|
||||
}
|
||||
}
|
||||
|
||||
// treeCanMatchPattern(pattern)(name) reports whether
|
||||
// name or children of name can possibly match pattern.
|
||||
// Pattern is the same limited glob accepted by matchPattern.
|
||||
func treeCanMatchPattern(pattern string) func(name string) bool {
|
||||
wildCard := false
|
||||
if i := strings.Index(pattern, "..."); i >= 0 {
|
||||
wildCard = true
|
||||
pattern = pattern[:i]
|
||||
}
|
||||
return func(name string) bool {
|
||||
return len(name) <= len(pattern) && hasPathPrefix(pattern, name) ||
|
||||
wildCard && strings.HasPrefix(name, pattern)
|
||||
}
|
||||
}
|
48
tools/vendor/github.com/kisielk/gotool/tool.go
generated
vendored
Normal file
48
tools/vendor/github.com/kisielk/gotool/tool.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// Package gotool contains utility functions used to implement the standard
|
||||
// "cmd/go" tool, provided as a convenience to developers who want to write
|
||||
// tools with similar semantics.
|
||||
package gotool
|
||||
|
||||
import "go/build"
|
||||
|
||||
// Export functions here to make it easier to keep the implementations up to date with upstream.
|
||||
|
||||
// DefaultContext is the default context that uses build.Default.
|
||||
var DefaultContext = Context{
|
||||
BuildContext: build.Default,
|
||||
}
|
||||
|
||||
// A Context specifies the supporting context.
|
||||
type Context struct {
|
||||
// BuildContext is the build.Context that is used when computing import paths.
|
||||
BuildContext build.Context
|
||||
}
|
||||
|
||||
// ImportPaths returns the import paths to use for the given command line.
|
||||
//
|
||||
// The path "all" is expanded to all packages in $GOPATH and $GOROOT.
|
||||
// The path "std" is expanded to all packages in the Go standard library.
|
||||
// The path "cmd" is expanded to all Go standard commands.
|
||||
// The string "..." is treated as a wildcard within a path.
|
||||
// When matching recursively, directories are ignored if they are prefixed with
|
||||
// a dot or an underscore (such as ".foo" or "_foo"), or are named "testdata".
|
||||
// Relative import paths are not converted to full import paths.
|
||||
// If args is empty, a single element "." is returned.
|
||||
func (c *Context) ImportPaths(args []string) []string {
|
||||
return c.importPaths(args)
|
||||
}
|
||||
|
||||
// ImportPaths returns the import paths to use for the given command line
|
||||
// using default context.
|
||||
//
|
||||
// The path "all" is expanded to all packages in $GOPATH and $GOROOT.
|
||||
// The path "std" is expanded to all packages in the Go standard library.
|
||||
// The path "cmd" is expanded to all Go standard commands.
|
||||
// The string "..." is treated as a wildcard within a path.
|
||||
// When matching recursively, directories are ignored if they are prefixed with
|
||||
// a dot or an underscore (such as ".foo" or "_foo"), or are named "testdata".
|
||||
// Relative import paths are not converted to full import paths.
|
||||
// If args is empty, a single element "." is returned.
|
||||
func ImportPaths(args []string) []string {
|
||||
return DefaultContext.importPaths(args)
|
||||
}
|
Reference in New Issue
Block a user