about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/codemap.rs72
1 files changed, 58 insertions, 14 deletions
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 6f17505c902..5be03317b77 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -221,6 +221,10 @@ impl FileMap {
     // UNCHECKED INVARIANT: these offsets must be added in the right
     // order and must be in the right places; there is shared knowledge
     // about what ends a line between this file and parse.rs
+    // WARNING: pos param here is the offset relative to start of CodeMap,
+    // and CodeMap will append a newline when adding a filemap without a newline at the end,
+    // so the safe way to call this is with value calculated as
+    // filemap.start_pos + newline_offset_relative_to_the_start_of_filemap.
     pub fn next_line(&self, pos: BytePos) {
         // the new charpos must be > the last one (or it's the first one).
         let mut lines = self.lines.borrow_mut();;
@@ -267,13 +271,21 @@ impl CodeMap {
         }
     }
 
-    pub fn new_filemap(&self, filename: FileName, src: ~str) -> @FileMap {
+    pub fn new_filemap(&self, filename: FileName, mut src: ~str) -> @FileMap {
         let mut files = self.files.borrow_mut();
         let start_pos = match files.get().last() {
             None => 0,
             Some(last) => last.start_pos.to_uint() + last.src.len(),
         };
 
+        // Append '\n' in case it's not already there.
+        // This is a workaround to prevent CodeMap.lookup_filemap_idx from accidentally
+        // overflowing into the next filemap in case the last byte of span is also the last
+        // byte of filemap, which leads to incorrect results from CodeMap.span_to_*.
+        if src.len() > 0 && !src.ends_with("\n") {
+            src.push_char('\n');
+        }
+
         let filemap = @FileMap {
             name: filename,
             src: src,
@@ -510,9 +522,9 @@ mod test {
 
         fm1.next_line(BytePos(0));
         fm1.next_line(BytePos(12));
-        fm2.next_line(BytePos(23));
-        fm3.next_line(BytePos(23));
-        fm3.next_line(BytePos(33));
+        fm2.next_line(BytePos(24));
+        fm3.next_line(BytePos(24));
+        fm3.next_line(BytePos(34));
 
         cm
     }
@@ -526,7 +538,7 @@ mod test {
         assert_eq!(fmabp1.fm.name, ~"blork.rs");
         assert_eq!(fmabp1.pos, BytePos(22));
 
-        let fmabp2 = cm.lookup_byte_offset(BytePos(23));
+        let fmabp2 = cm.lookup_byte_offset(BytePos(24));
         assert_eq!(fmabp2.fm.name, ~"blork2.rs");
         assert_eq!(fmabp2.pos, BytePos(0));
     }
@@ -539,7 +551,7 @@ mod test {
         let cp1 = cm.bytepos_to_file_charpos(BytePos(22));
         assert_eq!(cp1, CharPos(22));
 
-        let cp2 = cm.bytepos_to_file_charpos(BytePos(23));
+        let cp2 = cm.bytepos_to_file_charpos(BytePos(24));
         assert_eq!(cp2, CharPos(0));
     }
 
@@ -553,7 +565,7 @@ mod test {
         assert_eq!(loc1.line, 2);
         assert_eq!(loc1.col, CharPos(10));
 
-        let loc2 = cm.lookup_char_pos(BytePos(23));
+        let loc2 = cm.lookup_char_pos(BytePos(24));
         assert_eq!(loc2.file.name, ~"blork2.rs");
         assert_eq!(loc2.line, 1);
         assert_eq!(loc2.col, CharPos(0));
@@ -567,17 +579,17 @@ mod test {
 
         fm1.next_line(BytePos(0));
         fm1.next_line(BytePos(22));
-        fm2.next_line(BytePos(39));
-        fm2.next_line(BytePos(57));
+        fm2.next_line(BytePos(40));
+        fm2.next_line(BytePos(58));
 
         fm1.record_multibyte_char(BytePos(3), 3);
         fm1.record_multibyte_char(BytePos(9), 3);
         fm1.record_multibyte_char(BytePos(12), 3);
         fm1.record_multibyte_char(BytePos(15), 3);
         fm1.record_multibyte_char(BytePos(18), 3);
-        fm2.record_multibyte_char(BytePos(49), 3);
-        fm2.record_multibyte_char(BytePos(52), 3);
-        fm2.record_multibyte_char(BytePos(57), 3);
+        fm2.record_multibyte_char(BytePos(50), 3);
+        fm2.record_multibyte_char(BytePos(53), 3);
+        fm2.record_multibyte_char(BytePos(58), 3);
 
         cm
     }
@@ -593,10 +605,42 @@ mod test {
         let cp2 = cm.bytepos_to_file_charpos(BytePos(6));
         assert_eq!(cp2, CharPos(4));
 
-        let cp3 = cm.bytepos_to_file_charpos(BytePos(55));
+        let cp3 = cm.bytepos_to_file_charpos(BytePos(56));
         assert_eq!(cp3, CharPos(12));
 
-        let cp4 = cm.bytepos_to_file_charpos(BytePos(60));
+        let cp4 = cm.bytepos_to_file_charpos(BytePos(61));
         assert_eq!(cp4, CharPos(15));
     }
+
+    #[test]
+    fn t7() {
+        // Test span_to_lines for a span ending at the end of filemap
+        let cm = init_code_map();
+        let span = Span {lo: BytePos(12), hi: BytePos(23), expn_info: None};
+        let file_lines = cm.span_to_lines(span);
+
+        assert_eq!(file_lines.file.name, ~"blork.rs");
+        assert_eq!(file_lines.lines.len(), 1);
+        assert_eq!(*file_lines.lines.get(0), 1u);
+    }
+
+    #[test]
+    fn t8() {
+        // Test span_to_snippet for a span ending at the end of filemap
+        let cm = init_code_map();
+        let span = Span {lo: BytePos(12), hi: BytePos(23), expn_info: None};
+        let snippet = cm.span_to_snippet(span);
+
+        assert_eq!(snippet, Some(~"second line"));
+    }
+
+    #[test]
+    fn t9() {
+        // Test span_to_str for a span ending at the end of filemap
+        let cm = init_code_map();
+        let span = Span {lo: BytePos(12), hi: BytePos(23), expn_info: None};
+        let sstr =  cm.span_to_str(span);
+
+        assert_eq!(sstr, ~"blork.rs:2:1: 2:12");
+    }
 }