Skip to content

Commit d6b28cf

Browse files
committed
Add Diagnostics to make the cell diagnostics explicit
1 parent 86bde6d commit d6b28cf

File tree

5 files changed

+74
-55
lines changed

5 files changed

+74
-55
lines changed

crates/ty_server/src/document.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,6 @@ impl DocumentKey {
5555
| DocumentKey::Text(url) => url,
5656
}
5757
}
58-
59-
/// Converts the key back into its original URL.
60-
pub(crate) fn into_url(self) -> Url {
61-
match self {
62-
DocumentKey::NotebookCell(url)
63-
| DocumentKey::Notebook(url)
64-
| DocumentKey::Text(url) => url,
65-
}
66-
}
6758
}
6859

6960
impl std::fmt::Display for DocumentKey {

crates/ty_server/src/document/notebook.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ impl NotebookDocument {
211211
}
212212

213213
/// Returns a list of cell URIs in the order they appear in the array.
214-
pub(crate) fn urls(&self) -> impl Iterator<Item = &lsp_types::Url> {
214+
pub(crate) fn cell_urls(&self) -> impl Iterator<Item = &lsp_types::Url> {
215215
self.cells.iter().map(|cell| &cell.url)
216216
}
217217

crates/ty_server/src/server/api/diagnostics.rs

Lines changed: 68 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,29 @@ use crate::{DocumentSnapshot, PositionEncoding};
1818

1919
use super::LSPResult;
2020

21-
/// A series of diagnostics across a single text document or an arbitrary number of notebook cells.
22-
pub(super) type DiagnosticsMap = FxHashMap<Url, Vec<Diagnostic>>;
21+
/// Represents the diagnostics for a text document or a notebook document.
22+
pub(super) enum Diagnostics {
23+
TextDocument(Vec<Diagnostic>),
24+
25+
/// A map of cell URLs to the diagnostics for that cell.
26+
NotebookDocument(FxHashMap<Url, Vec<Diagnostic>>),
27+
}
28+
29+
impl Diagnostics {
30+
/// Returns the diagnostics for a text document.
31+
///
32+
/// # Panics
33+
///
34+
/// Panics if the diagnostics are for a notebook document.
35+
pub(super) fn expect_text_document(self) -> Vec<Diagnostic> {
36+
match self {
37+
Diagnostics::TextDocument(diagnostics) => diagnostics,
38+
Diagnostics::NotebookDocument(_) => {
39+
panic!("Expected a text document diagnostics, but got notebook diagnostics")
40+
}
41+
}
42+
}
43+
}
2344

2445
/// Clears the diagnostics for the document at `uri`.
2546
///
@@ -44,14 +65,29 @@ pub(super) fn publish_diagnostics_for_document(
4465
snapshot: &DocumentSnapshot,
4566
notifier: &Notifier,
4667
) -> Result<()> {
47-
for (uri, diagnostics) in compute_diagnostics(db, snapshot) {
68+
let Some(diagnostics) = compute_diagnostics(db, snapshot) else {
69+
return Ok(());
70+
};
71+
72+
let publish_diagnostics = |uri: Url, diagnostics: Vec<Diagnostic>| {
4873
notifier
4974
.notify::<PublishDiagnostics>(PublishDiagnosticsParams {
5075
uri,
5176
diagnostics,
5277
version: Some(snapshot.query().version()),
5378
})
54-
.with_failure_code(lsp_server::ErrorCode::InternalError)?;
79+
.with_failure_code(lsp_server::ErrorCode::InternalError)
80+
};
81+
82+
match diagnostics {
83+
Diagnostics::TextDocument(diagnostics) => {
84+
publish_diagnostics(snapshot.query().file_url().clone(), diagnostics)?;
85+
}
86+
Diagnostics::NotebookDocument(map) => {
87+
for (cell_url, diagnostics) in map {
88+
publish_diagnostics(cell_url, diagnostics)?;
89+
}
90+
}
5591
}
5692

5793
Ok(())
@@ -60,66 +96,60 @@ pub(super) fn publish_diagnostics_for_document(
6096
pub(super) fn compute_diagnostics(
6197
db: &ProjectDatabase,
6298
snapshot: &DocumentSnapshot,
63-
) -> DiagnosticsMap {
99+
) -> Option<Diagnostics> {
64100
let Some(file) = snapshot.file(db) else {
65101
tracing::info!(
66102
"No file found for snapshot for `{}`",
67103
snapshot.query().file_url()
68104
);
69-
return DiagnosticsMap::default();
105+
return None;
70106
};
71107

72108
let diagnostics = match db.check_file(file) {
73109
Ok(diagnostics) => diagnostics,
74110
Err(cancelled) => {
75111
tracing::info!("Diagnostics computation {cancelled}");
76-
return DiagnosticsMap::default();
112+
return None;
77113
}
78114
};
79115

80-
let mut diagnostics_map = DiagnosticsMap::default();
81116
let query = snapshot.query();
82-
// let source_kind = query.make_source_kind();
83117

84-
// Populates all relevant URLs with an empty diagnostic list.
85-
// This ensures that documents without diagnostics still get updated.
86118
if let Some(notebook) = query.as_notebook() {
87-
for url in notebook.urls() {
88-
diagnostics_map.entry(url.clone()).or_default();
89-
}
90-
} else {
91-
diagnostics_map
92-
.entry(query.make_key().into_url())
93-
.or_default();
94-
}
119+
let mut cell_diagnostics: FxHashMap<Url, Vec<Diagnostic>> = FxHashMap::default();
95120

96-
let lsp_diagnostics = diagnostics.as_slice().iter().map(|diagnostic| {
97-
(
98-
// TODO: Use the cell index instead using `source_kind`
99-
usize::default(),
100-
to_lsp_diagnostic(db, diagnostic, snapshot.encoding()),
101-
)
102-
});
121+
// Populates all relevant URLs with an empty diagnostic list. This ensures that documents
122+
// without diagnostics still get updated.
123+
for cell_url in notebook.cell_urls() {
124+
cell_diagnostics.entry(cell_url.clone()).or_default();
125+
}
103126

104-
if let Some(notebook) = query.as_notebook() {
105-
for (index, diagnostic) in lsp_diagnostics {
106-
let Some(uri) = notebook.cell_uri_by_index(index) else {
107-
tracing::warn!("Unable to find notebook cell at index {index}");
127+
for (cell_index, diagnostic) in diagnostics.iter().map(|diagnostic| {
128+
(
129+
// TODO: Use the cell index instead using `SourceKind`
130+
usize::default(),
131+
to_lsp_diagnostic(db, diagnostic, snapshot.encoding()),
132+
)
133+
}) {
134+
let Some(cell_uri) = notebook.cell_uri_by_index(cell_index) else {
135+
tracing::warn!("Unable to find notebook cell at index {cell_index}");
108136
continue;
109137
};
110-
diagnostics_map
111-
.entry(uri.clone())
138+
cell_diagnostics
139+
.entry(cell_uri.clone())
112140
.or_default()
113141
.push(diagnostic);
114142
}
143+
144+
Some(Diagnostics::NotebookDocument(cell_diagnostics))
115145
} else {
116-
diagnostics_map
117-
.entry(query.make_key().into_url())
118-
.or_default()
119-
.extend(lsp_diagnostics.map(|(_, diagnostic)| diagnostic));
146+
Some(Diagnostics::TextDocument(
147+
diagnostics
148+
.iter()
149+
.map(|diagnostic| to_lsp_diagnostic(db, diagnostic, snapshot.encoding()))
150+
.collect(),
151+
))
120152
}
121-
122-
diagnostics_map
123153
}
124154

125155
/// Converts the tool specific [`Diagnostic`][ruff_db::diagnostic::Diagnostic] to an LSP

crates/ty_server/src/server/api/requests/diagnostic.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use lsp_types::{
66
FullDocumentDiagnosticReport, RelatedFullDocumentDiagnosticReport,
77
};
88

9-
use crate::server::api::diagnostics::compute_diagnostics;
9+
use crate::server::api::diagnostics::{Diagnostics, compute_diagnostics};
1010
use crate::server::api::traits::{BackgroundDocumentRequestHandler, RequestHandler};
1111
use crate::server::{Result, client::Notifier};
1212
use crate::session::DocumentSnapshot;
@@ -34,13 +34,10 @@ impl BackgroundDocumentRequestHandler for DocumentDiagnosticRequestHandler {
3434
related_documents: None,
3535
full_document_diagnostic_report: FullDocumentDiagnosticReport {
3636
result_id: None,
37-
// Pull diagnostic requests are only called for text documents, not for
37+
// SAFETY: Pull diagnostic requests are only called for text documents, not for
3838
// notebook documents.
3939
items: compute_diagnostics(db, &snapshot)
40-
.into_iter()
41-
.next()
42-
.map(|(_, diagnostics)| diagnostics)
43-
.unwrap_or_default(),
40+
.map_or_else(Vec::new, Diagnostics::expect_text_document),
4441
},
4542
}),
4643
))

crates/ty_server/src/session/index.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ impl Index {
135135
}
136136

137137
pub(super) fn open_notebook_document(&mut self, notebook_url: Url, document: NotebookDocument) {
138-
for cell_url in document.urls() {
138+
for cell_url in document.cell_urls() {
139139
self.notebook_cells
140140
.insert(cell_url.clone(), notebook_url.clone());
141141
}
@@ -265,6 +265,7 @@ pub enum DocumentQuery {
265265

266266
impl DocumentQuery {
267267
/// Retrieve the original key that describes this document query.
268+
#[expect(dead_code)]
268269
pub(crate) fn make_key(&self) -> DocumentKey {
269270
match self {
270271
Self::Text { file_url, .. } => DocumentKey::Text(file_url.clone()),

0 commit comments

Comments
 (0)