diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_ide_db/src/line_index.rs | 12 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 18 |
2 files changed, 26 insertions, 4 deletions
diff --git a/crates/ra_ide_db/src/line_index.rs b/crates/ra_ide_db/src/line_index.rs index 00ba95913..212cb7b5b 100644 --- a/crates/ra_ide_db/src/line_index.rs +++ b/crates/ra_ide_db/src/line_index.rs | |||
@@ -8,7 +8,9 @@ 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 | /// Offset the the beginning of each line, zero-based | ||
11 | pub(crate) newlines: Vec<TextSize>, | 12 | pub(crate) newlines: Vec<TextSize>, |
13 | /// List of non-ASCII characters on each line | ||
12 | pub(crate) utf16_lines: FxHashMap<u32, Vec<Utf16Char>>, | 14 | pub(crate) utf16_lines: FxHashMap<u32, Vec<Utf16Char>>, |
13 | } | 15 | } |
14 | 16 | ||
@@ -22,7 +24,9 @@ pub struct LineCol { | |||
22 | 24 | ||
23 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] | 25 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] |
24 | pub(crate) struct Utf16Char { | 26 | pub(crate) struct Utf16Char { |
27 | /// Start offset of a character inside a line, zero-based | ||
25 | pub(crate) start: TextSize, | 28 | pub(crate) start: TextSize, |
29 | /// End offset of a character inside a line, zero-based | ||
26 | pub(crate) end: TextSize, | 30 | pub(crate) end: TextSize, |
27 | } | 31 | } |
28 | 32 | ||
@@ -120,7 +124,7 @@ impl LineIndex { | |||
120 | fn utf16_to_utf8_col(&self, line: u32, mut col: u32) -> TextSize { | 124 | fn utf16_to_utf8_col(&self, line: u32, mut col: u32) -> TextSize { |
121 | if let Some(utf16_chars) = self.utf16_lines.get(&line) { | 125 | if let Some(utf16_chars) = self.utf16_lines.get(&line) { |
122 | for c in utf16_chars { | 126 | for c in utf16_chars { |
123 | if col >= u32::from(c.start) { | 127 | if col > u32::from(c.start) { |
124 | col += u32::from(c.len()) - 1; | 128 | col += u32::from(c.len()) - 1; |
125 | } else { | 129 | } else { |
126 | // From here on, all utf16 characters come *after* the character we are mapping, | 130 | // From here on, all utf16 characters come *after* the character we are mapping, |
@@ -226,8 +230,10 @@ const C: char = \"メ メ\"; | |||
226 | // UTF-16 to UTF-8 | 230 | // UTF-16 to UTF-8 |
227 | assert_eq!(col_index.utf16_to_utf8_col(1, 15), TextSize::from(15)); | 231 | assert_eq!(col_index.utf16_to_utf8_col(1, 15), TextSize::from(15)); |
228 | 232 | ||
229 | assert_eq!(col_index.utf16_to_utf8_col(1, 18), TextSize::from(20)); | 233 | // メ UTF-8: 0xE3 0x83 0xA1, UTF-16: 0x30E1 |
230 | assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(23)); | 234 | assert_eq!(col_index.utf16_to_utf8_col(1, 17), TextSize::from(17)); // first メ at 17..20 |
235 | assert_eq!(col_index.utf16_to_utf8_col(1, 18), TextSize::from(20)); // space | ||
236 | assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(21)); // second メ at 21..24 | ||
231 | 237 | ||
232 | assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextSize::from(15)); | 238 | assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextSize::from(15)); |
233 | } | 239 | } |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 3bc2e0a46..401fae755 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -666,6 +666,10 @@ fn apply_document_changes( | |||
666 | mut line_index: Cow<'_, LineIndex>, | 666 | mut line_index: Cow<'_, LineIndex>, |
667 | content_changes: Vec<TextDocumentContentChangeEvent>, | 667 | content_changes: Vec<TextDocumentContentChangeEvent>, |
668 | ) { | 668 | ) { |
669 | // Remove when https://github.com/rust-analyzer/rust-analyzer/issues/4263 is fixed. | ||
670 | let backup_text = old_text.clone(); | ||
671 | let backup_changes = content_changes.clone(); | ||
672 | |||
669 | // The changes we got must be applied sequentially, but can cross lines so we | 673 | // The changes we got must be applied sequentially, but can cross lines so we |
670 | // have to keep our line index updated. | 674 | // have to keep our line index updated. |
671 | // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we | 675 | // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we |
@@ -693,7 +697,19 @@ fn apply_document_changes( | |||
693 | } | 697 | } |
694 | index_valid = IndexValid::UpToLine(range.start.line); | 698 | index_valid = IndexValid::UpToLine(range.start.line); |
695 | let range = range.conv_with(&line_index); | 699 | let range = range.conv_with(&line_index); |
696 | old_text.replace_range(Range::<usize>::from(range), &change.text); | 700 | let mut text = old_text.to_owned(); |
701 | match std::panic::catch_unwind(move || { | ||
702 | text.replace_range(Range::<usize>::from(range), &change.text); | ||
703 | text | ||
704 | }) { | ||
705 | Ok(t) => *old_text = t, | ||
706 | Err(e) => { | ||
707 | eprintln!("Bug in incremental text synchronization. Please report the following output on https://github.com/rust-analyzer/rust-analyzer/issues/4263"); | ||
708 | dbg!(&backup_text); | ||
709 | dbg!(&backup_changes); | ||
710 | std::panic::resume_unwind(e); | ||
711 | } | ||
712 | } | ||
697 | } | 713 | } |
698 | None => { | 714 | None => { |
699 | *old_text = change.text; | 715 | *old_text = change.text; |