diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index ab27a65de5..437f7c33ce 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -294,18 +294,6 @@ config_data! { /// This option does not take effect until rust-analyzer is restarted. rustc_source: Option = None, - /// Additional arguments to `rustfmt`. - rustfmt_extraArgs: Vec = vec![], - /// Advanced option, fully override the command rust-analyzer uses for - /// formatting. This should be the equivalent of `rustfmt` here, and - /// not that of `cargo fmt`. The file contents will be passed on the - /// standard input and the formatted result will be read from the - /// standard output. - rustfmt_overrideCommand: Option> = None, - /// Enables the use of rustfmt's unstable range formatting command for the - /// `textDocument/rangeFormatting` request. The rustfmt option is unstable and only - /// available on a nightly build. - rustfmt_rangeFormatting_enable: bool = false, /// Enables automatic discovery of projects using [`DiscoverWorkspaceConfig::command`]. /// @@ -439,6 +427,18 @@ config_data! { config_data! { workspace: struct WorkspaceDefaultConfigData <- WorkspaceConfigInput -> { + /// Additional arguments to `rustfmt`. + rustfmt_extraArgs: Vec = vec![], + /// Advanced option, fully override the command rust-analyzer uses for + /// formatting. This should be the equivalent of `rustfmt` here, and + /// not that of `cargo fmt`. The file contents will be passed on the + /// standard input and the formatted result will be read from the + /// standard output. + rustfmt_overrideCommand: Option> = None, + /// Enables the use of rustfmt's unstable range formatting command for the + /// `textDocument/rangeFormatting` request. The rustfmt option is unstable and only + /// available on a nightly build. + rustfmt_rangeFormatting_enable: bool = false, } } @@ -775,7 +775,7 @@ pub struct Config { user_config_path: VfsPath, /// Config node whose values apply to **every** Rust project. - user_config: Option<(GlobalLocalConfigInput, ConfigErrors)>, + user_config: Option<(GlobalWorkspaceLocalConfigInput, ConfigErrors)>, ratoml_file: FxHashMap, @@ -825,13 +825,13 @@ impl Config { if let Ok(table) = toml::from_str(&change) { let mut toml_errors = vec![]; validate_toml_table( - GlobalLocalConfigInput::FIELDS, + GlobalWorkspaceLocalConfigInput::FIELDS, &table, &mut String::new(), &mut toml_errors, ); config.user_config = Some(( - GlobalLocalConfigInput::from_toml(table, &mut toml_errors), + GlobalWorkspaceLocalConfigInput::from_toml(table, &mut toml_errors), ConfigErrors( toml_errors .into_iter() @@ -960,7 +960,7 @@ impl Config { match toml::from_str(&text) { Ok(table) => { validate_toml_table( - GlobalLocalConfigInput::FIELDS, + WorkspaceLocalConfigInput::FIELDS, &table, &mut String::new(), &mut toml_errors, @@ -1863,16 +1863,16 @@ impl Config { } } - pub fn rustfmt(&self) -> RustfmtConfig { - match &self.rustfmt_overrideCommand() { + pub fn rustfmt(&self, source_root_id: Option) -> RustfmtConfig { + match &self.rustfmt_overrideCommand(source_root_id) { Some(args) if !args.is_empty() => { let mut args = args.clone(); let command = args.remove(0); RustfmtConfig::CustomCommand { command, args } } Some(_) | None => RustfmtConfig::Rustfmt { - extra_args: self.rustfmt_extraArgs().clone(), - enable_range_formatting: *self.rustfmt_rangeFormatting_enable(), + extra_args: self.rustfmt_extraArgs(source_root_id).clone(), + enable_range_formatting: *self.rustfmt_rangeFormatting_enable(source_root_id), }, } } @@ -2555,24 +2555,20 @@ macro_rules! _impl_for_config_data { $vis fn $field(&self, source_root: Option) -> &$ty { let mut source_root = source_root.as_ref(); while let Some(sr) = source_root { - if let Some((file, _)) = self.ratoml_file.get(&sr) { - match file { - RatomlFile::Workspace(config) => { - if let Some(v) = config.workspace.$field.as_ref() { - return &v; - } - }, + if let Some((RatomlFile::Workspace(config), _)) = self.ratoml_file.get(&sr) { + if let Some(v) = config.workspace.$field.as_ref() { + return &v; } } source_root = self.source_root_parent_map.get(&sr); } - if let Some(v) = self.client_config.0.local.$field.as_ref() { + if let Some(v) = self.client_config.0.workspace.$field.as_ref() { return &v; } if let Some((user_config, _)) = self.user_config.as_ref() { - if let Some(v) = user_config.local.$field.as_ref() { + if let Some(v) = user_config.workspace.$field.as_ref() { return &v; } } @@ -2591,7 +2587,6 @@ macro_rules! _impl_for_config_data { $( $($doc)* #[allow(non_snake_case)] - // TODO Remove source_root $vis fn $field(&self) -> &$ty { if let Some(v) = self.client_config.0.global.$field.as_ref() { return &v; @@ -2730,6 +2725,7 @@ use _config_data as config_data; #[derive(Default, Debug, Clone)] struct DefaultConfigData { global: GlobalDefaultConfigData, + workspace: WorkspaceDefaultConfigData, local: LocalDefaultConfigData, client: ClientDefaultConfigData, } @@ -2740,6 +2736,7 @@ struct DefaultConfigData { #[derive(Debug, Clone, Default)] struct FullConfigInput { global: GlobalConfigInput, + workspace: WorkspaceConfigInput, local: LocalConfigInput, client: ClientConfigInput, } @@ -2753,6 +2750,7 @@ impl FullConfigInput { global: GlobalConfigInput::from_json(&mut json, error_sink), local: LocalConfigInput::from_json(&mut json, error_sink), client: ClientConfigInput::from_json(&mut json, error_sink), + workspace: WorkspaceConfigInput::from_json(&mut json, error_sink), } } @@ -2783,26 +2781,28 @@ impl FullConfigInput { /// some rust-analyzer.toml file or JSON blob. An empty rust-analyzer.toml corresponds to /// all fields being None. #[derive(Debug, Clone, Default)] -struct GlobalLocalConfigInput { +struct GlobalWorkspaceLocalConfigInput { global: GlobalConfigInput, local: LocalConfigInput, + workspace: WorkspaceConfigInput, } -impl GlobalLocalConfigInput { +impl GlobalWorkspaceLocalConfigInput { const FIELDS: &'static [&'static [&'static str]] = &[GlobalConfigInput::FIELDS, LocalConfigInput::FIELDS]; fn from_toml( toml: toml::Table, error_sink: &mut Vec<(String, toml::de::Error)>, - ) -> GlobalLocalConfigInput { - GlobalLocalConfigInput { + ) -> GlobalWorkspaceLocalConfigInput { + GlobalWorkspaceLocalConfigInput { global: GlobalConfigInput::from_toml(&toml, error_sink), local: LocalConfigInput::from_toml(&toml, error_sink), + workspace: WorkspaceConfigInput::from_toml(&toml, error_sink), } } } -/// All of the config levels, all fields `Option`, to describe fields that are actually set by +/// Workspace and local config levels, all fields `Option`, to describe fields that are actually set by /// some rust-analyzer.toml file or JSON blob. An empty rust-analyzer.toml corresponds to /// all fields being None. #[derive(Debug, Clone, Default)] diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 1475d03ca6..d78bd3b44d 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -2113,8 +2113,9 @@ fn run_rustfmt( let edition = editions.iter().copied().max(); let line_index = snap.file_line_index(file_id)?; + let source_root_id = snap.analysis.source_root_id(file_id).ok(); - let mut command = match snap.config.rustfmt() { + let mut command = match snap.config.rustfmt(source_root_id) { RustfmtConfig::Rustfmt { extra_args, enable_range_formatting } => { // FIXME: Set RUSTUP_TOOLCHAIN let mut cmd = process::Command::new(toolchain::Tool::Rustfmt.path()); @@ -2302,9 +2303,8 @@ pub(crate) fn internal_testing_fetch_config( .transpose()?; serde_json::to_value(match &*params.config { "local" => state.config.assist(source_root).assist_emit_must_use, - // TODO Most probably will fail because it was not renamed to workspace - "global" => matches!( - state.config.rustfmt(), + "workspace" => matches!( + state.config.rustfmt(source_root), RustfmtConfig::Rustfmt { enable_range_formatting: true, .. } ), _ => return Err(anyhow::anyhow!("Unknown test config key: {}", params.config)), diff --git a/crates/rust-analyzer/src/lsp/capabilities.rs b/crates/rust-analyzer/src/lsp/capabilities.rs index 212294b5d3..9610808c27 100644 --- a/crates/rust-analyzer/src/lsp/capabilities.rs +++ b/crates/rust-analyzer/src/lsp/capabilities.rs @@ -67,7 +67,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { code_action_provider: Some(config.caps().code_action_capabilities()), code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }), document_formatting_provider: Some(OneOf::Left(true)), - document_range_formatting_provider: match config.rustfmt() { + document_range_formatting_provider: match config.rustfmt(None) { RustfmtConfig::Rustfmt { enable_range_formatting: true, .. } => Some(OneOf::Left(true)), _ => Some(OneOf::Left(false)), }, diff --git a/crates/rust-analyzer/tests/slow-tests/ratoml.rs b/crates/rust-analyzer/tests/slow-tests/ratoml.rs index c06ba9eee1..8cb6409a84 100644 --- a/crates/rust-analyzer/tests/slow-tests/ratoml.rs +++ b/crates/rust-analyzer/tests/slow-tests/ratoml.rs @@ -17,7 +17,7 @@ enum QueryType { /// A query whose config key is a part of the global configs, so that /// testing for changes to this config means testing if global changes /// take affect. - Global, + Workspace, } struct RatomlTest { @@ -165,7 +165,7 @@ impl RatomlTest { fn query(&self, query: QueryType, source_file_idx: usize) -> bool { let config = match query { QueryType::Local => "local".to_owned(), - QueryType::Global => "global".to_owned(), + QueryType::Workspace => "workspace".to_owned(), }; let res = self.server.send_request::( InternalTestingFetchConfigParams { @@ -823,10 +823,8 @@ fn ratoml_multiple_ratoml_in_single_source_root() { // assert!(!server.query(QueryType::AssistEmitMustUse, 5)); // } -/// Having a ratoml file at the root of a project enables -/// configuring global level configurations as well. #[test] -fn ratoml_in_root_is_global() { +fn ratoml_in_root_is_workspace() { if skip_slow_tests() { return; } @@ -854,7 +852,7 @@ fn main() { None, ); - assert!(server.query(QueryType::Global, 2)); + assert!(server.query(QueryType::Workspace, 2)); } #[test] @@ -886,9 +884,9 @@ fn main() { None, ); - assert!(server.query(QueryType::Global, 2)); + assert!(server.query(QueryType::Workspace, 2)); server.edit(1, "rustfmt.rangeFormatting.enable = false".to_owned()); - assert!(!server.query(QueryType::Global, 2)); + assert!(!server.query(QueryType::Workspace, 2)); } #[test] @@ -920,7 +918,7 @@ fn main() { None, ); - assert!(server.query(QueryType::Global, 2)); + assert!(server.query(QueryType::Workspace, 2)); server.delete(1); - assert!(!server.query(QueryType::Global, 2)); + assert!(!server.query(QueryType::Workspace, 2)); } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index e4a8c6493a..1ea679d2a5 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -878,27 +878,6 @@ crates must set `[package.metadata.rust-analyzer] rustc_private=true` to use it. This option does not take effect until rust-analyzer is restarted. -- -[[rust-analyzer.rustfmt.extraArgs]]rust-analyzer.rustfmt.extraArgs (default: `[]`):: -+ --- -Additional arguments to `rustfmt`. --- -[[rust-analyzer.rustfmt.overrideCommand]]rust-analyzer.rustfmt.overrideCommand (default: `null`):: -+ --- -Advanced option, fully override the command rust-analyzer uses for -formatting. This should be the equivalent of `rustfmt` here, and -not that of `cargo fmt`. The file contents will be passed on the -standard input and the formatted result will be read from the -standard output. --- -[[rust-analyzer.rustfmt.rangeFormatting.enable]]rust-analyzer.rustfmt.rangeFormatting.enable (default: `false`):: -+ --- -Enables the use of rustfmt's unstable range formatting command for the -`textDocument/rangeFormatting` request. The rustfmt option is unstable and only -available on a nightly build. --- [[rust-analyzer.semanticHighlighting.doc.comment.inject.enable]]rust-analyzer.semanticHighlighting.doc.comment.inject.enable (default: `true`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 98e8bbf02a..15e08222ad 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -2358,45 +2358,6 @@ } } }, - { - "title": "rustfmt", - "properties": { - "rust-analyzer.rustfmt.extraArgs": { - "markdownDescription": "Additional arguments to `rustfmt`.", - "default": [], - "type": "array", - "items": { - "type": "string" - } - } - } - }, - { - "title": "rustfmt", - "properties": { - "rust-analyzer.rustfmt.overrideCommand": { - "markdownDescription": "Advanced option, fully override the command rust-analyzer uses for\nformatting. This should be the equivalent of `rustfmt` here, and\nnot that of `cargo fmt`. The file contents will be passed on the\nstandard input and the formatted result will be read from the\nstandard output.", - "default": null, - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - } - }, - { - "title": "rustfmt", - "properties": { - "rust-analyzer.rustfmt.rangeFormatting.enable": { - "markdownDescription": "Enables the use of rustfmt's unstable range formatting command for the\n`textDocument/rangeFormatting` request. The rustfmt option is unstable and only\navailable on a nightly build.", - "default": false, - "type": "boolean" - } - } - }, { "title": "semanticHighlighting", "properties": {