github.com/elek/golangci-lint@v1.42.2-0.20211208090441-c05b7fcb3a9a/pkg/golinters/maligned.go (about)

     1  package golinters
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	malignedAPI "github.com/golangci/maligned"
     8  	"golang.org/x/tools/go/analysis"
     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  func NewMaligned() *goanalysis.Linter {
    16  	const linterName = "maligned"
    17  	var mu sync.Mutex
    18  	var res []goanalysis.Issue
    19  	analyzer := &analysis.Analyzer{
    20  		Name: linterName,
    21  		Doc:  goanalysis.TheOnlyanalyzerDoc,
    22  	}
    23  	return goanalysis.NewLinter(
    24  		linterName,
    25  		"Tool to detect Go structs that would take less memory if their fields were sorted",
    26  		[]*analysis.Analyzer{analyzer},
    27  		nil,
    28  	).WithContextSetter(func(lintCtx *linter.Context) {
    29  		analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
    30  			prog := goanalysis.MakeFakeLoaderProgram(pass)
    31  
    32  			malignedIssues := malignedAPI.Run(prog)
    33  			if len(malignedIssues) == 0 {
    34  				return nil, nil
    35  			}
    36  
    37  			issues := make([]goanalysis.Issue, 0, len(malignedIssues))
    38  			for _, i := range malignedIssues {
    39  				text := fmt.Sprintf("struct of size %d bytes could be of size %d bytes", i.OldSize, i.NewSize)
    40  				if lintCtx.Settings().Maligned.SuggestNewOrder {
    41  					text += fmt.Sprintf(":\n%s", formatCodeBlock(i.NewStructDef, lintCtx.Cfg))
    42  				}
    43  				issues = append(issues, goanalysis.NewIssue(&result.Issue{
    44  					Pos:        i.Pos,
    45  					Text:       text,
    46  					FromLinter: linterName,
    47  				}, pass))
    48  			}
    49  
    50  			mu.Lock()
    51  			res = append(res, issues...)
    52  			mu.Unlock()
    53  			return nil, nil
    54  		}
    55  	}).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
    56  		return res
    57  	}).WithLoadMode(goanalysis.LoadModeTypesInfo)
    58  }