github.com/nozzle/golangci-lint@v1.49.0-nz3/pkg/golinters/gocyclo.go (about)

     1  package golinters
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	"github.com/fzipp/gocyclo"
     8  	"golang.org/x/tools/go/analysis"
     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 gocycloName = "gocyclo"
    17  
    18  //nolint:dupl
    19  func NewGocyclo(settings *config.GoCycloSettings) *goanalysis.Linter {
    20  	var mu sync.Mutex
    21  	var resIssues []goanalysis.Issue
    22  
    23  	analyzer := &analysis.Analyzer{
    24  		Name: gocycloName,
    25  		Doc:  goanalysis.TheOnlyanalyzerDoc,
    26  		Run: func(pass *analysis.Pass) (interface{}, error) {
    27  			issues := runGoCyclo(pass, settings)
    28  
    29  			if len(issues) == 0 {
    30  				return nil, nil
    31  			}
    32  
    33  			mu.Lock()
    34  			resIssues = append(resIssues, issues...)
    35  			mu.Unlock()
    36  
    37  			return nil, nil
    38  		},
    39  	}
    40  
    41  	return goanalysis.NewLinter(
    42  		gocycloName,
    43  		"Computes and checks the cyclomatic complexity of functions",
    44  		[]*analysis.Analyzer{analyzer},
    45  		nil,
    46  	).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
    47  		return resIssues
    48  	}).WithLoadMode(goanalysis.LoadModeSyntax)
    49  }
    50  
    51  func runGoCyclo(pass *analysis.Pass, settings *config.GoCycloSettings) []goanalysis.Issue {
    52  	var stats gocyclo.Stats
    53  	for _, f := range pass.Files {
    54  		stats = gocyclo.AnalyzeASTFile(f, pass.Fset, stats)
    55  	}
    56  	if len(stats) == 0 {
    57  		return nil
    58  	}
    59  
    60  	stats = stats.SortAndFilter(-1, settings.MinComplexity)
    61  
    62  	issues := make([]goanalysis.Issue, 0, len(stats))
    63  
    64  	for _, s := range stats {
    65  		text := fmt.Sprintf("cyclomatic complexity %d of func %s is high (> %d)",
    66  			s.Complexity, formatCode(s.FuncName, nil), settings.MinComplexity)
    67  
    68  		issues = append(issues, goanalysis.NewIssue(&result.Issue{
    69  			Pos:        s.Pos,
    70  			Text:       text,
    71  			FromLinter: gocycloName,
    72  		}, pass))
    73  	}
    74  
    75  	return issues
    76  }