github.com/nozzle/golangci-lint@v1.49.0-nz3/pkg/golinters/unused.go (about) 1 package golinters 2 3 import ( 4 "fmt" 5 "sync" 6 7 "golang.org/x/tools/go/analysis" 8 "honnef.co/go/tools/unused" 9 10 "github.com/golangci/golangci-lint/pkg/config" 11 "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 12 "github.com/golangci/golangci-lint/pkg/lint/linter" 13 "github.com/golangci/golangci-lint/pkg/result" 14 ) 15 16 const unusedName = "unused" 17 18 type UnusedSettings struct { 19 GoVersion string 20 } 21 22 func NewUnused(settings *config.StaticCheckSettings) *goanalysis.Linter { 23 var mu sync.Mutex 24 var resIssues []goanalysis.Issue 25 26 analyzer := &analysis.Analyzer{ 27 Name: unusedName, 28 Doc: unused.Analyzer.Analyzer.Doc, 29 Requires: unused.Analyzer.Analyzer.Requires, 30 Run: func(pass *analysis.Pass) (interface{}, error) { 31 issues, err := runUnused(pass) 32 if err != nil { 33 return nil, err 34 } 35 36 if len(issues) == 0 { 37 return nil, nil 38 } 39 40 mu.Lock() 41 resIssues = append(resIssues, issues...) 42 mu.Unlock() 43 44 return nil, nil 45 }, 46 } 47 48 setAnalyzerGoVersion(analyzer, getGoVersion(settings)) 49 50 return goanalysis.NewLinter( 51 unusedName, 52 "Checks Go code for unused constants, variables, functions and types", 53 []*analysis.Analyzer{analyzer}, 54 nil, 55 ).WithIssuesReporter(func(lintCtx *linter.Context) []goanalysis.Issue { 56 return resIssues 57 }).WithLoadMode(goanalysis.LoadModeTypesInfo) 58 } 59 60 func runUnused(pass *analysis.Pass) ([]goanalysis.Issue, error) { 61 res, err := unused.Analyzer.Analyzer.Run(pass) 62 if err != nil { 63 return nil, err 64 } 65 66 sr := unused.Serialize(pass, res.(unused.Result), pass.Fset) 67 68 used := make(map[string]bool) 69 for _, obj := range sr.Used { 70 used[fmt.Sprintf("%s %d %s", obj.Position.Filename, obj.Position.Line, obj.Name)] = true 71 } 72 73 var issues []goanalysis.Issue 74 75 // Inspired by https://github.com/dominikh/go-tools/blob/d694aadcb1f50c2d8ac0a1dd06217ebb9f654764/lintcmd/lint.go#L177-L197 76 for _, object := range sr.Unused { 77 if object.Kind == "type param" { 78 continue 79 } 80 81 if object.InGenerated { 82 continue 83 } 84 85 key := fmt.Sprintf("%s %d %s", object.Position.Filename, object.Position.Line, object.Name) 86 if used[key] { 87 continue 88 } 89 90 issue := goanalysis.NewIssue(&result.Issue{ 91 FromLinter: unusedName, 92 Text: fmt.Sprintf("%s %s is unused", object.Kind, object.Name), 93 Pos: object.Position, 94 }, pass) 95 96 issues = append(issues, issue) 97 } 98 99 return issues, nil 100 }