Centralize client options validation (#18623)
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 / mkdocs (push) Waiting to run
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 / 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 (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run

This commit is contained in:
Micha Reiser 2025-06-12 18:58:30 +02:00 committed by GitHub
parent ef564094a9
commit 3c6c017950
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 1164 additions and 1003 deletions

View file

@ -11,13 +11,15 @@ use thiserror::Error;
pub(crate) use ruff_settings::RuffSettings;
use crate::edit::LanguageId;
use crate::session::options::Combine;
use crate::session::settings::GlobalClientSettings;
use crate::workspace::{Workspace, Workspaces};
use crate::{
PositionEncoding, TextDocument,
edit::{DocumentKey, DocumentVersion, NotebookDocument},
};
use super::{ClientSettings, settings::ResolvedClientSettings};
use super::settings::ClientSettings;
mod ruff_settings;
@ -36,7 +38,7 @@ pub(crate) struct Index {
/// Settings associated with a workspace.
struct WorkspaceSettings {
client_settings: ResolvedClientSettings,
client_settings: Arc<ClientSettings>,
ruff_settings: ruff_settings::RuffSettingsIndex,
}
@ -70,11 +72,11 @@ pub enum DocumentQuery {
impl Index {
pub(super) fn new(
workspaces: &Workspaces,
global_settings: &ClientSettings,
global: &GlobalClientSettings,
) -> crate::Result<Self> {
let mut settings = WorkspaceSettingsIndex::default();
for workspace in &**workspaces {
settings.register_workspace(workspace, global_settings)?;
settings.register_workspace(workspace, global)?;
}
Ok(Self {
@ -170,11 +172,11 @@ impl Index {
pub(super) fn open_workspace_folder(
&mut self,
url: Url,
global_settings: &ClientSettings,
global: &GlobalClientSettings,
) -> crate::Result<()> {
// TODO(jane): Find a way for workspace client settings to be added or changed dynamically.
self.settings
.register_workspace(&Workspace::new(url), global_settings)
.register_workspace(&Workspace::new(url), global)
}
pub(super) fn close_workspace_folder(&mut self, workspace_url: &Url) -> crate::Result<()> {
@ -201,7 +203,7 @@ impl Index {
pub(super) fn make_document_ref(
&self,
key: DocumentKey,
global_settings: &ClientSettings,
global: &GlobalClientSettings,
) -> Option<DocumentQuery> {
let url = self.url_for_key(&key)?.clone();
@ -230,13 +232,12 @@ impl Index {
"No settings available for {} - falling back to default settings",
url
);
let resolved_global = ResolvedClientSettings::global(global_settings);
// The path here is only for completeness, it's okay to use a non-existing path
// in case this is an unsaved (untitled) document.
let path = Path::new(url.path());
let root = path.parent().unwrap_or(path);
Arc::new(RuffSettings::fallback(
resolved_global.editor_settings(),
global.to_settings().editor_settings(),
root,
))
});
@ -330,21 +331,12 @@ impl Index {
Ok(())
}
pub(super) fn client_settings(
&self,
key: &DocumentKey,
global_settings: &ClientSettings,
) -> ResolvedClientSettings {
let Some(url) = self.url_for_key(key) else {
return ResolvedClientSettings::global(global_settings);
};
let Some(WorkspaceSettings {
pub(super) fn client_settings(&self, key: &DocumentKey) -> Option<Arc<ClientSettings>> {
let url = self.url_for_key(key)?;
let WorkspaceSettings {
client_settings, ..
}) = self.settings_for_url(url)
else {
return ResolvedClientSettings::global(global_settings);
};
client_settings.clone()
} = self.settings_for_url(url)?;
Some(client_settings.clone())
}
fn document_controller_for_key(
@ -422,7 +414,7 @@ impl WorkspaceSettingsIndex {
fn register_workspace(
&mut self,
workspace: &Workspace,
global_settings: &ClientSettings,
global: &GlobalClientSettings,
) -> crate::Result<()> {
let workspace_url = workspace.url();
if workspace_url.scheme() != "file" {
@ -434,10 +426,21 @@ impl WorkspaceSettingsIndex {
anyhow!("Failed to convert workspace URL to file path: {workspace_url}")
})?;
let client_settings = if let Some(workspace_settings) = workspace.settings() {
ResolvedClientSettings::with_workspace(workspace_settings, global_settings)
let client_settings = if let Some(workspace_options) = workspace.options() {
let options = workspace_options.clone().combine(global.options().clone());
let settings = match options.into_settings() {
Ok(settings) => settings,
Err(settings) => {
show_err_msg!(
"The settings for the workspace {workspace_path} are invalid. Refer to the logs for more information.",
workspace_path = workspace_path.display()
);
settings
}
};
Arc::new(settings)
} else {
ResolvedClientSettings::global(global_settings)
global.to_settings_arc()
};
let workspace_settings_index = ruff_settings::RuffSettingsIndex::new(

View file

@ -18,9 +18,8 @@ use ruff_workspace::{
resolver::ConfigurationTransformer,
};
use crate::session::settings::{
ConfigurationPreference, ResolvedConfiguration, ResolvedEditorSettings,
};
use crate::session::options::ConfigurationPreference;
use crate::session::settings::{EditorSettings, ResolvedConfiguration};
#[derive(Debug)]
pub struct RuffSettings {
@ -64,7 +63,7 @@ impl RuffSettings {
///
/// In the absence of a valid configuration file, it gracefully falls back to
/// editor-only settings.
pub(crate) fn fallback(editor_settings: &ResolvedEditorSettings, root: &Path) -> RuffSettings {
pub(crate) fn fallback(editor_settings: &EditorSettings, root: &Path) -> RuffSettings {
struct FallbackTransformer<'a> {
inner: EditorConfigurationTransformer<'a>,
}
@ -122,14 +121,14 @@ impl RuffSettings {
/// Constructs [`RuffSettings`] by merging the editor-defined settings with the
/// default configuration.
fn editor_only(editor_settings: &ResolvedEditorSettings, root: &Path) -> RuffSettings {
fn editor_only(editor_settings: &EditorSettings, root: &Path) -> RuffSettings {
Self::with_editor_settings(editor_settings, root, Configuration::default())
.expect("editor configuration should merge successfully with default configuration")
}
/// Merges the `configuration` with the editor defined settings.
fn with_editor_settings(
editor_settings: &ResolvedEditorSettings,
editor_settings: &EditorSettings,
root: &Path,
configuration: Configuration,
) -> anyhow::Result<RuffSettings> {
@ -157,7 +156,7 @@ impl RuffSettingsIndex {
/// skipping (3).
pub(super) fn new(
root: &Path,
editor_settings: &ResolvedEditorSettings,
editor_settings: &EditorSettings,
is_default_workspace: bool,
) -> Self {
if editor_settings.configuration_preference == ConfigurationPreference::EditorOnly {
@ -392,11 +391,11 @@ impl RuffSettingsIndex {
}
}
struct EditorConfigurationTransformer<'a>(&'a ResolvedEditorSettings, &'a Path);
struct EditorConfigurationTransformer<'a>(&'a EditorSettings, &'a Path);
impl ConfigurationTransformer for EditorConfigurationTransformer<'_> {
fn transform(&self, filesystem_configuration: Configuration) -> Configuration {
let ResolvedEditorSettings {
let EditorSettings {
configuration,
format_preview,
lint_preview,
@ -515,7 +514,7 @@ mod tests {
/// This test ensures that the inline configuration is correctly applied to the configuration.
#[test]
fn inline_settings() {
let editor_settings = ResolvedEditorSettings {
let editor_settings = EditorSettings {
configuration: Some(ResolvedConfiguration::Inline(Box::new(Options {
line_length: Some(LineLength::try_from(120).unwrap()),
..Default::default()
@ -533,7 +532,7 @@ mod tests {
/// settings is prioritized.
#[test]
fn inline_and_specific_settings_resolution_order() {
let editor_settings = ResolvedEditorSettings {
let editor_settings = EditorSettings {
configuration: Some(ResolvedConfiguration::Inline(Box::new(Options {
line_length: Some(LineLength::try_from(120).unwrap()),
..Default::default()

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff