diff options
| author | Nick Cameron <ncameron@mozilla.com> | 2015-02-02 21:59:03 +1300 |
|---|---|---|
| committer | Nick Cameron <ncameron@mozilla.com> | 2015-02-02 21:59:03 +1300 |
| commit | f1e698c838defa9535750312d3fc11ebf3a830e9 (patch) | |
| tree | 4f0598da7db4eba36d9674a7494ce0454aa335c9 /src/changes.rs | |
| parent | 5caf49ff63ef84961f0b489706d6fcf3bcc0c6f0 (diff) | |
Save changes in the rope.
Also changes to using the new rustc interface
Diffstat (limited to 'src/changes.rs')
| -rw-r--r-- | src/changes.rs | 158 |
1 files changed, 19 insertions, 139 deletions
diff --git a/src/changes.rs b/src/changes.rs index ba2b90d185d..22fdc0ff51d 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -15,9 +15,8 @@ // docs use rope::{Rope, RopeSlice}; -use std::collections::{HashMap, BTreeMap}; -use std::collections::Bound::{Included, Unbounded}; -use syntax::codemap::{CodeMap, Span, Pos}; +use std::collections::HashMap; +use syntax::codemap::{CodeMap, Span, Pos, BytePos}; use std::fmt; pub struct ChangeSet<'a> { @@ -27,34 +26,6 @@ pub struct ChangeSet<'a> { // out into an adaptor. codemap: &'a CodeMap, pub count: u64, - // TODO we need to map the start and end of spans differently - // TODO needs to be per file - adjusts: BTreeMap<usize, Adjustment>, -} - -// An extent over which we must adjust the position values. -#[derive(Show, Clone, Eq, PartialEq)] -struct Adjustment { - // Start is implicit, given by its position in the map. - end: usize, - delta: isize, -} - -impl Adjustment { - fn chop_left(&self, new_end: usize) -> Adjustment { - Adjustment { - end: new_end, - delta: self.delta, - } - } - - fn move_left(&self, mov: usize) -> Adjustment { - assert!(self.delta > mov); - Adjustment { - end: self.end, - delta: self.delta - mov, - } - } } pub struct FileIterator<'c, 'a: 'c> { @@ -69,7 +40,6 @@ impl<'a> ChangeSet<'a> { file_map: HashMap::new(), codemap: codemap, count: 0, - adjusts: BTreeMap::new(), }; for f in codemap.files.borrow().iter() { @@ -84,100 +54,21 @@ impl<'a> ChangeSet<'a> { pub fn change(&mut self, file_name: &str, start: usize, end: usize, text: String) { println!("change: {}:{}-{} \"{}\"", file_name, start, end, text); - let new_len = text.len(); self.count += 1; - let (key_start, adj_start, abs_start): (Option<usize>, Option<Adjustment>, usize) = { - let before_start = self.adjusts.range(Unbounded, Included(&start)).next_back(); - match before_start { - Some((k, a)) if a.end > start => (Some(*k), Some(a.clone()), (start as isize + a.delta) as usize), - _ => (None, None, start) - } - }; - let (key_end, adj_end, abs_end) = { - let before_end = self.adjusts.range(Unbounded, Included(&end)).next_back(); - match before_end { - Some((k, a)) if a.end > end => (Some(*k), Some(a.clone()), (end as isize + a.delta) as usize), - _ => (None, None, end) - } - }; - - { - let file = &mut self.file_map[*file_name]; - - println!("change: absolute values {}-{}, replaces \"{}\"", - abs_start, abs_end, file.slice(abs_start..abs_end)); - - file.remove(abs_start, abs_end); - file.insert(abs_start, text); - - // Record the changed locations. - // TODO what if there is a change to the right of end? - need to iterate over all changes to the right :-( - match (key_start, key_end) { - (None, None) => { - // Factor this out? - let old_len = end as isize - start as isize; - let delta = new_len as isize - old_len; - self.adjusts.insert(end, Adjustment { end: file.len(), delta: delta }); - } - (Some(k), None) => { - // Adjust the old change. - self.adjusts[k] = adj_start.unwrap().chop_left(end); - - // Add the new one. - let old_len = end as isize - start as isize; - let delta = new_len as isize - old_len; - self.adjusts.insert(end, Adjustment { end: file.len(), delta: delta }); - } - (None, Some(k)) => { - let old_len = end as isize - start as isize; - let delta = new_len as isize - old_len; - - // Adjust the old change. - // TODO only if we move left, but what if moving right? - self.adjusts[abs_end] = adj_end.unwrap().move_left(TODO); - self.adjusts.remove(&k); - - // Add the new one. - self.adjusts.insert(end, Adjustment { end: file.len(), delta: delta }); - } - _ => { - println!("{}", file); - panic!(); - } - } - } - - debug_assert!(self.verify_adjustments(), "Bad change, created an overlapping adjustment"); - } + let file = &mut self.file_map[*file_name]; - // Intended for debugging. - fn verify_adjustments(&self) -> bool { - let mut prev_end = 0; - let mut prev_delta = 0; - for (&k, a) in self.adjusts.iter() { - if k < prev_end { - debug!("Found bad adjustment at start {}, overlaps with previous adjustment", k); - return false; - } - if k as isize + a.delta < 0 { - debug!("Found bad adjustment at start {}, absolute start < 0", k); - return false; - } - if k as isize + a.delta < prev_end as isize + prev_delta { - debug!("Found bad adjustment at start {}, \ - projection overlaps with previous projection", k); - return false; - } - // TODO Check end + delta <= file.len - needs per file - - prev_end = a.end; - prev_delta = a.delta; + if end - start == text.len() { + // TODO + panic!(); + file.replace_str(start, &text[]); + } else { + // TODO if we do this in one op, could we get better change info? + file.src_remove(start, end); + file.src_insert(start, text); } - true } - // span is unadjusted. pub fn change_span(&mut self, span: Span, text: String) { let l_loc = self.codemap.lookup_char_pos(span.lo); let file_offset = l_loc.file.start_pos.0; @@ -187,29 +78,11 @@ impl<'a> ChangeSet<'a> { text) } - // start and end are unadjusted. pub fn slice(&self, file_name: &str, start: usize, end: usize) -> RopeSlice { - // TODO refactor with change? - let abs_start = { - let before_start = self.adjusts.range(Unbounded, Included(&start)).next_back(); - match before_start { - Some((k, ref a)) if a.end > start => (start as isize + a.delta) as usize, - _ => start - } - }; - let abs_end = { - let before_end = self.adjusts.range(Unbounded, Included(&end)).next_back(); - match before_end { - Some((k, ref a)) if a.end > end => (end as isize + a.delta) as usize, - _ => end - } - }; - let file = &self.file_map[*file_name]; - file.slice(abs_start..abs_end) + file.src_slice(start..end) } - // span is unadjusted. pub fn slice_span(&self, span:Span) -> RopeSlice { let l_loc = self.codemap.lookup_char_pos(span.lo); let file_offset = l_loc.file.start_pos.0; @@ -225,6 +98,13 @@ impl<'a> ChangeSet<'a> { cur_key: 0, } } + + pub fn col(&self, loc: BytePos) -> usize { + let l_loc = self.codemap.lookup_char_pos(loc); + let file_offset = l_loc.file.start_pos.0; + let file = &self.file_map[l_loc.file.name[]]; + file.col_for_src_loc(loc.0 as usize - file_offset as usize) + } } impl<'c, 'a> Iterator for FileIterator<'c, 'a> { |
