mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 13:13:34 +00:00
cc: early returns are special
This commit is contained in:
parent
30f7651271
commit
bf4221c51a
2 changed files with 84 additions and 12 deletions
|
@ -9,7 +9,7 @@ use syntax::ast::Attribute;
|
|||
use syntax::attr;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use utils::{in_macro, LimitStack, span_help_and_lint};
|
||||
use utils::{in_macro, LimitStack, span_help_and_lint, paths, match_type};
|
||||
|
||||
/// **What it does:** This lint checks for methods with high cyclomatic complexity
|
||||
///
|
||||
|
@ -57,15 +57,26 @@ impl CyclomaticComplexity {
|
|||
match_arms: 0,
|
||||
divergence: 0,
|
||||
short_circuits: 0,
|
||||
returns: 0,
|
||||
tcx: &cx.tcx,
|
||||
};
|
||||
helper.visit_block(block);
|
||||
let CCHelper { match_arms, divergence, short_circuits, .. } = helper;
|
||||
|
||||
if cc + divergence < match_arms + short_circuits {
|
||||
report_cc_bug(cx, cc, match_arms, divergence, short_circuits, span);
|
||||
let CCHelper { match_arms, divergence, short_circuits, returns, .. } = helper;
|
||||
let ret_ty = cx.tcx.node_id_to_type(block.id);
|
||||
let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) {
|
||||
returns
|
||||
} else {
|
||||
let rust_cc = cc + divergence - match_arms - short_circuits;
|
||||
returns / 2
|
||||
};
|
||||
|
||||
if cc + divergence < match_arms + short_circuits {
|
||||
report_cc_bug(cx, cc, match_arms, divergence, short_circuits, ret_adjust, span);
|
||||
} else {
|
||||
let mut rust_cc = cc + divergence - match_arms - short_circuits;
|
||||
// prevent degenerate cases where unreachable code contains `return` statements
|
||||
if rust_cc >= ret_adjust {
|
||||
rust_cc -= ret_adjust;
|
||||
}
|
||||
if rust_cc > self.limit.limit() {
|
||||
span_help_and_lint(cx,
|
||||
CYCLOMATIC_COMPLEXITY,
|
||||
|
@ -109,6 +120,7 @@ impl LateLintPass for CyclomaticComplexity {
|
|||
struct CCHelper<'a, 'tcx: 'a> {
|
||||
match_arms: u64,
|
||||
divergence: u64,
|
||||
returns: u64,
|
||||
short_circuits: u64, // && and ||
|
||||
tcx: &'a ty::TyCtxt<'tcx>,
|
||||
}
|
||||
|
@ -142,31 +154,34 @@ impl<'a, 'b, 'tcx> Visitor<'a> for CCHelper<'b, 'tcx> {
|
|||
_ => (),
|
||||
}
|
||||
}
|
||||
ExprRet(_) => self.returns += 1,
|
||||
_ => walk_expr(self, e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="debugging")]
|
||||
fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, span: Span) {
|
||||
fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span) {
|
||||
span_bug!(span,
|
||||
"Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \
|
||||
div = {}, shorts = {}. Please file a bug report.",
|
||||
div = {}, shorts = {}, returns = {}. Please file a bug report.",
|
||||
cc,
|
||||
narms,
|
||||
div,
|
||||
shorts);
|
||||
shorts,
|
||||
returns);
|
||||
}
|
||||
#[cfg(not(feature="debugging"))]
|
||||
fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, span: Span) {
|
||||
fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span) {
|
||||
if cx.current_level(CYCLOMATIC_COMPLEXITY) != Level::Allow {
|
||||
cx.sess().span_note_without_error(span,
|
||||
&format!("Clippy encountered a bug calculating cyclomatic complexity \
|
||||
(hide this message with `#[allow(cyclomatic_complexity)]`): cc \
|
||||
= {}, arms = {}, div = {}, shorts = {}. Please file a bug report.",
|
||||
= {}, arms = {}, div = {}, shorts = {}, returns = {}. Please file a bug report.",
|
||||
cc,
|
||||
narms,
|
||||
div,
|
||||
shorts));
|
||||
shorts,
|
||||
returns));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -315,3 +315,60 @@ fn mcarton_sees_all() {
|
|||
panic!("meh");
|
||||
panic!("möh");
|
||||
}
|
||||
|
||||
#[cyclomatic_complexity = "0"]
|
||||
fn try() -> Result<i32, &'static str> { //~ ERROR: cyclomatic complexity of 1
|
||||
match 5 {
|
||||
5 => Ok(5),
|
||||
_ => return Err("bla"),
|
||||
}
|
||||
}
|
||||
|
||||
#[cyclomatic_complexity = "0"]
|
||||
fn try_again() -> Result<i32, &'static str> { //~ ERROR: cyclomatic complexity of 1
|
||||
let _ = try!(Ok(42));
|
||||
let _ = try!(Ok(43));
|
||||
let _ = try!(Ok(44));
|
||||
let _ = try!(Ok(45));
|
||||
let _ = try!(Ok(46));
|
||||
let _ = try!(Ok(47));
|
||||
let _ = try!(Ok(48));
|
||||
let _ = try!(Ok(49));
|
||||
match 5 {
|
||||
5 => Ok(5),
|
||||
_ => return Err("bla"),
|
||||
}
|
||||
}
|
||||
|
||||
#[cyclomatic_complexity = "0"]
|
||||
fn early() -> Result<i32, &'static str> { //~ ERROR: cyclomatic complexity of 1
|
||||
return Ok(5);
|
||||
return Ok(5);
|
||||
return Ok(5);
|
||||
return Ok(5);
|
||||
return Ok(5);
|
||||
return Ok(5);
|
||||
return Ok(5);
|
||||
return Ok(5);
|
||||
return Ok(5);
|
||||
}
|
||||
|
||||
#[cyclomatic_complexity = "0"]
|
||||
fn early_ret() -> i32 { //~ ERROR: cyclomatic complexity of 8
|
||||
let a = if true { 42 } else { return 0; };
|
||||
let a = if a < 99 { 42 } else { return 0; };
|
||||
let a = if a < 99 { 42 } else { return 0; };
|
||||
let a = if a < 99 { 42 } else { return 0; };
|
||||
let a = if a < 99 { 42 } else { return 0; };
|
||||
let a = if a < 99 { 42 } else { return 0; };
|
||||
let a = if a < 99 { 42 } else { return 0; };
|
||||
let a = if a < 99 { 42 } else { return 0; };
|
||||
let a = if a < 99 { 42 } else { return 0; };
|
||||
let a = if a < 99 { 42 } else { return 0; };
|
||||
let a = if a < 99 { 42 } else { return 0; };
|
||||
let a = if a < 99 { 42 } else { return 0; };
|
||||
match 5 {
|
||||
5 => 5,
|
||||
_ => return 6,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue