Updated staticcheck
This commit is contained in:
10
vendor/honnef.co/go/tools/lint/generated.go
vendored
10
vendor/honnef.co/go/tools/lint/generated.go
vendored
@ -4,6 +4,7 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -15,8 +16,13 @@ var (
|
||||
crnl = []byte("\r\n")
|
||||
)
|
||||
|
||||
func isGenerated(r io.Reader) bool {
|
||||
br := bufio.NewReader(r)
|
||||
func isGenerated(path string) bool {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
br := bufio.NewReader(f)
|
||||
for {
|
||||
s, err := br.ReadBytes('\n')
|
||||
if err != nil && err != io.EOF {
|
||||
|
305
vendor/honnef.co/go/tools/lint/lint.go
vendored
305
vendor/honnef.co/go/tools/lint/lint.go
vendored
@ -2,6 +2,7 @@
|
||||
package lint // import "honnef.co/go/tools/lint"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
@ -9,12 +10,14 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/tools/go/ast/inspector"
|
||||
"golang.org/x/tools/go/packages"
|
||||
"honnef.co/go/tools/config"
|
||||
"honnef.co/go/tools/ssa"
|
||||
@ -22,9 +25,9 @@ import (
|
||||
)
|
||||
|
||||
type Job struct {
|
||||
Program *Program
|
||||
Pkg *Pkg
|
||||
GoVersion int
|
||||
|
||||
checker string
|
||||
check Check
|
||||
problems []Problem
|
||||
|
||||
@ -106,20 +109,10 @@ func (gi *GlobIgnore) Match(p Problem) bool {
|
||||
}
|
||||
|
||||
type Program struct {
|
||||
SSA *ssa.Program
|
||||
InitialPackages []*Pkg
|
||||
InitialFunctions []*ssa.Function
|
||||
AllPackages []*packages.Package
|
||||
AllFunctions []*ssa.Function
|
||||
Files []*ast.File
|
||||
GoVersion int
|
||||
|
||||
tokenFileMap map[*token.File]*ast.File
|
||||
astFileMap map[*ast.File]*Pkg
|
||||
packagesMap map[string]*packages.Package
|
||||
|
||||
genMu sync.RWMutex
|
||||
generatedMap map[string]bool
|
||||
SSA *ssa.Program
|
||||
InitialPackages []*Pkg
|
||||
AllPackages []*packages.Package
|
||||
AllFunctions []*ssa.Function
|
||||
}
|
||||
|
||||
func (prog *Program) Fset() *token.FileSet {
|
||||
@ -141,7 +134,6 @@ type Problem struct {
|
||||
Position token.Position // position in source file
|
||||
Text string // the prose that describes the problem
|
||||
Check string
|
||||
Checker string
|
||||
Package *Pkg
|
||||
Severity Severity
|
||||
}
|
||||
@ -164,6 +156,7 @@ type Check struct {
|
||||
Fn Func
|
||||
ID string
|
||||
FilterGenerated bool
|
||||
Doc string
|
||||
}
|
||||
|
||||
// A Linter lints Go source code.
|
||||
@ -205,12 +198,8 @@ func (l *Linter) ignore(p Problem) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (prog *Program) File(node Positioner) *ast.File {
|
||||
return prog.tokenFileMap[prog.SSA.Fset.File(node.Pos())]
|
||||
}
|
||||
|
||||
func (j *Job) File(node Positioner) *ast.File {
|
||||
return j.Program.File(node)
|
||||
return j.Pkg.tokenFileMap[j.Pkg.Fset.File(node.Pos())]
|
||||
}
|
||||
|
||||
func parseDirective(s string) (cmd string, args []string) {
|
||||
@ -266,6 +255,7 @@ func (l *Linter) Lint(initial []*packages.Package, stats *PerfStats) []Problem {
|
||||
if stats != nil {
|
||||
stats.SSABuild = time.Since(t)
|
||||
}
|
||||
runtime.GC()
|
||||
|
||||
t = time.Now()
|
||||
pkgMap := map[*ssa.Package]*Pkg{}
|
||||
@ -291,9 +281,19 @@ func (l *Linter) Lint(initial []*packages.Package, stats *PerfStats) []Problem {
|
||||
}
|
||||
|
||||
pkg := &Pkg{
|
||||
SSA: ssapkg,
|
||||
Package: pkg,
|
||||
Config: cfg,
|
||||
SSA: ssapkg,
|
||||
Package: pkg,
|
||||
Config: cfg,
|
||||
Generated: map[string]bool{},
|
||||
tokenFileMap: map[*token.File]*ast.File{},
|
||||
}
|
||||
pkg.Inspector = inspector.New(pkg.Syntax)
|
||||
for _, f := range pkg.Syntax {
|
||||
tf := pkg.Fset.File(f.Pos())
|
||||
pkg.tokenFileMap[tf] = f
|
||||
|
||||
path := DisplayPosition(pkg.Fset, f.Pos()).Filename
|
||||
pkg.Generated[path] = isGenerated(path)
|
||||
}
|
||||
pkgMap[ssapkg] = pkg
|
||||
pkgs = append(pkgs, pkg)
|
||||
@ -303,42 +303,15 @@ func (l *Linter) Lint(initial []*packages.Package, stats *PerfStats) []Problem {
|
||||
SSA: ssaprog,
|
||||
InitialPackages: pkgs,
|
||||
AllPackages: allPkgs,
|
||||
GoVersion: l.GoVersion,
|
||||
tokenFileMap: map[*token.File]*ast.File{},
|
||||
astFileMap: map[*ast.File]*Pkg{},
|
||||
generatedMap: map[string]bool{},
|
||||
}
|
||||
prog.packagesMap = map[string]*packages.Package{}
|
||||
for _, pkg := range allPkgs {
|
||||
prog.packagesMap[pkg.Types.Path()] = pkg
|
||||
}
|
||||
|
||||
isInitial := map[*types.Package]struct{}{}
|
||||
for _, pkg := range pkgs {
|
||||
isInitial[pkg.Types] = struct{}{}
|
||||
}
|
||||
for fn := range ssautil.AllFunctions(ssaprog) {
|
||||
prog.AllFunctions = append(prog.AllFunctions, fn)
|
||||
if fn.Pkg == nil {
|
||||
continue
|
||||
}
|
||||
prog.AllFunctions = append(prog.AllFunctions, fn)
|
||||
if _, ok := isInitial[fn.Pkg.Pkg]; ok {
|
||||
prog.InitialFunctions = append(prog.InitialFunctions, fn)
|
||||
}
|
||||
}
|
||||
for _, pkg := range pkgs {
|
||||
prog.Files = append(prog.Files, pkg.Syntax...)
|
||||
|
||||
ssapkg := ssaprog.Package(pkg.Types)
|
||||
for _, f := range pkg.Syntax {
|
||||
prog.astFileMap[f] = pkgMap[ssapkg]
|
||||
}
|
||||
}
|
||||
|
||||
for _, pkg := range allPkgs {
|
||||
for _, f := range pkg.Syntax {
|
||||
tf := pkg.Fset.File(f.Pos())
|
||||
prog.tokenFileMap[tf] = f
|
||||
if pkg, ok := pkgMap[fn.Pkg]; ok {
|
||||
pkg.InitialFunctions = append(pkg.InitialFunctions, fn)
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,6 +319,19 @@ func (l *Linter) Lint(initial []*packages.Package, stats *PerfStats) []Problem {
|
||||
l.automaticIgnores = nil
|
||||
for _, pkg := range initial {
|
||||
for _, f := range pkg.Syntax {
|
||||
found := false
|
||||
commentLoop:
|
||||
for _, cg := range f.Comments {
|
||||
for _, c := range cg.List {
|
||||
if strings.Contains(c.Text, "//lint:") {
|
||||
found = true
|
||||
break commentLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
cm := ast.NewCommentMap(pkg.Fset, f, f.Comments)
|
||||
for node, cgs := range cm {
|
||||
for _, cg := range cgs {
|
||||
@ -359,10 +345,9 @@ func (l *Linter) Lint(initial []*packages.Package, stats *PerfStats) []Problem {
|
||||
if len(args) < 2 {
|
||||
// FIXME(dh): this causes duplicated warnings when using megacheck
|
||||
p := Problem{
|
||||
Position: prog.DisplayPosition(c.Pos()),
|
||||
Position: DisplayPosition(prog.Fset(), c.Pos()),
|
||||
Text: "malformed linter directive; missing the required reason field?",
|
||||
Check: "",
|
||||
Checker: "lint",
|
||||
Package: nil,
|
||||
}
|
||||
out = append(out, p)
|
||||
@ -373,7 +358,7 @@ func (l *Linter) Lint(initial []*packages.Package, stats *PerfStats) []Problem {
|
||||
continue
|
||||
}
|
||||
checks := strings.Split(args[0], ",")
|
||||
pos := prog.DisplayPosition(node.Pos())
|
||||
pos := DisplayPosition(prog.Fset(), node.Pos())
|
||||
var ig Ignore
|
||||
switch cmd {
|
||||
case "ignore":
|
||||
@ -396,23 +381,6 @@ func (l *Linter) Lint(initial []*packages.Package, stats *PerfStats) []Problem {
|
||||
}
|
||||
}
|
||||
|
||||
sizes := struct {
|
||||
types int
|
||||
defs int
|
||||
uses int
|
||||
implicits int
|
||||
selections int
|
||||
scopes int
|
||||
}{}
|
||||
for _, pkg := range pkgs {
|
||||
sizes.types += len(pkg.TypesInfo.Types)
|
||||
sizes.defs += len(pkg.TypesInfo.Defs)
|
||||
sizes.uses += len(pkg.TypesInfo.Uses)
|
||||
sizes.implicits += len(pkg.TypesInfo.Implicits)
|
||||
sizes.selections += len(pkg.TypesInfo.Selections)
|
||||
sizes.scopes += len(pkg.TypesInfo.Scopes)
|
||||
}
|
||||
|
||||
if stats != nil {
|
||||
stats.OtherInitWork = time.Since(t)
|
||||
}
|
||||
@ -428,41 +396,31 @@ func (l *Linter) Lint(initial []*packages.Package, stats *PerfStats) []Problem {
|
||||
var jobs []*Job
|
||||
var allChecks []string
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for _, checker := range l.Checkers {
|
||||
checks := checker.Checks()
|
||||
for _, check := range checks {
|
||||
for _, check := range checker.Checks() {
|
||||
allChecks = append(allChecks, check.ID)
|
||||
j := &Job{
|
||||
Program: prog,
|
||||
checker: checker.Name(),
|
||||
check: check,
|
||||
if check.Fn == nil {
|
||||
continue
|
||||
}
|
||||
for _, pkg := range pkgs {
|
||||
j := &Job{
|
||||
Pkg: pkg,
|
||||
check: check,
|
||||
GoVersion: l.GoVersion,
|
||||
}
|
||||
jobs = append(jobs, j)
|
||||
wg.Add(1)
|
||||
go func(check Check, j *Job) {
|
||||
t := time.Now()
|
||||
check.Fn(j)
|
||||
j.duration = time.Since(t)
|
||||
wg.Done()
|
||||
}(check, j)
|
||||
}
|
||||
jobs = append(jobs, j)
|
||||
}
|
||||
}
|
||||
|
||||
max := len(jobs)
|
||||
if l.MaxConcurrentJobs > 0 {
|
||||
max = l.MaxConcurrentJobs
|
||||
}
|
||||
|
||||
sem := make(chan struct{}, max)
|
||||
wg := &sync.WaitGroup{}
|
||||
for _, j := range jobs {
|
||||
wg.Add(1)
|
||||
go func(j *Job) {
|
||||
defer wg.Done()
|
||||
sem <- struct{}{}
|
||||
defer func() { <-sem }()
|
||||
fn := j.check.Fn
|
||||
if fn == nil {
|
||||
return
|
||||
}
|
||||
t := time.Now()
|
||||
fn(j)
|
||||
j.duration = time.Since(t)
|
||||
}(j)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for _, j := range jobs {
|
||||
@ -470,6 +428,9 @@ func (l *Linter) Lint(initial []*packages.Package, stats *PerfStats) []Problem {
|
||||
stats.Jobs = append(stats.Jobs, JobStat{j.check.ID, j.duration})
|
||||
}
|
||||
for _, p := range j.problems {
|
||||
if p.Package == nil {
|
||||
panic(fmt.Sprintf("internal error: problem at position %s has nil package", p.Position))
|
||||
}
|
||||
allowedChecks := FilterChecks(allChecks, p.Package.Config.Checks)
|
||||
|
||||
if l.ignore(p) {
|
||||
@ -498,19 +459,21 @@ func (l *Linter) Lint(initial []*packages.Package, stats *PerfStats) []Problem {
|
||||
}
|
||||
|
||||
couldveMatched := false
|
||||
for f, pkg := range prog.astFileMap {
|
||||
if prog.Fset().Position(f.Pos()).Filename != ig.File {
|
||||
continue
|
||||
}
|
||||
allowedChecks := FilterChecks(allChecks, pkg.Config.Checks)
|
||||
for _, c := range ig.Checks {
|
||||
if !allowedChecks[c] {
|
||||
for _, pkg := range pkgs {
|
||||
for _, f := range pkg.tokenFileMap {
|
||||
if prog.Fset().Position(f.Pos()).Filename != ig.File {
|
||||
continue
|
||||
}
|
||||
couldveMatched = true
|
||||
allowedChecks := FilterChecks(allChecks, pkg.Config.Checks)
|
||||
for _, c := range ig.Checks {
|
||||
if !allowedChecks[c] {
|
||||
continue
|
||||
}
|
||||
couldveMatched = true
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if !couldveMatched {
|
||||
@ -519,10 +482,9 @@ func (l *Linter) Lint(initial []*packages.Package, stats *PerfStats) []Problem {
|
||||
continue
|
||||
}
|
||||
p := Problem{
|
||||
Position: prog.DisplayPosition(ig.pos),
|
||||
Position: DisplayPosition(prog.Fset(), ig.pos),
|
||||
Text: "this linter directive didn't match anything; should it be removed?",
|
||||
Check: "",
|
||||
Checker: "lint",
|
||||
Package: nil,
|
||||
}
|
||||
out = append(out, p)
|
||||
@ -609,28 +571,30 @@ func FilterChecks(allChecks []string, checks []string) map[string]bool {
|
||||
return allowedChecks
|
||||
}
|
||||
|
||||
func (prog *Program) Package(path string) *packages.Package {
|
||||
return prog.packagesMap[path]
|
||||
}
|
||||
|
||||
// Pkg represents a package being linted.
|
||||
type Pkg struct {
|
||||
SSA *ssa.Package
|
||||
SSA *ssa.Package
|
||||
InitialFunctions []*ssa.Function
|
||||
*packages.Package
|
||||
Config config.Config
|
||||
Config config.Config
|
||||
Inspector *inspector.Inspector
|
||||
// TODO(dh): this map should probably map from *ast.File, not string
|
||||
Generated map[string]bool
|
||||
|
||||
tokenFileMap map[*token.File]*ast.File
|
||||
}
|
||||
|
||||
type Positioner interface {
|
||||
Pos() token.Pos
|
||||
}
|
||||
|
||||
func (prog *Program) DisplayPosition(p token.Pos) token.Position {
|
||||
func DisplayPosition(fset *token.FileSet, p token.Pos) token.Position {
|
||||
// Only use the adjusted position if it points to another Go file.
|
||||
// This means we'll point to the original file for cgo files, but
|
||||
// we won't point to a YACC grammar file.
|
||||
|
||||
pos := prog.Fset().PositionFor(p, false)
|
||||
adjPos := prog.Fset().PositionFor(p, true)
|
||||
pos := fset.PositionFor(p, false)
|
||||
adjPos := fset.PositionFor(p, true)
|
||||
|
||||
if filepath.Ext(adjPos.Filename) == ".go" {
|
||||
return adjPos
|
||||
@ -638,60 +602,21 @@ func (prog *Program) DisplayPosition(p token.Pos) token.Position {
|
||||
return pos
|
||||
}
|
||||
|
||||
func (prog *Program) isGenerated(path string) bool {
|
||||
// This function isn't very efficient in terms of lock contention
|
||||
// and lack of parallelism, but it really shouldn't matter.
|
||||
// Projects consists of thousands of files, and have hundreds of
|
||||
// errors. That's not a lot of calls to isGenerated.
|
||||
|
||||
prog.genMu.RLock()
|
||||
if b, ok := prog.generatedMap[path]; ok {
|
||||
prog.genMu.RUnlock()
|
||||
return b
|
||||
}
|
||||
prog.genMu.RUnlock()
|
||||
prog.genMu.Lock()
|
||||
defer prog.genMu.Unlock()
|
||||
// recheck to avoid doing extra work in case of race
|
||||
if b, ok := prog.generatedMap[path]; ok {
|
||||
return b
|
||||
}
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
b := isGenerated(f)
|
||||
prog.generatedMap[path] = b
|
||||
return b
|
||||
}
|
||||
|
||||
func (j *Job) Errorf(n Positioner, format string, args ...interface{}) *Problem {
|
||||
tf := j.Program.SSA.Fset.File(n.Pos())
|
||||
f := j.Program.tokenFileMap[tf]
|
||||
pkg := j.Program.astFileMap[f]
|
||||
|
||||
pos := j.Program.DisplayPosition(n.Pos())
|
||||
if j.Program.isGenerated(pos.Filename) && j.check.FilterGenerated {
|
||||
pos := DisplayPosition(j.Pkg.Fset, n.Pos())
|
||||
if j.Pkg.Generated[pos.Filename] && j.check.FilterGenerated {
|
||||
return nil
|
||||
}
|
||||
problem := Problem{
|
||||
Position: pos,
|
||||
Text: fmt.Sprintf(format, args...),
|
||||
Check: j.check.ID,
|
||||
Checker: j.checker,
|
||||
Package: pkg,
|
||||
Package: j.Pkg,
|
||||
}
|
||||
j.problems = append(j.problems, problem)
|
||||
return &j.problems[len(j.problems)-1]
|
||||
}
|
||||
|
||||
func (j *Job) NodePackage(node Positioner) *Pkg {
|
||||
f := j.File(node)
|
||||
return j.Program.astFileMap[f]
|
||||
}
|
||||
|
||||
func allPackages(pkgs []*packages.Package) []*packages.Package {
|
||||
var out []*packages.Package
|
||||
packages.Visit(
|
||||
@ -704,3 +629,51 @@ func allPackages(pkgs []*packages.Package) []*packages.Package {
|
||||
)
|
||||
return out
|
||||
}
|
||||
|
||||
var bufferPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
buf.Grow(64)
|
||||
return buf
|
||||
},
|
||||
}
|
||||
|
||||
func FuncName(f *types.Func) string {
|
||||
buf := bufferPool.Get().(*bytes.Buffer)
|
||||
buf.Reset()
|
||||
if f.Type() != nil {
|
||||
sig := f.Type().(*types.Signature)
|
||||
if recv := sig.Recv(); recv != nil {
|
||||
buf.WriteByte('(')
|
||||
if _, ok := recv.Type().(*types.Interface); ok {
|
||||
// gcimporter creates abstract methods of
|
||||
// named interfaces using the interface type
|
||||
// (not the named type) as the receiver.
|
||||
// Don't print it in full.
|
||||
buf.WriteString("interface")
|
||||
} else {
|
||||
types.WriteType(buf, recv.Type(), nil)
|
||||
}
|
||||
buf.WriteByte(')')
|
||||
buf.WriteByte('.')
|
||||
} else if f.Pkg() != nil {
|
||||
writePackage(buf, f.Pkg())
|
||||
}
|
||||
}
|
||||
buf.WriteString(f.Name())
|
||||
s := buf.String()
|
||||
bufferPool.Put(buf)
|
||||
return s
|
||||
}
|
||||
|
||||
func writePackage(buf *bytes.Buffer, pkg *types.Package) {
|
||||
if pkg == nil {
|
||||
return
|
||||
}
|
||||
var s string
|
||||
s = pkg.Path()
|
||||
if s != "" {
|
||||
buf.WriteString(s)
|
||||
buf.WriteByte('.')
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ func CallName(call *ssa.CallCommon) string {
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return fn.FullName()
|
||||
return lint.FuncName(fn)
|
||||
case *ssa.Builtin:
|
||||
return v.Name()
|
||||
}
|
||||
@ -63,7 +63,7 @@ func IsExample(fn *ssa.Function) bool {
|
||||
|
||||
func IsPointerLike(T types.Type) bool {
|
||||
switch T := T.Underlying().(type) {
|
||||
case *types.Interface, *types.Chan, *types.Map, *types.Pointer:
|
||||
case *types.Interface, *types.Chan, *types.Map, *types.Signature, *types.Pointer:
|
||||
return true
|
||||
case *types.Basic:
|
||||
return T.Kind() == types.UnsafePointer
|
||||
@ -103,26 +103,14 @@ func IsZero(expr ast.Expr) bool {
|
||||
return IsIntLiteral(expr, "0")
|
||||
}
|
||||
|
||||
func TypeOf(j *lint.Job, expr ast.Expr) types.Type {
|
||||
if expr == nil {
|
||||
return nil
|
||||
}
|
||||
return j.NodePackage(expr).TypesInfo.TypeOf(expr)
|
||||
}
|
||||
|
||||
func IsOfType(j *lint.Job, expr ast.Expr, name string) bool { return IsType(TypeOf(j, expr), name) }
|
||||
|
||||
func ObjectOf(j *lint.Job, ident *ast.Ident) types.Object {
|
||||
if ident == nil {
|
||||
return nil
|
||||
}
|
||||
return j.NodePackage(ident).TypesInfo.ObjectOf(ident)
|
||||
func IsOfType(j *lint.Job, expr ast.Expr, name string) bool {
|
||||
return IsType(j.Pkg.TypesInfo.TypeOf(expr), name)
|
||||
}
|
||||
|
||||
func IsInTest(j *lint.Job, node lint.Positioner) bool {
|
||||
// FIXME(dh): this doesn't work for global variables with
|
||||
// initializers
|
||||
f := j.Program.SSA.Fset.File(node.Pos())
|
||||
f := j.Pkg.Fset.File(node.Pos())
|
||||
return f != nil && strings.HasSuffix(f.Name(), "_test.go")
|
||||
}
|
||||
|
||||
@ -130,15 +118,11 @@ func IsInMain(j *lint.Job, node lint.Positioner) bool {
|
||||
if node, ok := node.(packager); ok {
|
||||
return node.Package().Pkg.Name() == "main"
|
||||
}
|
||||
pkg := j.NodePackage(node)
|
||||
if pkg == nil {
|
||||
return false
|
||||
}
|
||||
return pkg.Types.Name() == "main"
|
||||
return j.Pkg.Types.Name() == "main"
|
||||
}
|
||||
|
||||
func SelectorName(j *lint.Job, expr *ast.SelectorExpr) string {
|
||||
info := j.NodePackage(expr).TypesInfo
|
||||
info := j.Pkg.TypesInfo
|
||||
sel := info.Selections[expr]
|
||||
if sel == nil {
|
||||
if x, ok := expr.X.(*ast.Ident); ok {
|
||||
@ -155,11 +139,11 @@ func SelectorName(j *lint.Job, expr *ast.SelectorExpr) string {
|
||||
}
|
||||
|
||||
func IsNil(j *lint.Job, expr ast.Expr) bool {
|
||||
return j.NodePackage(expr).TypesInfo.Types[expr].IsNil()
|
||||
return j.Pkg.TypesInfo.Types[expr].IsNil()
|
||||
}
|
||||
|
||||
func BoolConst(j *lint.Job, expr ast.Expr) bool {
|
||||
val := j.NodePackage(expr).TypesInfo.ObjectOf(expr.(*ast.Ident)).(*types.Const).Val()
|
||||
val := j.Pkg.TypesInfo.ObjectOf(expr.(*ast.Ident)).(*types.Const).Val()
|
||||
return constant.BoolVal(val)
|
||||
}
|
||||
|
||||
@ -172,7 +156,7 @@ func IsBoolConst(j *lint.Job, expr ast.Expr) bool {
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
obj := j.NodePackage(expr).TypesInfo.ObjectOf(ident)
|
||||
obj := j.Pkg.TypesInfo.ObjectOf(ident)
|
||||
c, ok := obj.(*types.Const)
|
||||
if !ok {
|
||||
return false
|
||||
@ -188,7 +172,7 @@ func IsBoolConst(j *lint.Job, expr ast.Expr) bool {
|
||||
}
|
||||
|
||||
func ExprToInt(j *lint.Job, expr ast.Expr) (int64, bool) {
|
||||
tv := j.NodePackage(expr).TypesInfo.Types[expr]
|
||||
tv := j.Pkg.TypesInfo.Types[expr]
|
||||
if tv.Value == nil {
|
||||
return 0, false
|
||||
}
|
||||
@ -199,7 +183,7 @@ func ExprToInt(j *lint.Job, expr ast.Expr) (int64, bool) {
|
||||
}
|
||||
|
||||
func ExprToString(j *lint.Job, expr ast.Expr) (string, bool) {
|
||||
val := j.NodePackage(expr).TypesInfo.Types[expr].Value
|
||||
val := j.Pkg.TypesInfo.Types[expr].Value
|
||||
if val == nil {
|
||||
return "", false
|
||||
}
|
||||
@ -229,22 +213,22 @@ func DereferenceR(T types.Type) types.Type {
|
||||
}
|
||||
|
||||
func IsGoVersion(j *lint.Job, minor int) bool {
|
||||
return j.Program.GoVersion >= minor
|
||||
return j.GoVersion >= minor
|
||||
}
|
||||
|
||||
func CallNameAST(j *lint.Job, call *ast.CallExpr) string {
|
||||
switch fun := call.Fun.(type) {
|
||||
case *ast.SelectorExpr:
|
||||
fn, ok := ObjectOf(j, fun.Sel).(*types.Func)
|
||||
fn, ok := j.Pkg.TypesInfo.ObjectOf(fun.Sel).(*types.Func)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return fn.FullName()
|
||||
return lint.FuncName(fn)
|
||||
case *ast.Ident:
|
||||
obj := ObjectOf(j, fun)
|
||||
obj := j.Pkg.TypesInfo.ObjectOf(fun)
|
||||
switch obj := obj.(type) {
|
||||
case *types.Func:
|
||||
return obj.FullName()
|
||||
return lint.FuncName(obj)
|
||||
case *types.Builtin:
|
||||
return obj.Name()
|
||||
default:
|
||||
@ -273,9 +257,8 @@ func IsCallToAnyAST(j *lint.Job, node ast.Node, names ...string) bool {
|
||||
}
|
||||
|
||||
func Render(j *lint.Job, x interface{}) string {
|
||||
fset := j.Program.SSA.Fset
|
||||
var buf bytes.Buffer
|
||||
if err := printer.Fprint(&buf, fset, x); err != nil {
|
||||
if err := printer.Fprint(&buf, j.Pkg.Fset, x); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return buf.String()
|
||||
@ -311,11 +294,10 @@ func Inspect(node ast.Node, fn func(node ast.Node) bool) {
|
||||
ast.Inspect(node, fn)
|
||||
}
|
||||
|
||||
func GroupSpecs(j *lint.Job, specs []ast.Spec) [][]ast.Spec {
|
||||
func GroupSpecs(fset *token.FileSet, specs []ast.Spec) [][]ast.Spec {
|
||||
if len(specs) == 0 {
|
||||
return nil
|
||||
}
|
||||
fset := j.Program.SSA.Fset
|
||||
groups := make([][]ast.Spec, 1)
|
||||
groups[0] = append(groups[0], specs[0])
|
||||
|
||||
|
34
vendor/honnef.co/go/tools/lint/lintutil/util.go
vendored
34
vendor/honnef.co/go/tools/lint/lintutil/util.go
vendored
@ -17,6 +17,7 @@ import (
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"runtime/pprof"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -109,6 +110,7 @@ func FlagSet(name string) *flag.FlagSet {
|
||||
flags.Bool("version", false, "Print version and exit")
|
||||
flags.Bool("show-ignored", false, "Don't filter ignored problems")
|
||||
flags.String("f", "text", "Output `format` (valid choices are 'stylish', 'text' and 'json')")
|
||||
flags.String("explain", "", "Print description of `check`")
|
||||
|
||||
flags.Int("debug.max-concurrent-jobs", 0, "Number of jobs to run concurrently")
|
||||
flags.Bool("debug.print-stats", false, "Print debug statistics")
|
||||
@ -131,7 +133,22 @@ func FlagSet(name string) *flag.FlagSet {
|
||||
return flags
|
||||
}
|
||||
|
||||
func findCheck(cs []lint.Checker, check string) (lint.Check, bool) {
|
||||
for _, c := range cs {
|
||||
for _, cc := range c.Checks() {
|
||||
if cc.ID == check {
|
||||
return cc, true
|
||||
}
|
||||
}
|
||||
}
|
||||
return lint.Check{}, false
|
||||
}
|
||||
|
||||
func ProcessFlagSet(cs []lint.Checker, fs *flag.FlagSet) {
|
||||
if _, ok := os.LookupEnv("GOGC"); !ok {
|
||||
debug.SetGCPercent(50)
|
||||
}
|
||||
|
||||
tags := fs.Lookup("tags").Value.(flag.Getter).Get().(string)
|
||||
ignore := fs.Lookup("ignore").Value.(flag.Getter).Get().(string)
|
||||
tests := fs.Lookup("tests").Value.(flag.Getter).Get().(bool)
|
||||
@ -139,6 +156,7 @@ func ProcessFlagSet(cs []lint.Checker, fs *flag.FlagSet) {
|
||||
formatter := fs.Lookup("f").Value.(flag.Getter).Get().(string)
|
||||
printVersion := fs.Lookup("version").Value.(flag.Getter).Get().(bool)
|
||||
showIgnored := fs.Lookup("show-ignored").Value.(flag.Getter).Get().(bool)
|
||||
explain := fs.Lookup("explain").Value.(flag.Getter).Get().(string)
|
||||
|
||||
maxConcurrentJobs := fs.Lookup("debug.max-concurrent-jobs").Value.(flag.Getter).Get().(int)
|
||||
printStats := fs.Lookup("debug.print-stats").Value.(flag.Getter).Get().(bool)
|
||||
@ -175,6 +193,20 @@ func ProcessFlagSet(cs []lint.Checker, fs *flag.FlagSet) {
|
||||
exit(0)
|
||||
}
|
||||
|
||||
if explain != "" {
|
||||
check, ok := findCheck(cs, explain)
|
||||
if !ok {
|
||||
fmt.Fprintln(os.Stderr, "Couldn't find check", explain)
|
||||
exit(1)
|
||||
}
|
||||
if check.Doc == "" {
|
||||
fmt.Fprintln(os.Stderr, explain, "has no documentation")
|
||||
exit(1)
|
||||
}
|
||||
fmt.Println(check.Doc)
|
||||
exit(0)
|
||||
}
|
||||
|
||||
ps, err := Lint(cs, fs.Args(), &Options{
|
||||
Tags: strings.Fields(tags),
|
||||
LintTests: tests,
|
||||
@ -279,6 +311,7 @@ func Lint(cs []lint.Checker, paths []string, opt *Options) ([]lint.Problem, erro
|
||||
return nil, err
|
||||
}
|
||||
stats.PackageLoading = time.Since(t)
|
||||
runtime.GC()
|
||||
|
||||
var problems []lint.Problem
|
||||
workingPkgs := make([]*packages.Package, 0, len(pkgs))
|
||||
@ -346,7 +379,6 @@ func compileErrors(pkg *packages.Package) []lint.Problem {
|
||||
p := lint.Problem{
|
||||
Position: parsePos(err.Pos),
|
||||
Text: err.Msg,
|
||||
Checker: "compiler",
|
||||
Check: "compile",
|
||||
}
|
||||
ps = append(ps, p)
|
||||
|
Reference in New Issue
Block a user