diff options
| author | sinkuu <sinkuupump@gmail.com> | 2016-09-06 18:03:47 +0900 |
|---|---|---|
| committer | sinkuu <sinkuupump@gmail.com> | 2016-09-09 19:56:34 +0900 |
| commit | bf078566d7aaf62f3dc9f9f6cc2a95c377e00a37 (patch) | |
| tree | b4c17aa98bf3ae183b134713e943fc1625b79c42 /src/patterns.rs | |
| parent | a5d7073bf51937508ba38c3745622ef31473c0e5 (diff) | |
Fix #1021: Handle `..` in tuple / tuple struct patterns
Diffstat (limited to 'src/patterns.rs')
| -rw-r--r-- | src/patterns.rs | 133 |
1 files changed, 93 insertions, 40 deletions
diff --git a/src/patterns.rs b/src/patterns.rs index c35dd25672d..b52eeb9c445 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -13,10 +13,14 @@ use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, format_mutability}; use lists::{format_item_list, itemize_list}; -use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; +use expr::{rewrite_unary_prefix, rewrite_pair}; use types::rewrite_path; +use super::Spanned; +use comment::FindUncommented; -use syntax::ast::{BindingMode, Pat, PatKind, FieldPat}; +use syntax::ast::{self, BindingMode, Pat, PatKind, FieldPat}; +use syntax::ptr; +use syntax::codemap::{self, BytePos, Span}; impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> { @@ -60,49 +64,19 @@ impl Rewrite for Pat { let prefix = format!("&{}", format_mutability(mutability)); rewrite_unary_prefix(context, &prefix, &**pat, width, offset) } - // FIXME(#1021): Handle `..` in tuple / tuple struct patterns (RFC 1492) PatKind::Tuple(ref items, dotdot_pos) => { - if dotdot_pos.is_some() { - return None; - } - rewrite_tuple(context, - items.iter().map(|x| &**x), - self.span, - width, - offset) + rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, width, offset) } PatKind::Path(ref path) => rewrite_path(context, true, None, path, width, offset), PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { let path_str = try_opt!(rewrite_path(context, true, None, path, width, offset)); - - // FIXME(#1021): Handle `..` in tuple / tuple struct patterns (RFC 1492) - match dotdot_pos { - Some(_) => Some(format!("{}(..)", path_str)), - None => { - if pat_vec.is_empty() { - Some(path_str) - } else { - // 2 = "()".len() - let width = try_opt!(width.checked_sub(path_str.len() + 2)); - // 1 = "(".len() - let offset = offset + path_str.len() + 1; - let items = itemize_list(context.codemap, - pat_vec.iter(), - ")", - |item| item.span.lo, - |item| item.span.hi, - |item| item.rewrite(context, width, offset), - context.codemap.span_after(self.span, "("), - self.span.hi); - Some(format!("{}({})", - path_str, - try_opt!(format_item_list(items, - width, - offset, - context.config)))) - } - } - } + rewrite_tuple_pat(pat_vec, + dotdot_pos, + Some(path_str), + self.span, + context, + width, + offset) } PatKind::Lit(ref expr) => expr.rewrite(context, width, offset), PatKind::Vec(ref prefix, ref slice_pat, ref suffix) => { @@ -190,3 +164,82 @@ impl Rewrite for FieldPat { } } } + + +enum TuplePatField<'a> { + Pat(&'a ptr::P<ast::Pat>), + Dotdot(Span), +} + +impl<'a> Rewrite for TuplePatField<'a> { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> { + match *self { + TuplePatField::Pat(ref p) => p.rewrite(context, width, offset), + TuplePatField::Dotdot(_) => Some("..".to_string()), + } + } +} + +impl<'a> Spanned for TuplePatField<'a> { + fn span(&self) -> Span { + match *self { + TuplePatField::Pat(ref p) => p.span(), + TuplePatField::Dotdot(span) => span, + } + } +} + +fn rewrite_tuple_pat(pats: &[ptr::P<ast::Pat>], + dotdot_pos: Option<usize>, + path_str: Option<String>, + span: Span, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option<String> { + let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect(); + + if let Some(pos) = dotdot_pos { + let snippet = context.snippet(span); + let lo = span.lo + BytePos(snippet.find_uncommented("..").unwrap() as u32); + let span = Span { + lo: lo, + // 2 == "..".len() + hi: lo + BytePos(2), + expn_id: codemap::NO_EXPANSION, + }; + let dotdot = TuplePatField::Dotdot(span); + pat_vec.insert(pos, dotdot); + } + + if pat_vec.is_empty() { + path_str + } else { + // add comma if `(x,)` + let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); + + let path_len = path_str.as_ref().map(|p| p.len()).unwrap_or(0); + // 2 = "()".len(), 3 = "(,)".len() + let width = try_opt!(width.checked_sub(path_len + if add_comma { 3 } else { 2 })); + // 1 = "(".len() + let offset = offset + path_len + 1; + let items = itemize_list(context.codemap, + pat_vec.iter(), + if add_comma { ",)" } else { ")" }, + |item| item.span().lo, + |item| item.span().hi, + |item| item.rewrite(context, width, offset), + context.codemap.span_after(span, "("), + span.hi - BytePos(1)); + + let list = try_opt!(format_item_list(items, width, offset, context.config)); + + match path_str { + Some(path_str) => Some(format!("{}({})", path_str, list)), + None => { + let comma = if add_comma { "," } else { "" }; + Some(format!("({}{})", list, comma)) + } + } + } +} |
