Skip to content

Commit 7b670a9

Browse files
committed
Auto merge of #4935 - krishna-veerareddy:issue-4241-cognitive-complexity-lint-span, r=phansch
Reduce cognitive complexity lint span Currently the cognitive complexity lint spans the entire function body making it really difficult to read and refactor the code in editors. To fix this we reduce the lint span to the function name. changelog: Reduce cognitive complexity lint span Fixes #4241
2 parents cfb3320 + 91a491e commit 7b670a9

File tree

4 files changed

+125
-150
lines changed

4 files changed

+125
-150
lines changed

clippy_lints/src/cognitive_complexity.rs

+39-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
//! calculate cognitive complexity and warn about overly complex functions
22
3-
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
3+
use rustc::hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor};
44
use rustc::hir::*;
55
use rustc::impl_lint_pass;
66
use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
77
use rustc_session::declare_tool_lint;
88
use syntax::ast::Attribute;
99
use syntax::source_map::Span;
10+
use syntax_pos::BytePos;
1011

11-
use crate::utils::{match_type, paths, span_help_and_lint, LimitStack};
12+
use crate::utils::{match_type, paths, snippet_opt, span_help_and_lint, LimitStack};
1213

1314
declare_clippy_lint! {
1415
/// **What it does:** Checks for methods with high cognitive complexity.
@@ -41,8 +42,16 @@ impl CognitiveComplexity {
4142
impl_lint_pass!(CognitiveComplexity => [COGNITIVE_COMPLEXITY]);
4243

4344
impl CognitiveComplexity {
44-
fn check<'a, 'tcx>(&mut self, cx: &'a LateContext<'a, 'tcx>, body: &'tcx Body, span: Span) {
45-
if span.from_expansion() {
45+
#[allow(clippy::cast_possible_truncation)]
46+
fn check<'a, 'tcx>(
47+
&mut self,
48+
cx: &'a LateContext<'a, 'tcx>,
49+
kind: FnKind<'tcx>,
50+
decl: &'tcx FnDecl,
51+
body: &'tcx Body,
52+
body_span: Span,
53+
) {
54+
if body_span.from_expansion() {
4655
return;
4756
}
4857

@@ -64,11 +73,33 @@ impl CognitiveComplexity {
6473
if rust_cc >= ret_adjust {
6574
rust_cc -= ret_adjust;
6675
}
76+
6777
if rust_cc > self.limit.limit() {
78+
let fn_span = match kind {
79+
FnKind::ItemFn(ident, _, _, _, _) | FnKind::Method(ident, _, _, _) => ident.span,
80+
FnKind::Closure(_) => {
81+
let header_span = body_span.with_hi(decl.output.span().lo());
82+
let pos = snippet_opt(cx, header_span).and_then(|snip| {
83+
let low_offset = snip.find('|')?;
84+
let high_offset = 1 + snip.get(low_offset + 1..)?.find('|')?;
85+
let low = header_span.lo() + BytePos(low_offset as u32);
86+
let high = low + BytePos(high_offset as u32 + 1);
87+
88+
Some((low, high))
89+
});
90+
91+
if let Some((low, high)) = pos {
92+
Span::new(low, high, header_span.ctxt())
93+
} else {
94+
return;
95+
}
96+
},
97+
};
98+
6899
span_help_and_lint(
69100
cx,
70101
COGNITIVE_COMPLEXITY,
71-
span,
102+
fn_span,
72103
&format!(
73104
"the function has a cognitive complexity of ({}/{})",
74105
rust_cc,
@@ -84,15 +115,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CognitiveComplexity {
84115
fn check_fn(
85116
&mut self,
86117
cx: &LateContext<'a, 'tcx>,
87-
_: intravisit::FnKind<'tcx>,
88-
_: &'tcx FnDecl,
118+
kind: FnKind<'tcx>,
119+
decl: &'tcx FnDecl,
89120
body: &'tcx Body,
90121
span: Span,
91122
hir_id: HirId,
92123
) {
93124
let def_id = cx.tcx.hir().local_def_id(hir_id);
94125
if !cx.tcx.has_attr(def_id, sym!(test)) {
95-
self.check(cx, body, span);
126+
self.check(cx, kind, decl, body, span);
96127
}
97128
}
98129

tests/ui/cognitive_complexity.rs

+22
Original file line numberDiff line numberDiff line change
@@ -371,3 +371,25 @@ fn early_ret() -> i32 {
371371
_ => return 6,
372372
}
373373
}
374+
375+
#[clippy::cognitive_complexity = "1"]
376+
fn closures() {
377+
let x = |a: i32, b: i32| -> i32 {
378+
if true {
379+
println!("moo");
380+
}
381+
382+
a + b
383+
};
384+
}
385+
386+
struct Moo;
387+
388+
#[clippy::cognitive_complexity = "1"]
389+
impl Moo {
390+
fn moo(&self) {
391+
if true {
392+
println!("moo");
393+
}
394+
}
395+
}

tests/ui/cognitive_complexity.stderr

+61-133
Original file line numberDiff line numberDiff line change
@@ -1,211 +1,139 @@
11
error: the function has a cognitive complexity of (28/25)
2-
--> $DIR/cognitive_complexity.rs:6:1
2+
--> $DIR/cognitive_complexity.rs:6:4
33
|
4-
LL | / fn main() {
5-
LL | | if true {
6-
LL | | println!("a");
7-
LL | | }
8-
... |
9-
LL | | }
10-
LL | | }
11-
| |_^
4+
LL | fn main() {
5+
| ^^^^
126
|
137
= note: `-D clippy::cognitive-complexity` implied by `-D warnings`
148
= help: you could split it up into multiple smaller functions
159

1610
error: the function has a cognitive complexity of (7/1)
17-
--> $DIR/cognitive_complexity.rs:91:1
11+
--> $DIR/cognitive_complexity.rs:91:4
1812
|
19-
LL | / fn kaboom() {
20-
LL | | let n = 0;
21-
LL | | 'a: for i in 0..20 {
22-
LL | | 'b: for j in i..20 {
23-
... |
24-
LL | | }
25-
LL | | }
26-
| |_^
13+
LL | fn kaboom() {
14+
| ^^^^^^
2715
|
2816
= help: you could split it up into multiple smaller functions
2917

3018
error: the function has a cognitive complexity of (2/1)
31-
--> $DIR/cognitive_complexity.rs:149:1
19+
--> $DIR/cognitive_complexity.rs:149:4
3220
|
33-
LL | / fn baa() {
34-
LL | | let x = || match 99 {
35-
LL | | 0 => 0,
36-
LL | | 1 => 1,
37-
... |
38-
LL | | }
39-
LL | | }
40-
| |_^
21+
LL | fn baa() {
22+
| ^^^
4123
|
4224
= help: you could split it up into multiple smaller functions
4325

4426
error: the function has a cognitive complexity of (2/1)
4527
--> $DIR/cognitive_complexity.rs:150:13
4628
|
47-
LL | let x = || match 99 {
48-
| _____________^
49-
LL | | 0 => 0,
50-
LL | | 1 => 1,
51-
LL | | 2 => 2,
52-
... |
53-
LL | | _ => 42,
54-
LL | | };
55-
| |_____^
29+
LL | let x = || match 99 {
30+
| ^^
5631
|
5732
= help: you could split it up into multiple smaller functions
5833

5934
error: the function has a cognitive complexity of (2/1)
60-
--> $DIR/cognitive_complexity.rs:167:1
35+
--> $DIR/cognitive_complexity.rs:167:4
6136
|
62-
LL | / fn bar() {
63-
LL | | match 99 {
64-
LL | | 0 => println!("hi"),
65-
LL | | _ => println!("bye"),
66-
LL | | }
67-
LL | | }
68-
| |_^
37+
LL | fn bar() {
38+
| ^^^
6939
|
7040
= help: you could split it up into multiple smaller functions
7141

7242
error: the function has a cognitive complexity of (2/1)
73-
--> $DIR/cognitive_complexity.rs:186:1
43+
--> $DIR/cognitive_complexity.rs:186:4
7444
|
75-
LL | / fn barr() {
76-
LL | | match 99 {
77-
LL | | 0 => println!("hi"),
78-
LL | | 1 => println!("bla"),
79-
... |
80-
LL | | }
81-
LL | | }
82-
| |_^
45+
LL | fn barr() {
46+
| ^^^^
8347
|
8448
= help: you could split it up into multiple smaller functions
8549

8650
error: the function has a cognitive complexity of (3/1)
87-
--> $DIR/cognitive_complexity.rs:196:1
51+
--> $DIR/cognitive_complexity.rs:196:4
8852
|
89-
LL | / fn barr2() {
90-
LL | | match 99 {
91-
LL | | 0 => println!("hi"),
92-
LL | | 1 => println!("bla"),
93-
... |
94-
LL | | }
95-
LL | | }
96-
| |_^
53+
LL | fn barr2() {
54+
| ^^^^^
9755
|
9856
= help: you could split it up into multiple smaller functions
9957

10058
error: the function has a cognitive complexity of (2/1)
101-
--> $DIR/cognitive_complexity.rs:212:1
59+
--> $DIR/cognitive_complexity.rs:212:4
10260
|
103-
LL | / fn barrr() {
104-
LL | | match 99 {
105-
LL | | 0 => println!("hi"),
106-
LL | | 1 => panic!("bla"),
107-
... |
108-
LL | | }
109-
LL | | }
110-
| |_^
61+
LL | fn barrr() {
62+
| ^^^^^
11163
|
11264
= help: you could split it up into multiple smaller functions
11365

11466
error: the function has a cognitive complexity of (3/1)
115-
--> $DIR/cognitive_complexity.rs:222:1
67+
--> $DIR/cognitive_complexity.rs:222:4
11668
|
117-
LL | / fn barrr2() {
118-
LL | | match 99 {
119-
LL | | 0 => println!("hi"),
120-
LL | | 1 => panic!("bla"),
121-
... |
122-
LL | | }
123-
LL | | }
124-
| |_^
69+
LL | fn barrr2() {
70+
| ^^^^^^
12571
|
12672
= help: you could split it up into multiple smaller functions
12773

12874
error: the function has a cognitive complexity of (2/1)
129-
--> $DIR/cognitive_complexity.rs:238:1
75+
--> $DIR/cognitive_complexity.rs:238:4
13076
|
131-
LL | / fn barrrr() {
132-
LL | | match 99 {
133-
LL | | 0 => println!("hi"),
134-
LL | | 1 => println!("bla"),
135-
... |
136-
LL | | }
137-
LL | | }
138-
| |_^
77+
LL | fn barrrr() {
78+
| ^^^^^^
13979
|
14080
= help: you could split it up into multiple smaller functions
14181

14282
error: the function has a cognitive complexity of (3/1)
143-
--> $DIR/cognitive_complexity.rs:248:1
83+
--> $DIR/cognitive_complexity.rs:248:4
14484
|
145-
LL | / fn barrrr2() {
146-
LL | | match 99 {
147-
LL | | 0 => println!("hi"),
148-
LL | | 1 => println!("bla"),
149-
... |
150-
LL | | }
151-
LL | | }
152-
| |_^
85+
LL | fn barrrr2() {
86+
| ^^^^^^^
15387
|
15488
= help: you could split it up into multiple smaller functions
15589

15690
error: the function has a cognitive complexity of (2/1)
157-
--> $DIR/cognitive_complexity.rs:264:1
91+
--> $DIR/cognitive_complexity.rs:264:4
15892
|
159-
LL | / fn cake() {
160-
LL | | if 4 == 5 {
161-
LL | | println!("yea");
162-
LL | | } else {
163-
... |
164-
LL | | println!("whee");
165-
LL | | }
166-
| |_^
93+
LL | fn cake() {
94+
| ^^^^
16795
|
16896
= help: you could split it up into multiple smaller functions
16997

17098
error: the function has a cognitive complexity of (4/1)
171-
--> $DIR/cognitive_complexity.rs:274:1
99+
--> $DIR/cognitive_complexity.rs:274:8
172100
|
173-
LL | / pub fn read_file(input_path: &str) -> String {
174-
LL | | use std::fs::File;
175-
LL | | use std::io::{Read, Write};
176-
LL | | use std::path::Path;
177-
... |
178-
LL | | }
179-
LL | | }
180-
| |_^
101+
LL | pub fn read_file(input_path: &str) -> String {
102+
| ^^^^^^^^^
181103
|
182104
= help: you could split it up into multiple smaller functions
183105

184106
error: the function has a cognitive complexity of (2/1)
185-
--> $DIR/cognitive_complexity.rs:305:1
107+
--> $DIR/cognitive_complexity.rs:305:4
186108
|
187-
LL | / fn void(void: Void) {
188-
LL | | if true {
189-
LL | | match void {}
190-
LL | | }
191-
LL | | }
192-
| |_^
109+
LL | fn void(void: Void) {
110+
| ^^^^
193111
|
194112
= help: you could split it up into multiple smaller functions
195113

196114
error: the function has a cognitive complexity of (8/1)
197-
--> $DIR/cognitive_complexity.rs:356:1
115+
--> $DIR/cognitive_complexity.rs:356:4
198116
|
199-
LL | / fn early_ret() -> i32 {
200-
LL | | let a = if true { 42 } else { return 0; };
201-
LL | | let a = if a < 99 { 42 } else { return 0; };
202-
LL | | let a = if a < 99 { 42 } else { return 0; };
203-
... |
204-
LL | | }
205-
LL | | }
206-
| |_^
117+
LL | fn early_ret() -> i32 {
118+
| ^^^^^^^^^
207119
|
208120
= help: you could split it up into multiple smaller functions
209121

210-
error: aborting due to 15 previous errors
122+
error: the function has a cognitive complexity of (2/1)
123+
--> $DIR/cognitive_complexity.rs:377:13
124+
|
125+
LL | let x = |a: i32, b: i32| -> i32 {
126+
| ^^^^^^^^^^^^^^^^
127+
|
128+
= help: you could split it up into multiple smaller functions
129+
130+
error: the function has a cognitive complexity of (2/1)
131+
--> $DIR/cognitive_complexity.rs:390:8
132+
|
133+
LL | fn moo(&self) {
134+
| ^^^
135+
|
136+
= help: you could split it up into multiple smaller functions
137+
138+
error: aborting due to 17 previous errors
211139

0 commit comments

Comments
 (0)