[ty] Warn users if server received unknown options (#19779)

## Summary

This PR updates the client settings handling to recognize unknown
options provided by the user and show a warning popup along with a
warning log message.

## Test Plan

Add E2E tests.
This commit is contained in:
Dhruv Manilawala 2025-08-06 18:41:13 +05:30 committed by GitHub
parent 1f29a04e9a
commit fa711fa40f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 90 additions and 2 deletions

View file

@ -98,6 +98,15 @@ impl Server {
let (main_loop_sender, main_loop_receiver) = crossbeam::channel::bounded(32);
let client = Client::new(main_loop_sender.clone(), connection.sender.clone());
if !initialization_options.options.unknown.is_empty() {
let options = serde_json::to_string_pretty(&initialization_options.options.unknown)
.unwrap_or_else(|_| "<invalid JSON>".to_string());
tracing::warn!("Received unknown options during initialization: {options}");
client.show_warning_message(format_args!(
"Received unknown options during initialization: {options}"
));
}
// Get workspace URLs without settings - settings will come from workspace/configuration
let workspace_urls = workspace_folders
.filter(|folders| !folders.is_empty())

View file

@ -450,12 +450,23 @@ impl Session {
// Combine the global options specified during initialization with the
// workspace-specific options to create the final workspace options.
let ClientOptions { global, workspace } = self
let ClientOptions {
global, workspace, ..
} = self
.initialization_options
.options
.clone()
.combine(options.clone());
if !options.unknown.is_empty() {
let options = serde_json::to_string_pretty(&options.unknown)
.unwrap_or_else(|_| "<invalid JSON>".to_string());
tracing::warn!("Received unknown options for workspace `{url}`: {options}");
client.show_warning_message(format!(
"Received unknown options for workspace `{url}`: {options}",
));
}
combined_global_options.combine_with(Some(global));
let workspace_settings = workspace.into_settings();

View file

@ -1,3 +1,5 @@
use std::collections::HashMap;
use lsp_types::Url;
use ruff_db::system::SystemPathBuf;
use ruff_macros::Combine;
@ -84,6 +86,11 @@ pub struct ClientOptions {
#[serde(flatten)]
pub(crate) workspace: WorkspaceOptions,
/// Additional options that aren't valid as per the schema but we accept it to provide better
/// error message to the user.
#[serde(flatten)]
pub(crate) unknown: HashMap<String, Value>,
}
impl ClientOptions {
@ -98,6 +105,12 @@ impl ClientOptions {
self.workspace.disable_language_services = Some(disable_language_services);
self
}
#[must_use]
pub fn with_unknown(mut self, unknown: HashMap<String, Value>) -> Self {
self.unknown = unknown;
self
}
}
/// Options that are global to the language server.