about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/changes.rs42
-rw-r--r--src/mod.rs109
2 files changed, 101 insertions, 50 deletions
diff --git a/src/changes.rs b/src/changes.rs
index 752ae942f1f..068b6b7736c 100644
--- a/src/changes.rs
+++ b/src/changes.rs
@@ -15,7 +15,7 @@
 
 use strings::string_buffer::StringBuffer;
 use std::collections::HashMap;
-use syntax::codemap::{CodeMap, Span};
+use syntax::codemap::{CodeMap, Span,BytePos};
 use std::fmt;
 
 // This is basically a wrapper around a bunch of Ropes which makes it convenient
@@ -23,6 +23,7 @@ use std::fmt;
 pub struct ChangeSet<'a> {
     file_map: HashMap<String, StringBuffer>,
     codemap: &'a CodeMap,
+    file_spans: Vec<(u32, u32)>,
 }
 
 impl<'a> ChangeSet<'a> {
@@ -31,6 +32,7 @@ impl<'a> ChangeSet<'a> {
         let mut result = ChangeSet {
             file_map: HashMap::new(),
             codemap: codemap,
+            file_spans: Vec::with_capacity(codemap.files.borrow().len()),
         };
 
         for f in codemap.files.borrow().iter() {
@@ -39,11 +41,49 @@ impl<'a> ChangeSet<'a> {
             // power of two. TODO check that or do it here.
             result.file_map.insert(f.name.clone(),
                                    StringBuffer::with_capacity(f.src.as_ref().unwrap().len()));
+
+            result.file_spans.push((f.start_pos.0, f.end_pos.0));
         }
 
+        result.file_spans.sort();
+
         result
     }
 
+    pub fn filespans_for_span(&self, start: BytePos, end: BytePos) -> Vec<(u32, u32)> {
+        assert!(start.0 <= end.0);
+
+        if self.file_spans.len() == 0 {
+            return Vec::new();
+        }
+
+        let mut idx = match self.file_spans.binary_search(&(start.0, ::std::u32::MAX)) {
+            Ok(i) => i,
+            Err(0) => 0,
+            Err(i) => i - 1,
+        };
+
+        let mut result = Vec::new();
+        let mut start = start.0;
+        loop {
+            let cur_file = &self.file_spans[idx];
+            idx += 1;
+
+            if idx >= self.file_spans.len() || start >= end.0 {
+                if start < end.0 {
+                    result.push((start, end.0));
+                }
+                return result;
+            }
+
+            let end = ::std::cmp::min(cur_file.1 - 1, end.0);
+            if start < end {
+                result.push((start, end));
+            }
+            start = self.file_spans[idx].0;
+        }
+    }
+
     pub fn push_str(&mut self, file_name: &str, text: &str) {
         let buf = self.file_map.get_mut(&*file_name).unwrap();
         buf.push_str(text)
diff --git a/src/mod.rs b/src/mod.rs
index a124eb9e2b4..65951638c1c 100644
--- a/src/mod.rs
+++ b/src/mod.rs
@@ -22,8 +22,8 @@
 // TODO priorities
 // Fix fns and methods properly - need visibility in visit
 // Writing output
-// Working on multiple files, inclding empty ones
 // Smoke testing till we can use it
+// end of multi-line string has wspace
 
 #[macro_use]
 extern crate log;
@@ -123,10 +123,9 @@ struct FmtVisitor<'a> {
 
 impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
     fn visit_expr(&mut self, ex: &'v ast::Expr) {
-        // TODO uncomment
-        // debug!("visit_expr: {:?} {:?}",
-        //        self.codemap.lookup_char_pos(ex.span.lo),
-        //        self.codemap.lookup_char_pos(ex.span.hi));
+        debug!("visit_expr: {:?} {:?}",
+               self.codemap.lookup_char_pos(ex.span.lo),
+               self.codemap.lookup_char_pos(ex.span.hi));
         self.format_missing(ex.span.lo);
         let offset = self.changes.cur_offset_span(ex.span);
         let new_str = self.rewrite_expr(ex, MAX_WIDTH - offset, offset);
@@ -135,10 +134,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
     }
 
     fn visit_block(&mut self, b: &'v ast::Block) {
-        // TODO uncomment
-        // debug!("visit_block: {:?} {:?}",
-        //        self.codemap.lookup_char_pos(b.span.lo),
-        //        self.codemap.lookup_char_pos(b.span.hi));
+        debug!("visit_block: {:?} {:?}",
+               self.codemap.lookup_char_pos(b.span.lo),
+               self.codemap.lookup_char_pos(b.span.hi));
         self.format_missing(b.span.lo);
 
         self.changes.push_str_span(b.span, "{");
@@ -241,6 +239,15 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
     fn visit_mac(&mut self, mac: &'v ast::Mac) {
         visit::walk_mac(self, mac)
     }
+
+    fn visit_mod(&mut self, m: &'v ast::Mod, s: Span, _: ast::NodeId) {
+        // Only visit inline mods here.
+        if self.codemap.lookup_char_pos(s.lo).file.name !=
+           self.codemap.lookup_char_pos(m.inner.lo).file.name {
+            return;
+        }
+        visit::walk_mod(self, m);
+    }
 }
 
 fn make_indent(width: usize) -> String {
@@ -413,63 +420,67 @@ impl<'a> FmtVisitor<'a> {
                                                                       process_last_snippet: F)
     {
         let start = self.last_pos;
-        // TODO uncomment
-        // debug!("format_missing_inner: {:?} to {:?}",
-        //        self.codemap.lookup_char_pos(start),
-        //        self.codemap.lookup_char_pos(end));
-
-        // TODO(#11) gets tricky if we're missing more than one file
-        // assert!(self.codemap.lookup_char_pos(start).file.name == self.codemap.lookup_char_pos(end).file.name,
-        //         "not implemented: unformated span across files: {} and {}",
-        //         self.codemap.lookup_char_pos(start).file.name,
-        //         self.codemap.lookup_char_pos(end).file.name);
-        // assert!(start <= end,
-        //         "Request to format inverted span: {:?} to {:?}",
-        //         self.codemap.lookup_char_pos(start),
-        //         self.codemap.lookup_char_pos(end));
+        debug!("format_missing_inner: {:?} to {:?}",
+               self.codemap.lookup_char_pos(start),
+               self.codemap.lookup_char_pos(end));
 
         if start == end {
             return;
         }
 
-        self.last_pos = end;
-        let span = codemap::mk_sp(start, end);
-        let snippet = self.snippet(span);
-
-        // Trim whitespace from the right hand side of each line.
-        // Annoyingly, the library functions for splitting by lines etc. are not
-        // quite right, so we must do it ourselves.
-        let mut line_start = 0;
-        let mut last_wspace = None;
-        for (i, c) in snippet.char_indices() {
-            if c == '\n' {
-                if let Some(lw) = last_wspace {
-                    self.changes.push_str_span(span, &snippet[line_start..lw]);
-                    self.changes.push_str_span(span, "\n");
-                } else {
-                    self.changes.push_str_span(span, &snippet[line_start..i+1]);
-                }
+        assert!(start < end,
+                "Request to format inverted span: {:?} to {:?}",
+                self.codemap.lookup_char_pos(start),
+                self.codemap.lookup_char_pos(end));
 
-                line_start = i + 1;
-                last_wspace = None;
-            } else {
-                if c.is_whitespace() {
-                    if last_wspace.is_none() {
-                        last_wspace = Some(i);
+
+        self.last_pos = end;
+        let spans = self.changes.filespans_for_span(start, end);
+        for (i, &(start, end)) in spans.iter().enumerate() {
+            let span = codemap::mk_sp(BytePos(start), BytePos(end));
+            let snippet = self.snippet(span);
+
+            // Trim whitespace from the right hand side of each line.
+            // Annoyingly, the library functions for splitting by lines etc. are not
+            // quite right, so we must do it ourselves.
+            let mut line_start = 0;
+            let mut last_wspace = None;
+            for (i, c) in snippet.char_indices() {
+                if c == '\n' {
+                    if let Some(lw) = last_wspace {
+                        self.changes.push_str_span(span, &snippet[line_start..lw]);
+                        self.changes.push_str_span(span, "\n");
+                    } else {
+                        self.changes.push_str_span(span, &snippet[line_start..i+1]);
                     }
-                } else {
+
+                    line_start = i + 1;
                     last_wspace = None;
+                } else {
+                    if c.is_whitespace() {
+                        if last_wspace.is_none() {
+                            last_wspace = Some(i);
+                        }
+                    } else {
+                        last_wspace = None;
+                    }
                 }
             }
+            if i == spans.len() - 1 {
+                process_last_snippet(self, &snippet[line_start..], span, &snippet);
+            } else {
+                self.changes.push_str_span(span, &snippet[line_start..]);
+            }
         }
-        process_last_snippet(self, &snippet[line_start..], span, &snippet);
     }
 
     fn snippet(&self, span: Span) -> String {
         match self.codemap.span_to_snippet(span) {
             Ok(s) => s,
             Err(_) => {
-                println!("Couldn't make snippet for span {:?}", span);
+                println!("Couldn't make snippet for span {:?}->{:?}",
+                         self.codemap.lookup_char_pos(span.lo),
+                         self.codemap.lookup_char_pos(span.hi));
                 "".to_string()
             }
         }