github.com/chenfeining/golangci-lint@v1.0.2-0.20230730162517-14c6c67868df/pkg/golinters/gochecknoinits.go (about)

     1  package golinters
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"go/token"
     7  	"sync"
     8  
     9  	"golang.org/x/tools/go/analysis"
    10  
    11  	"github.com/chenfeining/golangci-lint/pkg/golinters/goanalysis"
    12  	"github.com/chenfeining/golangci-lint/pkg/lint/linter"
    13  	"github.com/chenfeining/golangci-lint/pkg/result"
    14  )
    15  
    16  const gochecknoinitsName = "gochecknoinits"
    17  
    18  func NewGochecknoinits() *goanalysis.Linter {
    19  	var mu sync.Mutex
    20  	var resIssues []goanalysis.Issue
    21  
    22  	analyzer := &analysis.Analyzer{
    23  		Name: gochecknoinitsName,
    24  		Doc:  goanalysis.TheOnlyanalyzerDoc,
    25  		Run: func(pass *analysis.Pass) (any, error) {
    26  			var res []goanalysis.Issue
    27  			for _, file := range pass.Files {
    28  				fileIssues := checkFileForInits(file, pass.Fset)
    29  				for i := range fileIssues {
    30  					res = append(res, goanalysis.NewIssue(&fileIssues[i], pass))
    31  				}
    32  			}
    33  			if len(res) == 0 {
    34  				return nil, nil
    35  			}
    36  
    37  			mu.Lock()
    38  			resIssues = append(resIssues, res...)
    39  			mu.Unlock()
    40  
    41  			return nil, nil
    42  		},
    43  	}
    44  
    45  	return goanalysis.NewLinter(
    46  		gochecknoinitsName,
    47  		"Checks that no init functions are present in Go code",
    48  		[]*analysis.Analyzer{analyzer},
    49  		nil,
    50  	).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
    51  		return resIssues
    52  	}).WithLoadMode(goanalysis.LoadModeSyntax)
    53  }
    54  
    55  func checkFileForInits(f *ast.File, fset *token.FileSet) []result.Issue {
    56  	var res []result.Issue
    57  	for _, decl := range f.Decls {
    58  		funcDecl, ok := decl.(*ast.FuncDecl)
    59  		if !ok {
    60  			continue
    61  		}
    62  
    63  		name := funcDecl.Name.Name
    64  		if name == "init" && funcDecl.Recv.NumFields() == 0 {
    65  			res = append(res, result.Issue{
    66  				Pos:        fset.Position(funcDecl.Pos()),
    67  				Text:       fmt.Sprintf("don't use %s function", formatCode(name, nil)),
    68  				FromLinter: gochecknoinitsName,
    69  			})
    70  		}
    71  	}
    72  
    73  	return res
    74  }