diff options
author | Laurențiu Nicola <[email protected]> | 2020-05-05 18:29:04 +0100 |
---|---|---|
committer | Laurențiu Nicola <[email protected]> | 2020-05-05 18:30:52 +0100 |
commit | 1d794e859028a71d182daf2fa5826aeeeab2876b (patch) | |
tree | 981d21ae4344d21df71a549f61973dbe927bb3dc | |
parent | 7ec1b63f813e45f26668c2d6d803ec72c3c75738 (diff) |
Fix column conversion for supplementary plane characters
-rw-r--r-- | crates/ra_ide_db/src/line_index.rs | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/crates/ra_ide_db/src/line_index.rs b/crates/ra_ide_db/src/line_index.rs index 212cb7b5b..c7c744fce 100644 --- a/crates/ra_ide_db/src/line_index.rs +++ b/crates/ra_ide_db/src/line_index.rs | |||
@@ -31,9 +31,19 @@ pub(crate) struct Utf16Char { | |||
31 | } | 31 | } |
32 | 32 | ||
33 | impl Utf16Char { | 33 | impl Utf16Char { |
34 | /// Returns the length in 8-bit UTF-8 code units. | ||
34 | fn len(&self) -> TextSize { | 35 | fn len(&self) -> TextSize { |
35 | self.end - self.start | 36 | self.end - self.start |
36 | } | 37 | } |
38 | |||
39 | /// Returns the length in 16-bit UTF-16 code units. | ||
40 | fn len_utf16(&self) -> usize { | ||
41 | if self.len() == TextSize::from(4) { | ||
42 | 2 | ||
43 | } else { | ||
44 | 1 | ||
45 | } | ||
46 | } | ||
37 | } | 47 | } |
38 | 48 | ||
39 | impl LineIndex { | 49 | impl LineIndex { |
@@ -110,7 +120,7 @@ impl LineIndex { | |||
110 | if let Some(utf16_chars) = self.utf16_lines.get(&line) { | 120 | if let Some(utf16_chars) = self.utf16_lines.get(&line) { |
111 | for c in utf16_chars { | 121 | for c in utf16_chars { |
112 | if c.end <= col { | 122 | if c.end <= col { |
113 | res -= usize::from(c.len()) - 1; | 123 | res -= usize::from(c.len()) - c.len_utf16(); |
114 | } else { | 124 | } else { |
115 | // From here on, all utf16 characters come *after* the character we are mapping, | 125 | // From here on, all utf16 characters come *after* the character we are mapping, |
116 | // so we don't need to take them into account | 126 | // so we don't need to take them into account |
@@ -125,7 +135,7 @@ impl LineIndex { | |||
125 | if let Some(utf16_chars) = self.utf16_lines.get(&line) { | 135 | if let Some(utf16_chars) = self.utf16_lines.get(&line) { |
126 | for c in utf16_chars { | 136 | for c in utf16_chars { |
127 | if col > u32::from(c.start) { | 137 | if col > u32::from(c.start) { |
128 | col += u32::from(c.len()) - 1; | 138 | col += u32::from(c.len()) - c.len_utf16() as u32; |
129 | } else { | 139 | } else { |
130 | // From here on, all utf16 characters come *after* the character we are mapping, | 140 | // From here on, all utf16 characters come *after* the character we are mapping, |
131 | // so we don't need to take them into account | 141 | // so we don't need to take them into account |
@@ -204,6 +214,9 @@ const C: char = 'メ'; | |||
204 | 214 | ||
205 | // UTF-16 to UTF-8 | 215 | // UTF-16 to UTF-8 |
206 | assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(21)); | 216 | assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(21)); |
217 | |||
218 | let col_index = LineIndex::new("a𐐏b"); | ||
219 | assert_eq!(col_index.utf16_to_utf8_col(0, 3), TextSize::from(5)); | ||
207 | } | 220 | } |
208 | 221 | ||
209 | #[test] | 222 | #[test] |