github.com/elek/golangci-lint@v1.42.2-0.20211208090441-c05b7fcb3a9a/pkg/golinters/gocognit.go (about) 1 package golinters 2 3 import ( 4 "fmt" 5 "sort" 6 "sync" 7 8 "github.com/uudashr/gocognit" 9 "golang.org/x/tools/go/analysis" 10 11 "github.com/elek/golangci-lint/pkg/golinters/goanalysis" 12 "github.com/elek/golangci-lint/pkg/lint/linter" 13 "github.com/elek/golangci-lint/pkg/result" 14 ) 15 16 const gocognitName = "gocognit" 17 18 func NewGocognit() *goanalysis.Linter { 19 var mu sync.Mutex 20 var resIssues []goanalysis.Issue 21 22 analyzer := &analysis.Analyzer{ 23 Name: goanalysis.TheOnlyAnalyzerName, 24 Doc: goanalysis.TheOnlyanalyzerDoc, 25 } 26 return goanalysis.NewLinter( 27 gocognitName, 28 "Computes and checks the cognitive complexity of functions", 29 []*analysis.Analyzer{analyzer}, 30 nil, 31 ).WithContextSetter(func(lintCtx *linter.Context) { 32 analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { 33 var stats []gocognit.Stat 34 for _, f := range pass.Files { 35 stats = gocognit.ComplexityStats(f, pass.Fset, stats) 36 } 37 if len(stats) == 0 { 38 return nil, nil 39 } 40 41 sort.SliceStable(stats, func(i, j int) bool { 42 return stats[i].Complexity > stats[j].Complexity 43 }) 44 45 res := make([]goanalysis.Issue, 0, len(stats)) 46 for _, s := range stats { 47 if s.Complexity <= lintCtx.Settings().Gocognit.MinComplexity { 48 break // Break as the stats is already sorted from greatest to least 49 } 50 51 res = append(res, goanalysis.NewIssue(&result.Issue{ 52 Pos: s.Pos, 53 Text: fmt.Sprintf("cognitive complexity %d of func %s is high (> %d)", 54 s.Complexity, formatCode(s.FuncName, lintCtx.Cfg), lintCtx.Settings().Gocognit.MinComplexity), 55 FromLinter: gocognitName, 56 }, pass)) 57 } 58 59 mu.Lock() 60 resIssues = append(resIssues, res...) 61 mu.Unlock() 62 63 return nil, nil 64 } 65 }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { 66 return resIssues 67 }).WithLoadMode(goanalysis.LoadModeSyntax) 68 }