]> git.lizzy.rs Git - rust.git/blobdiff - src/patterns.rs
Use trim_tries to extract post comment over simple trim_matches
[rust.git] / src / patterns.rs
index 700fbd0da218c82dbe5e0496dea25719fdcf5abb..d5c4802904b65ed9747d90099e413d556b7b4400 100644 (file)
@@ -8,22 +8,60 @@
 // 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> {
@@ -35,7 +73,7 @@ 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 - ` @ `.
@@ -60,15 +98,20 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
                 }
             }
             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,
@@ -101,7 +144,8 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
                 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.
@@ -112,24 +156,22 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
                 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)
             }
             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,
@@ -150,14 +192,14 @@ fn rewrite_struct_pat(
         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,
     );
@@ -173,7 +215,7 @@ fn rewrite_struct_pat(
     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");
@@ -182,7 +224,7 @@ fn rewrite_struct_pat(
         } 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 {
@@ -204,7 +246,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
             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))
@@ -290,51 +332,49 @@ fn rewrite_tuple_pat(
             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
+        },
     )
 }
 
@@ -347,14 +387,14 @@ fn count_wildcard_suffix_len(
     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();
@@ -365,7 +405,7 @@ fn count_wildcard_suffix_len(
     }) {
         suffix_len += 1;
 
-        if item.pre_comment.is_some() || item.post_comment.is_some() {
+        if item.has_comment() {
             break;
         }
     }