diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index b4fb6a503c..bf237b9ad9 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -738,7 +738,7 @@ mod tests { DisplayPoint, }; use gpui::TestAppContext; - use language::{Diagnostic, DiagnosticEntry, DiagnosticSeverity, PointUtf16}; + use language::{Diagnostic, DiagnosticEntry, DiagnosticSeverity, PointUtf16, Unclipped}; use serde_json::json; use unindent::Unindent as _; use workspace::AppState; @@ -788,7 +788,7 @@ mod tests { None, vec![ DiagnosticEntry { - range: PointUtf16::new(1, 8)..PointUtf16::new(1, 9), + range: Unclipped(PointUtf16::new(1, 8))..Unclipped(PointUtf16::new(1, 9)), diagnostic: Diagnostic { message: "move occurs because `x` has type `Vec`, which does not implement the `Copy` trait" @@ -801,7 +801,7 @@ mod tests { }, }, DiagnosticEntry { - range: PointUtf16::new(2, 8)..PointUtf16::new(2, 9), + range: Unclipped(PointUtf16::new(2, 8))..Unclipped(PointUtf16::new(2, 9)), diagnostic: Diagnostic { message: "move occurs because `y` has type `Vec`, which does not implement the `Copy` trait" @@ -814,7 +814,7 @@ mod tests { }, }, DiagnosticEntry { - range: PointUtf16::new(3, 6)..PointUtf16::new(3, 7), + range: Unclipped(PointUtf16::new(3, 6))..Unclipped(PointUtf16::new(3, 7)), diagnostic: Diagnostic { message: "value moved here".to_string(), severity: DiagnosticSeverity::INFORMATION, @@ -825,7 +825,7 @@ mod tests { }, }, DiagnosticEntry { - range: PointUtf16::new(4, 6)..PointUtf16::new(4, 7), + range: Unclipped(PointUtf16::new(4, 6))..Unclipped(PointUtf16::new(4, 7)), diagnostic: Diagnostic { message: "value moved here".to_string(), severity: DiagnosticSeverity::INFORMATION, @@ -836,7 +836,7 @@ mod tests { }, }, DiagnosticEntry { - range: PointUtf16::new(7, 6)..PointUtf16::new(7, 7), + range: Unclipped(PointUtf16::new(7, 6))..Unclipped(PointUtf16::new(7, 7)), diagnostic: Diagnostic { message: "use of moved value\nvalue used here after move".to_string(), severity: DiagnosticSeverity::ERROR, @@ -847,7 +847,7 @@ mod tests { }, }, DiagnosticEntry { - range: PointUtf16::new(8, 6)..PointUtf16::new(8, 7), + range: Unclipped(PointUtf16::new(8, 6))..Unclipped(PointUtf16::new(8, 7)), diagnostic: Diagnostic { message: "use of moved value\nvalue used here after move".to_string(), severity: DiagnosticSeverity::ERROR, @@ -939,7 +939,7 @@ mod tests { PathBuf::from("/test/consts.rs"), None, vec![DiagnosticEntry { - range: PointUtf16::new(0, 15)..PointUtf16::new(0, 15), + range: Unclipped(PointUtf16::new(0, 15))..Unclipped(PointUtf16::new(0, 15)), diagnostic: Diagnostic { message: "mismatched types\nexpected `usize`, found `char`".to_string(), severity: DiagnosticSeverity::ERROR, @@ -1040,7 +1040,8 @@ mod tests { None, vec![ DiagnosticEntry { - range: PointUtf16::new(0, 15)..PointUtf16::new(0, 15), + range: Unclipped(PointUtf16::new(0, 15)) + ..Unclipped(PointUtf16::new(0, 15)), diagnostic: Diagnostic { message: "mismatched types\nexpected `usize`, found `char`" .to_string(), @@ -1052,7 +1053,8 @@ mod tests { }, }, DiagnosticEntry { - range: PointUtf16::new(1, 15)..PointUtf16::new(1, 15), + range: Unclipped(PointUtf16::new(1, 15)) + ..Unclipped(PointUtf16::new(1, 15)), diagnostic: Diagnostic { message: "unresolved name `c`".to_string(), severity: DiagnosticSeverity::ERROR, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 4575e9ce5e..dd5934f979 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -55,7 +55,7 @@ use link_go_to_definition::{ }; pub use multi_buffer::{ Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset, - ToOffsetClipped, ToPoint, + ToPoint, }; use multi_buffer::{MultiBufferChunks, ToOffsetUtf16}; use ordered_float::OrderedFloat; diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index aa25b47680..969a970299 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -11,7 +11,7 @@ use language::{ char_kind, AutoindentMode, Buffer, BufferChunks, BufferSnapshot, CharKind, Chunk, CursorShape, DiagnosticEntry, Event, File, IndentSize, Language, OffsetRangeExt, OffsetUtf16, Outline, OutlineItem, Point, PointUtf16, Selection, TextDimension, ToOffset as _, ToOffsetUtf16 as _, - ToPoint as _, ToPointUtf16 as _, TransactionId, + ToPoint as _, ToPointUtf16 as _, TransactionId, Unclipped, }; use smallvec::SmallVec; use std::{ @@ -72,10 +72,6 @@ pub trait ToOffset: 'static + fmt::Debug { fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize; } -pub trait ToOffsetClipped: 'static + fmt::Debug { - fn to_offset_clipped(&self, snapshot: &MultiBufferSnapshot) -> usize; -} - pub trait ToOffsetUtf16: 'static + fmt::Debug { fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16; } @@ -1753,20 +1749,21 @@ impl MultiBufferSnapshot { *cursor.start() + overshoot } - pub fn clip_point_utf16(&self, point: PointUtf16, bias: Bias) -> PointUtf16 { + pub fn clip_point_utf16(&self, point: Unclipped, bias: Bias) -> PointUtf16 { if let Some((_, _, buffer)) = self.as_singleton() { return buffer.clip_point_utf16(point, bias); } let mut cursor = self.excerpts.cursor::(); - cursor.seek(&point, Bias::Right, &()); + //Cannot not panic if out of bounds as it will just not reach the target position + cursor.seek(&point.0, Bias::Right, &()); let overshoot = if let Some(excerpt) = cursor.item() { let excerpt_start = excerpt .buffer .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer)); let buffer_point = excerpt .buffer - .clip_point_utf16(excerpt_start + (point - cursor.start()), bias); + .clip_point_utf16(Unclipped(excerpt_start + (point.0 - cursor.start())), bias); buffer_point.saturating_sub(excerpt_start) } else { PointUtf16::zero() @@ -1949,9 +1946,9 @@ impl MultiBufferSnapshot { } } - pub fn point_utf16_to_offset_clipped(&self, point: PointUtf16) -> usize { + pub fn point_utf16_to_offset(&self, point: PointUtf16) -> usize { if let Some((_, _, buffer)) = self.as_singleton() { - return buffer.point_utf16_to_offset_clipped(point); + return buffer.point_utf16_to_offset(point); } let mut cursor = self.excerpts.cursor::<(PointUtf16, usize)>(); @@ -1965,7 +1962,7 @@ impl MultiBufferSnapshot { .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer)); let buffer_offset = excerpt .buffer - .point_utf16_to_offset_clipped(excerpt_start_point + overshoot); + .point_utf16_to_offset(excerpt_start_point + overshoot); *start_offset + (buffer_offset - excerpt_start_offset) } else { self.excerpts.summary().text.len @@ -3291,9 +3288,9 @@ impl ToOffset for OffsetUtf16 { } } -impl ToOffsetClipped for PointUtf16 { - fn to_offset_clipped<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize { - snapshot.point_utf16_to_offset_clipped(*self) +impl ToOffset for PointUtf16 { + fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize { + snapshot.point_utf16_to_offset(*self) } } @@ -4162,12 +4159,14 @@ mod tests { } for _ in 0..ch.len_utf16() { - let left_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Left); - let right_point_utf16 = snapshot.clip_point_utf16(point_utf16, Bias::Right); + let left_point_utf16 = + snapshot.clip_point_utf16(Unclipped(point_utf16), Bias::Left); + let right_point_utf16 = + snapshot.clip_point_utf16(Unclipped(point_utf16), Bias::Right); let buffer_left_point_utf16 = - buffer.clip_point_utf16(buffer_point_utf16, Bias::Left); + buffer.clip_point_utf16(Unclipped(buffer_point_utf16), Bias::Left); let buffer_right_point_utf16 = - buffer.clip_point_utf16(buffer_point_utf16, Bias::Right); + buffer.clip_point_utf16(Unclipped(buffer_point_utf16), Bias::Right); assert_eq!( left_point_utf16, excerpt_start.lines_utf16() diff --git a/crates/editor/src/selections_collection.rs b/crates/editor/src/selections_collection.rs index 14026d9f4e..facc1b0491 100644 --- a/crates/editor/src/selections_collection.rs +++ b/crates/editor/src/selections_collection.rs @@ -14,7 +14,6 @@ use util::post_inc; use crate::{ display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint}, Anchor, DisplayPoint, ExcerptId, MultiBuffer, MultiBufferSnapshot, SelectMode, ToOffset, - ToOffsetClipped, }; #[derive(Clone)] @@ -551,18 +550,6 @@ impl<'a> MutableSelectionsCollection<'a> { self.select_offset_ranges(ranges); } - pub fn select_clipped_ranges(&mut self, ranges: I) - where - I: IntoIterator>, - T: ToOffsetClipped, - { - let buffer = self.buffer.read(self.cx).snapshot(self.cx); - let ranges = ranges.into_iter().map(|range| { - range.start.to_offset_clipped(&buffer)..range.end.to_offset_clipped(&buffer) - }); - self.select_offset_ranges(ranges); - } - fn select_offset_ranges(&mut self, ranges: I) where I: IntoIterator>, diff --git a/crates/language/src/proto.rs b/crates/language/src/proto.rs index 674ce4f50e..ca86b93bfd 100644 --- a/crates/language/src/proto.rs +++ b/crates/language/src/proto.rs @@ -357,6 +357,7 @@ pub fn deserialize_diagnostics( .collect() } +//TODO: Deserialize anchors into `Unclipped`? pub fn deserialize_anchor(anchor: proto::Anchor) -> Option { Some(Anchor { timestamp: clock::Local { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index cb8e01d562..f4752270de 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -253,7 +253,7 @@ pub struct Symbol { pub label: CodeLabel, pub name: String, pub kind: lsp::SymbolKind, - pub range: Range, + pub range: Range>, pub signature: [u8; 32], } @@ -2682,9 +2682,9 @@ impl Project { // Expand empty ranges by one codepoint if range.start == range.end { // This will be go to the next boundary when being clipped - range.end.column += 1; - if range.start == range.end && range.end.column > 0 { - range.start.column -= 1; + range.end.0.column += 1; + if range.start == range.end && range.end.0.column > 0 { + range.start.0.column -= 1; } } @@ -3287,7 +3287,7 @@ impl Project { return Task::ready(Ok(Default::default())); }; - let position = position.to_point_utf16(source_buffer); + let position = Unclipped(position.to_point_utf16(source_buffer)); let anchor = source_buffer.anchor_after(position); if worktree.read(cx).as_local().is_some() { @@ -3306,7 +3306,7 @@ impl Project { lsp::TextDocumentIdentifier::new( lsp::Url::from_file_path(buffer_abs_path).unwrap(), ), - point_to_lsp(position), + point_to_lsp(position.0), ), context: Default::default(), work_done_progress_params: Default::default(), @@ -3349,7 +3349,7 @@ impl Project { let range = range_from_lsp(edit.range); let start = snapshot.clip_point_utf16(range.start, Bias::Left); let end = snapshot.clip_point_utf16(range.end, Bias::Left); - if start != range.start || end != range.end { + if start != range.start.0 || end != range.end.0 { log::info!("completion out of expected range"); return None; } @@ -3361,13 +3361,13 @@ impl Project { // If the language server does not provide a range, then infer // the range based on the syntax tree. None => { - if position != clipped_position { + if position.0 != clipped_position { log::info!("completion out of expected range"); return None; } let Range { start, end } = range_for_token .get_or_insert_with(|| { - let offset = position.to_offset_clipped(&snapshot); + let offset = position.to_offset(&snapshot); let (range, kind) = snapshot.surrounding_word(offset); if kind == Some(CharKind::Word) { range @@ -5116,22 +5116,30 @@ impl Project { _: Arc, mut cx: AsyncAppContext, ) -> Result { - let position = envelope - .payload - .position - .and_then(language::proto::deserialize_anchor) - .ok_or_else(|| anyhow!("invalid position"))?; - let version = deserialize_version(envelope.payload.version); let buffer = this.read_with(&cx, |this, cx| { this.opened_buffers .get(&envelope.payload.buffer_id) .and_then(|buffer| buffer.upgrade(cx)) .ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id)) })?; + + let position = envelope + .payload + .position + .and_then(language::proto::deserialize_anchor) + .map(|p| { + buffer.read_with(&cx, |buffer, _| { + buffer.clip_point_utf16(Unclipped(p.to_point_utf16(buffer)), Bias::Left) + }) + }) + .ok_or_else(|| anyhow!("invalid position"))?; + + let version = deserialize_version(envelope.payload.version); buffer .update(&mut cx, |buffer, _| buffer.wait_for_version(version)) .await; let version = buffer.read_with(&cx, |buffer, _| buffer.version()); + let completions = this .update(&mut cx, |this, cx| this.completions(&buffer, position, cx)) .await?; @@ -5618,8 +5626,8 @@ impl Project { }, name: serialized_symbol.name, - range: PointUtf16::new(start.row, start.column) - ..PointUtf16::new(end.row, end.column), + range: Unclipped(PointUtf16::new(start.row, start.column)) + ..Unclipped(PointUtf16::new(end.row, end.column)), kind, signature: serialized_symbol .signature @@ -5705,10 +5713,10 @@ impl Project { let mut lsp_edits = lsp_edits.into_iter().peekable(); let mut edits = Vec::new(); - while let Some((mut range, mut new_text)) = lsp_edits.next() { + while let Some((range, mut new_text)) = lsp_edits.next() { // Clip invalid ranges provided by the language server. - range.start = snapshot.clip_point_utf16(range.start, Bias::Left); - range.end = snapshot.clip_point_utf16(range.end, Bias::Left); + let mut range = snapshot.clip_point_utf16(range.start, Bias::Left) + ..snapshot.clip_point_utf16(range.end, Bias::Left); // Combine any LSP edits that are adjacent. // @@ -5720,11 +5728,11 @@ impl Project { // In order for the diffing logic below to work properly, any edits that // cancel each other out must be combined into one. while let Some((next_range, next_text)) = lsp_edits.peek() { - if next_range.start > range.end { - if next_range.start.row > range.end.row + 1 - || next_range.start.column > 0 + if next_range.start.0 > range.end { + if next_range.start.0.row > range.end.row + 1 + || next_range.start.0.column > 0 || snapshot.clip_point_utf16( - PointUtf16::new(range.end.row, u32::MAX), + Unclipped(PointUtf16::new(range.end.row, u32::MAX)), Bias::Left, ) > range.end { @@ -5732,7 +5740,7 @@ impl Project { } new_text.push('\n'); } - range.end = next_range.end; + range.end = snapshot.clip_point_utf16(next_range.end, Bias::Left); new_text.push_str(next_text); lsp_edits.next(); } @@ -5741,8 +5749,8 @@ 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_clipped(&snapshot); - let old_text = snapshot.text_for_clamped_range(range).collect::(); + let mut offset = range.start.to_offset(&snapshot); + let old_text = snapshot.text_for_range(range).collect::(); let diff = TextDiff::from_lines(old_text.as_str(), &new_text); let mut moved_since_edit = true; @@ -6053,13 +6061,13 @@ fn serialize_symbol(symbol: &Symbol) -> proto::Symbol { path: symbol.path.path.to_string_lossy().to_string(), name: symbol.name.clone(), kind: unsafe { mem::transmute(symbol.kind) }, - start: Some(proto::Point { - row: symbol.range.start.row, - column: symbol.range.start.column, + start: Some(proto::UnclippedPoint { + row: symbol.range.start.0.row, + column: symbol.range.start.0.column, }), - end: Some(proto::Point { - row: symbol.range.end.row, - column: symbol.range.end.column, + end: Some(proto::UnclippedPoint { + row: symbol.range.end.0.row, + column: symbol.range.end.0.column, }), signature: symbol.signature.to_vec(), } diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index ca274b18b8..dfb699fdbb 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -1239,7 +1239,7 @@ async fn test_empty_diagnostic_ranges(cx: &mut gpui::TestAppContext) { &buffer, vec![ DiagnosticEntry { - range: PointUtf16::new(0, 10)..PointUtf16::new(0, 10), + range: Unclipped(PointUtf16::new(0, 10))..Unclipped(PointUtf16::new(0, 10)), diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "syntax error 1".to_string(), @@ -1247,7 +1247,7 @@ async fn test_empty_diagnostic_ranges(cx: &mut gpui::TestAppContext) { }, }, DiagnosticEntry { - range: PointUtf16::new(1, 10)..PointUtf16::new(1, 10), + range: Unclipped(PointUtf16::new(1, 10))..Unclipped(PointUtf16::new(1, 10)), diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "syntax error 2".to_string(), diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index eb755d2d2f..273230fe26 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -151,7 +151,7 @@ impl ProjectSymbolsView { let editor = workspace.open_project_item::(buffer, cx); editor.update(cx, |editor, cx| { editor.change_selections(Some(Autoscroll::center()), cx, |s| { - s.select_clipped_ranges([position..position]) + s.select_ranges([position..position]) }); }); }); diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index ded708370d..b6516d235d 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -412,8 +412,8 @@ message Symbol { string name = 4; int32 kind = 5; string path = 6; - Point start = 7; - Point end = 8; + UnclippedPoint start = 7; + UnclippedPoint end = 8; bytes signature = 9; } @@ -1047,6 +1047,11 @@ message Point { uint32 column = 2; } +message UnclippedPoint { + uint32 row = 1; + uint32 column = 2; +} + message Nonce { uint64 upper_half = 1; uint64 lower_half = 2; diff --git a/crates/rpc/src/rpc.rs b/crates/rpc/src/rpc.rs index b6aef64677..5ca5711d9c 100644 --- a/crates/rpc/src/rpc.rs +++ b/crates/rpc/src/rpc.rs @@ -6,4 +6,4 @@ pub use conn::Connection; pub use peer::*; mod macros; -pub const PROTOCOL_VERSION: u32 = 39; +pub const PROTOCOL_VERSION: u32 = 40; diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index e4469ca141..aa4ef109cd 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -2475,28 +2475,6 @@ impl ToOffsetUtf16 for OffsetUtf16 { } } -// pub trait Clip { -// fn clip(&self, bias: Bias, snapshot: &BufferSnapshot) -> Self; -// } - -// impl Clip for usize { -// fn clip(&self, bias: Bias, snapshot: &BufferSnapshot) -> Self { -// snapshot.clip_offset(*self, bias) -// } -// } - -// impl Clip for Point { -// fn clip(&self, bias: Bias, snapshot: &BufferSnapshot) -> Self { -// snapshot.clip_point(*self, bias) -// } -// } - -// impl Clip for Unclipped { -// fn clip(&self, bias: Bias, snapshot: &BufferSnapshot) -> Self { -// snapshot.clip_point_utf16(self.0, bias) -// } -// } - pub trait FromAnchor { fn from_anchor(anchor: &Anchor, snapshot: &BufferSnapshot) -> Self; }