about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-10-18 11:23:05 +0000
committerbors <bors@rust-lang.org>2024-10-18 11:23:05 +0000
commit03cfa8e23444d0ccb97a0f697095a487cf5261c2 (patch)
tree8ee35b0e0d2c5cc87dd0e21aecc5b61b5780756c
parent5b85f1c2d9d171789ad24e4430315d108e163b75 (diff)
parent2af15d2ffdf52480ca3955e82535979f1b80e8e0 (diff)
downloadrust-03cfa8e23444d0ccb97a0f697095a487cf5261c2.tar.gz
rust-03cfa8e23444d0ccb97a0f697095a487cf5261c2.zip
Auto merge of #18243 - krobelus:clamp-position-character, r=Veykril
Clamp Position::character to line length

LSP says about Position::character

> If the character value is greater than the line length it defaults back to the line length.

but from_proto::offset() doesn't implement this.

A client might for example request code actions for a whole line by sending
Position::character=99999.  I don't think there is ever a reason (besides laziness) why the
client can't specify the line length instead but I guess we should not crash but follow protocol.

Not sure how to update Cargo.lock (lib/README.md doesn't say how).

Fixes #18240
-rw-r--r--src/tools/rust-analyzer/lib/line-index/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/lib/line-index/src/lib.rs8
-rw-r--r--src/tools/rust-analyzer/lib/line-index/src/tests.rs23
3 files changed, 32 insertions, 1 deletions
diff --git a/src/tools/rust-analyzer/lib/line-index/Cargo.toml b/src/tools/rust-analyzer/lib/line-index/Cargo.toml
index 8ae4954dd0d..14196ba3d09 100644
--- a/src/tools/rust-analyzer/lib/line-index/Cargo.toml
+++ b/src/tools/rust-analyzer/lib/line-index/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "line-index"
-version = "0.1.1"
+version = "0.1.2"
 description = "Maps flat `TextSize` offsets to/from `(line, column)` representation."
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/line-index"
diff --git a/src/tools/rust-analyzer/lib/line-index/src/lib.rs b/src/tools/rust-analyzer/lib/line-index/src/lib.rs
index 66875e25242..6f0455ee98b 100644
--- a/src/tools/rust-analyzer/lib/line-index/src/lib.rs
+++ b/src/tools/rust-analyzer/lib/line-index/src/lib.rs
@@ -177,6 +177,14 @@ impl LineIndex {
         Some(LineCol { line: line_col.line, col })
     }
 
+    /// Returns the given line's range.
+    pub fn line(&self, line: u32) -> Option<TextRange> {
+        let start = self.start_offset(line as usize)?;
+        let next_newline = self.newlines.get(line as usize).copied().unwrap_or(self.len);
+        let line_length = next_newline - start;
+        Some(TextRange::new(start, start + line_length))
+    }
+
     /// Given a range [start, end), returns a sorted iterator of non-empty ranges [start, x1), [x1,
     /// x2), ..., [xn, end) where all the xi, which are positions of newlines, are inside the range
     /// [start, end).
diff --git a/src/tools/rust-analyzer/lib/line-index/src/tests.rs b/src/tools/rust-analyzer/lib/line-index/src/tests.rs
index 57fad1dfc05..f2bb04aec32 100644
--- a/src/tools/rust-analyzer/lib/line-index/src/tests.rs
+++ b/src/tools/rust-analyzer/lib/line-index/src/tests.rs
@@ -195,3 +195,26 @@ fn test_every_chars() {
         }
     }
 }
+
+#[test]
+fn test_line() {
+    use text_size::TextRange;
+
+    macro_rules! validate {
+        ($text:expr, $line:expr, $expected_start:literal .. $expected_end:literal) => {
+            let line_index = LineIndex::new($text);
+            assert_eq!(
+                line_index.line($line),
+                Some(TextRange::new(
+                    TextSize::from($expected_start),
+                    TextSize::from($expected_end)
+                ))
+            );
+        };
+    }
+
+    validate!("", 0, 0..0);
+    validate!("\n", 1, 1..1);
+    validate!("\nabc", 1, 1..4);
+    validate!("\nabc\ndef", 1, 1..5);
+}