Better testing infra for ratoml

This commit is contained in:
Ali Bektas 2024-09-01 22:07:47 +02:00
parent 08c7bbc2db
commit 31ed8c9361
5 changed files with 228 additions and 103 deletions

View file

@ -75,6 +75,8 @@ config_data! {
/// How many worker threads to handle priming caches. The default `0` means to pick automatically. /// How many worker threads to handle priming caches. The default `0` means to pick automatically.
cachePriming_numThreads: NumThreads = NumThreads::Physical, cachePriming_numThreads: NumThreads = NumThreads::Physical,
/// Custom completion snippets.
completion_snippets_custom: FxHashMap<String, SnippetDef> = Config::completion_snippets_default(),
/// These directories will be ignored by rust-analyzer. They are /// These directories will be ignored by rust-analyzer. They are
@ -438,48 +440,6 @@ config_data! {
completion_postfix_enable: bool = true, completion_postfix_enable: bool = true,
/// Enables completions of private items and fields that are defined in the current workspace even if they are not visible at the current position. /// Enables completions of private items and fields that are defined in the current workspace even if they are not visible at the current position.
completion_privateEditable_enable: bool = false, completion_privateEditable_enable: bool = false,
/// Custom completion snippets.
completion_snippets_custom: FxHashMap<String, SnippetDef> = serde_json::from_str(r#"{
"Arc::new": {
"postfix": "arc",
"body": "Arc::new(${receiver})",
"requires": "std::sync::Arc",
"description": "Put the expression into an `Arc`",
"scope": "expr"
},
"Rc::new": {
"postfix": "rc",
"body": "Rc::new(${receiver})",
"requires": "std::rc::Rc",
"description": "Put the expression into an `Rc`",
"scope": "expr"
},
"Box::pin": {
"postfix": "pinbox",
"body": "Box::pin(${receiver})",
"requires": "std::boxed::Box",
"description": "Put the expression into a pinned `Box`",
"scope": "expr"
},
"Ok": {
"postfix": "ok",
"body": "Ok(${receiver})",
"description": "Wrap the expression in a `Result::Ok`",
"scope": "expr"
},
"Err": {
"postfix": "err",
"body": "Err(${receiver})",
"description": "Wrap the expression in a `Result::Err`",
"scope": "expr"
},
"Some": {
"postfix": "some",
"body": "Some(${receiver})",
"description": "Wrap the expression in an `Option::Some`",
"scope": "expr"
}
}"#).unwrap(),
/// Whether to enable term search based snippets like `Some(foo.bar().baz())`. /// Whether to enable term search based snippets like `Some(foo.bar().baz())`.
completion_termSearch_enable: bool = false, completion_termSearch_enable: bool = false,
/// Term search fuel in "units of work" for autocompletion (Defaults to 1000). /// Term search fuel in "units of work" for autocompletion (Defaults to 1000).
@ -889,7 +849,7 @@ impl Config {
// IMPORTANT : This holds as long as ` completion_snippets_custom` is declared `client`. // IMPORTANT : This holds as long as ` completion_snippets_custom` is declared `client`.
config.snippets.clear(); config.snippets.clear();
let snips = self.completion_snippets_custom(None).to_owned(); let snips = self.completion_snippets_custom().to_owned();
for (name, def) in snips.iter() { for (name, def) in snips.iter() {
if def.prefix.is_empty() && def.postfix.is_empty() { if def.prefix.is_empty() && def.postfix.is_empty() {
@ -1266,7 +1226,7 @@ pub struct NotificationsConfig {
pub cargo_toml_not_found: bool, pub cargo_toml_not_found: bool,
} }
#[derive(Debug, Clone)] #[derive(Deserialize, Serialize, Debug, Clone)]
pub enum RustfmtConfig { pub enum RustfmtConfig {
Rustfmt { extra_args: Vec<String>, enable_range_formatting: bool }, Rustfmt { extra_args: Vec<String>, enable_range_formatting: bool },
CustomCommand { command: String, args: Vec<String> }, CustomCommand { command: String, args: Vec<String> },
@ -1897,6 +1857,53 @@ impl Config {
} }
} }
pub(crate) fn completion_snippets_default() -> FxHashMap<String, SnippetDef> {
serde_json::from_str(
r#"{
"Arc::new": {
"postfix": "arc",
"body": "Arc::new(${receiver})",
"requires": "std::sync::Arc",
"description": "Put the expression into an `Arc`",
"scope": "expr"
},
"Rc::new": {
"postfix": "rc",
"body": "Rc::new(${receiver})",
"requires": "std::rc::Rc",
"description": "Put the expression into an `Rc`",
"scope": "expr"
},
"Box::pin": {
"postfix": "pinbox",
"body": "Box::pin(${receiver})",
"requires": "std::boxed::Box",
"description": "Put the expression into a pinned `Box`",
"scope": "expr"
},
"Ok": {
"postfix": "ok",
"body": "Ok(${receiver})",
"description": "Wrap the expression in a `Result::Ok`",
"scope": "expr"
},
"Err": {
"postfix": "err",
"body": "Err(${receiver})",
"description": "Wrap the expression in a `Result::Err`",
"scope": "expr"
},
"Some": {
"postfix": "some",
"body": "Some(${receiver})",
"description": "Wrap the expression in an `Option::Some`",
"scope": "expr"
}
}"#,
)
.unwrap()
}
pub fn rustfmt(&self, source_root_id: Option<SourceRootId>) -> RustfmtConfig { pub fn rustfmt(&self, source_root_id: Option<SourceRootId>) -> RustfmtConfig {
match &self.rustfmt_overrideCommand(source_root_id) { match &self.rustfmt_overrideCommand(source_root_id) {
Some(args) if !args.is_empty() => { Some(args) if !args.is_empty() => {

View file

@ -40,7 +40,10 @@ use crate::{
hack_recover_crate_name, hack_recover_crate_name,
line_index::LineEndings, line_index::LineEndings,
lsp::{ lsp::{
ext::InternalTestingFetchConfigParams, ext::{
InternalTestingFetchConfigOption, InternalTestingFetchConfigParams,
InternalTestingFetchConfigResponse,
},
from_proto, to_proto, from_proto, to_proto,
utils::{all_edits_are_disjoint, invalid_params_error}, utils::{all_edits_are_disjoint, invalid_params_error},
LspError, LspError,
@ -2292,7 +2295,7 @@ pub(crate) fn fetch_dependency_list(
pub(crate) fn internal_testing_fetch_config( pub(crate) fn internal_testing_fetch_config(
state: GlobalStateSnapshot, state: GlobalStateSnapshot,
params: InternalTestingFetchConfigParams, params: InternalTestingFetchConfigParams,
) -> anyhow::Result<serde_json::Value> { ) -> anyhow::Result<Option<InternalTestingFetchConfigResponse>> {
let source_root = params let source_root = params
.text_document .text_document
.map(|it| { .map(|it| {
@ -2302,15 +2305,18 @@ pub(crate) fn internal_testing_fetch_config(
.map_err(anyhow::Error::from) .map_err(anyhow::Error::from)
}) })
.transpose()?; .transpose()?;
serde_json::to_value(match &*params.config { Ok(Some(match params.config {
"local" => state.config.assist(source_root).assist_emit_must_use, InternalTestingFetchConfigOption::AssistEmitMustUse => {
"workspace" => matches!( InternalTestingFetchConfigResponse::AssistEmitMustUse(
state.config.rustfmt(source_root), state.config.assist(source_root).assist_emit_must_use,
RustfmtConfig::Rustfmt { enable_range_formatting: true, .. } )
), }
_ => return Err(anyhow::anyhow!("Unknown test config key: {}", params.config)), InternalTestingFetchConfigOption::CheckWorkspace => {
}) InternalTestingFetchConfigResponse::CheckWorkspace(
.map_err(Into::into) state.config.flycheck_workspace(source_root),
)
}
}))
} }
/// Searches for the directory of a Rust crate given this crate's root file path. /// Searches for the directory of a Rust crate given this crate's root file path.

View file

@ -16,9 +16,22 @@ use serde::{Deserialize, Serialize};
pub enum InternalTestingFetchConfig {} pub enum InternalTestingFetchConfig {}
#[derive(Deserialize, Serialize, Debug)]
pub enum InternalTestingFetchConfigOption {
AssistEmitMustUse,
CheckWorkspace,
}
#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)]
pub enum InternalTestingFetchConfigResponse {
AssistEmitMustUse(bool),
CheckWorkspace(bool),
}
impl Request for InternalTestingFetchConfig { impl Request for InternalTestingFetchConfig {
type Params = InternalTestingFetchConfigParams; type Params = InternalTestingFetchConfigParams;
type Result = serde_json::Value; // Option is solely to circumvent Default bound.
type Result = Option<InternalTestingFetchConfigResponse>;
const METHOD: &'static str = "rust-analyzer-internal/internalTestingFetchConfig"; const METHOD: &'static str = "rust-analyzer-internal/internalTestingFetchConfig";
} }
@ -26,7 +39,7 @@ impl Request for InternalTestingFetchConfig {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct InternalTestingFetchConfigParams { pub struct InternalTestingFetchConfigParams {
pub text_document: Option<TextDocumentIdentifier>, pub text_document: Option<TextDocumentIdentifier>,
pub config: String, pub config: InternalTestingFetchConfigOption,
} }
pub enum AnalyzerStatus {} pub enum AnalyzerStatus {}

View file

@ -9,18 +9,13 @@ use lsp_types::{
use paths::Utf8PathBuf; use paths::Utf8PathBuf;
use rust_analyzer::config::Config; use rust_analyzer::config::Config;
use rust_analyzer::lsp::ext::{InternalTestingFetchConfig, InternalTestingFetchConfigParams}; use rust_analyzer::lsp::ext::{
InternalTestingFetchConfig, InternalTestingFetchConfigOption, InternalTestingFetchConfigParams,
InternalTestingFetchConfigResponse,
};
use serde_json::json; use serde_json::json;
use test_utils::skip_slow_tests; use test_utils::skip_slow_tests;
enum QueryType {
Local,
/// A query whose config key is a part of the global configs, so that
/// testing for changes to this config means testing if global changes
/// take affect.
Workspace,
}
struct RatomlTest { struct RatomlTest {
urls: Vec<Url>, urls: Vec<Url>,
server: Server, server: Server,
@ -158,20 +153,24 @@ impl RatomlTest {
}); });
} }
fn query(&self, query: QueryType, source_file_idx: usize) -> bool { fn query(
let config = match query { &self,
QueryType::Local => "local".to_owned(), query: InternalTestingFetchConfigOption,
QueryType::Workspace => "workspace".to_owned(), source_file_idx: usize,
}; expected: InternalTestingFetchConfigResponse,
) {
let res = self.server.send_request::<InternalTestingFetchConfig>( let res = self.server.send_request::<InternalTestingFetchConfig>(
InternalTestingFetchConfigParams { InternalTestingFetchConfigParams {
text_document: Some(TextDocumentIdentifier { text_document: Some(TextDocumentIdentifier {
uri: self.urls[source_file_idx].clone(), uri: self.urls[source_file_idx].clone(),
}), }),
config, config: query,
}, },
); );
res.as_bool().unwrap() assert_eq!(
serde_json::from_value::<InternalTestingFetchConfigResponse>(res).unwrap(),
expected
)
} }
} }
@ -206,7 +205,11 @@ enum Value {
})), })),
); );
assert!(server.query(QueryType::Local, 1)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
1,
InternalTestingFetchConfigResponse::AssistEmitMustUse(true),
);
} }
/// Checks if client config can be modified. /// Checks if client config can be modified.
@ -311,7 +314,11 @@ enum Value {
None, None,
); );
assert!(server.query(QueryType::Local, 2)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
2,
InternalTestingFetchConfigResponse::AssistEmitMustUse(true),
);
} }
#[test] #[test]
@ -341,12 +348,20 @@ enum Value {
None, None,
); );
assert!(!server.query(QueryType::Local, 1)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
1,
InternalTestingFetchConfigResponse::AssistEmitMustUse(false),
);
server.create( server.create(
"//- /$$CONFIG_DIR$$/rust-analyzer/rust-analyzer.toml", "//- /$$CONFIG_DIR$$/rust-analyzer/rust-analyzer.toml",
RatomlTest::EMIT_MUST_USE.to_owned(), RatomlTest::EMIT_MUST_USE.to_owned(),
); );
assert!(server.query(QueryType::Local, 1)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
1,
InternalTestingFetchConfigResponse::AssistEmitMustUse(true),
);
} }
#[test] #[test]
@ -378,9 +393,17 @@ assist.emitMustUse = true"#,
None, None,
); );
assert!(server.query(QueryType::Local, 1)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
1,
InternalTestingFetchConfigResponse::AssistEmitMustUse(true),
);
server.edit(2, String::new()); server.edit(2, String::new());
assert!(!server.query(QueryType::Local, 1)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
1,
InternalTestingFetchConfigResponse::AssistEmitMustUse(false),
);
} }
#[test] #[test]
@ -412,9 +435,17 @@ assist.emitMustUse = true"#,
None, None,
); );
assert!(server.query(QueryType::Local, 1)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
1,
InternalTestingFetchConfigResponse::AssistEmitMustUse(true),
);
server.delete(2); server.delete(2);
assert!(!server.query(QueryType::Local, 1)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
1,
InternalTestingFetchConfigResponse::AssistEmitMustUse(false),
);
} }
#[test] #[test]
@ -461,7 +492,11 @@ pub fn add(left: usize, right: usize) -> usize {
None, None,
); );
assert!(server.query(QueryType::Local, 3)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
3,
InternalTestingFetchConfigResponse::AssistEmitMustUse(true),
);
} }
#[test] #[test]
@ -508,9 +543,17 @@ pub fn add(left: usize, right: usize) -> usize {
None, None,
); );
assert!(!server.query(QueryType::Local, 3)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
3,
InternalTestingFetchConfigResponse::AssistEmitMustUse(false),
);
server.edit(1, "assist.emitMustUse = true".to_owned()); server.edit(1, "assist.emitMustUse = true".to_owned());
assert!(server.query(QueryType::Local, 3)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
3,
InternalTestingFetchConfigResponse::AssistEmitMustUse(true),
);
} }
#[test] #[test]
@ -557,9 +600,17 @@ pub fn add(left: usize, right: usize) -> usize {
None, None,
); );
assert!(server.query(QueryType::Local, 3)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
3,
InternalTestingFetchConfigResponse::AssistEmitMustUse(true),
);
server.delete(1); server.delete(1);
assert!(!server.query(QueryType::Local, 3)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
3,
InternalTestingFetchConfigResponse::AssistEmitMustUse(false),
);
} }
#[test] #[test]
@ -606,9 +657,17 @@ pub fn add(left: usize, right: usize) -> usize {
None, None,
); );
assert!(server.query(QueryType::Local, 3)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
3,
InternalTestingFetchConfigResponse::AssistEmitMustUse(true),
);
server.create("//- /p1/p2/rust-analyzer.toml", RatomlTest::EMIT_MUST_NOT_USE.to_owned()); server.create("//- /p1/p2/rust-analyzer.toml", RatomlTest::EMIT_MUST_NOT_USE.to_owned());
assert!(!server.query(QueryType::Local, 3)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
3,
InternalTestingFetchConfigResponse::AssistEmitMustUse(false),
);
} }
#[test] #[test]
@ -656,9 +715,17 @@ pub fn add(left: usize, right: usize) -> usize {
None, None,
); );
assert!(server.query(QueryType::Local, 3)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
3,
InternalTestingFetchConfigResponse::AssistEmitMustUse(true),
);
server.delete(1); server.delete(1);
assert!(!server.query(QueryType::Local, 3)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
3,
InternalTestingFetchConfigResponse::AssistEmitMustUse(false),
);
} }
#[test] #[test]
@ -705,8 +772,16 @@ enum Value {
None, None,
); );
assert!(server.query(QueryType::Local, 3)); server.query(
assert!(server.query(QueryType::Local, 4)); InternalTestingFetchConfigOption::AssistEmitMustUse,
3,
InternalTestingFetchConfigResponse::AssistEmitMustUse(true),
);
server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
4,
InternalTestingFetchConfigResponse::AssistEmitMustUse(true),
);
} }
#[test] #[test]
@ -744,7 +819,11 @@ fn ratoml_multiple_ratoml_in_single_source_root() {
None, None,
); );
assert!(server.query(QueryType::Local, 3)); server.query(
InternalTestingFetchConfigOption::AssistEmitMustUse,
3,
InternalTestingFetchConfigResponse::AssistEmitMustUse(true),
);
} }
/// If a root is non-local, so we cannot find what its parent is /// If a root is non-local, so we cannot find what its parent is
@ -836,7 +915,7 @@ edition = "2021"
"#, "#,
r#" r#"
//- /p1/rust-analyzer.toml //- /p1/rust-analyzer.toml
rustfmt.rangeFormatting.enable = true check.workspace = false
"#, "#,
r#" r#"
//- /p1/src/lib.rs //- /p1/src/lib.rs
@ -848,7 +927,11 @@ fn main() {
None, None,
); );
assert!(server.query(QueryType::Workspace, 2)); server.query(
InternalTestingFetchConfigOption::CheckWorkspace,
2,
InternalTestingFetchConfigResponse::CheckWorkspace(false),
)
} }
#[test] #[test]
@ -868,7 +951,7 @@ edition = "2021"
"#, "#,
r#" r#"
//- /p1/rust-analyzer.toml //- /p1/rust-analyzer.toml
rustfmt.rangeFormatting.enable = true check.workspace = false
"#, "#,
r#" r#"
//- /p1/src/lib.rs //- /p1/src/lib.rs
@ -880,9 +963,17 @@ fn main() {
None, None,
); );
assert!(server.query(QueryType::Workspace, 2)); server.query(
server.edit(1, "rustfmt.rangeFormatting.enable = false".to_owned()); InternalTestingFetchConfigOption::CheckWorkspace,
assert!(!server.query(QueryType::Workspace, 2)); 2,
InternalTestingFetchConfigResponse::CheckWorkspace(false),
);
server.edit(1, "check.workspace = true".to_owned());
server.query(
InternalTestingFetchConfigOption::CheckWorkspace,
2,
InternalTestingFetchConfigResponse::CheckWorkspace(true),
);
} }
#[test] #[test]
@ -902,7 +993,7 @@ edition = "2021"
"#, "#,
r#" r#"
//- /p1/rust-analyzer.toml //- /p1/rust-analyzer.toml
rustfmt.rangeFormatting.enable = true check.workspace = false
"#, "#,
r#" r#"
//- /p1/src/lib.rs //- /p1/src/lib.rs
@ -914,7 +1005,15 @@ fn main() {
None, None,
); );
assert!(server.query(QueryType::Workspace, 2)); server.query(
InternalTestingFetchConfigOption::CheckWorkspace,
2,
InternalTestingFetchConfigResponse::CheckWorkspace(false),
);
server.delete(1); server.delete(1);
assert!(!server.query(QueryType::Workspace, 2)); server.query(
InternalTestingFetchConfigOption::CheckWorkspace,
2,
InternalTestingFetchConfigResponse::CheckWorkspace(true),
);
} }

View file

@ -1,5 +1,5 @@
<!--- <!---
lsp/ext.rs hash: c6e83d3d08d993de lsp/ext.rs hash: 6292ee8d88d4c9ec
If you need to change the above hash to make the test pass, please check if you If you need to change the above hash to make the test pass, please check if you
need to adjust this doc as well and ping this issue: need to adjust this doc as well and ping this issue: