about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMarcus Klaas <mail@marcusklaas.nl>2015-10-24 12:19:58 +0200
committerMarcus Klaas <mail@marcusklaas.nl>2015-10-24 13:13:15 +0200
commitd122ad5adc2164e34e59a7e9e7e8da2dfba7ffb5 (patch)
tree47c808713a466de490677005fa422f27a0260164 /src
parent58ff0d8730806332e05b34189d91c8504f71eccc (diff)
Address some issues with multiline patterns in let statements
Diffstat (limited to 'src')
-rw-r--r--src/expr.rs16
-rw-r--r--src/items.rs110
-rw-r--r--src/lib.rs8
-rw-r--r--src/visitor.rs8
4 files changed, 69 insertions, 73 deletions
diff --git a/src/expr.rs b/src/expr.rs
index 20a637bffca..16c46f6bef1 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1398,7 +1398,10 @@ pub fn rewrite_tuple<'a, R>(context: &RewriteContext,
                              |item| item.span().lo,
                              |item| item.span().hi,
                              |item| {
-                                 let inner_width = context.config.max_width - indent.width() - 1;
+                                 let inner_width = try_opt!(context.config
+                                                                   .max_width
+                                                                   .checked_sub(indent.width() +
+                                                                                1));
                                  item.rewrite(context, inner_width, indent)
                              },
                              span.lo + BytePos(1), // Remove parens
@@ -1522,10 +1525,15 @@ pub fn rewrite_assign_rhs<S: Into<String>>(context: &RewriteContext,
                                            offset: Indent)
                                            -> Option<String> {
     let mut result = lhs.into();
-
+    let last_line_width = last_line_width(&result) -
+                          if result.contains('\n') {
+        offset.width()
+    } else {
+        0
+    };
     // 1 = space between operator and rhs.
-    let max_width = try_opt!(width.checked_sub(result.len() + 1));
-    let rhs = ex.rewrite(&context, max_width, offset + result.len() + 1);
+    let max_width = try_opt!(width.checked_sub(last_line_width + 1));
+    let rhs = ex.rewrite(&context, max_width, offset + last_line_width + 1);
 
     match rhs {
         Some(new_str) => {
diff --git a/src/items.rs b/src/items.rs
index c8054b8d01f..e6b401d2ff3 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -26,85 +26,59 @@ use syntax::codemap::{Span, BytePos, mk_sp};
 use syntax::print::pprust;
 use syntax::parse::token;
 
-impl<'a> FmtVisitor<'a> {
-    pub fn visit_let(&mut self, local: &ast::Local, span: Span) {
-        self.format_missing_with_indent(span.lo);
-
-        // New scope so we drop the borrow of self (context) in time to mutably
-        // borrow self to mutate its buffer.
-        let result = {
-            let context = self.get_context();
-            let mut result = "let ".to_owned();
-            let pattern_offset = self.block_indent + result.len();
-            // 1 = ;
-            let pattern_width = match self.config
-                                          .max_width
-                                          .checked_sub(pattern_offset.width() + 1) {
-                Some(width) => width,
-                None => return,
-            };
+// Statements of the form
+// let pat: ty = init;
+impl Rewrite for ast::Local {
+    fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
+        let mut result = "let ".to_owned();
+        let pattern_offset = offset + result.len();
+        // 1 = ;
+        let pattern_width = try_opt!(width.checked_sub(pattern_offset.width() + 1));
 
-            match local.pat.rewrite(&context, pattern_width, pattern_offset) {
-                Some(ref pat_string) => result.push_str(pat_string),
-                None => return,
-            }
+        let pat_str = try_opt!(self.pat.rewrite(&context, pattern_width, pattern_offset));
+        result.push_str(&pat_str);
 
-            // String that is placed within the assignment pattern and expression.
-            let infix = {
-                let mut infix = String::new();
-
-                if let Some(ref ty) = local.ty {
-                    // 2 = ": ".len()
-                    // 1 = ;
-                    let offset = self.block_indent + result.len() + 2;
-                    let width = match self.config.max_width.checked_sub(offset.width() + 1) {
-                        Some(w) => w,
-                        None => return,
-                    };
-                    let rewrite = ty.rewrite(&self.get_context(), width, offset);
-
-                    match rewrite {
-                        Some(result) => {
-                            infix.push_str(": ");
-                            infix.push_str(&result);
-                        }
-                        None => return,
-                    }
-                }
+        // String that is placed within the assignment pattern and expression.
+        let infix = {
+            let mut infix = String::new();
 
-                if local.init.is_some() {
-                    infix.push_str(" =");
-                }
+            if let Some(ref ty) = self.ty {
+                // 2 = ": ".len()
+                // 1 = ;
+                let indent = offset + last_line_width(&result) + 2;
+                let budget = try_opt!(width.checked_sub(indent.width() + 1));
+                let rewrite = try_opt!(ty.rewrite(context, budget, indent));
 
-                infix
-            };
+                infix.push_str(": ");
+                infix.push_str(&rewrite);
+            }
 
-            result.push_str(&infix);
+            if self.init.is_some() {
+                infix.push_str(" =");
+            }
 
-            if let Some(ref ex) = local.init {
-                let max_width = self.config.max_width.checked_sub(context.block_indent.width() + 1);
-                let max_width = match max_width {
-                    Some(width) => width,
-                    None => return,
-                };
+            infix
+        };
 
-                // 1 = trailing semicolon;
-                let rhs = rewrite_assign_rhs(&context, result, ex, max_width, context.block_indent);
+        result.push_str(&infix);
 
-                match rhs {
-                    Some(s) => s,
-                    None => return,
-                }
-            } else {
-                result
-            }
-        };
+        if let Some(ref ex) = self.init {
+            let budget = try_opt!(width.checked_sub(context.block_indent.width() + 1));
 
-        self.buffer.push_str(&result);
-        self.buffer.push_str(";");
-        self.last_pos = span.hi;
+            // 1 = trailing semicolon;
+            result = try_opt!(rewrite_assign_rhs(&context,
+                                                 result,
+                                                 ex,
+                                                 budget,
+                                                 context.block_indent));
+        }
+
+        result.push(';');
+        Some(result)
     }
+}
 
+impl<'a> FmtVisitor<'a> {
     pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) {
         self.buffer.push_str("extern ");
 
diff --git a/src/lib.rs b/src/lib.rs
index 33753524348..a22e797fb68 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -168,6 +168,14 @@ impl Add<usize> for Indent {
     }
 }
 
+impl Sub<usize> for Indent {
+    type Output = Indent;
+
+    fn sub(self, rhs: usize) -> Indent {
+        Indent::new(self.block_indent, self.alignment - rhs)
+    }
+}
+
 #[derive(Copy, Clone)]
 pub enum WriteMode {
     // Backups the original file and overwrites the orignal.
diff --git a/src/visitor.rs b/src/visitor.rs
index 9a33fdae024..bd30e80e5a9 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -37,7 +37,13 @@ impl<'a> FmtVisitor<'a> {
         match stmt.node {
             ast::Stmt_::StmtDecl(ref decl, _) => {
                 match decl.node {
-                    ast::Decl_::DeclLocal(ref local) => self.visit_let(local, stmt.span),
+                    ast::Decl_::DeclLocal(ref local) => {
+                        let rewrite = {
+                            let context = self.get_context();
+                            local.rewrite(&context, self.config.max_width, self.block_indent)
+                        };
+                        self.push_rewrite(stmt.span, rewrite);
+                    }
                     ast::Decl_::DeclItem(ref item) => self.visit_item(item),
                 }
             }