about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs70
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs8
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs18
-rw-r--r--src/tools/rust-analyzer/docs/user/generated_config.adoc21
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json39
6 files changed, 48 insertions, 110 deletions
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index ab27a65de5a..437f7c33ced 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/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<String> = None,
 
-        /// Additional arguments to `rustfmt`.
-        rustfmt_extraArgs: Vec<String>               = 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<Vec<String>> = 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<String>               = 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<Vec<String>> = 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<SourceRootId, (RatomlFile, ConfigErrors)>,
 
@@ -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<SourceRootId>) -> 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<SourceRootId>) -> &$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<T>`, to describe fields that are actually set by
+/// Workspace and local config levels, all fields `Option<T>`, 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/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index 1475d03ca67..d78bd3b44d3 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs
index 212294b5d32..9610808c27e 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
index c06ba9eee14..8cb6409a848 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
+++ b/src/tools/rust-analyzer/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::<InternalTestingFetchConfig>(
             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/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index e4a8c6493a8..1ea679d2a52 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index 98e8bbf02aa..15e08222ad8 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -2359,45 +2359,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": {
                     "rust-analyzer.semanticHighlighting.doc.comment.inject.enable": {