Auto merge of #14313 - Veykril:notifs, r=Veykril
Make project loading errors less intrusive cc https://github.com/rust-lang/rust-analyzer/issues/14193 closes https://github.com/rust-lang/rust-analyzer/issues/9909 
This commit is contained in:
commit
070f8f8578
5 changed files with 69 additions and 46 deletions
|
|
@ -111,12 +111,7 @@ impl fmt::Debug for Event {
|
|||
|
||||
impl GlobalState {
|
||||
fn run(mut self, inbox: Receiver<lsp_server::Message>) -> Result<()> {
|
||||
if self.config.linked_projects().is_empty()
|
||||
&& self.config.detached_files().is_empty()
|
||||
&& self.config.notifications().cargo_toml_not_found
|
||||
{
|
||||
self.show_and_log_error("rust-analyzer failed to discover workspace".to_string(), None);
|
||||
};
|
||||
self.update_status_or_notify();
|
||||
|
||||
if self.config.did_save_text_document_dynamic_registration() {
|
||||
let save_registration_options = lsp_types::TextDocumentSaveRegistrationOptions {
|
||||
|
|
@ -394,18 +389,7 @@ impl GlobalState {
|
|||
});
|
||||
}
|
||||
|
||||
let status = self.current_status();
|
||||
if self.last_reported_status.as_ref() != Some(&status) {
|
||||
self.last_reported_status = Some(status.clone());
|
||||
|
||||
if self.config.server_status_notification() {
|
||||
self.send_notification::<lsp_ext::ServerStatusNotification>(status);
|
||||
} else {
|
||||
if let (lsp_ext::Health::Error, Some(message)) = (status.health, &status.message) {
|
||||
self.show_message(lsp_types::MessageType::ERROR, message.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
self.update_status_or_notify();
|
||||
|
||||
let loop_duration = loop_start.elapsed();
|
||||
if loop_duration > Duration::from_millis(100) && was_quiescent {
|
||||
|
|
@ -415,6 +399,20 @@ impl GlobalState {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn update_status_or_notify(&mut self) {
|
||||
let status = self.current_status();
|
||||
if self.last_reported_status.as_ref() != Some(&status) {
|
||||
self.last_reported_status = Some(status.clone());
|
||||
|
||||
if self.config.server_status_notification() {
|
||||
self.send_notification::<lsp_ext::ServerStatusNotification>(status);
|
||||
} else if let (lsp_ext::Health::Error, Some(message)) = (status.health, &status.message)
|
||||
{
|
||||
self.show_and_log_error(message.clone(), None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_task(&mut self, prime_caches_progress: &mut Vec<PrimeCachesProgress>, task: Task) {
|
||||
match task {
|
||||
Task::Response(response) => self.respond(response),
|
||||
|
|
@ -445,6 +443,9 @@ impl GlobalState {
|
|||
ProjectWorkspaceProgress::Report(msg) => (Progress::Report, Some(msg)),
|
||||
ProjectWorkspaceProgress::End(workspaces) => {
|
||||
self.fetch_workspaces_queue.op_completed(Some(workspaces));
|
||||
if let Err(e) = self.fetch_workspace_error() {
|
||||
tracing::error!("FetchWorkspaceError:\n{e}");
|
||||
}
|
||||
|
||||
let old = Arc::clone(&self.workspaces);
|
||||
self.switch_workspaces("fetched workspace".to_string());
|
||||
|
|
@ -466,6 +467,9 @@ impl GlobalState {
|
|||
BuildDataProgress::Report(msg) => (Some(Progress::Report), Some(msg)),
|
||||
BuildDataProgress::End(build_data_result) => {
|
||||
self.fetch_build_data_queue.op_completed(build_data_result);
|
||||
if let Err(e) = self.fetch_build_data_error() {
|
||||
tracing::error!("FetchBuildDataError:\n{e}");
|
||||
}
|
||||
|
||||
self.switch_workspaces("fetched build data".to_string());
|
||||
|
||||
|
|
@ -498,6 +502,7 @@ impl GlobalState {
|
|||
self.vfs_progress_n_total = n_total;
|
||||
self.vfs_progress_n_done = n_done;
|
||||
|
||||
// if n_total != 0 {
|
||||
let state = if n_done == 0 {
|
||||
Progress::Begin
|
||||
} else if n_done < n_total {
|
||||
|
|
@ -512,7 +517,8 @@ impl GlobalState {
|
|||
Some(format!("{n_done}/{n_total}")),
|
||||
Some(Progress::fraction(n_done, n_total)),
|
||||
None,
|
||||
)
|
||||
);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -554,7 +560,10 @@ impl GlobalState {
|
|||
flycheck::Progress::DidCheckCrate(target) => (Progress::Report, Some(target)),
|
||||
flycheck::Progress::DidCancel => (Progress::End, None),
|
||||
flycheck::Progress::DidFailToRestart(err) => {
|
||||
self.show_and_log_error("cargo check failed".to_string(), Some(err));
|
||||
self.show_and_log_error(
|
||||
"cargo check failed to start".to_string(),
|
||||
Some(err),
|
||||
);
|
||||
return;
|
||||
}
|
||||
flycheck::Progress::DidFinish(result) => {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ pub(crate) enum BuildDataProgress {
|
|||
|
||||
impl GlobalState {
|
||||
pub(crate) fn is_quiescent(&self) -> bool {
|
||||
!(self.fetch_workspaces_queue.op_in_progress()
|
||||
!(self.last_reported_status.is_none()
|
||||
|| self.fetch_workspaces_queue.op_in_progress()
|
||||
|| self.fetch_build_data_queue.op_in_progress()
|
||||
|| self.vfs_progress_config_version < self.vfs_config_version
|
||||
|| self.vfs_progress_n_done < self.vfs_progress_n_total)
|
||||
|
|
@ -108,9 +109,9 @@ impl GlobalState {
|
|||
status.message = Some("Workspace reload required".to_string())
|
||||
}
|
||||
|
||||
if let Err(error) = self.fetch_workspace_error() {
|
||||
if let Err(_) = self.fetch_workspace_error() {
|
||||
status.health = lsp_ext::Health::Error;
|
||||
status.message = Some(error)
|
||||
status.message = Some("Failed to load workspaces".to_string())
|
||||
}
|
||||
|
||||
if self.config.linked_projects().is_empty()
|
||||
|
|
@ -118,8 +119,9 @@ impl GlobalState {
|
|||
&& self.config.notifications().cargo_toml_not_found
|
||||
{
|
||||
status.health = lsp_ext::Health::Warning;
|
||||
status.message = Some("Workspace reload required".to_string())
|
||||
status.message = Some("Failed to discover workspace".to_string())
|
||||
}
|
||||
|
||||
status
|
||||
}
|
||||
|
||||
|
|
@ -201,10 +203,7 @@ impl GlobalState {
|
|||
let _p = profile::span("GlobalState::switch_workspaces");
|
||||
tracing::info!(%cause, "will switch workspaces");
|
||||
|
||||
if let Err(error_message) = self.fetch_workspace_error() {
|
||||
if !self.config.server_status_notification() {
|
||||
self.show_and_log_error(error_message, None);
|
||||
}
|
||||
if let Err(_) = self.fetch_workspace_error() {
|
||||
if !self.workspaces.is_empty() {
|
||||
// It only makes sense to switch to a partially broken workspace
|
||||
// if we don't have any workspace at all yet.
|
||||
|
|
@ -212,10 +211,6 @@ impl GlobalState {
|
|||
}
|
||||
}
|
||||
|
||||
if let Err(error) = self.fetch_build_data_error() {
|
||||
self.show_and_log_error("failed to run build scripts".to_string(), Some(error));
|
||||
}
|
||||
|
||||
let Some(workspaces) = self.fetch_workspaces_queue.last_op_result() else { return; };
|
||||
let workspaces =
|
||||
workspaces.iter().filter_map(|res| res.as_ref().ok().cloned()).collect::<Vec<_>>();
|
||||
|
|
@ -394,7 +389,7 @@ impl GlobalState {
|
|||
tracing::info!("did switch workspaces");
|
||||
}
|
||||
|
||||
fn fetch_workspace_error(&self) -> Result<(), String> {
|
||||
pub(super) fn fetch_workspace_error(&self) -> Result<(), String> {
|
||||
let mut buf = String::new();
|
||||
|
||||
let Some(last_op_result) = self.fetch_workspaces_queue.last_op_result() else { return Ok(()) };
|
||||
|
|
@ -415,7 +410,7 @@ impl GlobalState {
|
|||
Err(buf)
|
||||
}
|
||||
|
||||
fn fetch_build_data_error(&self) -> Result<(), String> {
|
||||
pub(super) fn fetch_build_data_error(&self) -> Result<(), String> {
|
||||
let mut buf = String::new();
|
||||
|
||||
for ws in &self.fetch_build_data_queue.last_op_result().1 {
|
||||
|
|
|
|||
|
|
@ -93,6 +93,14 @@ export function triggerParameterHints(_: CtxInit): Cmd {
|
|||
};
|
||||
}
|
||||
|
||||
export function openLogs(ctx: CtxInit): Cmd {
|
||||
return async () => {
|
||||
if (ctx.client.outputChannel) {
|
||||
ctx.client.outputChannel.show();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function matchingBrace(ctx: CtxInit): Cmd {
|
||||
return async () => {
|
||||
const editor = ctx.activeRustEditor;
|
||||
|
|
|
|||
|
|
@ -282,18 +282,18 @@ export class Ctx {
|
|||
setServerStatus(status: ServerStatusParams | { health: "stopped" }) {
|
||||
let icon = "";
|
||||
const statusBar = this.statusBar;
|
||||
statusBar.tooltip = new vscode.MarkdownString("", true);
|
||||
statusBar.tooltip.isTrusted = true;
|
||||
switch (status.health) {
|
||||
case "ok":
|
||||
statusBar.tooltip = (status.message ?? "Ready") + "\nClick to stop server.";
|
||||
statusBar.command = "rust-analyzer.stopServer";
|
||||
statusBar.tooltip.appendText(status.message ?? "Ready");
|
||||
statusBar.color = undefined;
|
||||
statusBar.backgroundColor = undefined;
|
||||
break;
|
||||
case "warning":
|
||||
statusBar.tooltip =
|
||||
(status.message ? status.message + "\n" : "") + "Click to reload.";
|
||||
|
||||
statusBar.command = "rust-analyzer.reloadWorkspace";
|
||||
if (status.message) {
|
||||
statusBar.tooltip.appendText(status.message);
|
||||
}
|
||||
statusBar.color = new vscode.ThemeColor("statusBarItem.warningForeground");
|
||||
statusBar.backgroundColor = new vscode.ThemeColor(
|
||||
"statusBarItem.warningBackground"
|
||||
|
|
@ -301,22 +301,32 @@ export class Ctx {
|
|||
icon = "$(warning) ";
|
||||
break;
|
||||
case "error":
|
||||
statusBar.tooltip =
|
||||
(status.message ? status.message + "\n" : "") + "Click to reload.";
|
||||
|
||||
statusBar.command = "rust-analyzer.reloadWorkspace";
|
||||
if (status.message) {
|
||||
statusBar.tooltip.appendText(status.message);
|
||||
}
|
||||
statusBar.color = new vscode.ThemeColor("statusBarItem.errorForeground");
|
||||
statusBar.backgroundColor = new vscode.ThemeColor("statusBarItem.errorBackground");
|
||||
icon = "$(error) ";
|
||||
break;
|
||||
case "stopped":
|
||||
statusBar.tooltip = "Server is stopped.\nClick to start.";
|
||||
statusBar.command = "rust-analyzer.startServer";
|
||||
statusBar.tooltip.appendText("Server is stopped");
|
||||
statusBar.tooltip.appendMarkdown(
|
||||
"\n\n[Start server](command:rust-analyzer.startServer)"
|
||||
);
|
||||
statusBar.color = undefined;
|
||||
statusBar.backgroundColor = undefined;
|
||||
statusBar.text = `$(stop-circle) rust-analyzer`;
|
||||
return;
|
||||
}
|
||||
if (statusBar.tooltip.value) {
|
||||
statusBar.tooltip.appendText("\n\n");
|
||||
}
|
||||
statusBar.tooltip.appendMarkdown("[Stop server](command:rust-analyzer.stopServer)");
|
||||
statusBar.tooltip.appendMarkdown(
|
||||
"\n\n[Reload Workspace](command:rust-analyzer.reloadWorkspace)"
|
||||
);
|
||||
statusBar.tooltip.appendMarkdown("\n\n[Restart server](command:rust-analyzer.startServer)");
|
||||
statusBar.tooltip.appendMarkdown("\n\n[Open logs](command:rust-analyzer.openLogs)");
|
||||
if (!status.quiescent) icon = "$(sync~spin) ";
|
||||
statusBar.text = `${icon}rust-analyzer`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,5 +188,6 @@ function createCommands(): Record<string, CommandFactory> {
|
|||
runSingle: { enabled: commands.runSingle },
|
||||
showReferences: { enabled: commands.showReferences },
|
||||
triggerParameterHints: { enabled: commands.triggerParameterHints },
|
||||
openLogs: { enabled: commands.openLogs },
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue