Skip to content

Commit 390918e

Browse files
authored
[ty] Add python.ty.disableLanguageServices config (#18230)
## Summary PR adding support for it in the VS Code extension: astral-sh/ty-vscode#36 This PR adds support for `python.ty.disableLanguageServices` to the ty language server by accepting this as server setting. This has the same issue as astral-sh/ty#282 in that it only works when configured globally. Fixing that requires support for multiple workspaces in the server itself. I also went ahead and did a similar refactor as the Ruff server to use "Options" and "Settings" to keep the code consistent although the combine functionality doesn't exists yet because workspace settings isn't supported in the ty server. ## Test Plan Refer to astral-sh/ty-vscode#36 for the test demo.
1 parent a1c69ca commit 390918e

10 files changed

Lines changed: 239 additions & 136 deletions

File tree

crates/ty_server/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::server::{ConnectionInitializer, Server};
22
use anyhow::Context;
33
pub use document::{NotebookDocument, PositionEncoding, TextDocument};
4-
pub use session::{ClientSettings, DocumentQuery, DocumentSnapshot, Session};
4+
pub use session::{DocumentQuery, DocumentSnapshot, Session};
55
use std::num::NonZeroUsize;
66

77
mod document;

crates/ty_server/src/server.rs

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use self::schedule::spawn_main_loop;
44
use crate::PositionEncoding;
5-
use crate::session::{AllSettings, ClientSettings, Session};
5+
use crate::session::{AllOptions, ClientOptions, Session};
66
use lsp_server::Connection;
77
use lsp_types::{
88
ClientCapabilities, DiagnosticOptions, DiagnosticServerCapabilities, HoverProviderCapability,
@@ -42,10 +42,10 @@ impl Server {
4242
) -> crate::Result<Self> {
4343
let (id, init_params) = connection.initialize_start()?;
4444

45-
let AllSettings {
46-
global_settings,
47-
mut workspace_settings,
48-
} = AllSettings::from_value(
45+
let AllOptions {
46+
global: global_options,
47+
workspace: mut workspace_options,
48+
} = AllOptions::from_value(
4949
init_params
5050
.initialization_options
5151
.unwrap_or_else(|| serde_json::Value::Object(serde_json::Map::default())),
@@ -68,34 +68,48 @@ impl Server {
6868
let client = Client::new(main_loop_sender.clone(), connection.sender.clone());
6969

7070
crate::logging::init_logging(
71-
global_settings.tracing.log_level.unwrap_or_default(),
72-
global_settings.tracing.log_file.as_deref(),
71+
global_options.tracing.log_level.unwrap_or_default(),
72+
global_options.tracing.log_file.as_deref(),
7373
);
7474

7575
let mut workspace_for_url = |url: Url| {
76-
let Some(workspace_settings) = workspace_settings.as_mut() else {
77-
return (url, ClientSettings::default());
76+
let Some(workspace_settings) = workspace_options.as_mut() else {
77+
return (url, ClientOptions::default());
7878
};
7979
let settings = workspace_settings.remove(&url).unwrap_or_else(|| {
80-
tracing::warn!("No workspace settings found for {}", url);
81-
ClientSettings::default()
80+
tracing::warn!(
81+
"No workspace options found for {}, using default options",
82+
url
83+
);
84+
ClientOptions::default()
8285
});
8386
(url, settings)
8487
};
8588

8689
let workspaces = init_params
8790
.workspace_folders
8891
.filter(|folders| !folders.is_empty())
89-
.map(|folders| folders.into_iter().map(|folder| {
90-
workspace_for_url(folder.uri)
91-
}).collect())
92+
.map(|folders| {
93+
folders
94+
.into_iter()
95+
.map(|folder| workspace_for_url(folder.uri))
96+
.collect()
97+
})
9298
.or_else(|| {
93-
tracing::warn!("No workspace(s) were provided during initialization. Using the current working directory as a default workspace...");
94-
let uri = Url::from_file_path(std::env::current_dir().ok()?).ok()?;
99+
let current_dir = std::env::current_dir().ok()?;
100+
tracing::warn!(
101+
"No workspace(s) were provided during initialization. \
102+
Using the current working directory as a default workspace: {}",
103+
current_dir.display()
104+
);
105+
let uri = Url::from_file_path(current_dir).ok()?;
95106
Some(vec![workspace_for_url(uri)])
96107
})
97108
.ok_or_else(|| {
98-
anyhow::anyhow!("Failed to get the current working directory while creating a default workspace.")
109+
anyhow::anyhow!(
110+
"Failed to get the current working directory while creating a \
111+
default workspace."
112+
)
99113
})?;
100114

101115
let workspaces = if workspaces.len() > 1 {
@@ -121,7 +135,7 @@ impl Server {
121135
session: Session::new(
122136
&client_capabilities,
123137
position_encoding,
124-
global_settings,
138+
global_options,
125139
&workspaces,
126140
)?,
127141
client_capabilities,

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ impl BackgroundDocumentRequestHandler for CompletionRequestHandler {
3030
_client: &Client,
3131
params: CompletionParams,
3232
) -> crate::server::Result<Option<CompletionResponse>> {
33+
if snapshot.client_settings().is_language_services_disabled() {
34+
return Ok(None);
35+
}
36+
3337
let Some(file) = snapshot.file(db) else {
3438
tracing::debug!("Failed to resolve file for {:?}", params);
3539
return Ok(None);

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ impl BackgroundDocumentRequestHandler for GotoTypeDefinitionRequestHandler {
2828
_client: &Client,
2929
params: GotoTypeDefinitionParams,
3030
) -> crate::server::Result<Option<GotoDefinitionResponse>> {
31+
if snapshot.client_settings().is_language_services_disabled() {
32+
return Ok(None);
33+
}
34+
3135
let Some(file) = snapshot.file(db) else {
3236
tracing::debug!("Failed to resolve file for {:?}", params);
3337
return Ok(None);

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ impl BackgroundDocumentRequestHandler for HoverRequestHandler {
2828
_client: &Client,
2929
params: HoverParams,
3030
) -> crate::server::Result<Option<lsp_types::Hover>> {
31+
if snapshot.client_settings().is_language_services_disabled() {
32+
return Ok(None);
33+
}
34+
3135
let Some(file) = snapshot.file(db) else {
3236
tracing::debug!("Failed to resolve file for {:?}", params);
3337
return Ok(None);

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ impl BackgroundDocumentRequestHandler for InlayHintRequestHandler {
2727
_client: &Client,
2828
params: InlayHintParams,
2929
) -> crate::server::Result<Option<Vec<lsp_types::InlayHint>>> {
30+
if snapshot.client_settings().is_language_services_disabled() {
31+
return Ok(None);
32+
}
33+
3034
let Some(file) = snapshot.file(db) else {
3135
tracing::debug!("Failed to resolve file for {:?}", params);
3236
return Ok(None);

crates/ty_server/src/session.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@ use std::sync::Arc;
77

88
use anyhow::anyhow;
99
use lsp_types::{ClientCapabilities, TextDocumentContentChangeEvent, Url};
10+
use options::GlobalOptions;
1011
use ruff_db::Db;
1112
use ruff_db::files::{File, system_path_to_file};
1213
use ruff_db::system::SystemPath;
1314
use ty_project::{ProjectDatabase, ProjectMetadata};
1415

1516
pub(crate) use self::capabilities::ResolvedClientCapabilities;
1617
pub use self::index::DocumentQuery;
17-
pub(crate) use self::settings::AllSettings;
18-
pub use self::settings::ClientSettings;
18+
pub(crate) use self::options::{AllOptions, ClientOptions};
19+
use self::settings::ClientSettings;
1920
use crate::document::{DocumentKey, DocumentVersion, NotebookDocument};
2021
use crate::session::request_queue::RequestQueue;
2122
use crate::system::{AnySystemPath, LSPSystem};
@@ -24,6 +25,7 @@ use crate::{PositionEncoding, TextDocument};
2425
mod capabilities;
2526
pub(crate) mod client;
2627
pub(crate) mod index;
28+
mod options;
2729
mod request_queue;
2830
mod settings;
2931

@@ -58,12 +60,13 @@ impl Session {
5860
pub(crate) fn new(
5961
client_capabilities: &ClientCapabilities,
6062
position_encoding: PositionEncoding,
61-
global_settings: ClientSettings,
62-
workspace_folders: &[(Url, ClientSettings)],
63+
global_options: GlobalOptions,
64+
workspace_folders: &[(Url, ClientOptions)],
6365
) -> crate::Result<Self> {
6466
let mut workspaces = BTreeMap::new();
65-
let index = Arc::new(index::Index::new(global_settings));
67+
let index = Arc::new(index::Index::new(global_options.into_settings()));
6668

69+
// TODO: Consider workspace settings
6770
for (url, _) in workspace_folders {
6871
let path = url
6972
.to_file_path()
@@ -168,6 +171,7 @@ impl Session {
168171
let key = self.key_from_url(url).ok()?;
169172
Some(DocumentSnapshot {
170173
resolved_client_capabilities: self.resolved_client_capabilities.clone(),
174+
client_settings: self.index().global_settings(),
171175
document_ref: self.index().make_document_ref(&key)?,
172176
position_encoding: self.position_encoding,
173177
})
@@ -303,6 +307,7 @@ impl Drop for MutIndexGuard<'_> {
303307
#[derive(Debug)]
304308
pub struct DocumentSnapshot {
305309
resolved_client_capabilities: Arc<ResolvedClientCapabilities>,
310+
client_settings: Arc<ClientSettings>,
306311
document_ref: index::DocumentQuery,
307312
position_encoding: PositionEncoding,
308313
}
@@ -312,14 +317,18 @@ impl DocumentSnapshot {
312317
&self.resolved_client_capabilities
313318
}
314319

315-
pub fn query(&self) -> &index::DocumentQuery {
320+
pub(crate) fn query(&self) -> &index::DocumentQuery {
316321
&self.document_ref
317322
}
318323

319324
pub(crate) fn encoding(&self) -> PositionEncoding {
320325
self.position_encoding
321326
}
322327

328+
pub(crate) fn client_settings(&self) -> &ClientSettings {
329+
&self.client_settings
330+
}
331+
323332
pub(crate) fn file(&self, db: &dyn Db) -> Option<File> {
324333
match AnySystemPath::try_from_url(self.document_ref.file_url()).ok()? {
325334
AnySystemPath::System(path) => system_path_to_file(db, path).ok(),

crates/ty_server/src/session/index.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@ use std::sync::Arc;
33
use lsp_types::Url;
44
use rustc_hash::FxHashMap;
55

6+
use crate::session::settings::ClientSettings;
67
use crate::{
78
PositionEncoding, TextDocument,
89
document::{DocumentKey, DocumentVersion, NotebookDocument},
910
system::AnySystemPath,
1011
};
1112

12-
use super::ClientSettings;
13-
1413
/// Stores and tracks all open documents in a session, along with their associated settings.
15-
#[derive(Default, Debug)]
14+
#[derive(Debug)]
1615
pub(crate) struct Index {
1716
/// Maps all document file paths to the associated document controller
1817
documents: FxHashMap<AnySystemPath, DocumentController>,
@@ -21,16 +20,15 @@ pub(crate) struct Index {
2120
notebook_cells: FxHashMap<Url, AnySystemPath>,
2221

2322
/// Global settings provided by the client.
24-
#[expect(dead_code)]
25-
global_settings: ClientSettings,
23+
global_settings: Arc<ClientSettings>,
2624
}
2725

2826
impl Index {
2927
pub(super) fn new(global_settings: ClientSettings) -> Self {
3028
Self {
3129
documents: FxHashMap::default(),
3230
notebook_cells: FxHashMap::default(),
33-
global_settings,
31+
global_settings: Arc::new(global_settings),
3432
}
3533
}
3634

@@ -177,6 +175,10 @@ impl Index {
177175
Ok(())
178176
}
179177

178+
pub(crate) fn global_settings(&self) -> Arc<ClientSettings> {
179+
self.global_settings.clone()
180+
}
181+
180182
fn document_controller_for_key(
181183
&mut self,
182184
key: &DocumentKey,

0 commit comments

Comments
 (0)