|
1 | 1 | package golinters
|
2 | 2 |
|
3 | 3 | import (
|
4 |
| - "fmt" |
5 |
| - "go/ast" |
6 |
| - "go/token" |
7 |
| - "sync" |
8 |
| - |
| 4 | + "github.com/alexkohler/nakedret/v2" |
9 | 5 | "golang.org/x/tools/go/analysis"
|
10 | 6 |
|
11 | 7 | "github.com/golangci/golangci-lint/pkg/config"
|
12 | 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
|
13 |
| - "github.com/golangci/golangci-lint/pkg/lint/linter" |
14 |
| - "github.com/golangci/golangci-lint/pkg/result" |
15 | 9 | )
|
16 | 10 |
|
17 | 11 | const nakedretName = "nakedret"
|
18 | 12 |
|
19 |
| -//nolint:dupl |
20 | 13 | func NewNakedret(settings *config.NakedretSettings) *goanalysis.Linter {
|
21 |
| - var mu sync.Mutex |
22 |
| - var resIssues []goanalysis.Issue |
23 |
| - |
24 |
| - analyzer := &analysis.Analyzer{ |
25 |
| - Name: nakedretName, |
26 |
| - Doc: goanalysis.TheOnlyanalyzerDoc, |
27 |
| - Run: func(pass *analysis.Pass) (any, error) { |
28 |
| - issues := runNakedRet(pass, settings) |
29 |
| - |
30 |
| - if len(issues) == 0 { |
31 |
| - return nil, nil |
32 |
| - } |
33 |
| - |
34 |
| - mu.Lock() |
35 |
| - resIssues = append(resIssues, issues...) |
36 |
| - mu.Unlock() |
37 |
| - |
38 |
| - return nil, nil |
39 |
| - }, |
| 14 | + var maxLines int |
| 15 | + if settings != nil { |
| 16 | + maxLines = settings.MaxFuncLines |
40 | 17 | }
|
41 | 18 |
|
| 19 | + analyzer := nakedret.NakedReturnAnalyzer(uint(maxLines)) |
| 20 | + |
42 | 21 | return goanalysis.NewLinter(
|
43 | 22 | nakedretName,
|
44 | 23 | "Finds naked returns in functions greater than a specified function length",
|
45 | 24 | []*analysis.Analyzer{analyzer},
|
46 | 25 | nil,
|
47 |
| - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { |
48 |
| - return resIssues |
49 |
| - }).WithLoadMode(goanalysis.LoadModeSyntax) |
50 |
| -} |
51 |
| - |
52 |
| -func runNakedRet(pass *analysis.Pass, settings *config.NakedretSettings) []goanalysis.Issue { |
53 |
| - var issues []goanalysis.Issue |
54 |
| - |
55 |
| - for _, file := range pass.Files { |
56 |
| - v := nakedretVisitor{ |
57 |
| - maxLength: settings.MaxFuncLines, |
58 |
| - f: pass.Fset, |
59 |
| - } |
60 |
| - |
61 |
| - ast.Walk(&v, file) |
62 |
| - |
63 |
| - for i := range v.issues { |
64 |
| - issues = append(issues, goanalysis.NewIssue(&v.issues[i], pass)) |
65 |
| - } |
66 |
| - } |
67 |
| - |
68 |
| - return issues |
69 |
| -} |
70 |
| - |
71 |
| -type nakedretVisitor struct { |
72 |
| - maxLength int |
73 |
| - f *token.FileSet |
74 |
| - issues []result.Issue |
75 |
| -} |
76 |
| - |
77 |
| -func (v *nakedretVisitor) processFuncDecl(funcDecl *ast.FuncDecl) { |
78 |
| - file := v.f.File(funcDecl.Pos()) |
79 |
| - functionLineLength := file.Position(funcDecl.End()).Line - file.Position(funcDecl.Pos()).Line |
80 |
| - |
81 |
| - // Scan the body for usage of the named returns |
82 |
| - for _, stmt := range funcDecl.Body.List { |
83 |
| - s, ok := stmt.(*ast.ReturnStmt) |
84 |
| - if !ok { |
85 |
| - continue |
86 |
| - } |
87 |
| - |
88 |
| - if len(s.Results) != 0 { |
89 |
| - continue |
90 |
| - } |
91 |
| - |
92 |
| - file := v.f.File(s.Pos()) |
93 |
| - if file == nil || functionLineLength <= v.maxLength { |
94 |
| - continue |
95 |
| - } |
96 |
| - if funcDecl.Name == nil { |
97 |
| - continue |
98 |
| - } |
99 |
| - |
100 |
| - v.issues = append(v.issues, result.Issue{ |
101 |
| - FromLinter: nakedretName, |
102 |
| - Text: fmt.Sprintf("naked return in func `%s` with %d lines of code", |
103 |
| - funcDecl.Name.Name, functionLineLength), |
104 |
| - Pos: v.f.Position(s.Pos()), |
105 |
| - }) |
106 |
| - } |
107 |
| -} |
108 |
| - |
109 |
| -func (v *nakedretVisitor) Visit(node ast.Node) ast.Visitor { |
110 |
| - funcDecl, ok := node.(*ast.FuncDecl) |
111 |
| - if !ok { |
112 |
| - return v |
113 |
| - } |
114 |
| - |
115 |
| - var namedReturns []*ast.Ident |
116 |
| - |
117 |
| - // We've found a function |
118 |
| - if funcDecl.Type != nil && funcDecl.Type.Results != nil { |
119 |
| - for _, field := range funcDecl.Type.Results.List { |
120 |
| - for _, ident := range field.Names { |
121 |
| - if ident != nil { |
122 |
| - namedReturns = append(namedReturns, ident) |
123 |
| - } |
124 |
| - } |
125 |
| - } |
126 |
| - } |
127 |
| - |
128 |
| - if len(namedReturns) == 0 || funcDecl.Body == nil { |
129 |
| - return v |
130 |
| - } |
131 |
| - |
132 |
| - v.processFuncDecl(funcDecl) |
133 |
| - return v |
| 26 | + ).WithLoadMode(goanalysis.LoadModeSyntax) |
134 | 27 | }
|
0 commit comments