Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Commit 9a91424

Browse files
committed
Auto merge of #1539 - Xanewok:config, r=Xanewok
Warn against deprecated config entries Addresses rust-lang/vscode-rust#643. Brings back removed option from #1509 but only not to trigger the unknown option warning.
2 parents 4971b90 + f7fe8c8 commit 9a91424

File tree

5 files changed

+88
-30
lines changed

5 files changed

+88
-30
lines changed

rls/src/actions/notifications.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,15 @@ impl BlockingNotificationAction for DidChangeConfiguration {
140140
use std::collections::HashMap;
141141
let mut dups = HashMap::new();
142142
let mut unknowns = vec![];
143-
let settings =
144-
ChangeConfigSettings::try_deserialize(&params.settings, &mut dups, &mut unknowns);
143+
let mut deprecated = vec![];
144+
let settings = ChangeConfigSettings::try_deserialize(
145+
&params.settings,
146+
&mut dups,
147+
&mut unknowns,
148+
&mut deprecated,
149+
);
145150
crate::server::maybe_notify_unknown_configs(&out, &unknowns);
151+
crate::server::maybe_notify_deprecated_configs(&out, &deprecated);
146152
crate::server::maybe_notify_duplicated_configs(&out, &dups);
147153

148154
let new_config = match settings {

rls/src/config.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Configuration for the workspace that RLS is operating within and options for
22
//! tweaking the RLS's behavior itself.
33
4+
use std::collections::HashMap;
45
use std::env;
56
use std::fmt;
67
use std::fmt::Debug;
@@ -172,6 +173,8 @@ pub struct Config {
172173
/// to be loaded by the RLS. The program given should output a list of
173174
/// resulting JSON files on stdout.
174175
pub build_command: Option<String>,
176+
/// DEPRECATED: Use `crate_blacklist` instead.
177+
pub use_crate_blacklist: Option<bool>,
175178
}
176179

177180
impl Default for Config {
@@ -201,20 +204,32 @@ impl Default for Config {
201204
show_hover_context: true,
202205
rustfmt_path: None,
203206
build_command: None,
207+
use_crate_blacklist: None,
204208
};
205209
result.normalise();
206210
result
207211
}
208212
}
209213

214+
lazy_static::lazy_static! {
215+
#[derive(Debug)]
216+
pub static ref DEPRECATED_OPTIONS: HashMap<&'static str, Option<&'static str>> = {
217+
[("use_crate_blacklist", Some("use `crate_blacklist` instead"))]
218+
.iter()
219+
.map(ToOwned::to_owned)
220+
.collect()
221+
};
222+
}
223+
210224
impl Config {
211225
/// try to deserialize a Config from a json value, val is expected to be a
212226
/// Value::Object, all first level keys of val are converted to snake_case,
213227
/// duplicated and unknown keys are reported
214228
pub fn try_deserialize(
215229
val: &serde_json::value::Value,
216230
dups: &mut std::collections::HashMap<String, Vec<String>>,
217-
unknowns: &mut Vec<(String)>,
231+
unknowns: &mut Vec<String>,
232+
deprecated: &mut Vec<String>,
218233
) -> Result<Config, ()> {
219234
#[derive(Clone)]
220235
struct JsonValue(serde_json::value::Value);
@@ -234,6 +249,10 @@ impl Config {
234249
vec.push(k.to_string());
235250

236251
if vec.len() == 1 {
252+
if DEPRECATED_OPTIONS.contains_key(snake_case.as_str()) {
253+
deprecated.push(snake_case.clone());
254+
}
255+
237256
Some((snake_case, JsonValue(v.to_owned().clone())))
238257
} else {
239258
None
@@ -486,14 +505,17 @@ fn clippy_preference_from_str() {
486505
#[test]
487506
fn blacklist_default() {
488507
let value = serde_json::json!({});
489-
let config = Config::try_deserialize(&value, &mut Default::default(), &mut vec![]).unwrap();
508+
let config =
509+
Config::try_deserialize(&value, &mut Default::default(), &mut vec![], &mut vec![]).unwrap();
490510
assert_eq!(config.crate_blacklist.as_ref(), &CrateBlacklist::default());
491511
let value = serde_json::json!({"crate_blacklist": []});
492512

493-
let config = Config::try_deserialize(&value, &mut Default::default(), &mut vec![]).unwrap();
513+
let config =
514+
Config::try_deserialize(&value, &mut Default::default(), &mut vec![], &mut vec![]).unwrap();
494515
assert_eq!(&*config.crate_blacklist.as_ref().0, &[] as &[String]);
495516

496517
let value = serde_json::json!({"crate_blacklist": ["serde"]});
497-
let config = Config::try_deserialize(&value, &mut Default::default(), &mut vec![]).unwrap();
518+
let config =
519+
Config::try_deserialize(&value, &mut Default::default(), &mut vec![], &mut vec![]).unwrap();
498520
assert_eq!(&*config.crate_blacklist.as_ref().0, &["serde".to_string()]);
499521
}

rls/src/lsp_data.rs

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ impl ChangeConfigSettings {
234234
val: &serde_json::value::Value,
235235
dups: &mut std::collections::HashMap<String, Vec<String>>,
236236
unknowns: &mut Vec<String>,
237+
deprecated: &mut Vec<String>,
237238
) -> Result<ChangeConfigSettings, ()> {
238239
let mut ret = Err(());
239240
if let serde_json::Value::Object(map) = val {
@@ -243,7 +244,8 @@ impl ChangeConfigSettings {
243244
continue;
244245
}
245246
if let serde_json::Value::Object(_) = v {
246-
if let Ok(rust) = config::Config::try_deserialize(v, dups, unknowns) {
247+
if let Ok(rust) = config::Config::try_deserialize(v, dups, unknowns, deprecated)
248+
{
247249
ret = Ok(ChangeConfigSettings { rust });
248250
}
249251
} else {
@@ -275,25 +277,16 @@ impl InitializationOptions {
275277
/// "rust", all first level keys of rust's value are converted to
276278
/// snake_case, duplicated and unknown keys are reported
277279
pub fn try_deserialize(
278-
val: &serde_json::value::Value,
280+
mut val: serde_json::value::Value,
279281
dups: &mut std::collections::HashMap<String, Vec<String>>,
280282
unknowns: &mut Vec<String>,
283+
deprecated: &mut Vec<String>,
281284
) -> Result<InitializationOptions, ()> {
282-
let mut val = val.to_owned();
283-
let mut set = None;
284-
if let Some(set1) = val.get_mut("settings") {
285-
set = Some(set1.take());
286-
}
287-
let mut ret: InitializationOptions = match serde_json::from_value(val) {
288-
Ok(ret) => ret,
289-
_ => return Err(()),
290-
};
291-
if let Some(set) = set {
292-
if let Ok(set) = ChangeConfigSettings::try_deserialize(&set, dups, unknowns) {
293-
ret.settings = Some(set);
294-
}
295-
}
296-
Ok(ret)
285+
let settings = val.get_mut("settings").map(|x| x.take()).and_then(|set| {
286+
ChangeConfigSettings::try_deserialize(&set, dups, unknowns, deprecated).ok()
287+
});
288+
289+
Ok(InitializationOptions { settings, ..serde_json::from_value(val).map_err(|_| ())? })
297290
}
298291
}
299292

@@ -326,17 +319,17 @@ impl ClientCapabilities {
326319
.and_then(|doc| doc.completion.as_ref())
327320
.and_then(|comp| comp.completion_item.as_ref())
328321
.and_then(|item| item.snippet_support.as_ref())
329-
.unwrap_or(&false)
330-
.to_owned();
322+
.copied()
323+
.unwrap_or(false);
331324

332325
let related_information_support = params
333326
.capabilities
334327
.text_document
335328
.as_ref()
336329
.and_then(|doc| doc.publish_diagnostics.as_ref())
337330
.and_then(|diag| diag.related_information.as_ref())
338-
.unwrap_or(&false)
339-
.to_owned();
331+
.copied()
332+
.unwrap_or(false);
340333

341334
ClientCapabilities { code_completion_has_snippet_support, related_information_support }
342335
}

rls/src/server/mod.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! requests).
44
55
use crate::actions::{notifications, requests, ActionContext};
6-
use crate::config::Config;
6+
use crate::config::{Config, DEPRECATED_OPTIONS};
77
use crate::lsp_data;
88
use crate::lsp_data::{
99
InitializationOptions, LSPNotification, LSPRequest, MessageType, ShowMessageParams,
@@ -94,6 +94,24 @@ pub(crate) fn maybe_notify_unknown_configs<O: Output>(out: &O, unknowns: &[Strin
9494
}));
9595
}
9696

97+
/// For each deprecated configuration key an appropriate warning is emitted via
98+
/// LSP, along with a deprecation notice (if there is one).
99+
pub(crate) fn maybe_notify_deprecated_configs<O: Output>(out: &O, keys: &[String]) {
100+
for key in keys {
101+
let notice = DEPRECATED_OPTIONS.get(key.as_str()).and_then(|x| *x);
102+
let message = format!(
103+
"RLS configuration option `{}` is deprecated{}",
104+
key,
105+
notice.map(|notice| format!(": {}", notice)).unwrap_or_default()
106+
);
107+
108+
out.notify(Notification::<ShowMessage>::new(ShowMessageParams {
109+
typ: MessageType::Warning,
110+
message,
111+
}));
112+
}
113+
}
114+
97115
pub(crate) fn maybe_notify_duplicated_configs<O: Output>(
98116
out: &O,
99117
dups: &std::collections::HashMap<String, Vec<String>>,
@@ -129,11 +147,18 @@ impl BlockingRequestAction for InitializeRequest {
129147
) -> Result<NoResponse, ResponseError> {
130148
let mut dups = std::collections::HashMap::new();
131149
let mut unknowns = Vec::new();
150+
let mut deprecated = Vec::new();
132151
let init_options = params
133152
.initialization_options
134153
.take()
135154
.and_then(|opt| {
136-
InitializationOptions::try_deserialize(&opt, &mut dups, &mut unknowns).ok()
155+
InitializationOptions::try_deserialize(
156+
opt,
157+
&mut dups,
158+
&mut unknowns,
159+
&mut deprecated,
160+
)
161+
.ok()
137162
})
138163
.unwrap_or_default();
139164

@@ -148,6 +173,7 @@ impl BlockingRequestAction for InitializeRequest {
148173
}
149174

150175
maybe_notify_unknown_configs(&out, &unknowns);
176+
maybe_notify_deprecated_configs(&out, &deprecated);
151177
maybe_notify_duplicated_configs(&out, &dups);
152178

153179
let result = InitializeResult { capabilities: server_caps(ctx) };

tests/client.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1272,6 +1272,11 @@ fn is_notification_for_unknown_config(msg: &serde_json::Value) -> bool {
12721272
&& msg["params"]["message"].as_str().unwrap().contains("Unknown")
12731273
}
12741274

1275+
fn is_notification_for_deprecated_config(msg: &serde_json::Value) -> bool {
1276+
msg["method"] == ShowMessage::METHOD
1277+
&& msg["params"]["message"].as_str().unwrap().contains("is deprecated")
1278+
}
1279+
12751280
fn is_notification_for_duplicated_config(msg: &serde_json::Value) -> bool {
12761281
msg["method"] == ShowMessage::METHOD
12771282
&& msg["params"]["message"].as_str().unwrap().contains("Duplicate")
@@ -1305,14 +1310,20 @@ fn client_init_duplicated_and_unknown_settings() {
13051310
"dup_val": false,
13061311
"dup_licated": "dup_lacated",
13071312
"DupLicated": "DupLicated",
1308-
"dup-licated": "dup-licated"
1313+
"dup-licated": "dup-licated",
1314+
// Deprecated
1315+
"use_crate_blacklist": true
13091316
}
13101317
}
13111318
});
13121319

13131320
rls.request::<Initialize>(0, initialize_params_with_opts(root_path, opts));
13141321

13151322
assert!(rls.messages().iter().any(is_notification_for_unknown_config));
1323+
assert!(
1324+
rls.messages().iter().any(is_notification_for_deprecated_config),
1325+
"`use_crate_blacklist` should be marked as deprecated"
1326+
);
13161327
assert!(rls.messages().iter().any(is_notification_for_duplicated_config));
13171328
}
13181329

0 commit comments

Comments
 (0)