Skip to content

Commit f7fc8fb

Browse files
authored
[ty] Request configuration from client (#18984)
## Summary This PR makes the necessary changes to the server that it can request configurations from the client using the `configuration` request. This PR doesn't make use of the request yet. It only sets up the foundation (mainly the coordination between client and server) so that future PRs could pull specific settings. I plan to use this for pulling the Python environment from the Python extension. Deno does something very similar to this. ## Test Plan Tested that diagnostics are still shown.
1 parent cdf91b8 commit f7fc8fb

File tree

17 files changed

+450
-187
lines changed

17 files changed

+450
-187
lines changed

crates/ruff_db/src/files.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,23 @@ impl Files {
263263

264264
impl fmt::Debug for Files {
265265
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
266-
let mut map = f.debug_map();
266+
if f.alternate() {
267+
let mut map = f.debug_map();
267268

268-
for entry in self.inner.system_by_path.iter() {
269-
map.entry(entry.key(), entry.value());
269+
for entry in self.inner.system_by_path.iter() {
270+
map.entry(entry.key(), entry.value());
271+
}
272+
map.finish()
273+
} else {
274+
f.debug_struct("Files")
275+
.field("system_by_path", &self.inner.system_by_path.len())
276+
.field(
277+
"system_virtual_by_path",
278+
&self.inner.system_virtual_by_path.len(),
279+
)
280+
.field("vendored_by_path", &self.inner.vendored_by_path.len())
281+
.finish()
270282
}
271-
map.finish()
272283
}
273284
}
274285

crates/ty_project/src/db.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::fmt::Formatter;
12
use std::panic::{AssertUnwindSafe, RefUnwindSafe};
23
use std::sync::Arc;
34
use std::{cmp, fmt};
@@ -146,6 +147,16 @@ impl ProjectDatabase {
146147
}
147148
}
148149

150+
impl std::fmt::Debug for ProjectDatabase {
151+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
152+
f.debug_struct("ProjectDatabase")
153+
.field("project", &self.project)
154+
.field("files", &self.files)
155+
.field("system", &self.system)
156+
.finish_non_exhaustive()
157+
}
158+
}
159+
149160
/// Stores memory usage information.
150161
pub struct SalsaMemoryDump {
151162
total_fields: usize,

crates/ty_project/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub fn default_lints_registry() -> LintRegistry {
5555
/// it remains the same project. That's why program is a narrowed view of the project only
5656
/// holding on to the most fundamental settings required for checking.
5757
#[salsa::input]
58+
#[derive(Debug)]
5859
pub struct Project {
5960
/// The files that are open in the project.
6061
///

crates/ty_server/src/server.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ impl Server {
136136
&client_capabilities,
137137
position_encoding,
138138
global_options,
139-
&workspaces,
139+
workspaces,
140140
)?,
141141
client_capabilities,
142142
})
@@ -227,12 +227,10 @@ impl ServerPanicHookHandler {
227227
writeln!(stderr, "{panic_info}\n{backtrace}").ok();
228228

229229
if let Some(client) = hook_client.upgrade() {
230-
client
231-
.show_message(
232-
"The ty language server exited with a panic. See the logs for more details.",
233-
MessageType::ERROR,
234-
)
235-
.ok();
230+
client.show_message(
231+
"The ty language server exited with a panic. See the logs for more details.",
232+
MessageType::ERROR,
233+
);
236234
}
237235
}));
238236

crates/ty_server/src/server/api.rs

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ where
160160
};
161161

162162
let db = match &path {
163-
AnySystemPath::System(path) => match session.project_db_for_path(path.as_std_path()) {
163+
AnySystemPath::System(path) => match session.project_db_for_path(path) {
164164
Some(db) => db.clone(),
165165
None => session.default_project_db().clone(),
166166
},
@@ -224,17 +224,14 @@ where
224224
request.id,
225225
request.method
226226
);
227-
if client.retry(request).is_ok() {
228-
return None;
229-
}
227+
client.retry(request);
228+
} else {
229+
tracing::trace!(
230+
"request id={} was cancelled by salsa, sending content modified",
231+
id
232+
);
233+
respond_silent_error(id.clone(), client, R::salsa_cancellation_error());
230234
}
231-
232-
tracing::trace!(
233-
"request id={} was cancelled by salsa, sending content modified",
234-
id
235-
);
236-
237-
respond_silent_error(id.clone(), client, R::salsa_cancellation_error());
238235
None
239236
} else {
240237
Some(Err(Error {
@@ -343,17 +340,13 @@ fn respond<Req>(
343340
tracing::error!("An error occurred with request ID {id}: {err}");
344341
client.show_error_message("ty encountered a problem. Check the logs for more details.");
345342
}
346-
if let Err(err) = client.respond(id, result) {
347-
tracing::error!("Failed to send response: {err}");
348-
}
343+
client.respond(id, result);
349344
}
350345

351346
/// Sends back an error response to the server using a [`Client`] without showing a warning
352347
/// to the user.
353348
fn respond_silent_error(id: RequestId, client: &Client, error: lsp_server::ResponseError) {
354-
if let Err(err) = client.respond_err(id, error) {
355-
tracing::error!("Failed to send response: {err}");
356-
}
349+
client.respond_err(id, error);
357350
}
358351

359352
/// Tries to cast a serialized request from the server into

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

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use lsp_server::ErrorCode;
21
use lsp_types::notification::PublishDiagnostics;
32
use lsp_types::{
43
CodeDescription, Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag,
@@ -46,20 +45,17 @@ impl Diagnostics {
4645
/// This is done by notifying the client with an empty list of diagnostics for the document.
4746
/// For notebook cells, this clears diagnostics for the specific cell.
4847
/// For other document types, this clears diagnostics for the main document.
49-
pub(super) fn clear_diagnostics(key: &DocumentKey, client: &Client) -> Result<()> {
48+
pub(super) fn clear_diagnostics(key: &DocumentKey, client: &Client) {
5049
let Some(uri) = key.to_url() else {
5150
// If we can't convert to URL, we can't clear diagnostics
52-
return Ok(());
51+
return;
5352
};
5453

55-
client
56-
.send_notification::<PublishDiagnostics>(PublishDiagnosticsParams {
57-
uri,
58-
diagnostics: vec![],
59-
version: None,
60-
})
61-
.with_failure_code(ErrorCode::InternalError)?;
62-
Ok(())
54+
client.send_notification::<PublishDiagnostics>(PublishDiagnosticsParams {
55+
uri,
56+
diagnostics: vec![],
57+
version: None,
58+
});
6359
}
6460

6561
/// Publishes the diagnostics for the given document snapshot using the [publish diagnostics
@@ -96,22 +92,20 @@ pub(super) fn publish_diagnostics(
9692

9793
// Sends a notification to the client with the diagnostics for the document.
9894
let publish_diagnostics_notification = |uri: Url, diagnostics: Vec<Diagnostic>| {
99-
client
100-
.send_notification::<PublishDiagnostics>(PublishDiagnosticsParams {
101-
uri,
102-
diagnostics,
103-
version: Some(snapshot.query().version()),
104-
})
105-
.with_failure_code(lsp_server::ErrorCode::InternalError)
95+
client.send_notification::<PublishDiagnostics>(PublishDiagnosticsParams {
96+
uri,
97+
diagnostics,
98+
version: Some(snapshot.query().version()),
99+
});
106100
};
107101

108102
match diagnostics {
109103
Diagnostics::TextDocument(diagnostics) => {
110-
publish_diagnostics_notification(url, diagnostics)?;
104+
publish_diagnostics_notification(url, diagnostics);
111105
}
112106
Diagnostics::NotebookDocument(cell_diagnostics) => {
113107
for (cell_url, diagnostics) in cell_diagnostics {
114-
publish_diagnostics_notification(cell_url, diagnostics)?;
108+
publish_diagnostics_notification(cell_url, diagnostics);
115109
}
116110
}
117111
}

crates/ty_server/src/server/api/notifications/cancel.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ impl SyncNotificationHandler for CancelNotificationHandler {
2020
lsp_types::NumberOrString::String(id) => id.into(),
2121
};
2222

23-
let _ = client.cancel(session, id);
23+
client.cancel(session, id);
2424

2525
Ok(())
2626
}

crates/ty_server/src/server/api/notifications/did_change.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ impl SyncNotificationHandler for DidChangeTextDocumentHandler {
3939

4040
match key.path() {
4141
AnySystemPath::System(path) => {
42-
let db = match session.project_db_for_path_mut(path.as_std_path()) {
42+
let db = match session.project_db_for_path_mut(path) {
4343
Some(db) => db,
4444
None => session.default_project_db_mut(),
4545
};

crates/ty_server/src/server/api/notifications/did_change_watched_files.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::server::Result;
2-
use crate::server::api::LSPResult;
32
use crate::server::api::diagnostics::publish_diagnostics;
43
use crate::server::api::traits::{NotificationHandler, SyncNotificationHandler};
54
use crate::session::Session;
@@ -45,7 +44,7 @@ impl SyncNotificationHandler for DidChangeWatchedFiles {
4544
}
4645
};
4746

48-
let Some(db) = session.project_db_for_path(system_path.as_std_path()) else {
47+
let Some(db) = session.project_db_for_path(&system_path) else {
4948
tracing::trace!(
5049
"Ignoring change event for `{system_path}` because it's not in any workspace"
5150
);
@@ -103,13 +102,11 @@ impl SyncNotificationHandler for DidChangeWatchedFiles {
103102

104103
if project_changed {
105104
if client_capabilities.diagnostics_refresh {
106-
client
107-
.send_request::<types::request::WorkspaceDiagnosticRefresh>(
108-
session,
109-
(),
110-
|_, ()| {},
111-
)
112-
.with_failure_code(lsp_server::ErrorCode::InternalError)?;
105+
client.send_request::<types::request::WorkspaceDiagnosticRefresh>(
106+
session,
107+
(),
108+
|_, ()| {},
109+
);
113110
} else {
114111
for key in session.text_document_keys() {
115112
publish_diagnostics(session, &key, client)?;
@@ -120,9 +117,7 @@ impl SyncNotificationHandler for DidChangeWatchedFiles {
120117
}
121118

122119
if client_capabilities.inlay_refresh {
123-
client
124-
.send_request::<types::request::InlayHintRefreshRequest>(session, (), |_, ()| {})
125-
.with_failure_code(lsp_server::ErrorCode::InternalError)?;
120+
client.send_request::<types::request::InlayHintRefreshRequest>(session, (), |_, ()| {});
126121
}
127122

128123
Ok(())

crates/ty_server/src/server/api/notifications/did_close.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ impl SyncNotificationHandler for DidCloseTextDocumentHandler {
4141
);
4242
}
4343

44-
clear_diagnostics(&key, client)
44+
clear_diagnostics(&key, client);
45+
46+
Ok(())
4547
}
4648
}

0 commit comments

Comments
 (0)