diff --git a/src/imports.rs b/src/imports.rs index 42d152fc6ac..70351ca8d79 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -51,7 +51,7 @@ impl Rewrite for ast::ViewPath { } fn rewrite_single_use_list(path_str: String, vpi: &ast::PathListItem) -> String { - let path_item_str = if let ast::PathListItem_::PathListIdent{ name, .. } = vpi.node { + let path_item_str = if let ast::PathListItem_::PathListIdent { name, .. } = vpi.node { // A name. if path_str.is_empty() { name.to_string() @@ -74,8 +74,8 @@ fn rewrite_single_use_list(path_str: String, vpi: &ast::PathListItem) -> String fn rewrite_path_item(vpi: &&ast::PathListItem) -> Option { let path_item_str = match vpi.node { - ast::PathListItem_::PathListIdent{ name, .. } => name.to_string(), - ast::PathListItem_::PathListMod{ .. } => "self".to_owned(), + ast::PathListItem_::PathListIdent { name, .. } => name.to_string(), + ast::PathListItem_::PathListMod { .. } => "self".to_owned(), }; Some(append_alias(path_item_str, vpi)) @@ -83,8 +83,8 @@ fn rewrite_path_item(vpi: &&ast::PathListItem) -> Option { fn append_alias(path_item_str: String, vpi: &ast::PathListItem) -> String { match vpi.node { - ast::PathListItem_::PathListIdent{ rename: Some(rename), .. } | - ast::PathListItem_::PathListMod{ rename: Some(rename), .. } => { + ast::PathListItem_::PathListIdent { rename: Some(rename), .. } | + ast::PathListItem_::PathListMod { rename: Some(rename), .. } => { format!("{} as {}", path_item_str, rename) } _ => path_item_str, diff --git a/src/patterns.rs b/src/patterns.rs index fdc418733fb..a5f09823212 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -15,20 +15,32 @@ use lists::{format_item_list, itemize_list}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; use types::rewrite_path; -use syntax::ast::{BindingMode, Pat, Pat_}; +use syntax::ast::{BindingMode, Pat, Pat_, FieldPat}; -// FIXME(#18): implement pattern formatting. impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match self.node { Pat_::PatBox(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, width, offset), - Pat_::PatIdent(binding_mode, ident, None) => { + Pat_::PatIdent(binding_mode, ident, ref sub_pat) => { let (prefix, mutability) = match binding_mode { BindingMode::BindByRef(mutability) => ("ref ", mutability), BindingMode::BindByValue(mutability) => ("", mutability), }; let mut_infix = format_mutability(mutability); - let result = format!("{}{}{}", prefix, mut_infix, ident.node); + let id_str = ident.node.to_string(); + + let sub_pat = match *sub_pat { + Some(ref p) => { + // 3 - ` @ `. + let width = try_opt!(width.checked_sub(prefix.len() + mut_infix.len() + + id_str.len() + + 3)); + format!(" @ {}", try_opt!(p.rewrite(context, width, offset))) + } + None => "".to_owned(), + }; + + let result = format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat); wrap_str(result, context.config.max_width, width, offset) } Pat_::PatWild => { @@ -55,39 +67,106 @@ impl Rewrite for Pat { width, offset) } - Pat_::PatEnum(ref path, Some(ref pat_vec)) => { - let path_str = try_opt!(::types::rewrite_path(context, - true, - None, - path, - width, - offset)); + Pat_::PatEnum(ref path, ref pat_vec) => { + let path_str = try_opt!(rewrite_path(context, true, None, path, width, offset)); - if pat_vec.is_empty() { - Some(path_str) - } else { - // 1 = ( - let width = try_opt!(width.checked_sub(path_str.len() + 1)); - 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), - span_after(self.span, "(", context.codemap), - self.span.hi); - Some(format!("{}({})", - path_str, - try_opt!(format_item_list(items, width, offset, context.config)))) + match *pat_vec { + Some(ref pat_vec) => { + if pat_vec.is_empty() { + Some(path_str) + } else { + // 1 = ( + let width = try_opt!(width.checked_sub(path_str.len() + 1)); + 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), + span_after(self.span, "(", context.codemap), + self.span.hi); + Some(format!("{}({})", + path_str, + try_opt!(format_item_list(items, + width, + offset, + context.config)))) + } + } + None => Some(format!("{}(..)", path_str)), } } Pat_::PatLit(ref expr) => expr.rewrite(context, width, offset), - // FIXME(#8): format remaining pattern variants. - Pat_::PatIdent(_, _, Some(..)) | - Pat_::PatEnum(_, None) | - Pat_::PatStruct(..) | - Pat_::PatVec(..) | + Pat_::PatVec(ref prefix, ref slice_pat, ref suffix) => { + // Rewrite all the sub-patterns. + let prefix = prefix.iter().map(|p| p.rewrite(context, width, offset)); + let slice_pat = slice_pat.as_ref().map(|p| { + Some(format!("{}..", try_opt!(p.rewrite(context, width, offset)))) + }); + let suffix = suffix.iter().map(|p| p.rewrite(context, width, offset)); + + // Munge them together. + let pats: Option> = prefix.chain(slice_pat.into_iter()) + .chain(suffix) + .collect(); + + // Check that all the rewrites succeeded, and if not return None. + let pats = try_opt!(pats); + + // Unwrap all the sub-strings and join them with commas. + let result = format!("[{}]", pats.join(", ")); + wrap_str(result, context.config.max_width, width, offset) + } + Pat_::PatStruct(ref path, ref fields, elipses) => { + let path = try_opt!(rewrite_path(context, true, None, path, width, offset)); + + let (elipses_str, terminator) = if elipses { + (", ..", "..") + } else { + ("", "}") + }; + + // 5 = `{` plus space before and after plus `}` plus space before. + let budget = try_opt!(width.checked_sub(path.len() + 5 + elipses_str.len())); + // FIXME Using visual indenting, should use block or visual to match + // struct lit preference (however, in practice I think it is rare + // for struct patterns to be multi-line). + // 3 = `{` plus space before and after. + let offset = offset + path.len() + 3; + + let items = itemize_list(context.codemap, + fields.iter(), + terminator, + |f| f.span.lo, + |f| f.span.hi, + |f| f.node.rewrite(context, budget, offset), + span_after(self.span, "{", context.codemap), + self.span.hi); + let mut field_string = try_opt!(format_item_list(items, + budget, + offset, + context.config)); + if elipses { + if field_string.contains('\n') { + field_string.push_str(",\n"); + field_string.push_str(&offset.to_string(context.config)); + field_string.push_str(".."); + } else { + if field_string.len() > 0 { + field_string.push_str(", "); + } + field_string.push_str(".."); + } + } + + if field_string.is_empty() { + Some(format!("{} {{}}", path)) + } else { + Some(format!("{} {{ {} }}", path, field_string)) + } + } + // FIXME(#819) format pattern macros. Pat_::PatMac(..) => { wrap_str(context.snippet(self.span), context.config.max_width, @@ -97,3 +176,17 @@ impl Rewrite for Pat { } } } + +impl Rewrite for FieldPat { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + let pat = self.pat.rewrite(context, width, offset); + if self.is_shorthand { + pat + } else { + wrap_str(format!("{}: {}", self.ident.to_string(), try_opt!(pat)), + context.config.max_width, + width, + offset) + } + } +} diff --git a/tests/source/pattern.rs b/tests/source/pattern.rs index 930ffe2258f..75f65806167 100644 --- a/tests/source/pattern.rs +++ b/tests/source/pattern.rs @@ -11,6 +11,20 @@ fn main() { let Some ( ref xyz /* comment! */) = opt; if let None = opt2 { panic!("oh noes"); } + + let foo@bar (f) = 42; + let a::foo ( ..) = 42; + let [ ] = 42; + let [a.., b,c ] = 42; + let [ a,b,c.. ] = 42; + let [a, b, c, d..,e,f, g] = 42; + let foo { } = 42; + let foo {..} = 42; + let foo { x, y: ref foo, .. } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. }; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, }; } impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> { diff --git a/tests/system.rs b/tests/system.rs index 497583f9d67..bc5298ae22d 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -287,6 +287,8 @@ fn handle_result(result: HashMap, if fmt_text != text { let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); + assert!(!diff.is_empty(), + "Empty diff? Maybe due to a missing a newline at the end of a file?"); failures.insert(file_name, diff); } } diff --git a/tests/target/match.rs b/tests/target/match.rs index 94f9bf8ae5e..defcc13ef51 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -251,7 +251,7 @@ fn issue280() { fn issue383() { match resolution.last_private { - LastImport{..} => false, + LastImport { .. } => false, _ => true, }; } diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs index eb42f9fde73..d77cb59f498 100644 --- a/tests/target/pattern.rs +++ b/tests/target/pattern.rs @@ -13,6 +13,23 @@ fn main() { if let None = opt2 { panic!("oh noes"); } + + let foo @ bar(f) = 42; + let a::foo(..) = 42; + let [] = 42; + let [a.., b, c] = 42; + let [a, b, c..] = 42; + let [a, b, c, d.., e, f, g] = 42; + let foo {} = 42; + let foo { .. } = 42; + let foo { x, y: ref foo, .. } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo } = 42; + let foo { x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + .. }; + let foo { x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo }; } impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> {