Skip to content

Commit f67d1db

Browse files
committed
Refine documentation
1 parent c2fcfc4 commit f67d1db

File tree

3 files changed

+152
-45
lines changed

3 files changed

+152
-45
lines changed

README.md

+99-12
Original file line numberDiff line numberDiff line change
@@ -169,14 +169,17 @@ Usage:
169169
170170
Flags:
171171
172-
-over N show functions with complexity > N only
173-
and return exit code 1 if the output is non-empty
174-
-top N show the top N most complex functions only
175-
-avg show the average complexity over all functions,
176-
not depending on whether -over or -top are set
177-
-json encode the output as JSON
178-
-f format string the format to use
179-
(default "{{.PkgName}}.{{.FuncName}}:{{.Complexity}}:{{.Pos}}")
172+
-over N show functions with complexity > N only
173+
and return exit code 1 if the output is non-empty
174+
-top N show the top N most complex functions only
175+
-avg show the average complexity over all functions,
176+
not depending on whether -over or -top are set
177+
-test indicates whether test files should be included
178+
-json encode the output as JSON
179+
-d enable diagnostic output
180+
-f format string the format to use
181+
(default "{{.Complexity}} {{.PkgName}} {{.FuncName}} {{.Pos}}")
182+
-ignore expr ignore files matching the given regexp
180183
181184
The (default) output fields for each line are:
182185
@@ -191,10 +194,24 @@ or equal to <complexity> <package> <function> <file:row:column>
191194
The struct being passed to the template is:
192195
193196
type Stat struct {
194-
PkgName string
195-
FuncName string
196-
Complexity int
197-
Pos token.Position
197+
PkgName string
198+
FuncName string
199+
Complexity int
200+
Pos token.Position
201+
Diagnostics []Diagnostics
202+
}
203+
204+
type Diagnostic struct {
205+
Inc string
206+
Nesting int
207+
Text string
208+
Pos DiagnosticPosition
209+
}
210+
211+
type DiagnosticPosition struct {
212+
Offset int
213+
Line int
214+
Column int
198215
}
199216
```
200217

@@ -223,6 +240,76 @@ func IgnoreMe() {
223240
}
224241
```
225242

243+
## Diagnostic
244+
To understand how the complexity are calculated, we can enable the diagnostic by using `-d` flag.
245+
246+
Example:
247+
```shell
248+
$ gocognit -json -d .
249+
```
250+
251+
It will show the diagnostic output in JSON format
252+
<details>
253+
254+
<summary>JSON Output</summary>
255+
256+
```json
257+
[
258+
{
259+
"PkgName": "prime",
260+
"FuncName": "SumOfPrimes",
261+
"Complexity": 7,
262+
"Pos": {
263+
"Filename": "prime.go",
264+
"Offset": 15,
265+
"Line": 3,
266+
"Column": 1
267+
},
268+
"Diagnostics": [
269+
{
270+
"Inc": 1,
271+
"Text": "for",
272+
"Pos": {
273+
"Offset": 69,
274+
"Line": 7,
275+
"Column": 2
276+
}
277+
},
278+
{
279+
"Inc": 2,
280+
"Nesting": 1,
281+
"Text": "for",
282+
"Pos": {
283+
"Offset": 104,
284+
"Line": 8,
285+
"Column": 3
286+
}
287+
},
288+
{
289+
"Inc": 3,
290+
"Nesting": 2,
291+
"Text": "if",
292+
"Pos": {
293+
"Offset": 152,
294+
"Line": 9,
295+
"Column": 4
296+
}
297+
},
298+
{
299+
"Inc": 1,
300+
"Text": "continue",
301+
"Pos": {
302+
"Offset": 190,
303+
"Line": 10,
304+
"Column": 5
305+
}
306+
}
307+
]
308+
}
309+
]
310+
```
311+
</details>
312+
226313
## Related project
227314
- [Gocyclo](https://github.com/fzipp/gocyclo) where the code are based on.
228315
- [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) white paper by G. Ann Campbell.

cmd/gocognit/main.go

+38-21
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
// -over N show functions with complexity > N only and return exit code 1 if the output is non-empty
1111
// -top N show the top N most complex functions only
1212
// -avg show the average complexity over all functions, not depending on whether -over or -top are set
13+
// -test indicates whether test files should be included
1314
// -json encode the output as JSON
14-
// -f format string the format to use (default "{{.PkgName}}.{{.FuncName}}:{{.Complexity}}:{{.Pos}}")
15+
// -d enable diagnostic output
16+
// -f format string the format to use (default "{{.Complexity}} {{.PkgName}} {{.FuncName}} {{.Pos}}")
1517
//
1618
// The (default) output fields for each line are:
1719
//
@@ -29,8 +31,22 @@
2931
// PkgName string
3032
// FuncName string
3133
// Complexity int
34+
// Diagnostics []Diagnostic
3235
// Pos token.Position
3336
// }
37+
//
38+
// type Diagnostic struct {
39+
// Inc string
40+
// Nesting int
41+
// Text string
42+
// Pos DiagnosticPosition
43+
// }
44+
//
45+
// type DiagnosticPosition struct {
46+
// Offset int
47+
// Line int
48+
// Column int
49+
// }
3450
package main
3551

3652
import (
@@ -59,16 +75,17 @@ Usage:
5975
6076
Flags:
6177
62-
-over N show functions with complexity > N only
63-
and return exit code 1 if the output is non-empty
64-
-top N show the top N most complex functions only
65-
-avg show the average complexity over all functions,
66-
not depending on whether -over or -top are set
67-
-test indicates whether test files should be included
68-
-json encode the output as JSON
69-
-d enable diagnostic output
70-
-f format string the format to use
71-
(default "{{.Complexity}} {{.PkgName}} {{.FuncName}} {{.Pos}}")
78+
-over N show functions with complexity > N only
79+
and return exit code 1 if the output is non-empty
80+
-top N show the top N most complex functions only
81+
-avg show the average complexity over all functions,
82+
not depending on whether -over or -top are set
83+
-test indicates whether test files should be included
84+
-json encode the output as JSON
85+
-d enable diagnostic output
86+
-f format string the format to use
87+
(default "{{.Complexity}} {{.PkgName}} {{.FuncName}} {{.Pos}}")
88+
-ignore expr ignore files matching the given regexp
7289
7390
The (default) output fields for each line are:
7491
@@ -118,14 +135,14 @@ func usage() {
118135

119136
func main() {
120137
var (
121-
over int
122-
top int
123-
avg bool
124-
includeTests bool
125-
format string
126-
jsonEncode bool
127-
ignoreExpr string
128-
diagnostic bool
138+
over int
139+
top int
140+
avg bool
141+
includeTests bool
142+
format string
143+
jsonEncode bool
144+
enableDiagnostics bool
145+
ignoreExpr string
129146
)
130147

131148
flag.IntVar(&over, "over", defaultOverFlagVal, "show functions with complexity > N only")
@@ -134,8 +151,8 @@ func main() {
134151
flag.BoolVar(&includeTests, "test", true, "indicates whether test files should be included")
135152
flag.StringVar(&format, "f", defaultFormat, "the format to use")
136153
flag.BoolVar(&jsonEncode, "json", false, "encode the output as JSON")
154+
flag.BoolVar(&enableDiagnostics, "d", false, "enable diagnostic output")
137155
flag.StringVar(&ignoreExpr, "ignore", "", "ignore files matching the given regexp")
138-
flag.BoolVar(&diagnostic, "d", false, "enable diagnostic output")
139156

140157
log.SetFlags(0)
141158
log.SetPrefix("gocognit: ")
@@ -153,7 +170,7 @@ func main() {
153170
log.Fatal(err)
154171
}
155172

156-
stats, err := analyze(args, includeTests, diagnostic)
173+
stats, err := analyze(args, includeTests, enableDiagnostics)
157174
if err != nil {
158175
log.Fatal(err)
159176
}

gocognit.go

+15-12
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,15 @@ func ComplexityStats(f *ast.File, fset *token.FileSet, stats []Stat) []Stat {
7777
}
7878

7979
// ComplexityStatsWithDiagnostic builds the complexity statistics with diagnostic.
80-
func ComplexityStatsWithDiagnostic(f *ast.File, fset *token.FileSet, stats []Stat, enableDiagnostic bool) []Stat {
80+
func ComplexityStatsWithDiagnostic(f *ast.File, fset *token.FileSet, stats []Stat, enableDiagnostics bool) []Stat {
8181
for _, decl := range f.Decls {
8282
if fn, ok := decl.(*ast.FuncDecl); ok {
8383
d := parseDirective(fn.Doc)
8484
if d.Ignore {
8585
continue
8686
}
8787

88-
res := ScanComplexity(fn, enableDiagnostic)
88+
res := ScanComplexity(fn, enableDiagnostics)
8989

9090
stats = append(stats, Stat{
9191
PkgName: f.Name.Name,
@@ -101,7 +101,8 @@ func ComplexityStatsWithDiagnostic(f *ast.File, fset *token.FileSet, stats []Sta
101101
}
102102

103103
func generateDiagnostics(fset *token.FileSet, diags []diagnostic) []Diagnostic {
104-
tags := make([]Diagnostic, 0, len(diags))
104+
out := make([]Diagnostic, 0, len(diags))
105+
105106
for _, diag := range diags {
106107
pos := fset.Position(diag.Pos)
107108
tracePos := DiagnosticPosition{
@@ -110,15 +111,15 @@ func generateDiagnostics(fset *token.FileSet, diags []diagnostic) []Diagnostic {
110111
Column: pos.Column,
111112
}
112113

113-
tags = append(tags, Diagnostic{
114+
out = append(out, Diagnostic{
114115
Inc: diag.Inc,
115116
Nesting: diag.Nesting,
116117
Text: diag.Text,
117118
Pos: tracePos,
118119
})
119120
}
120121

121-
return tags
122+
return out
122123
}
123124

124125
type directive struct {
@@ -161,10 +162,10 @@ func Complexity(fn *ast.FuncDecl) int {
161162
}
162163

163164
// ScanComplexity scans the function declaration.
164-
func ScanComplexity(fn *ast.FuncDecl, includeDiagnostic bool) ScanResult {
165+
func ScanComplexity(fn *ast.FuncDecl, includeDiagnostics bool) ScanResult {
165166
v := complexityVisitor{
166-
name: fn.Name,
167-
diagnosticEnabled: includeDiagnostic,
167+
name: fn.Name,
168+
diagnosticsEnabled: includeDiagnostics,
168169
}
169170

170171
ast.Walk(&v, fn)
@@ -194,8 +195,8 @@ type complexityVisitor struct {
194195
elseNodes map[ast.Node]bool
195196
calculatedExprs map[ast.Expr]bool
196197

197-
diagnosticEnabled bool
198-
diagnostics []diagnostic
198+
diagnosticsEnabled bool
199+
diagnostics []diagnostic
199200
}
200201

201202
func (v *complexityVisitor) incNesting() {
@@ -209,7 +210,7 @@ func (v *complexityVisitor) decNesting() {
209210
func (v *complexityVisitor) incComplexity(text string, pos token.Pos) {
210211
v.complexity++
211212

212-
if !v.diagnosticEnabled {
213+
if !v.diagnosticsEnabled {
213214
return
214215
}
215216

@@ -223,7 +224,7 @@ func (v *complexityVisitor) incComplexity(text string, pos token.Pos) {
223224
func (v *complexityVisitor) nestIncComplexity(text string, pos token.Pos) {
224225
v.complexity += (v.nesting + 1)
225226

226-
if !v.diagnosticEnabled {
227+
if !v.diagnosticsEnabled {
227228
return
228229
}
229230

@@ -414,13 +415,15 @@ func (v *complexityVisitor) visitFuncLit(n *ast.FuncLit) ast.Visitor {
414415
v.incNesting()
415416
ast.Walk(v, n.Body)
416417
v.decNesting()
418+
417419
return nil
418420
}
419421

420422
func (v *complexityVisitor) visitBranchStmt(n *ast.BranchStmt) ast.Visitor {
421423
if n.Label != nil {
422424
v.incComplexity(n.Tok.String(), n.Pos())
423425
}
426+
424427
return v
425428
}
426429

0 commit comments

Comments
 (0)