Skip to content

Commit a62875f

Browse files
committed
Add position/range conversion infrastructure for multi-document support
Introduce new infrastructure to support converting positions and ranges for documents that may map to multiple URIs (like notebook cells): - Add Db trait with document() and notebook_document() queries - Provides access to document metadata needed for conversion - notebook_document() returns notebook info for a file if it exists - Add LspRange and LspPosition types for deferred LSP conversion - Stores file, offset/range, db reference, and encoding - Allows callers to choose conversion strategy: * to_local_range()/to_local_position(): For use within same document/cell * to_location(): For cross-document references with URI - Critical for notebooks where one file maps to multiple cell URIs - Update conversion traits (RangeExt, PositionExt, etc.) - Add methods to create LspRange/LspPosition from internal types - Support both notebook cells and regular files This infrastructure prepares the codebase for notebook support where position/range conversions must account for cell boundaries and URIs.
1 parent 6c3d612 commit a62875f

22 files changed

+384
-278
lines changed

crates/ty_server/src/document/location.rs

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
use crate::PositionEncoding;
22
use crate::document::{FileRangeExt, ToRangeExt};
3-
use crate::system::file_to_url;
43
use lsp_types::Location;
54
use ruff_db::files::FileRange;
6-
use ruff_db::source::{line_index, source_text};
7-
use ruff_text_size::Ranged;
85
use ty_ide::{NavigationTarget, ReferenceTarget};
9-
use ty_project::Db;
6+
use ty_python_semantic::Db;
107

118
pub(crate) trait ToLink {
129
fn to_location(&self, db: &dyn Db, encoding: PositionEncoding) -> Option<Location>;
@@ -21,7 +18,9 @@ pub(crate) trait ToLink {
2118

2219
impl ToLink for NavigationTarget {
2320
fn to_location(&self, db: &dyn Db, encoding: PositionEncoding) -> Option<Location> {
24-
FileRange::new(self.file(), self.focus_range()).to_location(db, encoding)
21+
FileRange::new(self.file(), self.focus_range())
22+
.as_lsp_range(db, encoding)
23+
.to_location()
2524
}
2625

2726
fn to_link(
@@ -31,22 +30,24 @@ impl ToLink for NavigationTarget {
3130
encoding: PositionEncoding,
3231
) -> Option<lsp_types::LocationLink> {
3332
let file = self.file();
34-
let uri = file_to_url(db, file)?;
35-
let source = source_text(db, file);
36-
let index = line_index(db, file);
3733

38-
let target_range = self.full_range().to_lsp_range(&source, &index, encoding);
39-
let selection_range = self.focus_range().to_lsp_range(&source, &index, encoding);
34+
// Get target_range and URI together to ensure they're consistent (same cell for notebooks)
35+
let target_location = self
36+
.full_range()
37+
.as_lsp_range(db, file, encoding)
38+
.to_location()?;
39+
let target_range = target_location.range;
4040

41-
let src = src.map(|src| {
42-
let source = source_text(db, src.file());
43-
let index = line_index(db, src.file());
41+
// For selection_range, we can use as_local_range since we know it's in the same document/cell
42+
let selection_range = self
43+
.focus_range()
44+
.as_lsp_range(db, file, encoding)
45+
.to_local_range();
4446

45-
src.range().to_lsp_range(&source, &index, encoding)
46-
});
47+
let src = src.map(|src| src.as_lsp_range(db, encoding).to_local_range());
4748

4849
Some(lsp_types::LocationLink {
49-
target_uri: uri,
50+
target_uri: target_location.uri,
5051
target_range,
5152
target_selection_range: selection_range,
5253
origin_selection_range: src,
@@ -56,7 +57,7 @@ impl ToLink for NavigationTarget {
5657

5758
impl ToLink for ReferenceTarget {
5859
fn to_location(&self, db: &dyn Db, encoding: PositionEncoding) -> Option<Location> {
59-
self.file_range().to_location(db, encoding)
60+
self.file_range().as_lsp_range(db, encoding).to_location()
6061
}
6162

6263
fn to_link(
@@ -65,22 +66,18 @@ impl ToLink for ReferenceTarget {
6566
src: Option<FileRange>,
6667
encoding: PositionEncoding,
6768
) -> Option<lsp_types::LocationLink> {
68-
let uri = file_to_url(db, self.file())?;
69-
let source = source_text(db, self.file());
70-
let index = line_index(db, self.file());
71-
72-
let target_range = self.range().to_lsp_range(&source, &index, encoding);
69+
// Get target_range and URI together to ensure they're consistent (same cell for notebooks)
70+
let target_location = self
71+
.range()
72+
.as_lsp_range(db, self.file(), encoding)
73+
.to_location()?;
74+
let target_range = target_location.range;
7375
let selection_range = target_range;
7476

75-
let src = src.map(|src| {
76-
let source = source_text(db, src.file());
77-
let index = line_index(db, src.file());
78-
79-
src.range().to_lsp_range(&source, &index, encoding)
80-
});
77+
let src = src.map(|src| src.as_lsp_range(db, encoding).to_local_range());
8178

8279
Some(lsp_types::LocationLink {
83-
target_uri: uri,
80+
target_uri: target_location.uri,
8481
target_range,
8582
target_selection_range: selection_range,
8683
origin_selection_range: src,

0 commit comments

Comments
 (0)