Merge #11214
11214: feat: poke user when supplying faulty configurations r=Veykril a=Veykril bors r+ Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
commit
c574cf351a
4 changed files with 36 additions and 12 deletions
|
@ -150,7 +150,7 @@ fn run_server() -> Result<()> {
|
||||||
|
|
||||||
let mut config = Config::new(root_path, initialize_params.capabilities);
|
let mut config = Config::new(root_path, initialize_params.capabilities);
|
||||||
if let Some(json) = initialize_params.initialization_options {
|
if let Some(json) = initialize_params.initialization_options {
|
||||||
config.update(json);
|
let _ = config.update(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
let server_capabilities = rust_analyzer::server_capabilities(&config);
|
let server_capabilities = rust_analyzer::server_capabilities(&config);
|
||||||
|
|
|
@ -341,7 +341,7 @@ config_data! {
|
||||||
|
|
||||||
impl Default for ConfigData {
|
impl Default for ConfigData {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
ConfigData::from_json(serde_json::Value::Null)
|
ConfigData::from_json(serde_json::Value::Null, &mut Vec::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,16 +492,21 @@ impl Config {
|
||||||
snippets: Default::default(),
|
snippets: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn update(&mut self, mut json: serde_json::Value) {
|
pub fn update(
|
||||||
|
&mut self,
|
||||||
|
mut json: serde_json::Value,
|
||||||
|
) -> Result<(), Vec<(String, serde_json::Error)>> {
|
||||||
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;
|
return Ok(());
|
||||||
}
|
}
|
||||||
self.detached_files = get_field::<Vec<PathBuf>>(&mut json, "detachedFiles", None, "[]")
|
let mut errors = Vec::new();
|
||||||
.into_iter()
|
self.detached_files =
|
||||||
.map(AbsPathBuf::assert)
|
get_field::<Vec<PathBuf>>(&mut json, &mut errors, "detachedFiles", None, "[]")
|
||||||
.collect();
|
.into_iter()
|
||||||
self.data = ConfigData::from_json(json);
|
.map(AbsPathBuf::assert)
|
||||||
|
.collect();
|
||||||
|
self.data = ConfigData::from_json(json, &mut errors);
|
||||||
self.snippets.clear();
|
self.snippets.clear();
|
||||||
for (name, def) in self.data.completion_snippets.iter() {
|
for (name, def) in self.data.completion_snippets.iter() {
|
||||||
if def.prefix.is_empty() && def.postfix.is_empty() {
|
if def.prefix.is_empty() && def.postfix.is_empty() {
|
||||||
|
@ -524,6 +529,11 @@ impl Config {
|
||||||
None => tracing::info!("Invalid snippet {}", name),
|
None => tracing::info!("Invalid snippet {}", name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if errors.is_empty() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(errors)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn json_schema() -> serde_json::Value {
|
pub fn json_schema() -> serde_json::Value {
|
||||||
|
@ -1116,10 +1126,11 @@ macro_rules! _config_data {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct $name { $($field: $ty,)* }
|
struct $name { $($field: $ty,)* }
|
||||||
impl $name {
|
impl $name {
|
||||||
fn from_json(mut json: serde_json::Value) -> $name {
|
fn from_json(mut json: serde_json::Value, error_sink: &mut Vec<(String, serde_json::Error)>) -> $name {
|
||||||
$name {$(
|
$name {$(
|
||||||
$field: get_field(
|
$field: get_field(
|
||||||
&mut json,
|
&mut json,
|
||||||
|
error_sink,
|
||||||
stringify!($field),
|
stringify!($field),
|
||||||
None$(.or(Some(stringify!($alias))))*,
|
None$(.or(Some(stringify!($alias))))*,
|
||||||
$default,
|
$default,
|
||||||
|
@ -1156,6 +1167,7 @@ use _config_data as config_data;
|
||||||
|
|
||||||
fn get_field<T: DeserializeOwned>(
|
fn get_field<T: DeserializeOwned>(
|
||||||
json: &mut serde_json::Value,
|
json: &mut serde_json::Value,
|
||||||
|
error_sink: &mut Vec<(String, serde_json::Error)>,
|
||||||
field: &'static str,
|
field: &'static str,
|
||||||
alias: Option<&'static str>,
|
alias: Option<&'static str>,
|
||||||
default: &str,
|
default: &str,
|
||||||
|
@ -1174,6 +1186,7 @@ fn get_field<T: DeserializeOwned>(
|
||||||
Ok(it) => Some(it),
|
Ok(it) => Some(it),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::warn!("Failed to deserialize config field at {}: {:?}", pointer, e);
|
tracing::warn!("Failed to deserialize config field at {}: {:?}", pointer, e);
|
||||||
|
error_sink.push((pointer, e));
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,6 +9,7 @@ use std::{
|
||||||
use always_assert::always;
|
use always_assert::always;
|
||||||
use crossbeam_channel::{select, Receiver};
|
use crossbeam_channel::{select, Receiver};
|
||||||
use ide_db::base_db::{SourceDatabaseExt, VfsPath};
|
use ide_db::base_db::{SourceDatabaseExt, VfsPath};
|
||||||
|
use itertools::Itertools;
|
||||||
use lsp_server::{Connection, Notification, Request};
|
use lsp_server::{Connection, Notification, Request};
|
||||||
use lsp_types::notification::Notification as _;
|
use lsp_types::notification::Notification as _;
|
||||||
use vfs::{ChangeKind, FileId};
|
use vfs::{ChangeKind, FileId};
|
||||||
|
@ -731,7 +732,17 @@ impl GlobalState {
|
||||||
// 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);
|
||||||
config.update(json.take());
|
if let Err(errors) = config.update(json.take()) {
|
||||||
|
let errors = errors
|
||||||
|
.iter()
|
||||||
|
.format_with("\n", |(key, e),f| {
|
||||||
|
f(key)?;
|
||||||
|
f(&": ")?;
|
||||||
|
f(e)
|
||||||
|
});
|
||||||
|
let msg= format!("Failed to deserialize config key(s):\n{}", errors);
|
||||||
|
this.show_message(lsp_types::MessageType::WARNING, msg);
|
||||||
|
}
|
||||||
this.update_configuration(config);
|
this.update_configuration(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@ impl<'a> Project<'a> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
config.discovered_projects = Some(discovered_projects);
|
config.discovered_projects = Some(discovered_projects);
|
||||||
config.update(self.config);
|
let _ = config.update(self.config);
|
||||||
|
|
||||||
Server::new(tmp_dir, config)
|
Server::new(tmp_dir, config)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue