mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 22:31:23 +00:00
[ty] Make sure to always respond to client requests (#19277)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
## Summary This PR fixes a bug that didn't return a response to the client if the document snapshotting failed. This is resolved by making sure that the server always creates the document snapshot and embed the any failures inside the snapshot. Closes: astral-sh/ty#798 ## Test Plan Using the test case as described in the linked issue: https://github.com/user-attachments/assets/f32833f8-03e5-4641-8c7f-2a536fe2e270
This commit is contained in:
parent
39c6364545
commit
fd69533fe5
21 changed files with 243 additions and 144 deletions
|
@ -1,6 +1,8 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use lsp_types::Url;
|
||||
use ruff_db::Db;
|
||||
use ruff_db::files::{File, system_path_to_file};
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use crate::session::settings::ClientSettings;
|
||||
|
@ -68,16 +70,17 @@ impl Index {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn key_from_url(&self, url: Url) -> crate::Result<DocumentKey> {
|
||||
/// Returns the [`DocumentKey`] corresponding to the given URL.
|
||||
///
|
||||
/// It returns [`Err`] with the original URL if it cannot be converted to a [`AnySystemPath`].
|
||||
pub(crate) fn key_from_url(&self, url: Url) -> Result<DocumentKey, Url> {
|
||||
if let Some(notebook_path) = self.notebook_cells.get(&url) {
|
||||
Ok(DocumentKey::NotebookCell {
|
||||
cell_url: url,
|
||||
notebook_path: notebook_path.clone(),
|
||||
})
|
||||
} else {
|
||||
let path = AnySystemPath::try_from_url(&url)
|
||||
.map_err(|()| anyhow::anyhow!("Failed to convert URL to system path: {}", url))?;
|
||||
|
||||
let path = AnySystemPath::try_from_url(&url).map_err(|()| url)?;
|
||||
if path
|
||||
.extension()
|
||||
.is_some_and(|ext| ext.eq_ignore_ascii_case("ipynb"))
|
||||
|
@ -122,17 +125,27 @@ impl Index {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn make_document_ref(&self, key: &DocumentKey) -> Option<DocumentQuery> {
|
||||
/// Create a document reference corresponding to the given document key.
|
||||
///
|
||||
/// Returns an error if the document is not found or if the path cannot be converted to a URL.
|
||||
pub(crate) fn make_document_ref(
|
||||
&self,
|
||||
key: DocumentKey,
|
||||
) -> Result<DocumentQuery, DocumentQueryError> {
|
||||
let path = key.path();
|
||||
let controller = self.documents.get(path)?;
|
||||
let (cell_url, file_url) = match &key {
|
||||
let Some(controller) = self.documents.get(path) else {
|
||||
return Err(DocumentQueryError::NotFound(key));
|
||||
};
|
||||
// TODO: The `to_url` conversion shouldn't be an error because the paths themselves are
|
||||
// constructed from the URLs but the `Index` APIs don't maintain this invariant.
|
||||
let (cell_url, file_path) = match key {
|
||||
DocumentKey::NotebookCell {
|
||||
cell_url,
|
||||
notebook_path,
|
||||
} => (Some(cell_url.clone()), notebook_path.to_url()?),
|
||||
DocumentKey::Notebook(path) | DocumentKey::Text(path) => (None, path.to_url()?),
|
||||
} => (Some(cell_url), notebook_path),
|
||||
DocumentKey::Notebook(path) | DocumentKey::Text(path) => (None, path),
|
||||
};
|
||||
Some(controller.make_ref(cell_url, file_url))
|
||||
Ok(controller.make_ref(cell_url, file_path))
|
||||
}
|
||||
|
||||
pub(super) fn open_text_document(&mut self, path: &AnySystemPath, document: TextDocument) {
|
||||
|
@ -207,15 +220,15 @@ impl DocumentController {
|
|||
Self::Notebook(Arc::new(document))
|
||||
}
|
||||
|
||||
fn make_ref(&self, cell_url: Option<Url>, file_url: Url) -> DocumentQuery {
|
||||
fn make_ref(&self, cell_url: Option<Url>, file_path: AnySystemPath) -> DocumentQuery {
|
||||
match &self {
|
||||
Self::Notebook(notebook) => DocumentQuery::Notebook {
|
||||
cell_url,
|
||||
file_url,
|
||||
file_path,
|
||||
notebook: notebook.clone(),
|
||||
},
|
||||
Self::Text(document) => DocumentQuery::Text {
|
||||
file_url,
|
||||
file_path,
|
||||
document: document.clone(),
|
||||
},
|
||||
}
|
||||
|
@ -251,26 +264,27 @@ impl DocumentController {
|
|||
}
|
||||
|
||||
/// A read-only query to an open document.
|
||||
///
|
||||
/// This query can 'select' a text document, full notebook, or a specific notebook cell.
|
||||
/// It also includes document settings.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DocumentQuery {
|
||||
pub(crate) enum DocumentQuery {
|
||||
Text {
|
||||
file_url: Url,
|
||||
file_path: AnySystemPath,
|
||||
document: Arc<TextDocument>,
|
||||
},
|
||||
Notebook {
|
||||
/// The selected notebook cell, if it exists.
|
||||
cell_url: Option<Url>,
|
||||
/// The URL of the notebook.
|
||||
file_url: Url,
|
||||
/// The path to the notebook.
|
||||
file_path: AnySystemPath,
|
||||
notebook: Arc<NotebookDocument>,
|
||||
},
|
||||
}
|
||||
|
||||
impl DocumentQuery {
|
||||
/// Attempts to access the underlying notebook document that this query is selecting.
|
||||
pub fn as_notebook(&self) -> Option<&NotebookDocument> {
|
||||
pub(crate) fn as_notebook(&self) -> Option<&NotebookDocument> {
|
||||
match self {
|
||||
Self::Notebook { notebook, .. } => Some(notebook),
|
||||
Self::Text { .. } => None,
|
||||
|
@ -285,10 +299,10 @@ impl DocumentQuery {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the URL for the document selected by this query.
|
||||
pub(crate) fn file_url(&self) -> &Url {
|
||||
/// Get the system path for the document selected by this query.
|
||||
pub(crate) fn file_path(&self) -> &AnySystemPath {
|
||||
match self {
|
||||
Self::Text { file_url, .. } | Self::Notebook { file_url, .. } => file_url,
|
||||
Self::Text { file_path, .. } | Self::Notebook { file_path, .. } => file_path,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,4 +321,27 @@ impl DocumentQuery {
|
|||
.and_then(|cell_uri| notebook.cell_document_by_uri(cell_uri)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the salsa interned [`File`] for the document selected by this query.
|
||||
///
|
||||
/// It returns [`None`] for the following cases:
|
||||
/// - For virtual file, if it's not yet opened
|
||||
/// - For regular file, if it does not exists or is a directory
|
||||
pub(crate) fn file(&self, db: &dyn Db) -> Option<File> {
|
||||
match self.file_path() {
|
||||
AnySystemPath::System(path) => system_path_to_file(db, path).ok(),
|
||||
AnySystemPath::SystemVirtual(virtual_path) => db
|
||||
.files()
|
||||
.try_virtual_file(virtual_path)
|
||||
.map(|virtual_file| virtual_file.file()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, thiserror::Error)]
|
||||
pub(crate) enum DocumentQueryError {
|
||||
#[error("invalid URL: {0}")]
|
||||
InvalidUrl(Url),
|
||||
#[error("document not found for key: {0}")]
|
||||
NotFound(DocumentKey),
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue