From aecf26d09b589aa30635e78ed5a86e9d5e7fabc6 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 4 Jan 2022 20:40:16 +0100 Subject: [PATCH 1/3] feat: Add config to replace specific proc-macros with dummy expanders --- crates/hir_def/src/db.rs | 2 + crates/project_model/src/tests.rs | 2 +- crates/project_model/src/workspace.rs | 23 +++++++--- crates/rust-analyzer/src/cli/load_cargo.rs | 3 +- crates/rust-analyzer/src/config.rs | 4 ++ crates/rust-analyzer/src/reload.rs | 51 ++++++++++++++++++---- 6 files changed, 68 insertions(+), 17 deletions(-) diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 7946558311a2..9f93bbd27b85 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs @@ -55,6 +55,8 @@ pub trait InternDatabase: SourceDatabase { pub trait DefDatabase: InternDatabase + AstDatabase + Upcast { #[salsa::input] fn enable_proc_attr_macros(&self) -> bool; + #[salsa::input] + fn enablse_proc_attr_macros(&self) -> bool; #[salsa::invoke(ItemTree::file_item_tree_query)] fn file_item_tree(&self, file_id: HirFileId) -> Arc; diff --git a/crates/project_model/src/tests.rs b/crates/project_model/src/tests.rs index edf26736618d..2977ff74e2a3 100644 --- a/crates/project_model/src/tests.rs +++ b/crates/project_model/src/tests.rs @@ -88,7 +88,7 @@ fn rooted_project_json(data: ProjectJsonData) -> ProjectJson { } fn to_crate_graph(project_workspace: ProjectWorkspace) -> CrateGraph { - project_workspace.to_crate_graph(&mut |_| Vec::new(), &mut { + project_workspace.to_crate_graph(&Default::default(), &mut |_, _| Vec::new(), &mut { let mut counter = 0; move |_path| { counter += 1; diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 60f99f368bda..869b064e1da4 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -387,10 +387,14 @@ impl ProjectWorkspace { pub fn to_crate_graph( &self, - load_proc_macro: &mut dyn FnMut(&AbsPath) -> Vec, + dummy_replace: &FxHashMap, Box<[Box]>>, + load_proc_macro: &mut dyn FnMut(&AbsPath, &[Box]) -> Vec, load: &mut dyn FnMut(&AbsPath) -> Option, ) -> CrateGraph { let _p = profile::span("ProjectWorkspace::to_crate_graph"); + let load_proc_macro = &mut |crate_name: &_, path: &_| { + load_proc_macro(path, dummy_replace.get(crate_name).map(|it| &**it).unwrap_or_default()) + }; let mut crate_graph = match self { ProjectWorkspace::Json { project, sysroot, rustc_cfg } => project_json_to_crate_graph( @@ -432,7 +436,7 @@ impl ProjectWorkspace { fn project_json_to_crate_graph( rustc_cfg: Vec, - load_proc_macro: &mut dyn FnMut(&AbsPath) -> Vec, + load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> Vec, load: &mut dyn FnMut(&AbsPath) -> Option, project: &ProjectJson, sysroot: &Option, @@ -452,7 +456,12 @@ fn project_json_to_crate_graph( }) .map(|(crate_id, krate, file_id)| { let env = krate.env.clone().into_iter().collect(); - let proc_macro = krate.proc_macro_dylib_path.clone().map(|it| load_proc_macro(&it)); + let proc_macro = krate.proc_macro_dylib_path.clone().map(|it| { + load_proc_macro( + krate.display_name.as_ref().map(|it| it.canonical_name()).unwrap_or(""), + &it, + ) + }); let target_cfgs = match krate.target.as_deref() { Some(target) => { @@ -513,7 +522,7 @@ fn project_json_to_crate_graph( fn cargo_to_crate_graph( rustc_cfg: Vec, override_cfg: &CfgOverrides, - load_proc_macro: &mut dyn FnMut(&AbsPath) -> Vec, + load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> Vec, load: &mut dyn FnMut(&AbsPath) -> Option, cargo: &CargoWorkspace, build_scripts: &WorkspaceBuildScripts, @@ -571,7 +580,7 @@ fn cargo_to_crate_graph( &cargo[pkg], build_scripts.outputs.get(pkg), cfg_options, - load_proc_macro, + &mut |path| load_proc_macro(&cargo[tgt].name, path), file_id, &cargo[tgt].name, ); @@ -702,7 +711,7 @@ fn handle_rustc_crates( load: &mut dyn FnMut(&AbsPath) -> Option, crate_graph: &mut CrateGraph, cfg_options: &CfgOptions, - load_proc_macro: &mut dyn FnMut(&AbsPath) -> Vec, + load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> Vec, pkg_to_lib_crate: &mut FxHashMap, CrateId>, public_deps: &SysrootPublicDeps, cargo: &CargoWorkspace, @@ -738,7 +747,7 @@ fn handle_rustc_crates( &rustc_workspace[pkg], None, cfg_options, - load_proc_macro, + &mut |path| load_proc_macro(&rustc_workspace[tgt].name, path), file_id, &rustc_workspace[tgt].name, ); diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index d60861a62743..19ce86e3ffad 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs @@ -66,7 +66,8 @@ pub fn load_workspace( }; let crate_graph = ws.to_crate_graph( - &mut |path: &AbsPath| load_proc_macro(proc_macro_client.as_ref(), path), + &Default::default(), + &mut |path: &AbsPath, _| load_proc_macro(proc_macro_client.as_ref(), path, &[]), &mut |path: &AbsPath| { let contents = loader.load_sync(path); let path = vfs::VfsPath::from(path.to_path_buf()); diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 818aab35157a..665609cf9ab0 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -301,6 +301,7 @@ config_data! { /// Internal config, path to proc-macro server executable (typically, /// this is rust-analyzer itself, but we override this in tests). procMacro_server: Option = "null", + procMacro_dummies: FxHashMap, Box<[Box]>> = "{}", /// Command to be executed instead of 'cargo' for runnables. runnables_overrideCargo: Option = "null", @@ -716,6 +717,9 @@ impl Config { }; Some((path, vec!["proc-macro".into()])) } + pub fn dummy_replacements(&self) -> &FxHashMap, Box<[Box]>> { + &self.data.procMacro_dummies + } pub fn expand_proc_attr_macros(&self) -> bool { self.data.experimental_procAttrMacros } diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index b14b3dbcfa92..c687466bd230 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -10,6 +10,7 @@ use ide_db::base_db::{ }; use proc_macro_api::{MacroDylib, ProcMacroServer}; use project_model::{ProjectWorkspace, WorkspaceBuildScripts}; +use syntax::SmolStr; use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind}; use crate::{ @@ -290,6 +291,9 @@ impl GlobalState { } }, }; + self.analysis_host + .raw_database_mut() + .set_enable_proc_attr_macros(self.config.expand_proc_attr_macros()); } let watch = match files_config.watcher { @@ -306,8 +310,9 @@ impl GlobalState { // Create crate graph from all the workspaces let crate_graph = { let proc_macro_client = self.proc_macro_client.as_ref(); - let mut load_proc_macro = - move |path: &AbsPath| load_proc_macro(proc_macro_client, path); + let mut load_proc_macro = move |path: &AbsPath, dummy_replace: &_| { + load_proc_macro(proc_macro_client, path, dummy_replace) + }; let vfs = &mut self.vfs.write().0; let loader = &mut self.loader; @@ -328,7 +333,11 @@ impl GlobalState { let mut crate_graph = CrateGraph::default(); for ws in self.workspaces.iter() { - crate_graph.extend(ws.to_crate_graph(&mut load_proc_macro, &mut load)); + crate_graph.extend(ws.to_crate_graph( + self.config.dummy_replacements(), + &mut load_proc_macro, + &mut load, + )); } crate_graph }; @@ -505,7 +514,11 @@ impl SourceRootConfig { } } -pub(crate) fn load_proc_macro(client: Option<&ProcMacroServer>, path: &AbsPath) -> Vec { +pub(crate) fn load_proc_macro( + client: Option<&ProcMacroServer>, + path: &AbsPath, + dummy_replace: &[Box], +) -> Vec { let dylib = match MacroDylib::new(path.to_path_buf()) { Ok(it) => it, Err(err) => { @@ -532,17 +545,25 @@ pub(crate) fn load_proc_macro(client: Option<&ProcMacroServer>, path: &AbsPath) Vec::new() } }) - .map(expander_to_proc_macro) + .map(|expander| expander_to_proc_macro(expander, dummy_replace)) .collect(); - fn expander_to_proc_macro(expander: proc_macro_api::ProcMacro) -> ProcMacro { - let name = expander.name().into(); + fn expander_to_proc_macro( + expander: proc_macro_api::ProcMacro, + dummy_replace: &[Box], + ) -> ProcMacro { + let name = SmolStr::from(expander.name()); let kind = match expander.kind() { proc_macro_api::ProcMacroKind::CustomDerive => ProcMacroKind::CustomDerive, proc_macro_api::ProcMacroKind::FuncLike => ProcMacroKind::FuncLike, proc_macro_api::ProcMacroKind::Attr => ProcMacroKind::Attr, }; - let expander = Arc::new(Expander(expander)); + let expander: Arc = + if dummy_replace.iter().any(|replace| &**replace == name) { + Arc::new(DummyExpander) + } else { + Arc::new(Expander(expander)) + }; ProcMacro { name, kind, expander } } @@ -564,6 +585,20 @@ pub(crate) fn load_proc_macro(client: Option<&ProcMacroServer>, path: &AbsPath) } } } + + #[derive(Debug)] + struct DummyExpander; + + impl ProcMacroExpander for DummyExpander { + fn expand( + &self, + subtree: &tt::Subtree, + _: Option<&tt::Subtree>, + _: &Env, + ) -> Result { + Ok(subtree.clone()) + } + } } pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind) -> bool { From dd4b53402d469e80151845bf28c74c6782d775f1 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 5 Jan 2022 19:35:48 +0100 Subject: [PATCH 2/3] Regenrate docs and package.json --- crates/hir_def/src/db.rs | 2 -- crates/rust-analyzer/src/config.rs | 13 ++++++++++++- crates/rust-analyzer/src/reload.rs | 6 +++--- docs/user/generated_config.adoc | 6 ++++++ editors/code/package.json | 5 +++++ 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 9f93bbd27b85..7946558311a2 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs @@ -55,8 +55,6 @@ pub trait InternDatabase: SourceDatabase { pub trait DefDatabase: InternDatabase + AstDatabase + Upcast { #[salsa::input] fn enable_proc_attr_macros(&self) -> bool; - #[salsa::input] - fn enablse_proc_attr_macros(&self) -> bool; #[salsa::invoke(ItemTree::file_item_tree_query)] fn file_item_tree(&self, file_id: HirFileId) -> Arc; diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 665609cf9ab0..dba772259f9c 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -301,6 +301,8 @@ config_data! { /// Internal config, path to proc-macro server executable (typically, /// this is rust-analyzer itself, but we override this in tests). procMacro_server: Option = "null", + /// Replaces the proc-macro expanders for the named proc-macros in the named crates with + /// an identity expander that outputs the input again. procMacro_dummies: FxHashMap, Box<[Box]>> = "{}", /// Command to be executed instead of 'cargo' for runnables. @@ -1167,7 +1169,13 @@ fn get_field( .find_map(move |field| { let mut pointer = field.replace('_', "/"); pointer.insert(0, '/'); - json.pointer_mut(&pointer).and_then(|it| serde_json::from_value(it.take()).ok()) + json.pointer_mut(&pointer).and_then(|it| match serde_json::from_value(it.take()) { + Ok(it) => Some(it), + Err(e) => { + tracing::warn!("Failed to deserialize config field at {}: {:?}", pointer, e); + None + } + }) }) .unwrap_or(default) } @@ -1228,6 +1236,9 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json "items": { "type": "string" }, "uniqueItems": true, }, + "FxHashMap, Box<[Box]>>" => set! { + "type": "object", + }, "FxHashMap" => set! { "type": "object", }, diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index c687466bd230..eecc83e02ac4 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -291,9 +291,6 @@ impl GlobalState { } }, }; - self.analysis_host - .raw_database_mut() - .set_enable_proc_attr_macros(self.config.expand_proc_attr_macros()); } let watch = match files_config.watcher { @@ -514,6 +511,8 @@ impl SourceRootConfig { } } +/// Load the proc-macros for the given lib path, replacing all expanders whose names are in `dummy_replace` +/// with an identity dummy expander. pub(crate) fn load_proc_macro( client: Option<&ProcMacroServer>, path: &AbsPath, @@ -586,6 +585,7 @@ pub(crate) fn load_proc_macro( } } + /// Dummy identity expander, used for proc-macros that are deliberately ignored by the user. #[derive(Debug)] struct DummyExpander; diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 494051b30606..0b9abadf9888 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -455,6 +455,12 @@ Enable support for procedural macros, implies `#rust-analyzer.cargo.runBuildScri Internal config, path to proc-macro server executable (typically, this is rust-analyzer itself, but we override this in tests). -- +[[rust-analyzer.procMacro.dummies]]rust-analyzer.procMacro.dummies (default: `{}`):: ++ +-- +Replaces the proc-macro expanders for the named proc-macros in the named crates with +an identity expander that outputs the input again. +-- [[rust-analyzer.runnables.overrideCargo]]rust-analyzer.runnables.overrideCargo (default: `null`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 57757553a7c3..e7c958050e31 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -880,6 +880,11 @@ "string" ] }, + "rust-analyzer.procMacro.dummies": { + "markdownDescription": "Replaces the proc-macro expanders for the named proc-macros in the named crates with\nan identity expander that outputs the input again.", + "default": {}, + "type": "object" + }, "rust-analyzer.runnables.overrideCargo": { "markdownDescription": "Command to be executed instead of 'cargo' for runnables.", "default": null, From f6eba28ef811c1804723f6ea8334094b268ad3bd Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 6 Jan 2022 13:44:21 +0100 Subject: [PATCH 3/3] Adjust config name --- crates/rust-analyzer/src/config.rs | 9 +++++---- docs/user/generated_config.adoc | 7 ++++--- editors/code/package.json | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index dba772259f9c..a70413925543 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -301,9 +301,10 @@ config_data! { /// Internal config, path to proc-macro server executable (typically, /// this is rust-analyzer itself, but we override this in tests). procMacro_server: Option = "null", - /// Replaces the proc-macro expanders for the named proc-macros in the named crates with - /// an identity expander that outputs the input again. - procMacro_dummies: FxHashMap, Box<[Box]>> = "{}", + /// These proc-macros will be ignored when trying to expand them. + /// + /// This config takes a map of crate names with the exported proc-macro names to ignore as values. + procMacro_ignored: FxHashMap, Box<[Box]>> = "{}", /// Command to be executed instead of 'cargo' for runnables. runnables_overrideCargo: Option = "null", @@ -720,7 +721,7 @@ impl Config { Some((path, vec!["proc-macro".into()])) } pub fn dummy_replacements(&self) -> &FxHashMap, Box<[Box]>> { - &self.data.procMacro_dummies + &self.data.procMacro_ignored } pub fn expand_proc_attr_macros(&self) -> bool { self.data.experimental_procAttrMacros diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 0b9abadf9888..f46dda2351fb 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -455,11 +455,12 @@ Enable support for procedural macros, implies `#rust-analyzer.cargo.runBuildScri Internal config, path to proc-macro server executable (typically, this is rust-analyzer itself, but we override this in tests). -- -[[rust-analyzer.procMacro.dummies]]rust-analyzer.procMacro.dummies (default: `{}`):: +[[rust-analyzer.procMacro.ignored]]rust-analyzer.procMacro.ignored (default: `{}`):: + -- -Replaces the proc-macro expanders for the named proc-macros in the named crates with -an identity expander that outputs the input again. +These proc-macros will be ignored when trying to expand them. + +This config takes a map of crate names with the exported proc-macro names to ignore as values. -- [[rust-analyzer.runnables.overrideCargo]]rust-analyzer.runnables.overrideCargo (default: `null`):: + diff --git a/editors/code/package.json b/editors/code/package.json index e7c958050e31..d41886847480 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -880,8 +880,8 @@ "string" ] }, - "rust-analyzer.procMacro.dummies": { - "markdownDescription": "Replaces the proc-macro expanders for the named proc-macros in the named crates with\nan identity expander that outputs the input again.", + "rust-analyzer.procMacro.ignored": { + "markdownDescription": "These proc-macros will be ignored when trying to expand them.\n\nThis config takes a map of crate names with the exported proc-macro names to ignore as values.", "default": {}, "type": "object" },