Add staticcheck tool
This commit is contained in:
149
vendor/honnef.co/go/tools/unused/implements.go
vendored
Normal file
149
vendor/honnef.co/go/tools/unused/implements.go
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
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 implements(V types.Type, T *types.Interface, msV *types.MethodSet) ([]*types.Selection, bool) {
|
||||
// fast path for common case
|
||||
if T.Empty() {
|
||||
return nil, true
|
||||
}
|
||||
|
||||
if ityp, _ := V.Underlying().(*types.Interface); ityp != nil {
|
||||
// TODO(dh): is this code reachable?
|
||||
for m := range T.Methods() {
|
||||
_, obj := lookupMethod(ityp, m.Pkg(), m.Name())
|
||||
switch {
|
||||
case obj == nil:
|
||||
return nil, false
|
||||
case !types.Identical(obj.Type(), m.Type()):
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
return nil, true
|
||||
}
|
||||
|
||||
// A concrete type implements T if it implements all methods of T.
|
||||
var sels []*types.Selection
|
||||
var c methodsChecker
|
||||
for m := range T.Methods() {
|
||||
sel := msV.Lookup(m.Pkg(), m.Name())
|
||||
if sel == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
f, _ := sel.Obj().(*types.Func)
|
||||
if f == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if !c.methodIsCompatible(f, m) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
sels = append(sels, sel)
|
||||
}
|
||||
return sels, true
|
||||
}
|
||||
|
||||
type methodsChecker struct {
|
||||
typeParams map[*types.TypeParam]types.Type
|
||||
}
|
||||
|
||||
// Currently, this doesn't support methods like `foo(x []T)`.
|
||||
func (c *methodsChecker) methodIsCompatible(implFunc *types.Func, interfaceFunc *types.Func) bool {
|
||||
if types.Identical(implFunc.Type(), interfaceFunc.Type()) {
|
||||
return true
|
||||
}
|
||||
implSig, implOk := implFunc.Type().(*types.Signature)
|
||||
interfaceSig, interfaceOk := interfaceFunc.Type().(*types.Signature)
|
||||
if !implOk || !interfaceOk {
|
||||
// probably not reachable. handle conservatively.
|
||||
return false
|
||||
}
|
||||
|
||||
if !c.typesAreCompatible(implSig.Params(), interfaceSig.Params()) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !c.typesAreCompatible(implSig.Results(), interfaceSig.Results()) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *methodsChecker) typesAreCompatible(implTypes, interfaceTypes *types.Tuple) bool {
|
||||
if implTypes.Len() != interfaceTypes.Len() {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < implTypes.Len(); i++ {
|
||||
if !c.typeIsCompatible(implTypes.At(i).Type(), interfaceTypes.At(i).Type()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *methodsChecker) typeIsCompatible(implType, interfaceType types.Type) bool {
|
||||
if types.Identical(implType, interfaceType) {
|
||||
return true
|
||||
}
|
||||
// We only support trivial use of type parameters. This isn't fully compatible with compiler type checking yet.
|
||||
tp, ok := interfaceType.(*types.TypeParam)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if c.typeParams == nil {
|
||||
c.typeParams = make(map[*types.TypeParam]types.Type)
|
||||
}
|
||||
if c.typeParams[tp] == nil {
|
||||
if !satisfiesConstraint(implType, tp) {
|
||||
return false
|
||||
}
|
||||
c.typeParams[tp] = implType
|
||||
return true
|
||||
}
|
||||
return types.Identical(c.typeParams[tp], implType)
|
||||
}
|
||||
|
||||
func satisfiesConstraint(t types.Type, tp *types.TypeParam) bool {
|
||||
bound := tp.Constraint().Underlying().(*types.Interface)
|
||||
return types.Satisfies(t, bound)
|
||||
}
|
||||
331
vendor/honnef.co/go/tools/unused/runtime.go
vendored
Normal file
331
vendor/honnef.co/go/tools/unused/runtime.go
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
package unused
|
||||
|
||||
// Functions defined in the Go runtime that may be called through
|
||||
// compiler magic or via assembly.
|
||||
var runtimeFuncs = map[string]bool{
|
||||
// Copied from cmd/compile/internal/typecheck/builtin.go, var runtimeDecls
|
||||
"newobject": true,
|
||||
"panicindex": true,
|
||||
"panicslice": true,
|
||||
"panicdivide": true,
|
||||
"panicmakeslicelen": true,
|
||||
"throwinit": true,
|
||||
"panicwrap": true,
|
||||
"gopanic": true,
|
||||
"gorecover": true,
|
||||
"goschedguarded": true,
|
||||
"printbool": true,
|
||||
"printfloat": true,
|
||||
"printint": true,
|
||||
"printhex": true,
|
||||
"printuint": true,
|
||||
"printcomplex": true,
|
||||
"printstring": true,
|
||||
"printpointer": true,
|
||||
"printiface": true,
|
||||
"printeface": true,
|
||||
"printslice": true,
|
||||
"printnl": true,
|
||||
"printsp": true,
|
||||
"printlock": true,
|
||||
"printunlock": true,
|
||||
"concatstring2": true,
|
||||
"concatstring3": true,
|
||||
"concatstring4": true,
|
||||
"concatstring5": true,
|
||||
"concatstrings": true,
|
||||
"cmpstring": true,
|
||||
"intstring": true,
|
||||
"slicebytetostring": true,
|
||||
"slicebytetostringtmp": true,
|
||||
"slicerunetostring": true,
|
||||
"stringtoslicebyte": true,
|
||||
"stringtoslicerune": true,
|
||||
"slicecopy": true,
|
||||
"slicestringcopy": true,
|
||||
"decoderune": true,
|
||||
"countrunes": true,
|
||||
"convI2I": true,
|
||||
"convT16": true,
|
||||
"convT32": true,
|
||||
"convT64": true,
|
||||
"convTstring": true,
|
||||
"convTslice": true,
|
||||
"convT2E": true,
|
||||
"convT2Enoptr": true,
|
||||
"convT2I": true,
|
||||
"convT2Inoptr": true,
|
||||
"assertE2I": true,
|
||||
"assertE2I2": true,
|
||||
"assertI2I": true,
|
||||
"assertI2I2": true,
|
||||
"panicdottypeE": true,
|
||||
"panicdottypeI": true,
|
||||
"panicnildottype": true,
|
||||
"ifaceeq": true,
|
||||
"efaceeq": true,
|
||||
"fastrand": true,
|
||||
"makemap64": true,
|
||||
"makemap": true,
|
||||
"makemap_small": true,
|
||||
"mapaccess1": true,
|
||||
"mapaccess1_fast32": true,
|
||||
"mapaccess1_fast64": true,
|
||||
"mapaccess1_faststr": true,
|
||||
"mapaccess1_fat": true,
|
||||
"mapaccess2": true,
|
||||
"mapaccess2_fast32": true,
|
||||
"mapaccess2_fast64": true,
|
||||
"mapaccess2_faststr": true,
|
||||
"mapaccess2_fat": true,
|
||||
"mapassign": true,
|
||||
"mapassign_fast32": true,
|
||||
"mapassign_fast32ptr": true,
|
||||
"mapassign_fast64": true,
|
||||
"mapassign_fast64ptr": true,
|
||||
"mapassign_faststr": true,
|
||||
"mapiterinit": true,
|
||||
"mapdelete": true,
|
||||
"mapdelete_fast32": true,
|
||||
"mapdelete_fast64": true,
|
||||
"mapdelete_faststr": true,
|
||||
"mapiternext": true,
|
||||
"mapclear": true,
|
||||
"makechan64": true,
|
||||
"makechan": true,
|
||||
"chanrecv1": true,
|
||||
"chanrecv2": true,
|
||||
"chansend1": true,
|
||||
"closechan": true,
|
||||
"writeBarrier": true,
|
||||
"typedmemmove": true,
|
||||
"typedmemclr": true,
|
||||
"typedslicecopy": true,
|
||||
"selectnbsend": true,
|
||||
"selectnbrecv": true,
|
||||
"selectnbrecv2": true,
|
||||
"selectsetpc": true,
|
||||
"selectgo": true,
|
||||
"block": true,
|
||||
"makeslice": true,
|
||||
"makeslice64": true,
|
||||
"growslice": true,
|
||||
"memmove": true,
|
||||
"memclrNoHeapPointers": true,
|
||||
"memclrHasPointers": true,
|
||||
"memequal": true,
|
||||
"memequal8": true,
|
||||
"memequal16": true,
|
||||
"memequal32": true,
|
||||
"memequal64": true,
|
||||
"memequal128": true,
|
||||
"int64div": true,
|
||||
"uint64div": true,
|
||||
"int64mod": true,
|
||||
"uint64mod": true,
|
||||
"float64toint64": true,
|
||||
"float64touint64": true,
|
||||
"float64touint32": true,
|
||||
"int64tofloat64": true,
|
||||
"uint64tofloat64": true,
|
||||
"uint32tofloat64": true,
|
||||
"complex128div": true,
|
||||
"racefuncenter": true,
|
||||
"racefuncenterfp": true,
|
||||
"racefuncexit": true,
|
||||
"raceread": true,
|
||||
"racewrite": true,
|
||||
"racereadrange": true,
|
||||
"racewriterange": true,
|
||||
"msanread": true,
|
||||
"msanwrite": true,
|
||||
"x86HasPOPCNT": true,
|
||||
"x86HasSSE41": true,
|
||||
"arm64HasATOMICS": true,
|
||||
"mallocgc": true,
|
||||
"panicshift": true,
|
||||
"panicmakeslicecap": true,
|
||||
"goPanicIndex": true,
|
||||
"goPanicIndexU": true,
|
||||
"goPanicSliceAlen": true,
|
||||
"goPanicSliceAlenU": true,
|
||||
"goPanicSliceAcap": true,
|
||||
"goPanicSliceAcapU": true,
|
||||
"goPanicSliceB": true,
|
||||
"goPanicSliceBU": true,
|
||||
"goPanicSlice3Alen": true,
|
||||
"goPanicSlice3AlenU": true,
|
||||
"goPanicSlice3Acap": true,
|
||||
"goPanicSlice3AcapU": true,
|
||||
"goPanicSlice3B": true,
|
||||
"goPanicSlice3BU": true,
|
||||
"goPanicSlice3C": true,
|
||||
"goPanicSlice3CU": true,
|
||||
"goPanicSliceConvert": true,
|
||||
"printuintptr": true,
|
||||
"convT": true,
|
||||
"convTnoptr": true,
|
||||
"makeslicecopy": true,
|
||||
"unsafeslicecheckptr": true,
|
||||
"panicunsafeslicelen": true,
|
||||
"panicunsafeslicenilptr": true,
|
||||
"unsafestringcheckptr": true,
|
||||
"panicunsafestringlen": true,
|
||||
"panicunsafestringnilptr": true,
|
||||
"mulUintptr": true,
|
||||
"memequal0": true,
|
||||
"f32equal": true,
|
||||
"f64equal": true,
|
||||
"c64equal": true,
|
||||
"c128equal": true,
|
||||
"strequal": true,
|
||||
"interequal": true,
|
||||
"nilinterequal": true,
|
||||
"memhash": true,
|
||||
"memhash0": true,
|
||||
"memhash8": true,
|
||||
"memhash16": true,
|
||||
"memhash32": true,
|
||||
"memhash64": true,
|
||||
"memhash128": true,
|
||||
"f32hash": true,
|
||||
"f64hash": true,
|
||||
"c64hash": true,
|
||||
"c128hash": true,
|
||||
"strhash": true,
|
||||
"interhash": true,
|
||||
"nilinterhash": true,
|
||||
"int64tofloat32": true,
|
||||
"uint64tofloat32": true,
|
||||
"getcallerpc": true,
|
||||
"getcallersp": true,
|
||||
"msanmove": true,
|
||||
"asanread": true,
|
||||
"asanwrite": true,
|
||||
"checkptrAlignment": true,
|
||||
"checkptrArithmetic": true,
|
||||
"libfuzzerTraceCmp1": true,
|
||||
"libfuzzerTraceCmp2": true,
|
||||
"libfuzzerTraceCmp4": true,
|
||||
"libfuzzerTraceCmp8": true,
|
||||
"libfuzzerTraceConstCmp1": true,
|
||||
"libfuzzerTraceConstCmp2": true,
|
||||
"libfuzzerTraceConstCmp4": true,
|
||||
"libfuzzerTraceConstCmp8": true,
|
||||
"libfuzzerHookStrCmp": true,
|
||||
"libfuzzerHookEqualFold": true,
|
||||
"addCovMeta": true,
|
||||
"x86HasFMA": true,
|
||||
"armHasVFPv4": true,
|
||||
|
||||
// Extracted from assembly code in the standard library, with the exception of the runtime package itself
|
||||
"abort": true,
|
||||
"aeshashbody": true,
|
||||
"args": true,
|
||||
"asminit": true,
|
||||
"badctxt": true,
|
||||
"badmcall2": true,
|
||||
"badmcall": true,
|
||||
"badmorestackg0": true,
|
||||
"badmorestackgsignal": true,
|
||||
"badsignal2": true,
|
||||
"callbackasm1": true,
|
||||
"callCfunction": true,
|
||||
"cgocallback_gofunc": true,
|
||||
"cgocallbackg": true,
|
||||
"checkgoarm": true,
|
||||
"check": true,
|
||||
"debugCallCheck": true,
|
||||
"debugCallWrap": true,
|
||||
"emptyfunc": true,
|
||||
"entersyscall": true,
|
||||
"exit": true,
|
||||
"exits": true,
|
||||
"exitsyscall": true,
|
||||
"externalthreadhandler": true,
|
||||
"findnull": true,
|
||||
"goexit1": true,
|
||||
"gostring": true,
|
||||
"i386_set_ldt": true,
|
||||
"_initcgo": true,
|
||||
"init_thread_tls": true,
|
||||
"ldt0setup": true,
|
||||
"libpreinit": true,
|
||||
"load_g": true,
|
||||
"morestack": true,
|
||||
"mstart": true,
|
||||
"nacl_sysinfo": true,
|
||||
"nanotimeQPC": true,
|
||||
"nanotime": true,
|
||||
"newosproc0": true,
|
||||
"newproc": true,
|
||||
"newstack": true,
|
||||
"noted": true,
|
||||
"nowQPC": true,
|
||||
"osinit": true,
|
||||
"printf": true,
|
||||
"racecallback": true,
|
||||
"reflectcallmove": true,
|
||||
"reginit": true,
|
||||
"rt0_go": true,
|
||||
"save_g": true,
|
||||
"schedinit": true,
|
||||
"setldt": true,
|
||||
"settls": true,
|
||||
"sighandler": true,
|
||||
"sigprofNonGo": true,
|
||||
"sigtrampgo": true,
|
||||
"_sigtramp": true,
|
||||
"sigtramp": true,
|
||||
"stackcheck": true,
|
||||
"syscall_chdir": true,
|
||||
"syscall_chroot": true,
|
||||
"syscall_close": true,
|
||||
"syscall_dup2": true,
|
||||
"syscall_execve": true,
|
||||
"syscall_exit": true,
|
||||
"syscall_fcntl": true,
|
||||
"syscall_forkx": true,
|
||||
"syscall_gethostname": true,
|
||||
"syscall_getpid": true,
|
||||
"syscall_ioctl": true,
|
||||
"syscall_pipe": true,
|
||||
"syscall_rawsyscall6": true,
|
||||
"syscall_rawSyscall6": true,
|
||||
"syscall_rawsyscall": true,
|
||||
"syscall_RawSyscall": true,
|
||||
"syscall_rawsysvicall6": true,
|
||||
"syscall_setgid": true,
|
||||
"syscall_setgroups": true,
|
||||
"syscall_setpgid": true,
|
||||
"syscall_setsid": true,
|
||||
"syscall_setuid": true,
|
||||
"syscall_syscall6": true,
|
||||
"syscall_syscall": true,
|
||||
"syscall_Syscall": true,
|
||||
"syscall_sysvicall6": true,
|
||||
"syscall_wait4": true,
|
||||
"syscall_write": true,
|
||||
"traceback": true,
|
||||
"tstart": true,
|
||||
"usplitR0": true,
|
||||
"wbBufFlush": true,
|
||||
"write": true,
|
||||
|
||||
// Other runtime functions that can get called in non-standard ways
|
||||
"bgsweep": true,
|
||||
"memhash_varlen": true,
|
||||
"strhashFallback": true,
|
||||
"asanregisterglobals": true,
|
||||
"cgoUse": true,
|
||||
"cgoCheckPointer": true,
|
||||
"cgoCheckResult": true,
|
||||
"_cgo_panic_internal": true,
|
||||
"addExitHook": true,
|
||||
}
|
||||
|
||||
var runtimeCoverageFuncs = map[string]bool{
|
||||
"initHook": true,
|
||||
"markProfileEmitted": true,
|
||||
"processCoverTestDir": true,
|
||||
}
|
||||
99
vendor/honnef.co/go/tools/unused/serialize.go
vendored
Normal file
99
vendor/honnef.co/go/tools/unused/serialize.go
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
package unused
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
"os"
|
||||
|
||||
"golang.org/x/tools/go/types/objectpath"
|
||||
)
|
||||
|
||||
type ObjectPath struct {
|
||||
PkgPath string
|
||||
ObjPath objectpath.Path
|
||||
}
|
||||
|
||||
// XXX make sure that node 0 always exists and is always the root
|
||||
|
||||
type SerializedGraph struct {
|
||||
nodes []Node
|
||||
nodesByPath map[ObjectPath]NodeID
|
||||
// XXX deduplicating on position is dubious for `switch x := foo.(type)`, where x will be declared many times for
|
||||
// the different types, but all at the same position. On the other hand, merging these nodes is probably fine.
|
||||
nodesByPosition map[token.Position]NodeID
|
||||
}
|
||||
|
||||
func trace(f string, args ...any) {
|
||||
fmt.Fprintf(os.Stderr, f, args...)
|
||||
fmt.Fprintln(os.Stderr)
|
||||
}
|
||||
|
||||
func (g *SerializedGraph) Merge(nodes []Node) {
|
||||
if g.nodesByPath == nil {
|
||||
g.nodesByPath = map[ObjectPath]NodeID{}
|
||||
}
|
||||
if g.nodesByPosition == nil {
|
||||
g.nodesByPosition = map[token.Position]NodeID{}
|
||||
}
|
||||
if len(g.nodes) == 0 {
|
||||
// Seed nodes with a root node
|
||||
g.nodes = append(g.nodes, Node{})
|
||||
}
|
||||
// OPT(dh): reuse storage between calls to Merge
|
||||
remapping := make([]NodeID, len(nodes))
|
||||
|
||||
// First pass: compute remapping of IDs of to-be-merged nodes
|
||||
for _, n := range nodes {
|
||||
// XXX Column is never 0. it's 1 if there is no column information in the export data. which sucks, because
|
||||
// objects can also genuinely be in column 1.
|
||||
if n.id != 0 && n.obj.Path == (ObjectPath{}) && n.obj.Position.Column == 0 {
|
||||
// If the object has no path, then it couldn't have come from export data, which means it needs to have full
|
||||
// position information including a column.
|
||||
panic(fmt.Sprintf("object %q has no path but also no column information", n.obj.Name))
|
||||
}
|
||||
|
||||
if orig, ok := g.nodesByPath[n.obj.Path]; ok {
|
||||
// We already have a node for this object
|
||||
trace("deduplicating %d -> %d based on path %s", n.id, orig, n.obj.Path)
|
||||
remapping[n.id] = orig
|
||||
} else if orig, ok := g.nodesByPosition[n.obj.Position]; ok && n.obj.Position.Column != 0 {
|
||||
// We already have a node for this object
|
||||
trace("deduplicating %d -> %d based on position %s", n.id, orig, n.obj.Position)
|
||||
remapping[n.id] = orig
|
||||
} else {
|
||||
// This object is new to us; change ID to avoid collision
|
||||
newID := NodeID(len(g.nodes))
|
||||
trace("new node, remapping %d -> %d", n.id, newID)
|
||||
remapping[n.id] = newID
|
||||
g.nodes = append(g.nodes, Node{
|
||||
id: newID,
|
||||
obj: n.obj,
|
||||
uses: make([]NodeID, 0, len(n.uses)),
|
||||
owns: make([]NodeID, 0, len(n.owns)),
|
||||
})
|
||||
if n.id == 0 {
|
||||
// Our root uses all the roots of the subgraphs
|
||||
g.nodes[0].uses = append(g.nodes[0].uses, newID)
|
||||
}
|
||||
if n.obj.Path != (ObjectPath{}) {
|
||||
g.nodesByPath[n.obj.Path] = newID
|
||||
}
|
||||
if n.obj.Position.Column != 0 {
|
||||
g.nodesByPosition[n.obj.Position] = newID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Second step: apply remapping
|
||||
for _, n := range nodes {
|
||||
n.id = remapping[n.id]
|
||||
for i := range n.uses {
|
||||
n.uses[i] = remapping[n.uses[i]]
|
||||
}
|
||||
for i := range n.owns {
|
||||
n.owns[i] = remapping[n.owns[i]]
|
||||
}
|
||||
g.nodes[n.id].uses = append(g.nodes[n.id].uses, n.uses...)
|
||||
g.nodes[n.id].owns = append(g.nodes[n.id].owns, n.owns...)
|
||||
}
|
||||
}
|
||||
1725
vendor/honnef.co/go/tools/unused/unused.go
vendored
Normal file
1725
vendor/honnef.co/go/tools/unused/unused.go
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user