support deadcode
This commit is contained in:
parent
062caa018c
commit
b3f856af80
8
Gopkg.lock
generated
8
Gopkg.lock
generated
@ -58,6 +58,12 @@
|
||||
revision = "c34cdb4725f4c3844d095133c6e40e448b86589b"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golangci/go-misc"
|
||||
packages = ["deadcode"]
|
||||
revision = "a82b63c685e730fbc1efbade9ce6316ac85cceb7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golangci/gofmt"
|
||||
@ -231,6 +237,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "c4187e819ccca1b06537adb888a052a895c6236f90accd827314c12b2fd1ce3e"
|
||||
inputs-digest = "fd69e23afecb188e33d824ca597d116e47e913418eb1f0842ccb4f9bb44c7c7c"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
35
pkg/golinters/deadcode.go
Normal file
35
pkg/golinters/deadcode.go
Normal file
@ -0,0 +1,35 @@
|
||||
package golinters
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
deadcodeAPI "github.com/golangci/go-misc/deadcode"
|
||||
"github.com/golangci/golangci-lint/pkg/config"
|
||||
"github.com/golangci/golangci-lint/pkg/result"
|
||||
"github.com/golangci/golangci-shared/pkg/executors"
|
||||
)
|
||||
|
||||
type deadcode struct{}
|
||||
|
||||
func (deadcode) Name() string {
|
||||
return "deadcode"
|
||||
}
|
||||
|
||||
func (d deadcode) Run(ctx context.Context, exec executors.Executor, cfg *config.Run) (*result.Result, error) {
|
||||
issues, err := deadcodeAPI.Run(cfg.Paths.MixedPaths(), true) // TODO: configure need of tests
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := &result.Result{}
|
||||
for _, i := range issues {
|
||||
res.Issues = append(res.Issues, result.Issue{
|
||||
File: i.Pos.Filename,
|
||||
LineNumber: i.Pos.Line,
|
||||
Text: fmt.Sprintf("%s is unused", formatCode(i.UnusedIdentName, cfg)),
|
||||
FromLinter: d.Name(),
|
||||
})
|
||||
}
|
||||
return res, nil
|
||||
}
|
@ -36,9 +36,11 @@ func GetAllSupportedLinterConfigs() []LinterConfig {
|
||||
return []LinterConfig{
|
||||
enabledByDefault(govet{}, "Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string"),
|
||||
enabledByDefault(errcheck{}, "Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases"),
|
||||
enabledByDefault(golint{}, "Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes."),
|
||||
disabledByDefault(gofmt{}, "Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification."),
|
||||
disabledByDefault(gofmt{useGoimports: true}, "Goimports does everything that gofmt does. Additionally it checks unused imports."),
|
||||
enabledByDefault(golint{}, "Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes"),
|
||||
enabledByDefault(deadcode{}, "Finds unused code"),
|
||||
|
||||
disabledByDefault(gofmt{}, "Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification"),
|
||||
disabledByDefault(gofmt{useGoimports: true}, "Goimports does everything that gofmt does. Additionally it checks unused imports"),
|
||||
}
|
||||
}
|
||||
|
||||
|
20
pkg/golinters/testdata/deadcode.go
vendored
Normal file
20
pkg/golinters/testdata/deadcode.go
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
package testdata
|
||||
|
||||
var y int
|
||||
|
||||
var unused int // ERROR "`unused` is unused"
|
||||
|
||||
func f(x int) {
|
||||
}
|
||||
|
||||
func g(x int) { // ERROR "`g` is unused"
|
||||
}
|
||||
|
||||
func H(x int) {
|
||||
}
|
||||
|
||||
func init() {
|
||||
f(y)
|
||||
}
|
||||
|
||||
var _ int
|
10
pkg/golinters/testdata/errcheck.go
vendored
10
pkg/golinters/testdata/errcheck.go
vendored
@ -5,15 +5,15 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func retErr() error {
|
||||
func RetErr() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func missedErrorCheck() {
|
||||
retErr() // ERROR "Error return value of `retErr` is not checked"
|
||||
func MissedErrorCheck() {
|
||||
RetErr() // ERROR "Error return value of `RetErr` is not checked"
|
||||
}
|
||||
|
||||
func ignoreCloseMissingErrHandling() error {
|
||||
func IgnoreCloseMissingErrHandling() error {
|
||||
f, err := os.Open("t.go")
|
||||
if err != nil {
|
||||
return err
|
||||
@ -23,7 +23,7 @@ func ignoreCloseMissingErrHandling() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ignoreCloseInDeferMissingErrHandling() {
|
||||
func IgnoreCloseInDeferMissingErrHandling() {
|
||||
resp, err := http.Get("http://example.com/")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
2
pkg/golinters/testdata/gofmt.go
vendored
2
pkg/golinters/testdata/gofmt.go
vendored
@ -2,7 +2,7 @@ package testdata
|
||||
|
||||
import "fmt"
|
||||
|
||||
func gofmtNotSimplified() {
|
||||
func GofmtNotSimplified() {
|
||||
var x []string
|
||||
fmt.Print(x[1:len(x)]) // ERROR "File is not gofmt-ed with -s"
|
||||
}
|
||||
|
2
pkg/golinters/testdata/goimports.go
vendored
2
pkg/golinters/testdata/goimports.go
vendored
@ -5,7 +5,7 @@ import (
|
||||
"github.com/golangci/golangci-lint/pkg/config"
|
||||
)
|
||||
|
||||
func bar() {
|
||||
func Bar() {
|
||||
fmt.Print("x")
|
||||
_ = config.Config{}
|
||||
}
|
||||
|
2
pkg/golinters/testdata/golint.go
vendored
2
pkg/golinters/testdata/golint.go
vendored
@ -1,6 +1,6 @@
|
||||
package testdata
|
||||
|
||||
var go_lint string // ERROR "don't use underscores in Go names; var go_lint should be goLint"
|
||||
var Go_lint string // ERROR "don't use underscores in Go names; var Go_lint should be GoLint"
|
||||
|
||||
func ExportedFuncWithNoComment() {
|
||||
}
|
||||
|
4
pkg/golinters/testdata/govet.go
vendored
4
pkg/golinters/testdata/govet.go
vendored
@ -2,11 +2,11 @@ package testdata
|
||||
|
||||
import "os"
|
||||
|
||||
func govet() error {
|
||||
func Govet() error {
|
||||
return &os.PathError{"first", "path", os.ErrNotExist} // ERROR "os.PathError composite literal uses unkeyed fields"
|
||||
}
|
||||
|
||||
func govetShadow(f *os.File, buf []byte) (err error) {
|
||||
func GovetShadow(f *os.File, buf []byte) (err error) {
|
||||
if f != nil {
|
||||
_, err := f.Read(buf) // ERROR "declaration of .err. shadows declaration at testdata/govet.go:9"
|
||||
if err != nil {
|
||||
|
@ -27,6 +27,16 @@ type lintRes struct {
|
||||
res *result.Result
|
||||
}
|
||||
|
||||
func runLinter(ctx context.Context, linter Linter, exec executors.Executor, cfg *config.Run) (res *result.Result, err error) {
|
||||
defer func() {
|
||||
if panicData := recover(); panicData != nil {
|
||||
err = fmt.Errorf("panic occured: %s", panicData)
|
||||
}
|
||||
}()
|
||||
res, err = linter.Run(ctx, exec, cfg)
|
||||
return
|
||||
}
|
||||
|
||||
func runLinters(ctx context.Context, wg *sync.WaitGroup, tasksCh chan Linter, lintResultsCh chan lintRes, exec executors.Executor, cfg *config.Config) {
|
||||
for i := 0; i < cfg.Common.Concurrency; i++ {
|
||||
go func() {
|
||||
@ -47,7 +57,7 @@ func runLinters(ctx context.Context, wg *sync.WaitGroup, tasksCh chan Linter, li
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
res, lerr := linter.Run(ctx, exec, &cfg.Run)
|
||||
res, lerr := runLinter(ctx, linter, exec, &cfg.Run)
|
||||
lintResultsCh <- lintRes{
|
||||
linter: linter,
|
||||
err: lerr,
|
||||
|
27
vendor/github.com/golangci/go-misc/LICENSE
generated
vendored
Normal file
27
vendor/github.com/golangci/go-misc/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2012 Rémy Oudompheng. 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.
|
||||
* The name of Rémy Oudompheng may not 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.
|
||||
|
18
vendor/github.com/golangci/go-misc/deadcode/README.md
generated
vendored
Normal file
18
vendor/github.com/golangci/go-misc/deadcode/README.md
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
# deadcode
|
||||
|
||||
`deadcode` is a very simple utility which detects unused declarations in a Go package.
|
||||
|
||||
## Usage
|
||||
```
|
||||
deadcode [-test] [packages]
|
||||
|
||||
-test Include test files
|
||||
packages A list of packages using the same conventions as the go tool
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
* Self-referential unused code is not currently reported
|
||||
* A single package can be tested at a time
|
||||
* Unused methods are not reported
|
||||
|
125
vendor/github.com/golangci/go-misc/deadcode/deadcode.go
generated
vendored
Normal file
125
vendor/github.com/golangci/go-misc/deadcode/deadcode.go
generated
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
package deadcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"golang.org/x/tools/go/loader"
|
||||
)
|
||||
|
||||
var exitCode int
|
||||
|
||||
var (
|
||||
withTestFiles bool
|
||||
)
|
||||
|
||||
type Issue struct {
|
||||
Pos token.Position
|
||||
UnusedIdentName string
|
||||
}
|
||||
|
||||
func Run(paths []string, processTestFiles bool) ([]Issue, error) {
|
||||
ctx := &Context{
|
||||
withTests: processTestFiles,
|
||||
}
|
||||
ctx.Load(paths...)
|
||||
report := ctx.Process()
|
||||
var issues []Issue
|
||||
for _, obj := range report {
|
||||
issues = append(issues, Issue{
|
||||
Pos: ctx.Config.Fset.Position(obj.Pos()),
|
||||
UnusedIdentName: obj.Name(),
|
||||
})
|
||||
}
|
||||
|
||||
return issues, nil
|
||||
}
|
||||
|
||||
func fatalf(format string, args ...interface{}) {
|
||||
panic(fmt.Errorf(format, args...))
|
||||
}
|
||||
|
||||
type Context struct {
|
||||
cwd string
|
||||
withTests bool
|
||||
|
||||
loader.Config
|
||||
}
|
||||
|
||||
func (ctx *Context) Load(args ...string) {
|
||||
ctx.Config.FromArgs(args, ctx.withTests)
|
||||
}
|
||||
|
||||
// error formats the error to standard error, adding program
|
||||
// identification and a newline
|
||||
func (ctx *Context) errorf(pos token.Pos, format string, args ...interface{}) {
|
||||
if ctx.cwd == "" {
|
||||
ctx.cwd, _ = os.Getwd()
|
||||
}
|
||||
p := ctx.Config.Fset.Position(pos)
|
||||
f, err := filepath.Rel(ctx.cwd, p.Filename)
|
||||
if err == nil {
|
||||
p.Filename = f
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, p.String()+": "+format+"\n", args...)
|
||||
exitCode = 2
|
||||
}
|
||||
|
||||
func (ctx *Context) Process() []types.Object {
|
||||
prog, err := ctx.Config.Load()
|
||||
if err != nil {
|
||||
fatalf("cannot load packages: %s", err)
|
||||
}
|
||||
var allUnused []types.Object
|
||||
for _, pkg := range prog.Imported {
|
||||
unused := doPackage(prog, pkg)
|
||||
allUnused = append(allUnused, unused...)
|
||||
}
|
||||
for _, pkg := range prog.Created {
|
||||
unused := doPackage(prog, pkg)
|
||||
allUnused = append(allUnused, unused...)
|
||||
}
|
||||
sort.Sort(objects(allUnused))
|
||||
return allUnused
|
||||
}
|
||||
|
||||
func doPackage(prog *loader.Program, pkg *loader.PackageInfo) []types.Object {
|
||||
used := make(map[types.Object]bool)
|
||||
for _, file := range pkg.Files {
|
||||
ast.Inspect(file, func(n ast.Node) bool {
|
||||
id, ok := n.(*ast.Ident)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
obj := pkg.Info.Uses[id]
|
||||
if obj != nil {
|
||||
used[obj] = true
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
global := pkg.Pkg.Scope()
|
||||
var unused []types.Object
|
||||
for _, name := range global.Names() {
|
||||
if pkg.Pkg.Name() == "main" && name == "main" {
|
||||
continue
|
||||
}
|
||||
obj := global.Lookup(name)
|
||||
if !used[obj] && (pkg.Pkg.Name() == "main" || !ast.IsExported(name)) {
|
||||
unused = append(unused, obj)
|
||||
}
|
||||
}
|
||||
return unused
|
||||
}
|
||||
|
||||
type objects []types.Object
|
||||
|
||||
func (s objects) Len() int { return len(s) }
|
||||
func (s objects) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
func (s objects) Less(i, j int) bool { return s[i].Pos() < s[j].Pos() }
|
1
vendor/github.com/golangci/go-misc/webtoys/static/vdeck.js
generated
vendored
Symbolic link
1
vendor/github.com/golangci/go-misc/webtoys/static/vdeck.js
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../vdeck/vdeck.js
|
Loading…
x
Reference in New Issue
Block a user