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 }