Fix lint errs (#59)
This commit is contained in:
79
vendor/honnef.co/go/tools/unused/implements.go
vendored
Normal file
79
vendor/honnef.co/go/tools/unused/implements.go
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
package unused
|
||||
|
||||
import "go/types"
|
||||
|
||||
// lookupMethod returns the index of and method with matching package and name, or (-1, nil).
|
||||
func lookupMethod(T *types.Interface, pkg *types.Package, name string) (int, *types.Func) {
|
||||
if name != "_" {
|
||||
for i := 0; i < T.NumMethods(); i++ {
|
||||
m := T.Method(i)
|
||||
if sameId(m, pkg, name) {
|
||||
return i, m
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func sameId(obj types.Object, pkg *types.Package, name string) bool {
|
||||
// spec:
|
||||
// "Two identifiers are different if they are spelled differently,
|
||||
// or if they appear in different packages and are not exported.
|
||||
// Otherwise, they are the same."
|
||||
if name != obj.Name() {
|
||||
return false
|
||||
}
|
||||
// obj.Name == name
|
||||
if obj.Exported() {
|
||||
return true
|
||||
}
|
||||
// not exported, so packages must be the same (pkg == nil for
|
||||
// fields in Universe scope; this can only happen for types
|
||||
// introduced via Eval)
|
||||
if pkg == nil || obj.Pkg() == nil {
|
||||
return pkg == obj.Pkg()
|
||||
}
|
||||
// pkg != nil && obj.pkg != nil
|
||||
return pkg.Path() == obj.Pkg().Path()
|
||||
}
|
||||
|
||||
func (c *Checker) implements(V types.Type, T *types.Interface) bool {
|
||||
// fast path for common case
|
||||
if T.Empty() {
|
||||
return true
|
||||
}
|
||||
|
||||
if ityp, _ := V.Underlying().(*types.Interface); ityp != nil {
|
||||
for i := 0; i < T.NumMethods(); i++ {
|
||||
m := T.Method(i)
|
||||
_, obj := lookupMethod(ityp, m.Pkg(), m.Name())
|
||||
switch {
|
||||
case obj == nil:
|
||||
return false
|
||||
case !types.Identical(obj.Type(), m.Type()):
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// A concrete type implements T if it implements all methods of T.
|
||||
ms := c.msCache.MethodSet(V)
|
||||
for i := 0; i < T.NumMethods(); i++ {
|
||||
m := T.Method(i)
|
||||
sel := ms.Lookup(m.Pkg(), m.Name())
|
||||
if sel == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
f, _ := sel.Obj().(*types.Func)
|
||||
if f == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if !types.Identical(f.Type(), m.Type()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
197
vendor/honnef.co/go/tools/unused/unused.go
vendored
197
vendor/honnef.co/go/tools/unused/unused.go
vendored
@ -12,7 +12,7 @@ import (
|
||||
"honnef.co/go/tools/lint"
|
||||
. "honnef.co/go/tools/lint/lintdsl"
|
||||
|
||||
"golang.org/x/tools/go/loader"
|
||||
"golang.org/x/tools/go/packages"
|
||||
"golang.org/x/tools/go/types/typeutil"
|
||||
)
|
||||
|
||||
@ -31,9 +31,9 @@ func (*LintChecker) Name() string { return "unused" }
|
||||
func (*LintChecker) Prefix() string { return "U" }
|
||||
|
||||
func (l *LintChecker) Init(*lint.Program) {}
|
||||
func (l *LintChecker) Funcs() map[string]lint.Func {
|
||||
return map[string]lint.Func{
|
||||
"U1000": l.Lint,
|
||||
func (l *LintChecker) Checks() []lint.Check {
|
||||
return []lint.Check{
|
||||
{ID: "U1000", FilterGenerated: true, Fn: l.Lint},
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ func typString(obj types.Object) string {
|
||||
}
|
||||
|
||||
func (l *LintChecker) Lint(j *lint.Job) {
|
||||
unused := l.c.Check(j.Program.Prog)
|
||||
unused := l.c.Check(j.Program)
|
||||
for _, u := range unused {
|
||||
name := u.Obj.Name()
|
||||
if sig, ok := u.Obj.Type().(*types.Signature); ok && sig.Recv() != nil {
|
||||
@ -158,7 +158,7 @@ type Checker struct {
|
||||
graph *graph
|
||||
|
||||
msCache typeutil.MethodSetCache
|
||||
lprog *loader.Program
|
||||
prog *lint.Program
|
||||
topmostCache map[*types.Scope]*types.Scope
|
||||
interfaces []*types.Interface
|
||||
}
|
||||
@ -199,13 +199,13 @@ func (e Error) Error() string {
|
||||
return fmt.Sprintf("errors in %d packages", len(e.Errors))
|
||||
}
|
||||
|
||||
func (c *Checker) Check(lprog *loader.Program) []Unused {
|
||||
func (c *Checker) Check(prog *lint.Program) []Unused {
|
||||
var unused []Unused
|
||||
c.lprog = lprog
|
||||
c.prog = prog
|
||||
if c.WholeProgram {
|
||||
c.findExportedInterfaces()
|
||||
}
|
||||
for _, pkg := range c.lprog.InitialPackages() {
|
||||
for _, pkg := range prog.InitialPackages {
|
||||
c.processDefs(pkg)
|
||||
c.processUses(pkg)
|
||||
c.processTypes(pkg)
|
||||
@ -231,6 +231,7 @@ func (c *Checker) Check(lprog *loader.Program) []Unused {
|
||||
}
|
||||
markNodesUsed(roots)
|
||||
c.markNodesQuiet()
|
||||
c.deduplicate()
|
||||
|
||||
if c.Debug != nil {
|
||||
c.printDebugGraph(c.Debug)
|
||||
@ -246,8 +247,8 @@ func (c *Checker) Check(lprog *loader.Program) []Unused {
|
||||
}
|
||||
found := false
|
||||
if !false {
|
||||
for _, pkg := range c.lprog.InitialPackages() {
|
||||
if pkg.Pkg == obj.Pkg() {
|
||||
for _, pkg := range prog.InitialPackages {
|
||||
if pkg.Types == obj.Pkg() {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
@ -257,25 +258,14 @@ func (c *Checker) Check(lprog *loader.Program) []Unused {
|
||||
continue
|
||||
}
|
||||
|
||||
pos := c.lprog.Fset.Position(obj.Pos())
|
||||
pos := c.prog.Fset().Position(obj.Pos())
|
||||
if pos.Filename == "" || filepath.Base(pos.Filename) == "C" {
|
||||
continue
|
||||
}
|
||||
generated := false
|
||||
for _, file := range c.lprog.Package(obj.Pkg().Path()).Files {
|
||||
if c.lprog.Fset.Position(file.Pos()).Filename != pos.Filename {
|
||||
continue
|
||||
}
|
||||
if len(file.Comments) > 0 {
|
||||
generated = isGenerated(file.Comments[0].Text())
|
||||
}
|
||||
break
|
||||
}
|
||||
if generated {
|
||||
continue
|
||||
}
|
||||
|
||||
unused = append(unused, Unused{Obj: obj, Position: pos})
|
||||
}
|
||||
|
||||
return unused
|
||||
}
|
||||
|
||||
@ -325,16 +315,24 @@ func (c *Checker) useNoCopyFields(typ types.Type) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Checker) useExportedFields(typ types.Type) {
|
||||
func (c *Checker) useExportedFields(typ types.Type, by types.Type) bool {
|
||||
any := false
|
||||
if st, ok := typ.Underlying().(*types.Struct); ok {
|
||||
n := st.NumFields()
|
||||
for i := 0; i < n; i++ {
|
||||
field := st.Field(i)
|
||||
if field.Anonymous() {
|
||||
if c.useExportedFields(field.Type(), typ) {
|
||||
c.graph.markUsedBy(field, typ)
|
||||
}
|
||||
}
|
||||
if field.Exported() {
|
||||
c.graph.markUsedBy(field, typ)
|
||||
c.graph.markUsedBy(field, by)
|
||||
any = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return any
|
||||
}
|
||||
|
||||
func (c *Checker) useExportedMethods(typ types.Type) {
|
||||
@ -370,8 +368,8 @@ func (c *Checker) useExportedMethods(typ types.Type) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Checker) processDefs(pkg *loader.PackageInfo) {
|
||||
for _, obj := range pkg.Defs {
|
||||
func (c *Checker) processDefs(pkg *lint.Pkg) {
|
||||
for _, obj := range pkg.TypesInfo.Defs {
|
||||
if obj == nil {
|
||||
continue
|
||||
}
|
||||
@ -392,7 +390,7 @@ func (c *Checker) processDefs(pkg *loader.PackageInfo) {
|
||||
// mark them used if an instance of the type was
|
||||
// accessible via an interface value.
|
||||
if !c.WholeProgram || c.ConsiderReflection {
|
||||
c.useExportedFields(obj.Type())
|
||||
c.useExportedFields(obj.Type(), obj.Type())
|
||||
}
|
||||
|
||||
// TODO(dh): Traditionally we have not marked all exported
|
||||
@ -420,8 +418,8 @@ func (c *Checker) processDefs(pkg *loader.PackageInfo) {
|
||||
if obj.Name() == "_" {
|
||||
node := c.graph.getNode(obj)
|
||||
node.quiet = true
|
||||
scope := c.topmostScope(pkg.Pkg.Scope().Innermost(obj.Pos()), pkg.Pkg)
|
||||
if scope == pkg.Pkg.Scope() {
|
||||
scope := c.topmostScope(pkg.Types.Scope().Innermost(obj.Pos()), pkg.Types)
|
||||
if scope == pkg.Types.Scope() {
|
||||
c.graph.roots = append(c.graph.roots, node)
|
||||
} else {
|
||||
c.graph.markUsedBy(obj, scope)
|
||||
@ -471,15 +469,15 @@ func (c *Checker) processDefs(pkg *loader.PackageInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Checker) processUses(pkg *loader.PackageInfo) {
|
||||
for ident, usedObj := range pkg.Uses {
|
||||
func (c *Checker) processUses(pkg *lint.Pkg) {
|
||||
for ident, usedObj := range pkg.TypesInfo.Uses {
|
||||
if _, ok := usedObj.(*types.PkgName); ok {
|
||||
continue
|
||||
}
|
||||
pos := ident.Pos()
|
||||
scope := pkg.Pkg.Scope().Innermost(pos)
|
||||
scope = c.topmostScope(scope, pkg.Pkg)
|
||||
if scope != pkg.Pkg.Scope() {
|
||||
scope := pkg.Types.Scope().Innermost(pos)
|
||||
scope = c.topmostScope(scope, pkg.Types)
|
||||
if scope != pkg.Types.Scope() {
|
||||
c.graph.markUsedBy(usedObj, scope)
|
||||
}
|
||||
|
||||
@ -492,17 +490,17 @@ func (c *Checker) processUses(pkg *loader.PackageInfo) {
|
||||
|
||||
func (c *Checker) findExportedInterfaces() {
|
||||
c.interfaces = []*types.Interface{types.Universe.Lookup("error").Type().(*types.Named).Underlying().(*types.Interface)}
|
||||
var pkgs []*loader.PackageInfo
|
||||
var pkgs []*packages.Package
|
||||
if c.WholeProgram {
|
||||
for _, pkg := range c.lprog.AllPackages {
|
||||
pkgs = append(pkgs, pkg)
|
||||
}
|
||||
pkgs = append(pkgs, c.prog.AllPackages...)
|
||||
} else {
|
||||
pkgs = c.lprog.InitialPackages()
|
||||
for _, pkg := range c.prog.InitialPackages {
|
||||
pkgs = append(pkgs, pkg.Package)
|
||||
}
|
||||
}
|
||||
|
||||
for _, pkg := range pkgs {
|
||||
for _, tv := range pkg.Types {
|
||||
for _, tv := range pkg.TypesInfo.Types {
|
||||
iface, ok := tv.Type.(*types.Interface)
|
||||
if !ok {
|
||||
continue
|
||||
@ -515,10 +513,10 @@ func (c *Checker) findExportedInterfaces() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Checker) processTypes(pkg *loader.PackageInfo) {
|
||||
func (c *Checker) processTypes(pkg *lint.Pkg) {
|
||||
named := map[*types.Named]*types.Pointer{}
|
||||
var interfaces []*types.Interface
|
||||
for _, tv := range pkg.Types {
|
||||
for _, tv := range pkg.TypesInfo.Types {
|
||||
if typ, ok := tv.Type.(interface {
|
||||
Elem() types.Type
|
||||
}); ok {
|
||||
@ -536,8 +534,8 @@ func (c *Checker) processTypes(pkg *loader.PackageInfo) {
|
||||
}
|
||||
case *types.Struct:
|
||||
c.useNoCopyFields(obj)
|
||||
if pkg.Pkg.Name() != "main" && !c.WholeProgram {
|
||||
c.useExportedFields(obj)
|
||||
if pkg.Types.Name() != "main" && !c.WholeProgram {
|
||||
c.useExportedFields(obj, obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -547,15 +545,30 @@ func (c *Checker) processTypes(pkg *loader.PackageInfo) {
|
||||
//
|
||||
// TODO(dh): For normal operations, that's the best we can do, as
|
||||
// we have no idea what external users will do with our types. In
|
||||
// whole-program mode, we could be more conservative, in two ways:
|
||||
// whole-program mode, we could be more precise, in two ways:
|
||||
// 1) Only consider interfaces if a type has been assigned to one
|
||||
// 2) Use SSA and flow analysis and determine the exact set of
|
||||
// interfaces that is relevant.
|
||||
fn := func(iface *types.Interface) {
|
||||
for i := 0; i < iface.NumEmbeddeds(); i++ {
|
||||
c.graph.markUsedBy(iface.Embedded(i), iface)
|
||||
}
|
||||
namedLoop:
|
||||
for obj, objPtr := range named {
|
||||
if !types.Implements(obj, iface) && !types.Implements(objPtr, iface) {
|
||||
continue
|
||||
switch obj.Underlying().(type) {
|
||||
case *types.Interface:
|
||||
// pointers to interfaces have no methods, only checking non-pointer
|
||||
if !c.implements(obj, iface) {
|
||||
continue namedLoop
|
||||
}
|
||||
default:
|
||||
// pointer receivers include the method set of non-pointer receivers,
|
||||
// only checking pointer
|
||||
if !c.implements(objPtr, iface) {
|
||||
continue namedLoop
|
||||
}
|
||||
}
|
||||
|
||||
ifaceMethods := make(map[string]struct{}, iface.NumMethods())
|
||||
n := iface.NumMethods()
|
||||
for i := 0; i < n; i++ {
|
||||
@ -591,23 +604,23 @@ func (c *Checker) processTypes(pkg *loader.PackageInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Checker) processSelections(pkg *loader.PackageInfo) {
|
||||
func (c *Checker) processSelections(pkg *lint.Pkg) {
|
||||
fn := func(expr *ast.SelectorExpr, sel *types.Selection, offset int) {
|
||||
scope := pkg.Pkg.Scope().Innermost(expr.Pos())
|
||||
c.graph.markUsedBy(expr.X, c.topmostScope(scope, pkg.Pkg))
|
||||
c.graph.markUsedBy(sel.Obj(), expr.X)
|
||||
scope := pkg.Types.Scope().Innermost(expr.Pos())
|
||||
c.graph.markUsedBy(sel, c.topmostScope(scope, pkg.Types))
|
||||
c.graph.markUsedBy(sel.Obj(), sel)
|
||||
if len(sel.Index()) > 1 {
|
||||
typ := sel.Recv()
|
||||
indices := sel.Index()
|
||||
for _, idx := range indices[:len(indices)-offset] {
|
||||
obj := getField(typ, idx)
|
||||
typ = obj.Type()
|
||||
c.graph.markUsedBy(obj, expr.X)
|
||||
c.graph.markUsedBy(obj, sel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for expr, sel := range pkg.Selections {
|
||||
for expr, sel := range pkg.TypesInfo.Selections {
|
||||
switch sel.Kind() {
|
||||
case types.FieldVal:
|
||||
fn(expr, sel, 0)
|
||||
@ -625,9 +638,9 @@ func dereferenceType(typ types.Type) types.Type {
|
||||
}
|
||||
|
||||
// processConversion marks fields as used if they're part of a type conversion.
|
||||
func (c *Checker) processConversion(pkg *loader.PackageInfo, node ast.Node) {
|
||||
func (c *Checker) processConversion(pkg *lint.Pkg, node ast.Node) {
|
||||
if node, ok := node.(*ast.CallExpr); ok {
|
||||
callTyp := pkg.TypeOf(node.Fun)
|
||||
callTyp := pkg.TypesInfo.TypeOf(node.Fun)
|
||||
var typDst *types.Struct
|
||||
var ok bool
|
||||
switch typ := callTyp.(type) {
|
||||
@ -642,7 +655,7 @@ func (c *Checker) processConversion(pkg *loader.PackageInfo, node ast.Node) {
|
||||
return
|
||||
}
|
||||
|
||||
if typ, ok := pkg.TypeOf(node.Args[0]).(*types.Basic); ok && typ.Kind() == types.UnsafePointer {
|
||||
if typ, ok := pkg.TypesInfo.TypeOf(node.Args[0]).(*types.Basic); ok && typ.Kind() == types.UnsafePointer {
|
||||
// This is an unsafe conversion. Assume that all the
|
||||
// fields are relevant (they are, because of memory
|
||||
// layout)
|
||||
@ -653,7 +666,7 @@ func (c *Checker) processConversion(pkg *loader.PackageInfo, node ast.Node) {
|
||||
return
|
||||
}
|
||||
|
||||
typSrc, ok := dereferenceType(pkg.TypeOf(node.Args[0])).Underlying().(*types.Struct)
|
||||
typSrc, ok := dereferenceType(pkg.TypesInfo.TypeOf(node.Args[0])).Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@ -683,10 +696,10 @@ func (c *Checker) processConversion(pkg *loader.PackageInfo, node ast.Node) {
|
||||
|
||||
// processCompositeLiteral marks fields as used if the struct is used
|
||||
// in a composite literal.
|
||||
func (c *Checker) processCompositeLiteral(pkg *loader.PackageInfo, node ast.Node) {
|
||||
func (c *Checker) processCompositeLiteral(pkg *lint.Pkg, node ast.Node) {
|
||||
// XXX how does this actually work? wouldn't it match t{}?
|
||||
if node, ok := node.(*ast.CompositeLit); ok {
|
||||
typ := pkg.TypeOf(node)
|
||||
typ := pkg.TypesInfo.TypeOf(node)
|
||||
if _, ok := typ.(*types.Named); ok {
|
||||
typ = typ.Underlying()
|
||||
}
|
||||
@ -702,7 +715,7 @@ func (c *Checker) processCompositeLiteral(pkg *loader.PackageInfo, node ast.Node
|
||||
|
||||
// processCgoExported marks functions as used if they're being
|
||||
// exported to cgo.
|
||||
func (c *Checker) processCgoExported(pkg *loader.PackageInfo, node ast.Node) {
|
||||
func (c *Checker) processCgoExported(pkg *lint.Pkg, node ast.Node) {
|
||||
if node, ok := node.(*ast.FuncDecl); ok {
|
||||
if node.Doc == nil {
|
||||
return
|
||||
@ -711,13 +724,13 @@ func (c *Checker) processCgoExported(pkg *loader.PackageInfo, node ast.Node) {
|
||||
if !strings.HasPrefix(cmt.Text, "//go:cgo_export_") {
|
||||
return
|
||||
}
|
||||
obj := pkg.ObjectOf(node.Name)
|
||||
obj := pkg.TypesInfo.ObjectOf(node.Name)
|
||||
c.graph.roots = append(c.graph.roots, c.graph.getNode(obj))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Checker) processVariableDeclaration(pkg *loader.PackageInfo, node ast.Node) {
|
||||
func (c *Checker) processVariableDeclaration(pkg *lint.Pkg, node ast.Node) {
|
||||
if decl, ok := node.(*ast.GenDecl); ok {
|
||||
for _, spec := range decl.Specs {
|
||||
spec, ok := spec.(*ast.ValueSpec)
|
||||
@ -731,11 +744,11 @@ func (c *Checker) processVariableDeclaration(pkg *loader.PackageInfo, node ast.N
|
||||
value := spec.Values[i]
|
||||
fn := func(node ast.Node) bool {
|
||||
if node3, ok := node.(*ast.Ident); ok {
|
||||
obj := pkg.ObjectOf(node3)
|
||||
obj := pkg.TypesInfo.ObjectOf(node3)
|
||||
if _, ok := obj.(*types.PkgName); ok {
|
||||
return true
|
||||
}
|
||||
c.graph.markUsedBy(obj, pkg.ObjectOf(name))
|
||||
c.graph.markUsedBy(obj, pkg.TypesInfo.ObjectOf(name))
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -745,17 +758,17 @@ func (c *Checker) processVariableDeclaration(pkg *loader.PackageInfo, node ast.N
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Checker) processArrayConstants(pkg *loader.PackageInfo, node ast.Node) {
|
||||
func (c *Checker) processArrayConstants(pkg *lint.Pkg, node ast.Node) {
|
||||
if decl, ok := node.(*ast.ArrayType); ok {
|
||||
ident, ok := decl.Len.(*ast.Ident)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
c.graph.markUsedBy(pkg.ObjectOf(ident), pkg.TypeOf(decl))
|
||||
c.graph.markUsedBy(pkg.TypesInfo.ObjectOf(ident), pkg.TypesInfo.TypeOf(decl))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Checker) processKnownReflectMethodCallers(pkg *loader.PackageInfo, node ast.Node) {
|
||||
func (c *Checker) processKnownReflectMethodCallers(pkg *lint.Pkg, node ast.Node) {
|
||||
call, ok := node.(*ast.CallExpr)
|
||||
if !ok {
|
||||
return
|
||||
@ -764,12 +777,12 @@ func (c *Checker) processKnownReflectMethodCallers(pkg *loader.PackageInfo, node
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if !IsType(pkg.TypeOf(sel.X), "*net/rpc.Server") {
|
||||
if !IsType(pkg.TypesInfo.TypeOf(sel.X), "*net/rpc.Server") {
|
||||
x, ok := sel.X.(*ast.Ident)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
pkgname, ok := pkg.ObjectOf(x).(*types.PkgName)
|
||||
pkgname, ok := pkg.TypesInfo.ObjectOf(x).(*types.PkgName)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@ -791,14 +804,14 @@ func (c *Checker) processKnownReflectMethodCallers(pkg *loader.PackageInfo, node
|
||||
}
|
||||
arg = call.Args[1]
|
||||
}
|
||||
typ := pkg.TypeOf(arg)
|
||||
typ := pkg.TypesInfo.TypeOf(arg)
|
||||
ms := types.NewMethodSet(typ)
|
||||
for i := 0; i < ms.Len(); i++ {
|
||||
c.graph.markUsedBy(ms.At(i).Obj(), typ)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Checker) processAST(pkg *loader.PackageInfo) {
|
||||
func (c *Checker) processAST(pkg *lint.Pkg) {
|
||||
fn := func(node ast.Node) bool {
|
||||
c.processConversion(pkg, node)
|
||||
c.processKnownReflectMethodCallers(pkg, node)
|
||||
@ -808,7 +821,7 @@ func (c *Checker) processAST(pkg *loader.PackageInfo) {
|
||||
c.processArrayConstants(pkg, node)
|
||||
return true
|
||||
}
|
||||
for _, file := range pkg.Files {
|
||||
for _, file := range pkg.Syntax {
|
||||
ast.Inspect(file, fn)
|
||||
}
|
||||
}
|
||||
@ -914,7 +927,7 @@ func (c *Checker) isRoot(obj types.Object) bool {
|
||||
return true
|
||||
}
|
||||
if obj.Exported() {
|
||||
f := c.lprog.Fset.Position(obj.Pos()).Filename
|
||||
f := c.prog.Fset().Position(obj.Pos()).Filename
|
||||
if strings.HasSuffix(f, "_test.go") {
|
||||
return strings.HasPrefix(obj.Name(), "Test") ||
|
||||
strings.HasPrefix(obj.Name(), "Benchmark") ||
|
||||
@ -939,6 +952,33 @@ func markNodesUsed(nodes map[*graphNode]struct{}) {
|
||||
}
|
||||
}
|
||||
|
||||
// deduplicate merges objects based on their positions. This is done
|
||||
// to work around packages existing multiple times in go/packages.
|
||||
func (c *Checker) deduplicate() {
|
||||
m := map[token.Position]struct{ used, quiet bool }{}
|
||||
for _, node := range c.graph.nodes {
|
||||
obj, ok := node.obj.(types.Object)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
pos := c.prog.Fset().Position(obj.Pos())
|
||||
m[pos] = struct{ used, quiet bool }{
|
||||
m[pos].used || node.used,
|
||||
m[pos].quiet || node.quiet,
|
||||
}
|
||||
}
|
||||
|
||||
for _, node := range c.graph.nodes {
|
||||
obj, ok := node.obj.(types.Object)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
pos := c.prog.Fset().Position(obj.Pos())
|
||||
node.used = m[pos].used
|
||||
node.quiet = m[pos].quiet
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Checker) markNodesQuiet() {
|
||||
for _, node := range c.graph.nodes {
|
||||
if node.used {
|
||||
@ -1058,8 +1098,3 @@ func (c *Checker) printDebugGraph(w io.Writer) {
|
||||
}
|
||||
fmt.Fprintln(w, "}")
|
||||
}
|
||||
|
||||
func isGenerated(comment string) bool {
|
||||
return strings.Contains(comment, "Code generated by") ||
|
||||
strings.Contains(comment, "DO NOT EDIT")
|
||||
}
|
||||
|
Reference in New Issue
Block a user