Report config errors via status

This commit is contained in:
Lukas Wirth 2023-05-26 15:21:00 +02:00
parent 79fe11ced3
commit a2b59b110f
5 changed files with 19 additions and 14 deletions

View file

@ -720,11 +720,11 @@ pub struct ClientCommandsConfig {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct ConfigUpdateError { pub struct ConfigError {
errors: Vec<(String, serde_json::Error)>, errors: Vec<(String, serde_json::Error)>,
} }
impl fmt::Display for ConfigUpdateError { impl fmt::Display for ConfigError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let errors = self.errors.iter().format_with("\n", |(key, e), f| { let errors = self.errors.iter().format_with("\n", |(key, e), f| {
f(key)?; f(key)?;
@ -733,7 +733,7 @@ impl fmt::Display for ConfigUpdateError {
}); });
write!( write!(
f, f,
"rust-analyzer found {} invalid config value{}:\n{}", "invalid config value{}:\n{}",
self.errors.len(), self.errors.len(),
if self.errors.len() == 1 { "" } else { "s" }, if self.errors.len() == 1 { "" } else { "s" },
errors errors
@ -777,7 +777,7 @@ impl Config {
self.workspace_roots.extend(paths); self.workspace_roots.extend(paths);
} }
pub fn update(&mut self, mut json: serde_json::Value) -> Result<(), ConfigUpdateError> { pub fn update(&mut self, mut json: serde_json::Value) -> Result<(), ConfigError> {
tracing::info!("updating config from JSON: {:#}", json); tracing::info!("updating config from JSON: {:#}", json);
if json.is_null() || json.as_object().map_or(false, |it| it.is_empty()) { if json.is_null() || json.as_object().map_or(false, |it| it.is_empty()) {
return Ok(()); return Ok(());
@ -824,7 +824,7 @@ impl Config {
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
} else { } else {
Err(ConfigUpdateError { errors }) Err(ConfigError { errors })
} }
} }

View file

@ -19,7 +19,7 @@ use triomphe::Arc;
use vfs::AnchoredPathBuf; use vfs::AnchoredPathBuf;
use crate::{ use crate::{
config::Config, config::{Config, ConfigError},
diagnostics::{CheckFixes, DiagnosticCollection}, diagnostics::{CheckFixes, DiagnosticCollection},
from_proto, from_proto,
line_index::{LineEndings, LineIndex}, line_index::{LineEndings, LineIndex},
@ -56,6 +56,7 @@ pub(crate) struct GlobalState {
pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>, pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>,
pub(crate) config: Arc<Config>, pub(crate) config: Arc<Config>,
pub(crate) config_errors: Option<ConfigError>,
pub(crate) analysis_host: AnalysisHost, pub(crate) analysis_host: AnalysisHost,
pub(crate) diagnostics: DiagnosticCollection, pub(crate) diagnostics: DiagnosticCollection,
pub(crate) mem_docs: MemDocs, pub(crate) mem_docs: MemDocs,
@ -168,6 +169,7 @@ impl GlobalState {
shutdown_requested: false, shutdown_requested: false,
last_reported_status: None, last_reported_status: None,
source_root_config: SourceRootConfig::default(), source_root_config: SourceRootConfig::default(),
config_errors: Default::default(),
proc_macro_changed: false, proc_macro_changed: false,
// FIXME: use `Arc::from_iter` when it becomes available // FIXME: use `Arc::from_iter` when it becomes available

View file

@ -169,13 +169,7 @@ pub(crate) fn handle_did_change_configuration(
// Note that json can be null according to the spec if the client can't // Note that json can be null according to the spec if the client can't
// provide a configuration. This is handled in Config::update below. // provide a configuration. This is handled in Config::update below.
let mut config = Config::clone(&*this.config); let mut config = Config::clone(&*this.config);
if let Err(error) = config.update(json.take()) { config.update(json.take());
this.show_message(
lsp_types::MessageType::WARNING,
error.to_string(),
false,
);
}
this.update_configuration(config); this.update_configuration(config);
} }
} }

View file

@ -419,7 +419,11 @@ impl GlobalState {
if self.config.server_status_notification() { if self.config.server_status_notification() {
self.send_notification::<lsp_ext::ServerStatusNotification>(status); self.send_notification::<lsp_ext::ServerStatusNotification>(status);
} else if let (health, Some(message)) = (status.health, &status.message) { } else if let (
health @ (lsp_ext::Health::Warning | lsp_ext::Health::Error),
Some(message),
) = (status.health, &status.message)
{
let open_log_button = tracing::enabled!(tracing::Level::ERROR) let open_log_button = tracing::enabled!(tracing::Level::ERROR)
&& (self.fetch_build_data_error().is_err() && (self.fetch_build_data_error().is_err()
|| self.fetch_workspace_error().is_err()); || self.fetch_workspace_error().is_err());

View file

@ -27,6 +27,7 @@ use ide_db::{
use itertools::Itertools; use itertools::Itertools;
use proc_macro_api::{MacroDylib, ProcMacroServer}; use proc_macro_api::{MacroDylib, ProcMacroServer};
use project_model::{PackageRoot, ProjectWorkspace, WorkspaceBuildScripts}; use project_model::{PackageRoot, ProjectWorkspace, WorkspaceBuildScripts};
use stdx::format_to;
use syntax::SmolStr; use syntax::SmolStr;
use triomphe::Arc; use triomphe::Arc;
use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind}; use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind};
@ -134,6 +135,10 @@ impl GlobalState {
message.push_str("Failed to discover workspace.\n"); message.push_str("Failed to discover workspace.\n");
message.push_str("Consider adding the `Cargo.toml` of the workspace to the [`linkedProjects`](https://rust-analyzer.github.io/manual.html#rust-analyzer.linkedProjects) setting.\n\n"); message.push_str("Consider adding the `Cargo.toml` of the workspace to the [`linkedProjects`](https://rust-analyzer.github.io/manual.html#rust-analyzer.linkedProjects) setting.\n\n");
} }
if let Some(err) = &self.config_errors {
status.health = lsp_ext::Health::Warning;
format_to!(message, "{err}\n");
}
for ws in self.workspaces.iter() { for ws in self.workspaces.iter() {
let (ProjectWorkspace::Cargo { sysroot, .. } let (ProjectWorkspace::Cargo { sysroot, .. }