github.com/vanstinator/golangci-lint@v0.0.0-20240223191551-cc572f00d9d1/pkg/golinters/gochecksumtype.go (about)

     1  package golinters
     2  
     3  import (
     4  	"strings"
     5  	"sync"
     6  
     7  	gochecksumtype "github.com/alecthomas/go-check-sumtype"
     8  	"golang.org/x/tools/go/analysis"
     9  	"golang.org/x/tools/go/packages"
    10  
    11  	"github.com/vanstinator/golangci-lint/pkg/golinters/goanalysis"
    12  	"github.com/vanstinator/golangci-lint/pkg/lint/linter"
    13  	"github.com/vanstinator/golangci-lint/pkg/result"
    14  )
    15  
    16  const goCheckSumTypeName = "gochecksumtype"
    17  
    18  func NewGoCheckSumType() *goanalysis.Linter {
    19  	var mu sync.Mutex
    20  	var resIssues []goanalysis.Issue
    21  
    22  	analyzer := &analysis.Analyzer{
    23  		Name: goCheckSumTypeName,
    24  		Doc:  goanalysis.TheOnlyanalyzerDoc,
    25  		Run: func(pass *analysis.Pass) (any, error) {
    26  			issues, err := runGoCheckSumType(pass)
    27  			if err != nil {
    28  				return nil, err
    29  			}
    30  
    31  			if len(issues) == 0 {
    32  				return nil, nil
    33  			}
    34  
    35  			mu.Lock()
    36  			resIssues = append(resIssues, issues...)
    37  			mu.Unlock()
    38  
    39  			return nil, nil
    40  		},
    41  	}
    42  
    43  	return goanalysis.NewLinter(
    44  		goCheckSumTypeName,
    45  		`Run exhaustiveness checks on Go "sum types"`,
    46  		[]*analysis.Analyzer{analyzer},
    47  		nil,
    48  	).WithIssuesReporter(func(ctx *linter.Context) []goanalysis.Issue {
    49  		return resIssues
    50  	}).WithLoadMode(goanalysis.LoadModeTypesInfo)
    51  }
    52  
    53  func runGoCheckSumType(pass *analysis.Pass) ([]goanalysis.Issue, error) {
    54  	var resIssues []goanalysis.Issue
    55  
    56  	pkg := &packages.Package{
    57  		Fset:      pass.Fset,
    58  		Syntax:    pass.Files,
    59  		Types:     pass.Pkg,
    60  		TypesInfo: pass.TypesInfo,
    61  	}
    62  
    63  	var unknownError error
    64  	errors := gochecksumtype.Run([]*packages.Package{pkg})
    65  	for _, err := range errors {
    66  		err, ok := err.(gochecksumtype.Error)
    67  		if !ok {
    68  			unknownError = err
    69  			continue
    70  		}
    71  
    72  		resIssues = append(resIssues, goanalysis.NewIssue(&result.Issue{
    73  			FromLinter: goCheckSumTypeName,
    74  			Text:       strings.TrimPrefix(err.Error(), err.Pos().String()+": "),
    75  			Pos:        err.Pos(),
    76  		}, pass))
    77  	}
    78  
    79  	return resIssues, unknownError
    80  }