};
use proc_macro_api::{MacroDylib, ProcMacroServer};
use project_model::{ProjectWorkspace, WorkspaceBuildScripts};
+use syntax::SmolStr;
use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind};
use crate::{
}
if let FilesWatcher::Client = self.config.files().watcher {
- if self.config.did_change_watched_files_dynamic_registration() {
- let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions {
- watchers: self
- .workspaces
- .iter()
- .flat_map(|ws| ws.to_roots())
- .filter(|it| it.is_local)
- .flat_map(|root| {
- root.include.into_iter().flat_map(|it| {
- [
- format!("{}/**/*.rs", it.display()),
- format!("{}/**/Cargo.toml", it.display()),
- format!("{}/**/Cargo.lock", it.display()),
- ]
- })
- })
- .map(|glob_pattern| lsp_types::FileSystemWatcher {
- glob_pattern,
- kind: None,
+ let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions {
+ watchers: self
+ .workspaces
+ .iter()
+ .flat_map(|ws| ws.to_roots())
+ .filter(|it| it.is_local)
+ .flat_map(|root| {
+ root.include.into_iter().flat_map(|it| {
+ [
+ format!("{}/**/*.rs", it.display()),
+ format!("{}/**/Cargo.toml", it.display()),
+ format!("{}/**/Cargo.lock", it.display()),
+ ]
})
- .collect(),
- };
- let registration = lsp_types::Registration {
- id: "workspace/didChangeWatchedFiles".to_string(),
- method: "workspace/didChangeWatchedFiles".to_string(),
- register_options: Some(serde_json::to_value(registration_options).unwrap()),
- };
- self.send_request::<lsp_types::request::RegisterCapability>(
- lsp_types::RegistrationParams { registrations: vec![registration] },
- |_, _| (),
- );
- }
+ })
+ .map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, kind: None })
+ .collect(),
+ };
+ let registration = lsp_types::Registration {
+ id: "workspace/didChangeWatchedFiles".to_string(),
+ method: "workspace/didChangeWatchedFiles".to_string(),
+ register_options: Some(serde_json::to_value(registration_options).unwrap()),
+ };
+ self.send_request::<lsp_types::request::RegisterCapability>(
+ lsp_types::RegistrationParams { registrations: vec![registration] },
+ |_, _| (),
+ );
}
let mut change = Change::new();
// 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;
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
};
}
}
-pub(crate) fn load_proc_macro(client: Option<&ProcMacroServer>, path: &AbsPath) -> Vec<ProcMacro> {
+/// 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,
+ dummy_replace: &[Box<str>],
+) -> Vec<ProcMacro> {
let dylib = match MacroDylib::new(path.to_path_buf()) {
Ok(it) => it,
Err(err) => {
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<str>],
+ ) -> 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<dyn ProcMacroExpander> =
+ if dummy_replace.iter().any(|replace| &**replace == name) {
+ Arc::new(DummyExpander)
+ } else {
+ Arc::new(Expander(expander))
+ };
ProcMacro { name, kind, expander }
}
}
}
}
+
+ /// Dummy identity expander, used for proc-macros that are deliberately ignored by the user.
+ #[derive(Debug)]
+ struct DummyExpander;
+
+ impl ProcMacroExpander for DummyExpander {
+ fn expand(
+ &self,
+ subtree: &tt::Subtree,
+ _: Option<&tt::Subtree>,
+ _: &Env,
+ ) -> Result<tt::Subtree, ProcMacroExpansionError> {
+ Ok(subtree.clone())
+ }
+ }
}
pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind) -> bool {