This commit is contained in:
Andre Bogus 2015-10-14 11:44:09 +02:00
commit b3d035d252
2 changed files with 32 additions and 26 deletions

View File

@ -174,25 +174,31 @@ impl LateLintPass for LoopsPass {
the loop body."); the loop body.");
} }
// extract the first statement (if any) in a block // extract the expression from the first statement (if any) in a block
let inner_stmt = extract_expr_from_first_stmt(block); let inner_stmt_expr = extract_expr_from_first_stmt(block);
// extract a single expression // extract the first expression (if any) from the block
let inner_expr = extract_first_expr(block); let inner_expr = extract_first_expr(block);
let extracted = match inner_stmt { let (extracted, collect_expr) = match inner_stmt_expr {
Some(_) => inner_stmt, Some(_) => (inner_stmt_expr, true), // check if an expression exists in the first statement
None => inner_expr, None => (inner_expr, false), // if not, let's go for the first expression in the block
}; };
if let Some(inner) = extracted { if let Some(inner) = extracted {
// collect remaining expressions below the match if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node {
let other_stuff = block.stmts // collect the remaining statements below the match
let mut other_stuff = block.stmts
.iter() .iter()
.skip(1) .skip(1)
.map(|stmt| { .map(|stmt| {
format!("{}", snippet(cx, stmt.span, "..")) format!("{}", snippet(cx, stmt.span, ".."))
}).collect::<Vec<String>>(); }).collect::<Vec<String>>();
if collect_expr { // if we have a statement which has a match,
match block.expr { // then collect the expression (without semicolon) below it
Some(ref expr) => other_stuff.push(format!("{}", snippet(cx, expr.span, ".."))),
None => (),
}
}
if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node {
// ensure "if let" compatible match structure // ensure "if let" compatible match structure
match *source { match *source {
MatchSource::Normal | MatchSource::IfLetDesugar{..} => if MatchSource::Normal | MatchSource::IfLetDesugar{..} => if
@ -203,7 +209,7 @@ impl LateLintPass for LoopsPass {
is_break_expr(&arms[1].body) is_break_expr(&arms[1].body)
{ {
if in_external_macro(cx, expr.span) { return; } if in_external_macro(cx, expr.span) { return; }
let loop_body = match inner_stmt { let loop_body = match inner_stmt_expr {
// FIXME: should probably be an ellipsis // FIXME: should probably be an ellipsis
// tabbing and newline is probably a bad idea, especially for large blocks // tabbing and newline is probably a bad idea, especially for large blocks
Some(_) => Cow::Owned(format!("{{\n {}\n}}", other_stuff.join("\n "))), Some(_) => Cow::Owned(format!("{{\n {}\n}}", other_stuff.join("\n "))),
@ -321,20 +327,12 @@ fn is_iterable_array(ty: ty::Ty) -> bool {
/// If a block begins with a statement (possibly a `let` binding) and has an expression, return it. /// If a block begins with a statement (possibly a `let` binding) and has an expression, return it.
fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> { fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> {
match block.expr { if block.stmts.is_empty() { return None; }
Some(_) => None, if let StmtDecl(ref decl, _) = block.stmts[0].node {
None if !block.stmts.is_empty() => match block.stmts[0].node { if let DeclLocal(ref local) = decl.node {
StmtDecl(ref decl, _) => match decl.node { if let Some(ref expr) = local.init { Some(expr) } else { None }
DeclLocal(ref local) => match local.init { } else { None }
Some(ref expr) => Some(expr), } else { None }
None => None,
},
_ => None,
},
_ => None,
},
_ => None,
}
} }
/// If a block begins with an expression (with or without semicolon), return it. /// If a block begins with an expression (with or without semicolon), return it.

View File

@ -33,6 +33,14 @@ fn main() {
let _x = x; let _x = x;
let _str = "foo"; let _str = "foo";
} }
loop { //~ERROR
let x = match y {
Some(x) => x,
None => break,
};
{ let _a = "bar"; };
{ let _b = "foobar"; }
}
loop { // no error, else branch does something other than break loop { // no error, else branch does something other than break
match y { match y {
Some(_x) => true, Some(_x) => true,
@ -53,7 +61,7 @@ fn main() {
// cause this function to trigger it // cause this function to trigger it
fn no_panic<T>(slice: &[T]) { fn no_panic<T>(slice: &[T]) {
let mut iter = slice.iter(); let mut iter = slice.iter();
loop { loop { //~ERROR
let _ = match iter.next() { let _ = match iter.next() {
Some(ele) => ele, Some(ele) => ele,
None => break None => break