// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use config::lists::*;
use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax};
-use syntax::codemap::{self, BytePos, Span};
use syntax::ptr;
+use syntax::source_map::{self, BytePos, Span};
-use spanned::Spanned;
-use codemap::SpanUtils;
use comment::FindUncommented;
-use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix,
- wrap_struct_field, PairParts};
-use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape,
- struct_lit_tactic, write_list, DefinitiveListTactic, SeparatorPlace, SeparatorTactic};
+use expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field};
+use lists::{
+ itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic,
+ write_list,
+};
+use macros::{rewrite_macro, MacroPosition};
+use overflow;
+use pairs::{rewrite_pair, PairParts};
use rewrite::{Rewrite, RewriteContext};
use shape::Shape;
+use source_map::SpanUtils;
+use spanned::Spanned;
use types::{rewrite_path, PathContext};
-use utils::{format_mutability, mk_sp};
+use utils::{format_mutability, mk_sp, rewrite_ident};
+
+/// Returns true if the given pattern is short. A short pattern is defined by the following grammer:
+///
+/// [small, ntp]:
+/// - single token
+/// - `&[single-line, ntp]`
+///
+/// [small]:
+/// - `[small, ntp]`
+/// - unary tuple constructor `([small, ntp])`
+/// - `&[small]`
+pub fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool {
+ // We also require that the pattern is reasonably 'small' with its literal width.
+ pat_str.len() <= 20 && !pat_str.contains('\n') && is_short_pattern_inner(pat)
+}
+
+fn is_short_pattern_inner(pat: &ast::Pat) -> bool {
+ match pat.node {
+ ast::PatKind::Wild | ast::PatKind::Lit(_) => true,
+ ast::PatKind::Ident(_, _, ref pat) => pat.is_none(),
+ ast::PatKind::Struct(..)
+ | ast::PatKind::Mac(..)
+ | ast::PatKind::Slice(..)
+ | ast::PatKind::Path(..)
+ | ast::PatKind::Range(..) => false,
+ ast::PatKind::Tuple(ref subpats, _) => subpats.len() <= 1,
+ ast::PatKind::TupleStruct(ref path, ref subpats, _) => {
+ path.segments.len() <= 1 && subpats.len() <= 1
+ }
+ ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) | ast::PatKind::Paren(ref p) => {
+ is_short_pattern_inner(&*p)
+ }
+ }
+}
impl Rewrite for Pat {
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
BindingMode::ByValue(mutability) => ("", mutability),
};
let mut_infix = format_mutability(mutability);
- let id_str = ident.node.to_string();
+ let id_str = rewrite_ident(context, ident);
let sub_pat = match *sub_pat {
Some(ref p) => {
// 3 - ` @ `.
Some(format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat))
}
- PatKind::Wild => if 1 <= shape.width {
- Some("_".to_owned())
- } else {
- None
- },
+ PatKind::Wild => {
+ if 1 <= shape.width {
+ Some("_".to_owned())
+ } else {
+ None
+ }
+ }
PatKind::Range(ref lhs, ref rhs, ref end_kind) => {
- let infix = match *end_kind {
+ let infix = match end_kind.node {
RangeEnd::Included(RangeSyntax::DotDotDot) => "...",
RangeEnd::Included(RangeSyntax::DotDotEq) => "..=",
RangeEnd::Excluded => "..",
};
+ let infix = if context.config.spaces_around_ranges() {
+ format!(" {} ", infix)
+ } else {
+ infix.to_owned()
+ };
rewrite_pair(
&**lhs,
&**rhs,
- PairParts::new("", infix, ""),
+ PairParts::infix(&infix),
context,
shape,
SeparatorPlace::Front,
let prefix = prefix.iter().map(|p| p.rewrite(context, shape));
let slice_pat = slice_pat
.as_ref()
- .map(|p| Some(format!("{}..", p.rewrite(context, shape)?)));
+ .and_then(|p| p.rewrite(context, shape))
+ .map(|rw| Some(format!("{}..", if rw == "_" { "" } else { &rw })));
let suffix = suffix.iter().map(|p| p.rewrite(context, shape));
// Munge them together.
let pats = pats?;
// Unwrap all the sub-strings and join them with commas.
- let result = if context.config.spaces_within_parens_and_brackets() {
- format!("[ {} ]", pats.join(", "))
- } else {
- format!("[{}]", pats.join(", "))
- };
- Some(result)
+ Some(format!("[{}]", pats.join(", ")))
}
PatKind::Struct(ref path, ref fields, ellipsis) => {
rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape)
}
- // FIXME(#819) format pattern macros.
- PatKind::Mac(..) => Some(context.snippet(self.span)),
+ PatKind::Mac(ref mac) => rewrite_macro(mac, None, context, shape, MacroPosition::Pat),
+ PatKind::Paren(ref pat) => pat
+ .rewrite(context, shape.offset_left(1)?.sub_width(1)?)
+ .map(|inner_pat| format!("({})", inner_pat)),
}
}
}
fn rewrite_struct_pat(
path: &ast::Path,
- fields: &[codemap::Spanned<ast::FieldPat>],
+ fields: &[source_map::Spanned<ast::FieldPat>],
ellipsis: bool,
span: Span,
context: &RewriteContext,
struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)?;
let items = itemize_list(
- context.codemap,
+ context.snippet_provider,
fields.iter(),
terminator,
+ ",",
|f| f.span.lo(),
|f| f.span.hi(),
|f| f.node.rewrite(context, v_shape),
- context.codemap.span_after(span, "{"),
+ context.snippet_provider.span_after(span, "{"),
span.hi(),
false,
);
if ellipsis {
if fields_str.contains('\n') || fields_str.len() > one_line_width {
// Add a missing trailing comma.
- if fmt.trailing_separator == SeparatorTactic::Never {
+ if context.config.trailing_comma() == SeparatorTactic::Never {
fields_str.push_str(",");
}
fields_str.push_str("\n");
} else {
if !fields_str.is_empty() {
// there are preceding struct fields being matched on
- if fmt.tactic == DefinitiveListTactic::Vertical {
+ if tactic == DefinitiveListTactic::Vertical {
// if the tactic is Vertical, write_list already added a trailing ,
fields_str.push_str(" ");
} else {
pat
} else {
let pat_str = pat?;
- let id_str = self.ident.to_string();
+ let id_str = rewrite_ident(context, self.ident);
let one_line_width = id_str.len() + 2 + pat_str.len();
if one_line_width <= shape.width {
Some(format!("{}: {}", id_str, pat_str))
pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: usize) -> bool {
match *pat {
TuplePatField::Pat(pat) => match pat.node {
- ast::PatKind::Path(..) |
- ast::PatKind::Tuple(..) |
- ast::PatKind::Struct(..) |
- ast::PatKind::TupleStruct(..) => context.use_block_indent() && len == 1,
+ ast::PatKind::Path(..)
+ | ast::PatKind::Tuple(..)
+ | ast::PatKind::Struct(..)
+ | ast::PatKind::TupleStruct(..) => context.use_block_indent() && len == 1,
ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => {
can_be_overflowed_pat(context, &TuplePatField::Pat(p), len)
}
lo,
// 2 == "..".len()
lo + BytePos(2),
- codemap::NO_EXPANSION,
+ source_map::NO_EXPANSION,
));
pat_vec.insert(pos, dotdot);
}
-
if pat_vec.is_empty() {
return Some(format!("{}()", path_str.unwrap_or_default()));
}
-
let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape);
- let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2
- {
- let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len;
- let sp = pat_vec[new_item_count - 1].span();
- let snippet = context.snippet(sp);
- let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32);
- pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1)));
- (
- &pat_vec[..new_item_count],
- mk_sp(span.lo(), lo + BytePos(1)),
- )
- } else {
- (&pat_vec[..], span)
- };
+ let (pat_vec, span, condensed) =
+ if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 {
+ let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len;
+ let sp = pat_vec[new_item_count - 1].span();
+ let snippet = context.snippet(sp);
+ let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32);
+ pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1)));
+ (
+ &pat_vec[..new_item_count],
+ mk_sp(span.lo(), lo + BytePos(1)),
+ true,
+ )
+ } else {
+ (&pat_vec[..], span, false)
+ };
// add comma if `(x,)`
- let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none();
- let mut context = context.clone();
- if let Some(&TuplePatField::Dotdot(..)) = pat_vec.last() {
- context.inside_macro = true;
- }
+ let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none() && !condensed;
let path_str = path_str.unwrap_or_default();
- let mut pat_ref_vec = Vec::with_capacity(pat_vec.len());
- for pat in pat_vec {
- pat_ref_vec.push(pat);
- }
+ let pat_ref_vec = pat_vec.iter().collect::<Vec<_>>();
- rewrite_call_inner(
+ overflow::rewrite_with_parens(
&context,
&path_str,
- &pat_ref_vec[..],
- span,
+ &pat_ref_vec,
shape,
- shape.width,
- add_comma,
+ span,
+ context.config.max_width(),
+ if dotdot_pos.is_some() {
+ Some(SeparatorTactic::Never)
+ } else if add_comma {
+ Some(SeparatorTactic::Always)
+ } else {
+ None
+ },
)
}
let mut suffix_len = 0;
let items: Vec<_> = itemize_list(
- context.codemap,
+ context.snippet_provider,
patterns.iter(),
")",
+ ",",
|item| item.span().lo(),
|item| item.span().hi(),
|item| item.rewrite(context, shape),
- context.codemap.span_after(span, "("),
+ context.snippet_provider.span_after(span, "("),
span.hi() - BytePos(1),
false,
).collect();
}) {
suffix_len += 1;
- if item.pre_comment.is_some() || item.post_comment.is_some() {
+ if item.has_comment() {
break;
}
}