diff options
Diffstat (limited to 'crates/ra_ide_db/src/line_index.rs')
-rw-r--r-- | crates/ra_ide_db/src/line_index.rs | 66 |
1 files changed, 31 insertions, 35 deletions
diff --git a/crates/ra_ide_db/src/line_index.rs b/crates/ra_ide_db/src/line_index.rs index 8ae745ff2..00ba95913 100644 --- a/crates/ra_ide_db/src/line_index.rs +++ b/crates/ra_ide_db/src/line_index.rs | |||
@@ -1,14 +1,14 @@ | |||
1 | //! `LineIndex` maps flat `TextUnit` offsets into `(Line, Column)` | 1 | //! `LineIndex` maps flat `TextSize` offsets into `(Line, Column)` |
2 | //! representation. | 2 | //! representation. |
3 | use std::iter; | 3 | use std::iter; |
4 | 4 | ||
5 | use ra_syntax::{TextRange, TextUnit}; | 5 | use ra_syntax::{TextRange, TextSize}; |
6 | use rustc_hash::FxHashMap; | 6 | use rustc_hash::FxHashMap; |
7 | use superslice::Ext; | 7 | use superslice::Ext; |
8 | 8 | ||
9 | #[derive(Clone, Debug, PartialEq, Eq)] | 9 | #[derive(Clone, Debug, PartialEq, Eq)] |
10 | pub struct LineIndex { | 10 | pub struct LineIndex { |
11 | pub(crate) newlines: Vec<TextUnit>, | 11 | pub(crate) newlines: Vec<TextSize>, |
12 | pub(crate) utf16_lines: FxHashMap<u32, Vec<Utf16Char>>, | 12 | pub(crate) utf16_lines: FxHashMap<u32, Vec<Utf16Char>>, |
13 | } | 13 | } |
14 | 14 | ||
@@ -22,12 +22,12 @@ pub struct LineCol { | |||
22 | 22 | ||
23 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] | 23 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] |
24 | pub(crate) struct Utf16Char { | 24 | pub(crate) struct Utf16Char { |
25 | pub(crate) start: TextUnit, | 25 | pub(crate) start: TextSize, |
26 | pub(crate) end: TextUnit, | 26 | pub(crate) end: TextSize, |
27 | } | 27 | } |
28 | 28 | ||
29 | impl Utf16Char { | 29 | impl Utf16Char { |
30 | fn len(&self) -> TextUnit { | 30 | fn len(&self) -> TextSize { |
31 | self.end - self.start | 31 | self.end - self.start |
32 | } | 32 | } |
33 | } | 33 | } |
@@ -42,7 +42,8 @@ impl LineIndex { | |||
42 | let mut curr_col = 0.into(); | 42 | let mut curr_col = 0.into(); |
43 | let mut line = 0; | 43 | let mut line = 0; |
44 | for c in text.chars() { | 44 | for c in text.chars() { |
45 | curr_row += TextUnit::of_char(c); | 45 | let c_len = TextSize::of(c); |
46 | curr_row += c_len; | ||
46 | if c == '\n' { | 47 | if c == '\n' { |
47 | newlines.push(curr_row); | 48 | newlines.push(curr_row); |
48 | 49 | ||
@@ -58,12 +59,11 @@ impl LineIndex { | |||
58 | continue; | 59 | continue; |
59 | } | 60 | } |
60 | 61 | ||
61 | let char_len = TextUnit::of_char(c); | 62 | if !c.is_ascii() { |
62 | if char_len > TextUnit::from_usize(1) { | 63 | utf16_chars.push(Utf16Char { start: curr_col, end: curr_col + c_len }); |
63 | utf16_chars.push(Utf16Char { start: curr_col, end: curr_col + char_len }); | ||
64 | } | 64 | } |
65 | 65 | ||
66 | curr_col += char_len; | 66 | curr_col += c_len; |
67 | } | 67 | } |
68 | 68 | ||
69 | // Save any utf-16 characters seen in the last line | 69 | // Save any utf-16 characters seen in the last line |
@@ -74,7 +74,7 @@ impl LineIndex { | |||
74 | LineIndex { newlines, utf16_lines } | 74 | LineIndex { newlines, utf16_lines } |
75 | } | 75 | } |
76 | 76 | ||
77 | pub fn line_col(&self, offset: TextUnit) -> LineCol { | 77 | pub fn line_col(&self, offset: TextSize) -> LineCol { |
78 | let line = self.newlines.upper_bound(&offset) - 1; | 78 | let line = self.newlines.upper_bound(&offset) - 1; |
79 | let line_start_offset = self.newlines[line]; | 79 | let line_start_offset = self.newlines[line]; |
80 | let col = offset - line_start_offset; | 80 | let col = offset - line_start_offset; |
@@ -82,7 +82,7 @@ impl LineIndex { | |||
82 | LineCol { line: line as u32, col_utf16: self.utf8_to_utf16_col(line as u32, col) as u32 } | 82 | LineCol { line: line as u32, col_utf16: self.utf8_to_utf16_col(line as u32, col) as u32 } |
83 | } | 83 | } |
84 | 84 | ||
85 | pub fn offset(&self, line_col: LineCol) -> TextUnit { | 85 | pub fn offset(&self, line_col: LineCol) -> TextSize { |
86 | //FIXME: return Result | 86 | //FIXME: return Result |
87 | let col = self.utf16_to_utf8_col(line_col.line, line_col.col_utf16); | 87 | let col = self.utf16_to_utf8_col(line_col.line, line_col.col_utf16); |
88 | self.newlines[line_col.line as usize] + col | 88 | self.newlines[line_col.line as usize] + col |
@@ -97,35 +97,31 @@ impl LineIndex { | |||
97 | 97 | ||
98 | all.clone() | 98 | all.clone() |
99 | .zip(all.skip(1)) | 99 | .zip(all.skip(1)) |
100 | .map(|(lo, hi)| TextRange::from_to(lo, hi)) | 100 | .map(|(lo, hi)| TextRange::new(lo, hi)) |
101 | .filter(|it| !it.is_empty()) | 101 | .filter(|it| !it.is_empty()) |
102 | } | 102 | } |
103 | 103 | ||
104 | fn utf8_to_utf16_col(&self, line: u32, col: TextUnit) -> usize { | 104 | fn utf8_to_utf16_col(&self, line: u32, col: TextSize) -> usize { |
105 | let mut res: usize = col.into(); | ||
105 | if let Some(utf16_chars) = self.utf16_lines.get(&line) { | 106 | if let Some(utf16_chars) = self.utf16_lines.get(&line) { |
106 | let mut correction = 0; | ||
107 | for c in utf16_chars { | 107 | for c in utf16_chars { |
108 | if col >= c.end { | 108 | if c.end <= col { |
109 | correction += c.len().to_usize() - 1; | 109 | res -= usize::from(c.len()) - 1; |
110 | } else { | 110 | } else { |
111 | // From here on, all utf16 characters come *after* the character we are mapping, | 111 | // From here on, all utf16 characters come *after* the character we are mapping, |
112 | // so we don't need to take them into account | 112 | // so we don't need to take them into account |
113 | break; | 113 | break; |
114 | } | 114 | } |
115 | } | 115 | } |
116 | |||
117 | col.to_usize() - correction | ||
118 | } else { | ||
119 | col.to_usize() | ||
120 | } | 116 | } |
117 | res | ||
121 | } | 118 | } |
122 | 119 | ||
123 | fn utf16_to_utf8_col(&self, line: u32, col: u32) -> TextUnit { | 120 | fn utf16_to_utf8_col(&self, line: u32, mut col: u32) -> TextSize { |
124 | let mut col: TextUnit = col.into(); | ||
125 | if let Some(utf16_chars) = self.utf16_lines.get(&line) { | 121 | if let Some(utf16_chars) = self.utf16_lines.get(&line) { |
126 | for c in utf16_chars { | 122 | for c in utf16_chars { |
127 | if col >= c.start { | 123 | if col >= u32::from(c.start) { |
128 | col += c.len() - TextUnit::from_usize(1); | 124 | col += u32::from(c.len()) - 1; |
129 | } else { | 125 | } else { |
130 | // From here on, all utf16 characters come *after* the character we are mapping, | 126 | // From here on, all utf16 characters come *after* the character we are mapping, |
131 | // so we don't need to take them into account | 127 | // so we don't need to take them into account |
@@ -134,12 +130,12 @@ impl LineIndex { | |||
134 | } | 130 | } |
135 | } | 131 | } |
136 | 132 | ||
137 | col | 133 | col.into() |
138 | } | 134 | } |
139 | } | 135 | } |
140 | 136 | ||
141 | #[cfg(test)] | 137 | #[cfg(test)] |
142 | mod test_line_index { | 138 | mod tests { |
143 | use super::*; | 139 | use super::*; |
144 | 140 | ||
145 | #[test] | 141 | #[test] |
@@ -200,10 +196,10 @@ const C: char = 'メ'; | |||
200 | assert_eq!(col_index.utf8_to_utf16_col(1, 22.into()), 20); | 196 | assert_eq!(col_index.utf8_to_utf16_col(1, 22.into()), 20); |
201 | 197 | ||
202 | // UTF-16 to UTF-8, no changes | 198 | // UTF-16 to UTF-8, no changes |
203 | assert_eq!(col_index.utf16_to_utf8_col(1, 15), TextUnit::from(15)); | 199 | assert_eq!(col_index.utf16_to_utf8_col(1, 15), TextSize::from(15)); |
204 | 200 | ||
205 | // UTF-16 to UTF-8 | 201 | // UTF-16 to UTF-8 |
206 | assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextUnit::from(21)); | 202 | assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(21)); |
207 | } | 203 | } |
208 | 204 | ||
209 | #[test] | 205 | #[test] |
@@ -228,18 +224,18 @@ const C: char = \"メ メ\"; | |||
228 | assert!(col_index.utf8_to_utf16_col(2, 15.into()) == 15); | 224 | assert!(col_index.utf8_to_utf16_col(2, 15.into()) == 15); |
229 | 225 | ||
230 | // UTF-16 to UTF-8 | 226 | // UTF-16 to UTF-8 |
231 | assert_eq!(col_index.utf16_to_utf8_col(1, 15), TextUnit::from_usize(15)); | 227 | assert_eq!(col_index.utf16_to_utf8_col(1, 15), TextSize::from(15)); |
232 | 228 | ||
233 | assert_eq!(col_index.utf16_to_utf8_col(1, 18), TextUnit::from_usize(20)); | 229 | assert_eq!(col_index.utf16_to_utf8_col(1, 18), TextSize::from(20)); |
234 | assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextUnit::from_usize(23)); | 230 | assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(23)); |
235 | 231 | ||
236 | assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextUnit::from_usize(15)); | 232 | assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextSize::from(15)); |
237 | } | 233 | } |
238 | 234 | ||
239 | #[test] | 235 | #[test] |
240 | fn test_splitlines() { | 236 | fn test_splitlines() { |
241 | fn r(lo: u32, hi: u32) -> TextRange { | 237 | fn r(lo: u32, hi: u32) -> TextRange { |
242 | TextRange::from_to(lo.into(), hi.into()) | 238 | TextRange::new(lo.into(), hi.into()) |
243 | } | 239 | } |
244 | 240 | ||
245 | let text = "a\nbb\nccc\n"; | 241 | let text = "a\nbb\nccc\n"; |