]> git.lizzy.rs Git - rust.git/blob - src/changes.rs
New reformatting of fns
[rust.git] / src / changes.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11
12 // TODO
13 // print to files 
14 // tests
15
16 use string_buffer::StringBuffer;
17 use std::collections::HashMap;
18 use syntax::codemap::{CodeMap, Span};
19 use std::fmt;
20
21 // This is basically a wrapper around a bunch of Ropes which makes it convenient
22 // to work with libsyntax. It is badly named.
23 pub struct ChangeSet<'a> {
24     file_map: HashMap<String, StringBuffer>,
25     codemap: &'a CodeMap,
26 }
27
28 impl<'a> ChangeSet<'a> {
29     // Create a new ChangeSet for a given libsyntax CodeMap.
30     pub fn from_codemap(codemap: &'a CodeMap) -> ChangeSet<'a> {
31         let mut result = ChangeSet {
32             file_map: HashMap::new(),
33             codemap: codemap,
34         };
35
36         for f in codemap.files.borrow().iter() {
37             // Use the length of the file as a heuristic for how much space we
38             // need. I hope that at some stage someone rounds this up to the next
39             // power of two. TODO check that or do it here.
40             result.file_map.insert(f.name.clone(),
41                                    StringBuffer::with_capacity(f.src.as_ref().unwrap().len()));
42         }
43
44         result
45     }
46
47     pub fn push_str(&mut self, file_name: &str, text: &str) {
48         let buf = self.file_map.get_mut(&*file_name).unwrap();
49         buf.push_str(text)
50     }
51
52     pub fn push_str_span(&mut self, span: Span, text: &str) {
53         let file_name = self.codemap.span_to_filename(span);
54         self.push_str(&file_name, text)
55     }
56
57     pub fn cur_offset(&mut self, file_name: &str) -> usize {
58         self.file_map[&*file_name].cur_offset()
59     }
60
61     pub fn cur_offset_span(&mut self, span: Span) -> usize {
62         let file_name = self.codemap.span_to_filename(span);
63         self.cur_offset(&file_name)
64     }
65
66     // Return an iterator over the entire changed text.
67     pub fn text<'c>(&'c self) -> FileIterator<'c, 'a> {
68         FileIterator {
69             change_set: self,
70             keys: self.file_map.keys().collect(),
71             cur_key: 0,
72         }
73     }
74
75 }
76
77 // Iterates over each file in the ChangSet. Yields the filename and the changed
78 // text for that file.
79 pub struct FileIterator<'c, 'a: 'c> {
80     change_set: &'c ChangeSet<'a>,
81     keys: Vec<&'c String>,
82     cur_key: usize,
83 }
84
85 impl<'c, 'a> Iterator for FileIterator<'c, 'a> {
86     type Item = (&'c str, &'c StringBuffer);
87
88     fn next(&mut self) -> Option<(&'c str, &'c StringBuffer)> {
89         if self.cur_key >= self.keys.len() {
90             return None;
91         }
92
93         let key = self.keys[self.cur_key];
94         self.cur_key += 1;
95         return Some((&key, &self.change_set.file_map[&*key]))
96     }
97 }
98
99 impl<'a> fmt::Display for ChangeSet<'a> {
100     // Prints the entire changed text.
101     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
102         for (f, r) in self.text() {
103             try!(write!(fmt, "{}:\n", f));
104             try!(write!(fmt, "{}\n\n", r));
105         }
106         Ok(())
107     }    
108 }