diff --git a/crates/ruff_server/src/session/settings.rs b/crates/ruff_server/src/session/settings.rs index 610c6d5bea..0786d29be2 100644 --- a/crates/ruff_server/src/session/settings.rs +++ b/crates/ruff_server/src/session/settings.rs @@ -1,4 +1,4 @@ -use std::{ops::Deref, str::FromStr}; +use std::{ffi::OsString, ops::Deref, path::PathBuf, str::FromStr}; use lsp_types::Url; use ruff_linter::{line_width::LineLength, RuleSelector}; @@ -31,6 +31,7 @@ pub(crate) struct ResolvedClientSettings { #[derive(Clone, Debug)] #[cfg_attr(test, derive(PartialEq, Eq))] pub(crate) struct ResolvedEditorSettings { + pub(super) configuration: Option, pub(super) lint_preview: Option, pub(super) format_preview: Option, pub(super) select: Option>, @@ -44,11 +45,10 @@ pub(crate) struct ResolvedEditorSettings { /// Determines how multiple conflicting configurations should be resolved - in this /// case, the configuration from the client settings and configuration from local /// `.toml` files (aka 'workspace' configuration). -#[derive(Clone, Copy, Debug, Deserialize, Default)] -#[cfg_attr(test, derive(PartialEq, Eq))] +#[derive(Clone, Copy, Debug, Deserialize, Default, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub(crate) enum ConfigurationPreference { - /// Configuration set in the editor takes priority over workspace configuration set in `.toml` files. + /// Configuration set in the editor takes priority over configuration set in `.toml` files. #[default] EditorFirst, /// Configuration set in `.toml` files takes priority over configuration set in the editor. @@ -62,6 +62,7 @@ pub(crate) enum ConfigurationPreference { #[cfg_attr(test, derive(PartialEq, Eq))] #[serde(rename_all = "camelCase")] pub(crate) struct ClientSettings { + configuration: Option, fix_all: Option, organize_imports: Option, lint: Option, @@ -229,6 +230,12 @@ impl ResolvedClientSettings { true, ), editor_settings: ResolvedEditorSettings { + configuration: Self::resolve_optional(all_settings, |settings| { + settings + .configuration + .as_ref() + .map(|config_path| OsString::from(config_path.clone()).into()) + }), lint_preview: Self::resolve_optional(all_settings, |settings| { settings.lint.as_ref()?.preview }), @@ -357,6 +364,7 @@ mod tests { assert_debug_snapshot!(options, @r###" HasWorkspaces { global_settings: ClientSettings { + configuration: None, fix_all: Some( false, ), @@ -411,6 +419,7 @@ mod tests { workspace_settings: [ WorkspaceSettings { settings: ClientSettings { + configuration: None, fix_all: Some( true, ), @@ -469,6 +478,7 @@ mod tests { }, WorkspaceSettings { settings: ClientSettings { + configuration: None, fix_all: Some( true, ), @@ -555,6 +565,7 @@ mod tests { disable_rule_comment_enable: false, fix_violation_enable: false, editor_settings: ResolvedEditorSettings { + configuration: None, lint_preview: Some(true), format_preview: None, select: Some(vec![ @@ -584,6 +595,7 @@ mod tests { disable_rule_comment_enable: true, fix_violation_enable: false, editor_settings: ResolvedEditorSettings { + configuration: None, lint_preview: Some(false), format_preview: None, select: Some(vec![ @@ -608,6 +620,7 @@ mod tests { GlobalOnly { settings: Some( ClientSettings { + configuration: None, fix_all: Some( false, ), @@ -671,6 +684,7 @@ mod tests { disable_rule_comment_enable: false, fix_violation_enable: true, editor_settings: ResolvedEditorSettings { + configuration: None, lint_preview: None, format_preview: None, select: None, diff --git a/crates/ruff_server/src/session/workspace/ruff_settings.rs b/crates/ruff_server/src/session/workspace/ruff_settings.rs index c8da8f3de4..120713e069 100644 --- a/crates/ruff_server/src/session/workspace/ruff_settings.rs +++ b/crates/ruff_server/src/session/workspace/ruff_settings.rs @@ -110,6 +110,7 @@ impl<'a> ConfigurationTransformer for EditorConfigurationTransformer<'a> { filesystem_configuration: ruff_workspace::configuration::Configuration, ) -> ruff_workspace::configuration::Configuration { let ResolvedEditorSettings { + configuration, format_preview, lint_preview, select, @@ -150,6 +151,19 @@ impl<'a> ConfigurationTransformer for EditorConfigurationTransformer<'a> { ..Default::default() }; + // Merge in the editor-specified configuration file, if it exists + let editor_configuration = if let Some(config_file_path) = configuration { + match open_configuration_file(&config_file_path, project_root) { + Ok(config_from_file) => editor_configuration.combine(config_from_file), + Err(err) => { + tracing::error!("Unable to find editor-specified configuration file {err}"); + editor_configuration + } + } + } else { + editor_configuration + }; + match configuration_preference { ConfigurationPreference::EditorFirst => { editor_configuration.combine(filesystem_configuration) @@ -161,3 +175,12 @@ impl<'a> ConfigurationTransformer for EditorConfigurationTransformer<'a> { } } } + +fn open_configuration_file( + config_path: &Path, + project_root: &Path, +) -> crate::Result { + let options = ruff_workspace::pyproject::load_options(config_path)?; + + Configuration::from_options(options, Some(config_path), project_root) +}