From 5f579a4287625a109cfa855f97bdd6fccbe1a7da Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 31 Mar 2023 18:03:38 +0200 Subject: [PATCH] Fix prefix/suffix calculation when determining copilot suggestion Co-Authored-By: Nathan Sobo Co-Authored-By: Mikayla Maki --- crates/editor/src/editor.rs | 34 +++++++++++++++---------------- crates/editor/src/multi_buffer.rs | 4 ++++ crates/text/src/text.rs | 8 ++++++++ 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 62efad288d9733990bf17a3ec62a5970cf248c94..0b6d19e34a2ba30cf0ef77a381c08954199d4fbd 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1041,29 +1041,26 @@ impl CopilotState { cursor: Anchor, buffer: &MultiBufferSnapshot, ) -> Option<&str> { + use language::ToOffset as _; + let completion = self.completions.get(self.active_completion_index)?; let excerpt_id = self.excerpt_id?; - let completion_buffer_id = buffer.buffer_id_for_excerpt(excerpt_id); - let completion_start = Anchor { - excerpt_id, - buffer_id: completion_buffer_id, - text_anchor: completion.range.start, - }; - let completion_end = Anchor { - excerpt_id, - buffer_id: completion_buffer_id, - text_anchor: completion.range.end, - }; - let prefix_len = common_prefix(buffer.chars_at(completion_start), completion.text.chars()); + let completion_buffer = buffer.buffer_for_excerpt(excerpt_id)?; + + let mut completion_range = completion.range.to_offset(&completion_buffer); + let prefix_len = common_prefix( + completion_buffer.chars_for_range(completion_range.clone()), + completion.text.chars(), + ); + completion_range.start += prefix_len; let suffix_len = common_prefix( - buffer.reversed_chars_at(completion_end), - completion.text.chars().rev(), + completion_buffer.reversed_chars_for_range(completion_range.clone()), + completion.text[prefix_len..].chars().rev(), ); + completion_range.end = completion_range.end.saturating_sub(suffix_len); - let prefix_end_offset = completion_start.to_offset(&buffer) + prefix_len; - let suffix_start_offset = completion_end.to_offset(&buffer) - suffix_len; - if prefix_end_offset == suffix_start_offset - && prefix_end_offset == cursor.to_offset(&buffer) + if completion_range.is_empty() + && completion_range.start == cursor.text_anchor.to_offset(&completion_buffer) { Some(&completion.text[prefix_len..completion.text.len() - suffix_len]) } else { @@ -6492,6 +6489,7 @@ impl Editor { multi_buffer::Event::Edited => { self.refresh_active_diagnostics(cx); self.refresh_code_actions(cx); + self.refresh_copilot_suggestions(cx); cx.emit(Event::BufferEdited); } multi_buffer::Event::ExcerptsAdded { diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 0b85f94f087ab8da62a070d2c036103b53dcdd3d..ed4d297c51ed683426880ae54ee60f7217985f6d 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -2933,6 +2933,10 @@ impl MultiBufferSnapshot { Some(self.excerpt(excerpt_id)?.buffer_id) } + pub fn buffer_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<&BufferSnapshot> { + Some(&self.excerpt(excerpt_id)?.buffer) + } + fn excerpt<'a>(&'a self, excerpt_id: ExcerptId) -> Option<&'a Excerpt> { let mut cursor = self.excerpts.cursor::>(); let locator = self.excerpt_locator_for_id(excerpt_id); diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index c7d36e29def55aa2be84445ed14090b26a970b52..11d451eab0621fb779da6f1f344359bfd708ced2 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -1579,6 +1579,14 @@ impl BufferSnapshot { self.text_for_range(range).flat_map(str::chars) } + pub fn reversed_chars_for_range( + &self, + range: Range, + ) -> impl Iterator + '_ { + self.reversed_chunks_in_range(range) + .flat_map(|chunk| chunk.chars().rev()) + } + pub fn contains_str_at(&self, position: T, needle: &str) -> bool where T: ToOffset,