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

     1  package golinters
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	structcheckAPI "github.com/golangci/check/cmd/structcheck"
     8  	"golang.org/x/tools/go/analysis"
     9  
    10  	"github.com/vanstinator/golangci-lint/pkg/config"
    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 structcheckName = "structcheck"
    17  
    18  //nolint:dupl
    19  func NewStructcheck(settings *config.StructCheckSettings) *goanalysis.Linter {
    20  	var mu sync.Mutex
    21  	var resIssues []goanalysis.Issue
    22  
    23  	analyzer := &analysis.Analyzer{
    24  		Name: structcheckName,
    25  		Doc:  goanalysis.TheOnlyanalyzerDoc,
    26  		Run: func(pass *analysis.Pass) (any, error) {
    27  			issues := runStructCheck(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  		structcheckName,
    43  		"Finds unused struct fields",
    44  		[]*analysis.Analyzer{analyzer},
    45  		nil,
    46  	).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
    47  		return resIssues
    48  	}).WithLoadMode(goanalysis.LoadModeTypesInfo)
    49  }
    50  
    51  //nolint:dupl
    52  func runStructCheck(pass *analysis.Pass, settings *config.StructCheckSettings) []goanalysis.Issue {
    53  	prog := goanalysis.MakeFakeLoaderProgram(pass)
    54  
    55  	lintIssues := structcheckAPI.Run(prog, settings.CheckExportedFields)
    56  	if len(lintIssues) == 0 {
    57  		return nil
    58  	}
    59  
    60  	issues := make([]goanalysis.Issue, 0, len(lintIssues))
    61  
    62  	for _, i := range lintIssues {
    63  		issues = append(issues, goanalysis.NewIssue(&result.Issue{
    64  			Pos:        i.Pos,
    65  			Text:       fmt.Sprintf("%s is unused", formatCode(i.FieldName, nil)),
    66  			FromLinter: structcheckName,
    67  		}, pass))
    68  	}
    69  
    70  	return issues
    71  }