Merge pull request #1910 from zed-industries/lsp-coordinate-clamp

Don't trust LSP coordinates to be within document bounds
This commit is contained in:
Julia 2022-11-23 14:07:37 -05:00 committed by GitHub
commit e4185f38cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 267 additions and 163 deletions

View file

@ -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::{
@ -1749,20 +1749,20 @@ impl MultiBufferSnapshot {
*cursor.start() + overshoot
}
pub fn clip_point_utf16(&self, point: PointUtf16, bias: Bias) -> PointUtf16 {
pub fn clip_point_utf16(&self, point: Unclipped<PointUtf16>, bias: Bias) -> PointUtf16 {
if let Some((_, _, buffer)) = self.as_singleton() {
return buffer.clip_point_utf16(point, bias);
}
let mut cursor = self.excerpts.cursor::<PointUtf16>();
cursor.seek(&point, Bias::Right, &());
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()
@ -3274,12 +3274,6 @@ impl ToOffset for Point {
}
}
impl ToOffset for PointUtf16 {
fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
snapshot.point_utf16_to_offset(*self)
}
}
impl ToOffset for usize {
fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
assert!(*self <= snapshot.len(), "offset is out of range");
@ -3293,6 +3287,12 @@ impl ToOffset for OffsetUtf16 {
}
}
impl ToOffset for PointUtf16 {
fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
snapshot.point_utf16_to_offset(*self)
}
}
impl ToOffsetUtf16 for OffsetUtf16 {
fn to_offset_utf16(&self, _snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
*self
@ -4158,12 +4158,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()

View file

@ -544,11 +544,21 @@ impl<'a> MutableSelectionsCollection<'a> {
T: ToOffset,
{
let buffer = self.buffer.read(self.cx).snapshot(self.cx);
let ranges = ranges
.into_iter()
.map(|range| range.start.to_offset(&buffer)..range.end.to_offset(&buffer));
self.select_offset_ranges(ranges);
}
fn select_offset_ranges<I>(&mut self, ranges: I)
where
I: IntoIterator<Item = Range<usize>>,
{
let selections = ranges
.into_iter()
.map(|range| {
let mut start = range.start.to_offset(&buffer);
let mut end = range.end.to_offset(&buffer);
let mut start = range.start;
let mut end = range.end;
let reversed = if start > end {
mem::swap(&mut start, &mut end);
true