1package golinters // nolint:dupl 2 3import ( 4 "fmt" 5 "sync" 6 7 structcheckAPI "github.com/golangci/check/cmd/structcheck" 8 "golang.org/x/tools/go/analysis" 9 10 "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 11 "github.com/golangci/golangci-lint/pkg/lint/linter" 12 "github.com/golangci/golangci-lint/pkg/result" 13) 14 15func NewStructcheck() *goanalysis.Linter { 16 const linterName = "structcheck" 17 var mu sync.Mutex 18 var res []goanalysis.Issue 19 analyzer := &analysis.Analyzer{ 20 Name: linterName, 21 Doc: goanalysis.TheOnlyanalyzerDoc, 22 } 23 return goanalysis.NewLinter( 24 linterName, 25 "Finds unused struct fields", 26 []*analysis.Analyzer{analyzer}, 27 nil, 28 ).WithContextSetter(func(lintCtx *linter.Context) { 29 checkExported := lintCtx.Settings().Structcheck.CheckExportedFields 30 analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { 31 prog := goanalysis.MakeFakeLoaderProgram(pass) 32 33 structcheckIssues := structcheckAPI.Run(prog, checkExported) 34 if len(structcheckIssues) == 0 { 35 return nil, nil 36 } 37 38 issues := make([]goanalysis.Issue, 0, len(structcheckIssues)) 39 for _, i := range structcheckIssues { 40 issues = append(issues, goanalysis.NewIssue(&result.Issue{ 41 Pos: i.Pos, 42 Text: fmt.Sprintf("%s is unused", formatCode(i.FieldName, lintCtx.Cfg)), 43 FromLinter: linterName, 44 }, pass)) 45 } 46 47 mu.Lock() 48 res = append(res, issues...) 49 mu.Unlock() 50 return nil, nil 51 } 52 }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { 53 return res 54 }).WithLoadMode(goanalysis.LoadModeTypesInfo) 55} 56