diff --git a/crates/language/src/diagnostic_set.rs b/crates/language/src/diagnostic_set.rs index b52327cac0e81b4ddbf7f224ebef170ac92d3f15..fe2e4c9c212a642c9f8b24e4d5347d5d46e994c2 100644 --- a/crates/language/src/diagnostic_set.rs +++ b/crates/language/src/diagnostic_set.rs @@ -70,8 +70,8 @@ impl DiagnosticSet { Self { diagnostics: SumTree::from_iter( entries.into_iter().map(|entry| DiagnosticEntry { - range: buffer.anchor_before(entry.range.start) - ..buffer.anchor_after(entry.range.end), + range: buffer.clamped_anchor_before(entry.range.start) + ..buffer.clamped_anchor_after(entry.range.end), diagnostic: entry.diagnostic, }), buffer, diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 37f6e76340ebdc59f623a61bd1cbb9ef4e168b04..78c6b50003605bf65c1e2b3f05b75d2d00ca9e89 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -131,7 +131,9 @@ impl LspCommand for PrepareRename { if buffer.clip_point_utf16(start, Bias::Left) == start && buffer.clip_point_utf16(end, Bias::Left) == end { - return Ok(Some(buffer.anchor_after(start)..buffer.anchor_before(end))); + return Ok(Some( + buffer.clamped_anchor_after(start)..buffer.clamped_anchor_before(end), + )); } } Ok(None) @@ -143,7 +145,7 @@ impl LspCommand for PrepareRename { project_id, buffer_id: buffer.remote_id(), position: Some(language::proto::serialize_anchor( - &buffer.anchor_before(self.position), + &buffer.clamped_anchor_before(self.position), )), version: serialize_version(&buffer.version()), } @@ -262,7 +264,7 @@ impl LspCommand for PerformRename { project_id, buffer_id: buffer.remote_id(), position: Some(language::proto::serialize_anchor( - &buffer.anchor_before(self.position), + &buffer.clamped_anchor_before(self.position), )), new_name: self.new_name.clone(), version: serialize_version(&buffer.version()), @@ -360,7 +362,7 @@ impl LspCommand for GetDefinition { project_id, buffer_id: buffer.remote_id(), position: Some(language::proto::serialize_anchor( - &buffer.anchor_before(self.position), + &buffer.clamped_anchor_before(self.position), )), version: serialize_version(&buffer.version()), } @@ -446,7 +448,7 @@ impl LspCommand for GetTypeDefinition { project_id, buffer_id: buffer.remote_id(), position: Some(language::proto::serialize_anchor( - &buffer.anchor_before(self.position), + &buffer.clamped_anchor_before(self.position), )), version: serialize_version(&buffer.version()), } @@ -629,8 +631,8 @@ async fn location_links_from_lsp( origin_buffer.clip_point_utf16(point_from_lsp(origin_range.end), Bias::Left); Location { buffer: buffer.clone(), - range: origin_buffer.anchor_after(origin_start) - ..origin_buffer.anchor_before(origin_end), + range: origin_buffer.clamped_anchor_after(origin_start) + ..origin_buffer.clamped_anchor_before(origin_end), } }); @@ -641,8 +643,8 @@ async fn location_links_from_lsp( target_buffer.clip_point_utf16(point_from_lsp(target_range.end), Bias::Left); let target_location = Location { buffer: target_buffer_handle, - range: target_buffer.anchor_after(target_start) - ..target_buffer.anchor_before(target_end), + range: target_buffer.clamped_anchor_after(target_start) + ..target_buffer.clamped_anchor_before(target_end), }; definitions.push(LocationLink { @@ -741,8 +743,8 @@ impl LspCommand for GetReferences { .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left); references.push(Location { buffer: target_buffer_handle, - range: target_buffer.anchor_after(target_start) - ..target_buffer.anchor_before(target_end), + range: target_buffer.clamped_anchor_after(target_start) + ..target_buffer.clamped_anchor_before(target_end), }); }); } @@ -756,7 +758,7 @@ impl LspCommand for GetReferences { project_id, buffer_id: buffer.remote_id(), position: Some(language::proto::serialize_anchor( - &buffer.anchor_before(self.position), + &buffer.clamped_anchor_before(self.position), )), version: serialize_version(&buffer.version()), } @@ -882,7 +884,8 @@ impl LspCommand for GetDocumentHighlights { let end = buffer .clip_point_utf16(point_from_lsp(lsp_highlight.range.end), Bias::Left); DocumentHighlight { - range: buffer.anchor_after(start)..buffer.anchor_before(end), + range: buffer.clamped_anchor_after(start) + ..buffer.clamped_anchor_before(end), kind: lsp_highlight .kind .unwrap_or(lsp::DocumentHighlightKind::READ), @@ -897,7 +900,7 @@ impl LspCommand for GetDocumentHighlights { project_id, buffer_id: buffer.remote_id(), position: Some(language::proto::serialize_anchor( - &buffer.anchor_before(self.position), + &buffer.clamped_anchor_before(self.position), )), version: serialize_version(&buffer.version()), } @@ -1017,7 +1020,8 @@ impl LspCommand for GetHover { let token_start = buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left); let token_end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left); - buffer.anchor_after(token_start)..buffer.anchor_before(token_end) + buffer.clamped_anchor_after(token_start) + ..buffer.clamped_anchor_before(token_end) }) }); @@ -1099,7 +1103,7 @@ impl LspCommand for GetHover { project_id, buffer_id: buffer.remote_id(), position: Some(language::proto::serialize_anchor( - &buffer.anchor_before(self.position), + &buffer.clamped_anchor_before(self.position), )), version: serialize_version(&buffer.version), } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index c4e920db84cd35585be6643bd68f67daaa612ebb..2036ef3cd8bc3729aa95da920a99bc7c6852e8c0 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -25,7 +25,8 @@ use language::{ range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CachedLspAdapter, CharKind, CodeAction, CodeLabel, Completion, Diagnostic, DiagnosticEntry, DiagnosticSet, Event as BufferEvent, File as _, Language, LanguageRegistry, LanguageServerName, LocalFile, OffsetRangeExt, - Operation, Patch, PointUtf16, TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction, + Operation, Patch, PointUtf16, TextBufferSnapshot, ToOffset, ToOffsetClamped, ToPointUtf16, + Transaction, }; use lsp::{ DiagnosticSeverity, DiagnosticTag, DocumentHighlightKind, LanguageServer, LanguageString, @@ -3289,7 +3290,7 @@ impl Project { }; let position = position.to_point_utf16(source_buffer); - let anchor = source_buffer.anchor_after(position); + let anchor = source_buffer.clamped_anchor_after(position); if worktree.read(cx).as_local().is_some() { let buffer_abs_path = buffer_abs_path.unwrap(); @@ -3355,7 +3356,7 @@ impl Project { return None; } ( - snapshot.anchor_before(start)..snapshot.anchor_after(end), + snapshot.clamped_anchor_before(start)..snapshot.clamped_anchor_after(end), edit.new_text.clone(), ) } @@ -3368,7 +3369,7 @@ impl Project { } let Range { start, end } = range_for_token .get_or_insert_with(|| { - let offset = position.to_offset(&snapshot); + let offset = position.to_offset_clamped(&snapshot); let (range, kind) = snapshot.surrounding_word(offset); if kind == Some(CharKind::Word) { range @@ -5742,7 +5743,7 @@ impl Project { // we can identify the changes more precisely, preserving the locations // of any anchors positioned in the unchanged regions. if range.end.row > range.start.row { - let mut offset = range.start.to_offset(&snapshot); + let mut offset = range.start.to_offset_clamped(&snapshot); let old_text = snapshot.text_for_clamped_range(range).collect::(); let diff = TextDiff::from_lines(old_text.as_str(), &new_text); @@ -5778,11 +5779,11 @@ impl Project { } } } else if range.end == range.start { - let anchor = snapshot.anchor_after(range.start); + let anchor = snapshot.clamped_anchor_after(range.start); edits.push((anchor..anchor, new_text)); } else { - let edit_start = snapshot.anchor_after(range.start); - let edit_end = snapshot.anchor_before(range.end); + let edit_start = snapshot.clamped_anchor_after(range.start); + let edit_end = snapshot.clamped_anchor_before(range.end); edits.push((edit_start..edit_end, new_text)); } } diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index 272e425651cd7dca74c57206d3de04f68d9a6d89..42ffe5c6edc266283f0e54590f5c7dc6b1c877fa 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -1808,12 +1808,23 @@ impl BufferSnapshot { self.anchor_at(position, Bias::Left) } + pub fn clamped_anchor_before(&self, position: T) -> Anchor { + self.anchor_at_offset(position.to_offset_clamped(self), Bias::Left) + } + pub fn anchor_after(&self, position: T) -> Anchor { self.anchor_at(position, Bias::Right) } + pub fn clamped_anchor_after(&self, position: T) -> Anchor { + self.anchor_at_offset(position.to_offset_clamped(self), Bias::Right) + } + pub fn anchor_at(&self, position: T, bias: Bias) -> Anchor { - let offset = position.to_offset(self); + self.anchor_at_offset(position.to_offset(self), bias) + } + + fn anchor_at_offset(&self, offset: usize, bias: Bias) -> Anchor { if bias == Bias::Left && offset == 0 { Anchor::MIN } else if bias == Bias::Right && offset == self.len() { @@ -2369,12 +2380,6 @@ impl ToOffset for Point { } } -impl ToOffset for PointUtf16 { - fn to_offset<'a>(&self, snapshot: &BufferSnapshot) -> usize { - snapshot.point_utf16_to_offset(*self) - } -} - impl ToOffset for usize { fn to_offset<'a>(&self, snapshot: &BufferSnapshot) -> usize { assert!(*self <= snapshot.len(), "offset {self} is out of range"); @@ -2382,12 +2387,6 @@ impl ToOffset for usize { } } -impl ToOffset for OffsetUtf16 { - fn to_offset<'a>(&self, snapshot: &BufferSnapshot) -> usize { - snapshot.offset_utf16_to_offset(*self) - } -} - impl ToOffset for Anchor { fn to_offset<'a>(&self, snapshot: &BufferSnapshot) -> usize { snapshot.summary_for_anchor(self)