4
4
"fmt"
5
5
"go/ast"
6
6
"go/token"
7
+ "strconv"
7
8
8
9
"golang.org/x/tools/go/analysis"
9
10
"golang.org/x/tools/go/analysis/passes/inspect"
@@ -12,64 +13,108 @@ import (
12
13
13
14
// Stat is statistic of the complexity.
14
15
type Stat struct {
15
- PkgName string
16
- FuncName string
17
- Complexity int
18
- Traces [] Trace `json:",omitempty"`
19
- Pos token.Position
16
+ PkgName string
17
+ FuncName string
18
+ Complexity int
19
+ Diagnostics [] Diagnostic `json:",omitempty"`
20
+ Pos token.Position
20
21
}
21
22
22
- type Trace struct {
23
+ // Diagnostic contrains information how the complexity increase.
24
+ type Diagnostic struct {
23
25
Inc int
24
26
Nesting int `json:",omitempty"`
25
27
Text string
26
- Pos token. Position
28
+ Pos DiagnosticPosition
27
29
}
28
30
29
- func (t Trace ) String () string {
30
- if t .Nesting == 0 {
31
- return fmt .Sprintf ("+%d" , t .Inc )
31
+ // DiagnosticPosition is the position of the diagnostic.
32
+ type DiagnosticPosition struct {
33
+ Offset int // offset, starting at 0
34
+ Line int // line number, starting at 1
35
+ Column int // column number, starting at 1 (byte count)
36
+ }
37
+
38
+ func (pos DiagnosticPosition ) isValid () bool {
39
+ return pos .Line > 0
40
+ }
41
+
42
+ func (pos DiagnosticPosition ) String () string {
43
+ var s string
44
+ if pos .isValid () {
45
+ if s != "" {
46
+ s += ":"
47
+ }
48
+
49
+ s += strconv .Itoa (pos .Line )
50
+ if pos .Column != 0 {
51
+ s += fmt .Sprintf (":%d" , pos .Column )
52
+ }
53
+ }
54
+
55
+ if s == "" {
56
+ s = "-"
32
57
}
33
58
34
- return fmt .Sprintf ("+%d (nesting=%d)" , t .Inc , t .Nesting )
59
+ return s
60
+ }
61
+
62
+ func (d Diagnostic ) String () string {
63
+ if d .Nesting == 0 {
64
+ return fmt .Sprintf ("+%d" , d .Inc )
65
+ }
66
+
67
+ return fmt .Sprintf ("+%d (nesting=%d)" , d .Inc , d .Nesting )
35
68
}
36
69
37
70
func (s Stat ) String () string {
38
71
return fmt .Sprintf ("%d %s %s %s" , s .Complexity , s .PkgName , s .FuncName , s .Pos )
39
72
}
40
73
41
74
// ComplexityStats builds the complexity statistics.
42
- func ComplexityStats (f * ast.File , fset * token.FileSet , stats []Stat , includeTrace bool ) []Stat {
75
+ func ComplexityStats (f * ast.File , fset * token.FileSet , stats []Stat ) []Stat {
76
+ return ComplexityStatsWithDiagnostic (f , fset , stats , false )
77
+ }
78
+
79
+ // ComplexityStatsWithDiagnostic builds the complexity statistics with diagnostic.
80
+ func ComplexityStatsWithDiagnostic (f * ast.File , fset * token.FileSet , stats []Stat , enableDiagnostic bool ) []Stat {
43
81
for _ , decl := range f .Decls {
44
82
if fn , ok := decl .(* ast.FuncDecl ); ok {
45
83
d := parseDirective (fn .Doc )
46
84
if d .Ignore {
47
85
continue
48
86
}
49
87
50
- res := ScanComplexity (fn , includeTrace )
88
+ res := ScanComplexity (fn , enableDiagnostic )
51
89
52
90
stats = append (stats , Stat {
53
- PkgName : f .Name .Name ,
54
- FuncName : funcName (fn ),
55
- Complexity : res .Complexity ,
56
- Traces : traces (fset , res .Traces ),
57
- Pos : fset .Position (fn .Pos ()),
91
+ PkgName : f .Name .Name ,
92
+ FuncName : funcName (fn ),
93
+ Complexity : res .Complexity ,
94
+ Diagnostics : generateDiagnostics (fset , res .Diagnostics ),
95
+ Pos : fset .Position (fn .Pos ()),
58
96
})
59
97
}
60
98
}
61
99
62
100
return stats
63
101
}
64
102
65
- func traces (fset * token.FileSet , traces []trace ) []Trace {
66
- tags := make ([]Trace , 0 , len (traces ))
67
- for _ , t := range traces {
68
- tags = append (tags , Trace {
69
- Inc : t .Inc ,
70
- Nesting : t .Nesting ,
71
- Text : t .Text ,
72
- Pos : fset .Position (t .Pos ),
103
+ func generateDiagnostics (fset * token.FileSet , diags []diagnostic ) []Diagnostic {
104
+ tags := make ([]Diagnostic , 0 , len (diags ))
105
+ for _ , diag := range diags {
106
+ pos := fset .Position (diag .Pos )
107
+ tracePos := DiagnosticPosition {
108
+ Offset : pos .Offset ,
109
+ Line : pos .Line ,
110
+ Column : pos .Column ,
111
+ }
112
+
113
+ tags = append (tags , Diagnostic {
114
+ Inc : diag .Inc ,
115
+ Nesting : diag .Nesting ,
116
+ Text : diag .Text ,
117
+ Pos : tracePos ,
73
118
})
74
119
}
75
120
@@ -116,26 +161,26 @@ func Complexity(fn *ast.FuncDecl) int {
116
161
}
117
162
118
163
// ScanComplexity scans the function declaration.
119
- func ScanComplexity (fn * ast.FuncDecl , trace bool ) ScanResult {
164
+ func ScanComplexity (fn * ast.FuncDecl , includeDiagnostic bool ) ScanResult {
120
165
v := complexityVisitor {
121
- name : fn .Name ,
122
- trace : trace ,
166
+ name : fn .Name ,
167
+ diagnosticEnabled : includeDiagnostic ,
123
168
}
124
169
125
170
ast .Walk (& v , fn )
126
171
127
172
return ScanResult {
128
- Traces : v . traces ,
129
- Complexity : v .complexity ,
173
+ Diagnostics : v . diagnostics ,
174
+ Complexity : v .complexity ,
130
175
}
131
176
}
132
177
133
178
type ScanResult struct {
134
- Traces [] trace
135
- Complexity int
179
+ Diagnostics [] diagnostic
180
+ Complexity int
136
181
}
137
182
138
- type trace struct {
183
+ type diagnostic struct {
139
184
Inc int
140
185
Nesting int
141
186
Text string
@@ -151,8 +196,8 @@ type complexityVisitor struct {
151
196
152
197
fset * token.FileSet
153
198
154
- trace bool
155
- traces [] trace
199
+ diagnosticEnabled bool
200
+ diagnostics [] diagnostic
156
201
}
157
202
158
203
func (v * complexityVisitor ) incNesting () {
@@ -166,11 +211,11 @@ func (v *complexityVisitor) decNesting() {
166
211
func (v * complexityVisitor ) incComplexity (text string , pos token.Pos ) {
167
212
v .complexity ++
168
213
169
- if ! v .trace {
214
+ if ! v .diagnosticEnabled {
170
215
return
171
216
}
172
217
173
- v .traces = append (v .traces , trace {
218
+ v .diagnostics = append (v .diagnostics , diagnostic {
174
219
Inc : 1 ,
175
220
Text : text ,
176
221
Pos : pos ,
@@ -180,11 +225,11 @@ func (v *complexityVisitor) incComplexity(text string, pos token.Pos) {
180
225
func (v * complexityVisitor ) nestIncComplexity (text string , pos token.Pos ) {
181
226
v .complexity += (v .nesting + 1 )
182
227
183
- if ! v .trace {
228
+ if ! v .diagnosticEnabled {
184
229
return
185
230
}
186
231
187
- v .traces = append (v .traces , trace {
232
+ v .diagnostics = append (v .diagnostics , diagnostic {
188
233
Inc : v .nesting + 1 ,
189
234
Nesting : v .nesting ,
190
235
Text : text ,
0 commit comments