github.com/elek/golangci-lint@v1.42.2-0.20211208090441-c05b7fcb3a9a/pkg/golinters/interfacer.go (about) 1 package golinters 2 3 import ( 4 "sync" 5 6 "golang.org/x/tools/go/analysis" 7 "golang.org/x/tools/go/analysis/passes/buildssa" 8 "mvdan.cc/interfacer/check" 9 10 "github.com/elek/golangci-lint/pkg/golinters/goanalysis" 11 "github.com/elek/golangci-lint/pkg/lint/linter" 12 "github.com/elek/golangci-lint/pkg/result" 13 ) 14 15 const interfacerName = "interfacer" 16 17 func NewInterfacer() *goanalysis.Linter { 18 var mu sync.Mutex 19 var resIssues []goanalysis.Issue 20 21 analyzer := &analysis.Analyzer{ 22 Name: interfacerName, 23 Doc: goanalysis.TheOnlyanalyzerDoc, 24 Requires: []*analysis.Analyzer{buildssa.Analyzer}, 25 } 26 return goanalysis.NewLinter( 27 interfacerName, 28 "Linter that suggests narrower interface types", 29 []*analysis.Analyzer{analyzer}, 30 nil, 31 ).WithContextSetter(func(lintCtx *linter.Context) { 32 analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { 33 ssa := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA) 34 ssaPkg := ssa.Pkg 35 c := &check.Checker{} 36 prog := goanalysis.MakeFakeLoaderProgram(pass) 37 c.Program(prog) 38 c.ProgramSSA(ssaPkg.Prog) 39 40 issues, err := c.Check() 41 if err != nil { 42 return nil, err 43 } 44 if len(issues) == 0 { 45 return nil, nil 46 } 47 48 res := make([]goanalysis.Issue, 0, len(issues)) 49 for _, i := range issues { 50 pos := pass.Fset.Position(i.Pos()) 51 res = append(res, goanalysis.NewIssue(&result.Issue{ 52 Pos: pos, 53 Text: i.Message(), 54 FromLinter: interfacerName, 55 }, pass)) 56 } 57 58 mu.Lock() 59 resIssues = append(resIssues, res...) 60 mu.Unlock() 61 62 return nil, nil 63 } 64 }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { 65 return resIssues 66 }).WithLoadMode(goanalysis.LoadModeTypesInfo) 67 }