diff --git a/src/lang/db/mod.rs b/src/lang/db/mod.rs index c81b6995..7edfc65e 100644 --- a/src/lang/db/mod.rs +++ b/src/lang/db/mod.rs @@ -126,6 +126,13 @@ impl AnalysisDatabase { }) } + /// Removes plugin suit from database. + pub fn remove_plugin_suite(&mut self, plugins: PluginSuite) { + self.with_plugins_mut(move |macro_plugins, analyzer_plugins, inline_macro_plugins| { + remove_plugin_suite(plugins, macro_plugins, analyzer_plugins, inline_macro_plugins) + }) + } + /// Adds plugin suit to database. pub fn add_plugin_suite(&mut self, plugins: PluginSuite) { self.with_plugins_mut(move |macro_plugins, analyzer_plugins, inline_macro_plugins| { diff --git a/src/lang/proc_macros/controller.rs b/src/lang/proc_macros/controller.rs index 535f37a4..7812fa7b 100644 --- a/src/lang/proc_macros/controller.rs +++ b/src/lang/proc_macros/controller.rs @@ -88,6 +88,25 @@ impl ProcMacroClientController { } } + /// Forcibly restarts the proc-macro-server, shutting down any currently running instances. + /// + /// A new server instance is only started if there are available restart attempts left. + /// This ensures that a fresh proc-macro-server is used. + pub fn force_restart(&mut self, db: &mut AnalysisDatabase, config: &Config) { + // We have to make sure that snapshots will not report errors from previous client after we + // create new one. + db.cancel_all(); + + // Otherwise we can get messages from old client after initialization of new one. + self.channels.clear_all(); + + if let Some(plugin_suite) = self.plugin_suite.take() { + db.remove_plugin_suite(plugin_suite); + } + + self.try_initialize(db, config); + } + /// Check if an error was reported. If so, try to restart. pub fn handle_error(&mut self, db: &mut AnalysisDatabase, config: &Config) { if !self.try_initialize(db, config) { @@ -272,4 +291,10 @@ impl ProcMacroChannels { Self { response_sender, response_receiver, error_sender, error_receiver } } + + /// Make all channels empty in a non-blocking manner. + fn clear_all(&self) { + self.error_receiver.try_iter().for_each(|_| {}); + self.response_receiver.try_iter().for_each(|_| {}); + } } diff --git a/src/server/routing/traits.rs b/src/server/routing/traits.rs index a745f056..f7e07c4f 100644 --- a/src/server/routing/traits.rs +++ b/src/server/routing/traits.rs @@ -198,6 +198,8 @@ impl SyncNotificationHandler for DidChangeWatchedFiles { if ["Scarb.toml", "cairo_project.toml"].map(Some).contains(&changed_file_name.to_str()) { Backend::reload(state, requester)?; + + state.proc_macro_controller.force_restart(&mut state.db, &state.config); } }