github.com/shulhan/golangci-lint@v1.10.1/pkg/golinters/nakedret.go (about) 1 package golinters 2 3 import ( 4 "context" 5 "fmt" 6 "go/ast" 7 "go/token" 8 9 "github.com/golangci/golangci-lint/pkg/lint/linter" 10 "github.com/golangci/golangci-lint/pkg/result" 11 ) 12 13 type Nakedret struct{} 14 15 func (Nakedret) Name() string { 16 return "nakedret" 17 } 18 19 func (Nakedret) Desc() string { 20 return "Finds naked returns in functions greater than a specified function length" 21 } 22 23 type nakedretVisitor struct { 24 maxLength int 25 f *token.FileSet 26 issues []result.Issue 27 } 28 29 func (v *nakedretVisitor) processFuncDecl(funcDecl *ast.FuncDecl) { 30 file := v.f.File(funcDecl.Pos()) 31 functionLineLength := file.Position(funcDecl.End()).Line - file.Position(funcDecl.Pos()).Line 32 33 // Scan the body for usage of the named returns 34 for _, stmt := range funcDecl.Body.List { 35 s, ok := stmt.(*ast.ReturnStmt) 36 if !ok { 37 continue 38 } 39 40 if len(s.Results) != 0 { 41 continue 42 } 43 44 file := v.f.File(s.Pos()) 45 if file == nil || functionLineLength <= v.maxLength { 46 continue 47 } 48 if funcDecl.Name == nil { 49 continue 50 } 51 52 v.issues = append(v.issues, result.Issue{ 53 FromLinter: Nakedret{}.Name(), 54 Text: fmt.Sprintf("naked return in func `%s` with %d lines of code", 55 funcDecl.Name.Name, functionLineLength), 56 Pos: v.f.Position(s.Pos()), 57 }) 58 } 59 } 60 61 func (v *nakedretVisitor) Visit(node ast.Node) ast.Visitor { 62 funcDecl, ok := node.(*ast.FuncDecl) 63 if !ok { 64 return v 65 } 66 67 var namedReturns []*ast.Ident 68 69 // We've found a function 70 if funcDecl.Type != nil && funcDecl.Type.Results != nil { 71 for _, field := range funcDecl.Type.Results.List { 72 for _, ident := range field.Names { 73 if ident != nil { 74 namedReturns = append(namedReturns, ident) 75 } 76 } 77 } 78 } 79 80 if len(namedReturns) == 0 || funcDecl.Body == nil { 81 return v 82 } 83 84 v.processFuncDecl(funcDecl) 85 return v 86 } 87 88 func (lint Nakedret) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) { 89 var res []result.Issue 90 for _, f := range lintCtx.ASTCache.GetAllValidFiles() { 91 v := nakedretVisitor{ 92 maxLength: lintCtx.Settings().Nakedret.MaxFuncLines, 93 f: f.Fset, 94 } 95 ast.Walk(&v, f.F) 96 res = append(res, v.issues...) 97 } 98 99 return res, nil 100 }