X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmatches.rs;h=85d9c5d2b9bbf4f3e80ec3371cc733d9dea157ea;hb=ce301d92f12658edf6fe410d39de445270d1420e;hp=2e2c547761685029f08709a0b080a658992fedf4;hpb=cc97eaf9f9181aec5a1ba6459b204ed4a7fba62a;p=rust.git diff --git a/src/matches.rs b/src/matches.rs index 2e2c5477616..85d9c5d2b9b 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -2,15 +2,15 @@ use std::iter::repeat; -use syntax::source_map::{BytePos, Span}; -use syntax::{ast, ptr}; +use rustc_ast::{ast, ptr}; +use rustc_span::{BytePos, Span}; use crate::comment::{combine_strs_with_missing_comments, rewrite_comment}; use crate::config::lists::*; -use crate::config::{Config, ControlBraceStyle, IndentStyle, Version}; +use crate::config::{Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe, Version}; use crate::expr::{ format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond, - rewrite_multiple_patterns, ExprType, RhsTactics, + ExprType, RhsTactics, }; use crate::lists::{itemize_list, write_list, ListFormatting}; use crate::rewrite::{Rewrite, RewriteContext}; @@ -19,7 +19,7 @@ use crate::spanned::Spanned; use crate::utils::{ contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp, - ptr_vec_to_ref_vec, semicolon_for_expr, trimmed_last_line_width, + semicolon_for_expr, trimmed_last_line_width, unicode_str_width, }; /// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. @@ -45,6 +45,7 @@ fn new(arm: &'a ast::Arm, is_last: bool, beginning_vert: Option) -> Arm impl<'a> Spanned for ArmWrapper<'a> { fn span(&self) -> Span { if let Some(lo) = self.beginning_vert { + let lo = std::cmp::min(lo, self.arm.span().lo()); mk_sp(lo, self.arm.span().hi()) } else { self.arm.span() @@ -54,7 +55,13 @@ fn span(&self) -> Span { impl<'a> Rewrite for ArmWrapper<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - rewrite_match_arm(context, self.arm, shape, self.is_last) + rewrite_match_arm( + context, + self.arm, + shape, + self.is_last, + self.beginning_vert.is_some(), + ) } } @@ -111,7 +118,7 @@ pub(crate) fn rewrite_match( .snippet_provider .span_after(mk_sp(cond.span.hi(), hi), "{") } else { - inner_attrs[inner_attrs.len() - 1].span().hi() + inner_attrs[inner_attrs.len() - 1].span.hi() }; if arms.is_empty() { @@ -141,7 +148,7 @@ fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { "" } else if config.match_block_trailing_comma() { "," - } else if let ast::ExprKind::Block(ref block, _) = body.node { + } else if let ast::ExprKind::Block(ref block, _) = body.kind { if let ast::BlockCheckMode::Default = block.rules { "" } else { @@ -156,17 +163,15 @@ fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { fn collect_beginning_verts( context: &RewriteContext<'_>, arms: &[ast::Arm], - span: Span, ) -> Vec> { - let mut beginning_verts = Vec::with_capacity(arms.len()); - let mut lo = context.snippet_provider.span_after(span, "{"); - for arm in arms { - let hi = arm.pats[0].span.lo(); - let missing_span = mk_sp(lo, hi); - beginning_verts.push(context.snippet_provider.opt_span_before(missing_span, "|")); - lo = arm.span().hi(); - } - beginning_verts + arms.iter() + .map(|a| { + context + .snippet(a.pat.span) + .starts_with('|') + .then(|| a.pat.span().lo()) + }) + .collect() } fn rewrite_match_arms( @@ -184,7 +189,7 @@ fn rewrite_match_arms( let is_last_iter = repeat(false) .take(arm_len.saturating_sub(1)) .chain(repeat(true)); - let beginning_verts = collect_beginning_verts(context, arms, span); + let beginning_verts = collect_beginning_verts(context, arms); let items = itemize_list( context.snippet_provider, arms.iter() @@ -214,6 +219,7 @@ fn rewrite_match_arm( arm: &ast::Arm, shape: Shape, is_last: bool, + has_leading_pipe: bool, ) -> Option { let (missing_span, attrs_str) = if !arm.attrs.is_empty() { if contains_skip(&arm.attrs) { @@ -225,19 +231,24 @@ fn rewrite_match_arm( arm_comma(context.config, body, is_last), )); } - let missing_span = mk_sp( - arm.attrs[arm.attrs.len() - 1].span.hi(), - arm.pats[0].span.lo(), - ); + let missing_span = mk_sp(arm.attrs[arm.attrs.len() - 1].span.hi(), arm.pat.span.lo()); (missing_span, arm.attrs.rewrite(context, shape)?) } else { (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) }; + // Leading pipe offset + // 2 = `| ` + let (pipe_offset, pipe_str) = match context.config.match_arm_leading_pipes() { + MatchArmLeadingPipe::Never => (0, ""), + MatchArmLeadingPipe::Preserve if !has_leading_pipe => (0, ""), + MatchArmLeadingPipe::Preserve | MatchArmLeadingPipe::Always => (2, "| "), + }; + // Patterns // 5 = ` => {` - let pat_shape = shape.sub_width(5)?; - let pats_str = rewrite_multiple_patterns(context, &ptr_vec_to_ref_vec(&arm.pats), pat_shape)?; + let pat_shape = shape.sub_width(5)?.offset_left(pipe_offset)?; + let pats_str = arm.pat.rewrite(context, pat_shape)?; // Guard let block_like_pat = trimmed_last_line_width(&pats_str) <= context.config.tab_spaces(); @@ -253,13 +264,13 @@ fn rewrite_match_arm( let lhs_str = combine_strs_with_missing_comments( context, &attrs_str, - &format!("{}{}", pats_str, guard_str), + &format!("{}{}{}", pipe_str, pats_str, guard_str), missing_span, shape, false, )?; - let arrow_span = mk_sp(arm.pats.last().unwrap().span.hi(), arm.body.span().lo()); + let arrow_span = mk_sp(arm.pat.span.hi(), arm.body.span().lo()); rewrite_match_body( context, &arm.body, @@ -271,14 +282,25 @@ fn rewrite_match_arm( ) } +fn stmt_is_expr_mac(stmt: &ast::Stmt) -> bool { + if let ast::StmtKind::Expr(expr) = &stmt.kind { + if let ast::ExprKind::MacCall(_) = &expr.kind { + return true; + } + } + false +} + fn block_can_be_flattened<'a>( context: &RewriteContext<'_>, expr: &'a ast::Expr, ) -> Option<&'a ast::Block> { - match expr.node { + match expr.kind { ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) - && is_simple_block(block, Some(&expr.attrs), context.source_map) => + && !context.inside_macro() + && is_simple_block(context, block, Some(&expr.attrs)) + && !stmt_is_expr_mac(&block.stmts[0]) => { Some(&*block) } @@ -297,10 +319,14 @@ fn flatten_arm_body<'a>( let can_extend = |expr| !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr); - if let Some(ref block) = block_can_be_flattened(context, body) { - if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { - if let ast::ExprKind::Block(..) = expr.node { - flatten_arm_body(context, expr, None) + if let Some(block) = block_can_be_flattened(context, body) { + if let ast::StmtKind::Expr(ref expr) = block.stmts[0].kind { + if let ast::ExprKind::Block(..) = expr.kind { + if expr.attrs.is_empty() { + flatten_arm_body(context, expr, None) + } else { + (true, body) + } } else { let cond_becomes_muti_line = opt_shape .and_then(|shape| rewrite_cond(context, expr, shape)) @@ -333,11 +359,8 @@ fn rewrite_match_body( body, shape.offset_left(extra_offset(pats_str, shape) + 4), ); - let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block, _) = body.node { - ( - true, - is_empty_block(block, Some(&body.attrs), context.source_map), - ) + let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block, _) = body.kind { + (true, is_empty_block(context, block, Some(&body.attrs))) } else { (false, false) }; @@ -374,7 +397,7 @@ fn rewrite_match_body( if comment_str.is_empty() { String::new() } else { - rewrite_comment(comment_str, false, shape, &context.config)? + rewrite_comment(comment_str, false, shape, context.config)? } }; @@ -389,30 +412,32 @@ fn rewrite_match_body( result.push_str(&arrow_comment); } result.push_str(&nested_indent_str); - result.push_str(&body_str); + result.push_str(body_str); + result.push_str(comma); return Some(result); } let indent_str = shape.indent.to_string_with_newline(context.config); - let (body_prefix, body_suffix) = if context.config.match_arm_blocks() { - let comma = if context.config.match_block_trailing_comma() { - "," - } else { - "" - }; - let semicolon = if context.config.version() == Version::One { - "" - } else { - if semicolon_for_expr(context, body) { - ";" + let (body_prefix, body_suffix) = + if context.config.match_arm_blocks() && !context.inside_macro() { + let comma = if context.config.match_block_trailing_comma() { + "," } else { "" - } + }; + let semicolon = if context.config.version() == Version::One { + "" + } else { + if semicolon_for_expr(context, body) { + ";" + } else { + "" + } + }; + ("{", format!("{}{}}}{}", semicolon, indent_str, comma)) + } else { + ("", String::from(",")) }; - ("{", format!("{}{}}}{}", semicolon, indent_str, comma)) - } else { - ("", String::from(",")) - }; let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine => format!("{}{}", alt_block_sep, body_prefix), @@ -430,7 +455,7 @@ fn rewrite_match_body( result.push_str(&arrow_comment); } result.push_str(&block_sep); - result.push_str(&body_str); + result.push_str(body_str); result.push_str(&body_suffix); Some(result) }; @@ -450,7 +475,9 @@ fn rewrite_match_body( match rewrite { Some(ref body_str) - if is_block || (!body_str.contains('\n') && body_str.len() <= body_shape.width) => + if is_block + || (!body_str.contains('\n') + && unicode_str_width(body_str) <= body_shape.width) => { return combine_orig_body(body_str); } @@ -485,18 +512,10 @@ fn rewrite_match_body( } } -impl Rewrite for ast::Guard { - fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - match self { - ast::Guard::If(ref expr) => expr.rewrite(context, shape), - } - } -} - // The `if ...` guard on a match arm. fn rewrite_guard( context: &RewriteContext<'_>, - guard: &Option, + guard: &Option>, shape: Shape, // The amount of space used up on this line for the pattern in // the arm (excludes offset). @@ -555,15 +574,13 @@ fn nop_block_collapse(block_str: Option, budget: usize) -> Option bool { - match body.node { + match body.kind { // We do not allow `if` to stay on the same line, since we could easily mistake // `pat => if cond { ... }` and `pat if cond => { ... }`. - ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => false, + ast::ExprKind::If(..) => false, // We do not allow collapsing a block around expression with condition // to avoid it being cluttered with match arm. - ast::ExprKind::ForLoop(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) => { - false - } + ast::ExprKind::ForLoop(..) | ast::ExprKind::While(..) => false, ast::ExprKind::Loop(..) | ast::ExprKind::Match(..) | ast::ExprKind::Block(..) @@ -571,13 +588,14 @@ fn can_flatten_block_around_this(body: &ast::Expr) -> bool { | ast::ExprKind::Array(..) | ast::ExprKind::Call(..) | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Mac(..) + | ast::ExprKind::MacCall(..) | ast::ExprKind::Struct(..) | ast::ExprKind::Tup(..) => true, - ast::ExprKind::AddrOf(_, ref expr) + ast::ExprKind::AddrOf(_, _, ref expr) | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Index(ref expr, _) | ast::ExprKind::Cast(ref expr, _) => can_flatten_block_around_this(expr), _ => false, }