diff --git a/crates/ty_server/src/document/location.rs b/crates/ty_server/src/document/location.rs index 91a064acd3..67b7d0c659 100644 --- a/crates/ty_server/src/document/location.rs +++ b/crates/ty_server/src/document/location.rs @@ -20,7 +20,7 @@ pub(crate) trait ToLink { impl ToLink for NavigationTarget { fn to_location(&self, db: &dyn Db, encoding: PositionEncoding) -> Option { FileRange::new(self.file(), self.focus_range()) - .as_lsp_range(db, encoding) + .to_lsp_range(db, encoding)? .to_location() } @@ -35,17 +35,17 @@ impl ToLink for NavigationTarget { // Get target_range and URI together to ensure they're consistent (same cell for notebooks) let target_location = self .full_range() - .as_lsp_range(db, file, encoding) - .to_location()?; + .to_lsp_range(db, file, encoding)? + .into_location()?; let target_range = target_location.range; // For selection_range, we can use as_local_range since we know it's in the same document/cell let selection_range = self .focus_range() - .as_lsp_range(db, file, encoding) - .to_local_range(); + .to_lsp_range(db, file, encoding)? + .local_range(); - let src = src.map(|src| src.as_lsp_range(db, encoding).to_local_range()); + let src = src.and_then(|src| Some(src.to_lsp_range(db, encoding)?.local_range())); Some(lsp_types::LocationLink { target_uri: target_location.uri, @@ -58,7 +58,9 @@ impl ToLink for NavigationTarget { impl ToLink for ReferenceTarget { fn to_location(&self, db: &dyn Db, encoding: PositionEncoding) -> Option { - self.file_range().as_lsp_range(db, encoding).to_location() + self.file_range() + .to_lsp_range(db, encoding)? + .into_location() } fn to_link( @@ -70,12 +72,12 @@ impl ToLink for ReferenceTarget { // Get target_range and URI together to ensure they're consistent (same cell for notebooks) let target_location = self .range() - .as_lsp_range(db, self.file(), encoding) - .to_location()?; + .to_lsp_range(db, self.file(), encoding)? + .into_location()?; let target_range = target_location.range; let selection_range = target_range; - let src = src.map(|src| src.as_lsp_range(db, encoding).to_local_range()); + let src = src.and_then(|src| Some(src.to_lsp_range(db, encoding)?.local_range())); Some(lsp_types::LocationLink { target_uri: target_location.uri, diff --git a/crates/ty_server/src/document/range.rs b/crates/ty_server/src/document/range.rs index 6d3d3eb0d4..894ef9ba09 100644 --- a/crates/ty_server/src/document/range.rs +++ b/crates/ty_server/src/document/range.rs @@ -2,133 +2,94 @@ use super::PositionEncoding; use crate::Db; use crate::system::file_to_url; -use lsp_types as types; -use lsp_types::{Location, Position, Url}; use ruff_db::files::{File, FileRange}; use ruff_db::source::{line_index, source_text}; use ruff_source_file::LineIndex; use ruff_source_file::{OneIndexed, SourceLocation}; use ruff_text_size::{Ranged, TextRange, TextSize}; -/// Represents a range that has been prepared for LSP conversion but requires -/// a decision about how to use it - either as a local range within the same -/// document/cell, or as a location that can reference any document in the project. -#[derive(Clone)] -pub(crate) struct LspRange<'db> { - file: File, - range: TextRange, - db: &'db dyn Db, - encoding: PositionEncoding, +/// A range in an LSP text document (cell or a regular document). +#[derive(Clone, Debug, Default)] +pub(crate) struct LspRange { + range: lsp_types::Range, + + /// The URI of this range's text document + uri: Option, } -impl std::fmt::Debug for LspRange<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("LspRange") - .field("range", &self.range) - .field("file", &self.file) - .field("encoding", &self.encoding) - .finish_non_exhaustive() - } -} - -impl LspRange<'_> { - /// Convert to an LSP Range for use within the same document/cell. - /// Returns only the LSP Range without any URI information. +impl LspRange { + /// Returns the range within this document. /// - /// Use this when you already have a URI context and this range is guaranteed + /// Only use `range` when you already have a URI context and this range is guaranteed /// to be within the same document/cell: /// - Selection ranges within a `LocationLink` (where `target_uri` provides context) /// - Additional ranges in the same cell (e.g., `selection_range` when you already have `target_range`) /// - /// Do NOT use this for standalone ranges - use `to_location()` instead to ensure + /// Do NOT use this for standalone ranges - use [`Self::to_location`] instead to ensure /// the URI and range are consistent. - pub(crate) fn to_local_range(&self) -> types::Range { - self.to_uri_and_range().1 + pub(crate) fn local_range(&self) -> lsp_types::Range { + self.range } - /// Convert to a Location that can reference any document. - /// Returns a Location with both URI and Range. + /// Converts this range into an LSP location. /// - /// Use this for: - /// - Go-to-definition targets - /// - References - /// - Diagnostics related information - /// - Any cross-file navigation - pub(crate) fn to_location(&self) -> Option { - let (uri, range) = self.to_uri_and_range(); - Some(Location { uri: uri?, range }) + /// Returns `None` if the URI for this file couldn't be resolved. + pub(crate) fn to_location(&self) -> Option { + Some(lsp_types::Location { + uri: self.uri.clone()?, + range: self.range, + }) } - pub(crate) fn to_uri_and_range(&self) -> (Option, lsp_types::Range) { - let source = source_text(self.db, self.file); - let index = line_index(self.db, self.file); - - let uri = file_to_url(self.db, self.file); - let range = text_range_to_lsp_range(self.range, &source, &index, self.encoding); - (uri, range) + pub(crate) fn into_location(self) -> Option { + Some(lsp_types::Location { + uri: self.uri?, + range: self.range, + }) } } -/// Represents a position that has been prepared for LSP conversion but requires -/// a decision about how to use it - either as a local position within the same -/// document/cell, or as a location with a single-point range that can reference -/// any document in the project. -#[derive(Clone)] -pub(crate) struct LspPosition<'db> { - file: File, - position: TextSize, - db: &'db dyn Db, - encoding: PositionEncoding, +/// A position in an LSP text document (cell or a regular document). +#[derive(Clone, Debug, Default)] +pub(crate) struct LspPosition { + position: lsp_types::Position, + + /// The URI of this range's text document + uri: Option, } -impl std::fmt::Debug for LspPosition<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("LspPosition") - .field("position", &self.position) - .field("file", &self.file) - .field("encoding", &self.encoding) - .finish_non_exhaustive() - } -} - -impl LspPosition<'_> { - /// Convert to an LSP Position for use within the same document/cell. - /// Returns only the LSP Position without any URI information. +impl LspPosition { + /// Returns the position within this document. /// - /// Use this when you already have a URI context and this position is guaranteed - /// to be within the same document/cell: - /// - Inlay hints (where the document URI is already known) - /// - Positions within the same cell as a parent range + /// Only use [`Self::local_position`] when you already have a URI context and this position is guaranteed + /// to be within the same document/cell /// - /// Do NOT use this for standalone positions that might need a URI - use - /// `to_location()` instead to ensure the URI and position are consistent. - pub(crate) fn to_local_position(&self) -> types::Position { - self.to_location().1 + /// Do NOT use this for standalone positions - use [`Self::to_location`] instead to ensure + /// the URI and position are consistent. + pub(crate) fn local_position(&self) -> lsp_types::Position { + self.position } - /// Convert to a Location with a single-point range that can reference any document. - /// Returns a Location with both URI and a range where start == end. - /// - /// Use this for any cross-file navigation where you need both URI and position. - pub(crate) fn to_location(&self) -> (Option, Position) { - let source = source_text(self.db, self.file); - let index = line_index(self.db, self.file); - - let uri = file_to_url(self.db, self.file); - let position = text_size_to_lsp_position(self.position, &source, &index, self.encoding); - (uri, position) + /// Returns the uri of the text document this position belongs to. + #[expect(unused)] + pub(crate) fn uri(&self) -> Option<&lsp_types::Url> { + self.uri.as_ref() } } pub(crate) trait RangeExt { - /// Convert an LSP Range to internal `TextRange`. + /// Convert an LSP Range to internal [`TextRange`]. + /// + /// Returns `None` if `file` is a notebook and the + /// cell identified by `url` can't be looked up or if the notebook + /// isn't open in the editor. fn to_text_range( &self, db: &dyn Db, file: File, url: &lsp_types::Url, encoding: PositionEncoding, - ) -> TextRange; + ) -> Option; } impl RangeExt for lsp_types::Range { @@ -138,23 +99,27 @@ impl RangeExt for lsp_types::Range { file: File, url: &lsp_types::Url, encoding: PositionEncoding, - ) -> TextRange { - let start = self.start.to_text_size(db, file, url, encoding); - let end = self.end.to_text_size(db, file, url, encoding); + ) -> Option { + let start = self.start.to_text_size(db, file, url, encoding)?; + let end = self.end.to_text_size(db, file, url, encoding)?; - TextRange::new(start, end) + Some(TextRange::new(start, end)) } } pub(crate) trait PositionExt { /// Convert an LSP Position to internal `TextSize`. + /// + /// Returns `None` if `file` is a notebook and the + /// cell identified by `url` can't be looked up or if the notebook + /// isn't open in the editor. fn to_text_size( &self, db: &dyn Db, file: File, url: &lsp_types::Url, encoding: PositionEncoding, - ) -> TextSize; + ) -> Option; } impl PositionExt for lsp_types::Position { @@ -164,52 +129,59 @@ impl PositionExt for lsp_types::Position { file: File, _url: &lsp_types::Url, encoding: PositionEncoding, - ) -> TextSize { + ) -> Option { let source = source_text(db, file); let index = line_index(db, file); - lsp_position_to_text_size(*self, &source, &index, encoding) + Some(lsp_position_to_text_size(*self, &source, &index, encoding)) } } pub(crate) trait TextSizeExt { - /// Converts this position to an `LspPosition`, which then requires an explicit - /// decision about how to use it (as a local position or as a location). - fn as_lsp_position<'db>( + /// Converts self into a position into an LSP text document (can be a cell or regular document). + /// + /// Returns `None` if the position can't be converted: + /// + /// * If `file` is a notebook but the notebook isn't open in the editor, + /// preventing us from looking up the corresponding cell. + /// * If `position` is out of bounds. + fn to_lsp_position( &self, - db: &'db dyn Db, + db: &dyn Db, file: File, encoding: PositionEncoding, - ) -> LspPosition<'db> + ) -> Option where Self: Sized; } impl TextSizeExt for TextSize { - fn as_lsp_position<'db>( + fn to_lsp_position( &self, - db: &'db dyn Db, + db: &dyn Db, file: File, encoding: PositionEncoding, - ) -> LspPosition<'db> { - LspPosition { - file, - position: *self, - db, - encoding, - } + ) -> Option { + let source = source_text(db, file); + let index = line_index(db, file); + + let uri = file_to_url(db, file); + let position = text_size_to_lsp_position(*self, &source, &index, encoding); + + Some(LspPosition { position, uri }) } } pub(crate) trait ToRangeExt { - /// Converts this range to an `LspRange`, which then requires an explicit - /// decision about how to use it (as a local range or as a location). - fn as_lsp_range<'db>( - &self, - db: &'db dyn Db, - file: File, - encoding: PositionEncoding, - ) -> LspRange<'db>; + /// Converts self into a range into an LSP text document (can be a cell or regular document). + /// + /// Returns `None` if the range can't be converted: + /// + /// * If `file` is a notebook but the notebook isn't open in the editor, + /// preventing us from looking up the corresponding cell. + /// * If range is out of bounds. + fn to_lsp_range(&self, db: &dyn Db, file: File, encoding: PositionEncoding) + -> Option; } fn u32_index_to_usize(index: u32) -> usize { @@ -221,7 +193,7 @@ fn text_size_to_lsp_position( text: &str, index: &LineIndex, encoding: PositionEncoding, -) -> types::Position { +) -> lsp_types::Position { let source_location = index.source_location(offset, text, encoding.into()); source_location_to_position(&source_location) } @@ -231,8 +203,8 @@ fn text_range_to_lsp_range( text: &str, index: &LineIndex, encoding: PositionEncoding, -) -> types::Range { - types::Range { +) -> lsp_types::Range { + lsp_types::Range { start: text_size_to_lsp_position(range.start(), text, index, encoding), end: text_size_to_lsp_position(range.end(), text, index, encoding), } @@ -272,23 +244,23 @@ pub(crate) fn lsp_range_to_text_range( } impl ToRangeExt for TextRange { - fn as_lsp_range<'db>( + fn to_lsp_range( &self, - db: &'db dyn Db, + db: &dyn Db, file: File, encoding: PositionEncoding, - ) -> LspRange<'db> { - LspRange { - file, - range: *self, - db, - encoding, - } + ) -> Option { + let source = source_text(db, file); + let index = line_index(db, file); + let range = text_range_to_lsp_range(*self, &source, &index, encoding); + + let uri = file_to_url(db, file); + Some(LspRange { range, uri }) } } -fn source_location_to_position(location: &SourceLocation) -> types::Position { - types::Position { +fn source_location_to_position(location: &SourceLocation) -> lsp_types::Position { + lsp_types::Position { line: u32::try_from(location.line.to_zero_indexed()).expect("line usize fits in u32"), character: u32::try_from(location.character_offset.to_zero_indexed()) .expect("character usize fits in u32"), @@ -298,16 +270,11 @@ fn source_location_to_position(location: &SourceLocation) -> types::Position { pub(crate) trait FileRangeExt { /// Converts this file range to an `LspRange`, which then requires an explicit /// decision about how to use it (as a local range or as a location). - fn as_lsp_range<'db>(&self, db: &'db dyn Db, encoding: PositionEncoding) -> LspRange<'db>; + fn to_lsp_range(&self, db: &dyn Db, encoding: PositionEncoding) -> Option; } impl FileRangeExt for FileRange { - fn as_lsp_range<'db>(&self, db: &'db dyn Db, encoding: PositionEncoding) -> LspRange<'db> { - LspRange { - file: self.file(), - range: self.range(), - db, - encoding, - } + fn to_lsp_range(&self, db: &dyn Db, encoding: PositionEncoding) -> Option { + self.range().to_lsp_range(db, self.file(), encoding) } } diff --git a/crates/ty_server/src/server/api/diagnostics.rs b/crates/ty_server/src/server/api/diagnostics.rs index 54a0e79a2e..98d927cf2e 100644 --- a/crates/ty_server/src/server/api/diagnostics.rs +++ b/crates/ty_server/src/server/api/diagnostics.rs @@ -281,8 +281,9 @@ pub(super) fn to_lsp_diagnostic( let file = span.expect_ty_file(); span.range() - .map(|range| range.as_lsp_range(db, file, encoding).to_local_range()) + .and_then(|range| range.to_lsp_range(db, file, encoding)) .unwrap_or_default() + .local_range() } else { Range::default() }; @@ -363,7 +364,7 @@ fn annotation_to_related_information( let annotation_message = annotation.get_message()?; let range = FileRange::try_from(span).ok()?; - let location = range.as_lsp_range(db, encoding).to_location()?; + let location = range.to_lsp_range(db, encoding)?.into_location()?; Some(DiagnosticRelatedInformation { location, @@ -381,7 +382,7 @@ fn sub_diagnostic_to_related_information( let span = primary_annotation.get_span(); let range = FileRange::try_from(span).ok()?; - let location = range.as_lsp_range(db, encoding).to_location()?; + let location = range.to_lsp_range(db, encoding)?.into_location()?; Some(DiagnosticRelatedInformation { location, diff --git a/crates/ty_server/src/server/api/requests/completion.rs b/crates/ty_server/src/server/api/requests/completion.rs index 6473661939..e99de7fb39 100644 --- a/crates/ty_server/src/server/api/requests/completion.rs +++ b/crates/ty_server/src/server/api/requests/completion.rs @@ -48,12 +48,15 @@ impl BackgroundDocumentRequestHandler for CompletionRequestHandler { return Ok(None); }; - let offset = params.text_document_position.position.to_text_size( + let Some(offset) = params.text_document_position.position.to_text_size( db, file, snapshot.url(), snapshot.encoding(), - ); + ) else { + return Ok(None); + }; + let settings = CompletionSettings { auto_import: snapshot.global_settings().is_auto_import_enabled(), }; @@ -70,15 +73,15 @@ impl BackgroundDocumentRequestHandler for CompletionRequestHandler { .map(|(i, comp)| { let kind = comp.kind(db).map(ty_kind_to_lsp_kind); let type_display = comp.ty.map(|ty| ty.display(db).to_string()); - let import_edit = comp.import.as_ref().map(|edit| { + let import_edit = comp.import.as_ref().and_then(|edit| { let range = edit .range() - .as_lsp_range(db, file, snapshot.encoding()) - .to_local_range(); - TextEdit { + .to_lsp_range(db, file, snapshot.encoding())? + .local_range(); + Some(TextEdit { range, new_text: edit.content().map(ToString::to_string).unwrap_or_default(), - } + }) }); let name = comp.name.to_string(); diff --git a/crates/ty_server/src/server/api/requests/doc_highlights.rs b/crates/ty_server/src/server/api/requests/doc_highlights.rs index c96c3d4fef..bf10a95310 100644 --- a/crates/ty_server/src/server/api/requests/doc_highlights.rs +++ b/crates/ty_server/src/server/api/requests/doc_highlights.rs @@ -40,12 +40,14 @@ impl BackgroundDocumentRequestHandler for DocumentHighlightRequestHandler { return Ok(None); }; - let offset = params.text_document_position_params.position.to_text_size( + let Some(offset) = params.text_document_position_params.position.to_text_size( db, file, snapshot.url(), snapshot.encoding(), - ); + ) else { + return Ok(None); + }; let Some(highlights_result) = document_highlights(db, file, offset) else { return Ok(None); @@ -53,11 +55,11 @@ impl BackgroundDocumentRequestHandler for DocumentHighlightRequestHandler { let highlights: Vec<_> = highlights_result .into_iter() - .map(|target| { + .filter_map(|target| { let range = target .range() - .as_lsp_range(db, file, snapshot.encoding()) - .to_local_range(); + .to_lsp_range(db, file, snapshot.encoding())? + .local_range(); let kind = match target.kind() { ReferenceKind::Read => Some(DocumentHighlightKind::READ), @@ -65,7 +67,7 @@ impl BackgroundDocumentRequestHandler for DocumentHighlightRequestHandler { ReferenceKind::Other => Some(DocumentHighlightKind::TEXT), }; - DocumentHighlight { range, kind } + Some(DocumentHighlight { range, kind }) }) .collect(); diff --git a/crates/ty_server/src/server/api/requests/document_symbols.rs b/crates/ty_server/src/server/api/requests/document_symbols.rs index 95edd391f4..1001d33648 100644 --- a/crates/ty_server/src/server/api/requests/document_symbols.rs +++ b/crates/ty_server/src/server/api/requests/document_symbols.rs @@ -57,7 +57,7 @@ impl BackgroundDocumentRequestHandler for DocumentSymbolRequestHandler { let symbols = symbols.to_hierarchical(); let lsp_symbols: Vec = symbols .iter() - .map(|(id, symbol)| { + .filter_map(|(id, symbol)| { convert_to_lsp_document_symbol( db, file, @@ -93,10 +93,10 @@ fn convert_to_lsp_document_symbol( id: SymbolId, symbol: SymbolInfo<'_>, encoding: PositionEncoding, -) -> DocumentSymbol { +) -> Option { let symbol_kind = convert_symbol_kind(symbol.kind); - DocumentSymbol { + Some(DocumentSymbol { name: symbol.name.into_owned(), detail: None, kind: symbol_kind, @@ -105,19 +105,19 @@ fn convert_to_lsp_document_symbol( deprecated: None, range: symbol .full_range - .as_lsp_range(db, file, encoding) - .to_local_range(), + .to_lsp_range(db, file, encoding)? + .local_range(), selection_range: symbol .name_range - .as_lsp_range(db, file, encoding) - .to_local_range(), + .to_lsp_range(db, file, encoding)? + .local_range(), children: Some( symbols .children(id) - .map(|(child_id, child)| { + .filter_map(|(child_id, child)| { convert_to_lsp_document_symbol(db, file, symbols, child_id, child, encoding) }) .collect(), ), - } + }) } diff --git a/crates/ty_server/src/server/api/requests/goto_declaration.rs b/crates/ty_server/src/server/api/requests/goto_declaration.rs index 2a8c931401..7d8864ced9 100644 --- a/crates/ty_server/src/server/api/requests/goto_declaration.rs +++ b/crates/ty_server/src/server/api/requests/goto_declaration.rs @@ -40,12 +40,14 @@ impl BackgroundDocumentRequestHandler for GotoDeclarationRequestHandler { return Ok(None); }; - let offset = params.text_document_position_params.position.to_text_size( + let Some(offset) = params.text_document_position_params.position.to_text_size( db, file, snapshot.url(), snapshot.encoding(), - ); + ) else { + return Ok(None); + }; let Some(ranged) = goto_declaration(db, file, offset) else { return Ok(None); diff --git a/crates/ty_server/src/server/api/requests/goto_definition.rs b/crates/ty_server/src/server/api/requests/goto_definition.rs index 343f90a5c9..24dd781032 100644 --- a/crates/ty_server/src/server/api/requests/goto_definition.rs +++ b/crates/ty_server/src/server/api/requests/goto_definition.rs @@ -40,12 +40,14 @@ impl BackgroundDocumentRequestHandler for GotoDefinitionRequestHandler { return Ok(None); }; - let offset = params.text_document_position_params.position.to_text_size( + let Some(offset) = params.text_document_position_params.position.to_text_size( db, file, snapshot.url(), snapshot.encoding(), - ); + ) else { + return Ok(None); + }; let Some(ranged) = goto_definition(db, file, offset) else { return Ok(None); diff --git a/crates/ty_server/src/server/api/requests/goto_references.rs b/crates/ty_server/src/server/api/requests/goto_references.rs index 6cdb8e21a4..a2bba12569 100644 --- a/crates/ty_server/src/server/api/requests/goto_references.rs +++ b/crates/ty_server/src/server/api/requests/goto_references.rs @@ -40,12 +40,14 @@ impl BackgroundDocumentRequestHandler for ReferencesRequestHandler { return Ok(None); }; - let offset = params.text_document_position.position.to_text_size( + let Some(offset) = params.text_document_position.position.to_text_size( db, file, snapshot.url(), snapshot.encoding(), - ); + ) else { + return Ok(None); + }; let include_declaration = params.context.include_declaration; diff --git a/crates/ty_server/src/server/api/requests/goto_type_definition.rs b/crates/ty_server/src/server/api/requests/goto_type_definition.rs index 11564f50d7..31e2816225 100644 --- a/crates/ty_server/src/server/api/requests/goto_type_definition.rs +++ b/crates/ty_server/src/server/api/requests/goto_type_definition.rs @@ -40,12 +40,14 @@ impl BackgroundDocumentRequestHandler for GotoTypeDefinitionRequestHandler { return Ok(None); }; - let offset = params.text_document_position_params.position.to_text_size( + let Some(offset) = params.text_document_position_params.position.to_text_size( db, file, snapshot.url(), snapshot.encoding(), - ); + ) else { + return Ok(None); + }; let Some(ranged) = goto_type_definition(db, file, offset) else { return Ok(None); diff --git a/crates/ty_server/src/server/api/requests/hover.rs b/crates/ty_server/src/server/api/requests/hover.rs index d051007003..d9e7ec6430 100644 --- a/crates/ty_server/src/server/api/requests/hover.rs +++ b/crates/ty_server/src/server/api/requests/hover.rs @@ -39,12 +39,14 @@ impl BackgroundDocumentRequestHandler for HoverRequestHandler { return Ok(None); }; - let offset = params.text_document_position_params.position.to_text_size( + let Some(offset) = params.text_document_position_params.position.to_text_size( db, file, snapshot.url(), snapshot.encoding(), - ); + ) else { + return Ok(None); + }; let Some(range_info) = hover(db, file, offset) else { return Ok(None); @@ -66,12 +68,10 @@ impl BackgroundDocumentRequestHandler for HoverRequestHandler { kind: lsp_markup_kind, value: contents, }), - range: Some( - range_info - .file_range() - .as_lsp_range(db, snapshot.encoding()) - .to_local_range(), - ), + range: range_info + .file_range() + .to_lsp_range(db, snapshot.encoding()) + .map(|lsp_range| lsp_range.local_range()), })) } } diff --git a/crates/ty_server/src/server/api/requests/inlay_hints.rs b/crates/ty_server/src/server/api/requests/inlay_hints.rs index ec445f9b1e..2698456970 100644 --- a/crates/ty_server/src/server/api/requests/inlay_hints.rs +++ b/crates/ty_server/src/server/api/requests/inlay_hints.rs @@ -39,26 +39,31 @@ impl BackgroundDocumentRequestHandler for InlayHintRequestHandler { return Ok(None); }; - let range = params + let Some(range) = params .range - .to_text_range(db, file, snapshot.url(), snapshot.encoding()); + .to_text_range(db, file, snapshot.url(), snapshot.encoding()) + else { + return Ok(None); + }; let inlay_hints = inlay_hints(db, file, range, workspace_settings.inlay_hints()); let inlay_hints = inlay_hints .into_iter() - .map(|hint| lsp_types::InlayHint { - position: hint - .position - .as_lsp_position(db, file, snapshot.encoding()) - .to_local_position(), - label: inlay_hint_label(&hint.label), - kind: Some(inlay_hint_kind(&hint.kind)), - tooltip: None, - padding_left: None, - padding_right: None, - data: None, - text_edits: None, + .filter_map(|hint| { + Some(lsp_types::InlayHint { + position: hint + .position + .to_lsp_position(db, file, snapshot.encoding())? + .local_position(), + label: inlay_hint_label(&hint.label), + kind: Some(inlay_hint_kind(&hint.kind)), + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + text_edits: None, + }) }) .collect(); diff --git a/crates/ty_server/src/server/api/requests/prepare_rename.rs b/crates/ty_server/src/server/api/requests/prepare_rename.rs index 2593122530..f12dde90b7 100644 --- a/crates/ty_server/src/server/api/requests/prepare_rename.rs +++ b/crates/ty_server/src/server/api/requests/prepare_rename.rs @@ -40,17 +40,24 @@ impl BackgroundDocumentRequestHandler for PrepareRenameRequestHandler { return Ok(None); }; - let offset = params - .position - .to_text_size(db, file, snapshot.url(), snapshot.encoding()); + let Some(offset) = + params + .position + .to_text_size(db, file, snapshot.url(), snapshot.encoding()) + else { + return Ok(None); + }; let Some(range) = can_rename(db, file, offset) else { return Ok(None); }; - let lsp_range = range - .as_lsp_range(db, file, snapshot.encoding()) - .to_local_range(); + let Some(lsp_range) = range + .to_lsp_range(db, file, snapshot.encoding()) + .map(|lsp_range| lsp_range.local_range()) + else { + return Ok(None); + }; Ok(Some(PrepareRenameResponse::Range(lsp_range))) } diff --git a/crates/ty_server/src/server/api/requests/rename.rs b/crates/ty_server/src/server/api/requests/rename.rs index efa3891ced..978e1769df 100644 --- a/crates/ty_server/src/server/api/requests/rename.rs +++ b/crates/ty_server/src/server/api/requests/rename.rs @@ -41,12 +41,14 @@ impl BackgroundDocumentRequestHandler for RenameRequestHandler { return Ok(None); }; - let offset = params.text_document_position.position.to_text_size( + let Some(offset) = params.text_document_position.position.to_text_size( db, file, snapshot.url(), snapshot.encoding(), - ); + ) else { + return Ok(None); + }; let Some(rename_results) = rename(db, file, offset, ¶ms.new_name) else { return Ok(None); diff --git a/crates/ty_server/src/server/api/requests/selection_range.rs b/crates/ty_server/src/server/api/requests/selection_range.rs index 77d9df4c25..46518810f6 100644 --- a/crates/ty_server/src/server/api/requests/selection_range.rs +++ b/crates/ty_server/src/server/api/requests/selection_range.rs @@ -43,17 +43,25 @@ impl BackgroundDocumentRequestHandler for SelectionRangeRequestHandler { let mut results = Vec::new(); for position in params.positions { - let offset = position.to_text_size(db, file, snapshot.url(), snapshot.encoding()); + let Some(offset) = position.to_text_size(db, file, snapshot.url(), snapshot.encoding()) + else { + continue; + }; let ranges = selection_range(db, file, offset); if !ranges.is_empty() { // Convert ranges to nested LSP SelectionRange structure let mut lsp_range = None; for &range in &ranges { + let Some(range) = range + .to_lsp_range(db, file, snapshot.encoding()) + .map(|lsp_range| lsp_range.local_range()) + else { + break; + }; + lsp_range = Some(LspSelectionRange { - range: range - .as_lsp_range(db, file, snapshot.encoding()) - .to_local_range(), + range, parent: lsp_range.map(Box::new), }); } diff --git a/crates/ty_server/src/server/api/requests/semantic_tokens_range.rs b/crates/ty_server/src/server/api/requests/semantic_tokens_range.rs index 7daa116876..1cd0484f14 100644 --- a/crates/ty_server/src/server/api/requests/semantic_tokens_range.rs +++ b/crates/ty_server/src/server/api/requests/semantic_tokens_range.rs @@ -39,10 +39,13 @@ impl BackgroundDocumentRequestHandler for SemanticTokensRangeRequestHandler { }; // Convert LSP range to text offsets - let requested_range = + let Some(requested_range) = params .range - .to_text_range(db, file, snapshot.url(), snapshot.encoding()); + .to_text_range(db, file, snapshot.url(), snapshot.encoding()) + else { + return Ok(None); + }; let lsp_tokens = generate_semantic_tokens( db, diff --git a/crates/ty_server/src/server/api/requests/signature_help.rs b/crates/ty_server/src/server/api/requests/signature_help.rs index 99d60c398f..81c31adc1b 100644 --- a/crates/ty_server/src/server/api/requests/signature_help.rs +++ b/crates/ty_server/src/server/api/requests/signature_help.rs @@ -42,12 +42,14 @@ impl BackgroundDocumentRequestHandler for SignatureHelpRequestHandler { return Ok(None); }; - let offset = params.text_document_position_params.position.to_text_size( + let Some(offset) = params.text_document_position_params.position.to_text_size( db, file, snapshot.url(), snapshot.encoding(), - ); + ) else { + return Ok(None); + }; // Extract signature help capabilities from the client let resolved_capabilities = snapshot.resolved_client_capabilities(); diff --git a/crates/ty_server/src/server/api/semantic_tokens.rs b/crates/ty_server/src/server/api/semantic_tokens.rs index ee9808b791..a6208087c0 100644 --- a/crates/ty_server/src/server/api/semantic_tokens.rs +++ b/crates/ty_server/src/server/api/semantic_tokens.rs @@ -24,10 +24,14 @@ pub(crate) fn generate_semantic_tokens( let mut prev_start = 0u32; for token in &*semantic_token_data { - let lsp_range = token + let Some(lsp_range) = token .range() - .as_lsp_range(db, file, encoding) - .to_local_range(); + .to_lsp_range(db, file, encoding) + .map(|lsp_range| lsp_range.local_range()) + else { + continue; + }; + let line = lsp_range.start.line; let character = lsp_range.start.character; diff --git a/crates/ty_server/src/server/api/symbols.rs b/crates/ty_server/src/server/api/symbols.rs index e823e32a98..dd0dc67dcb 100644 --- a/crates/ty_server/src/server/api/symbols.rs +++ b/crates/ty_server/src/server/api/symbols.rs @@ -36,7 +36,7 @@ pub(crate) fn convert_to_lsp_symbol_information( let location = symbol .full_range - .as_lsp_range(db, file, encoding) + .to_lsp_range(db, file, encoding)? .to_location()?; Some(SymbolInformation {