mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Merge #4337
4337: Cleanup assists tests r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
d81bf3772f
39 changed files with 242 additions and 261 deletions
|
@ -1,39 +0,0 @@
|
|||
//! Each assist definition has a special comment, which specifies docs and
|
||||
//! example.
|
||||
//!
|
||||
//! We collect all the example and write the as tests in this module.
|
||||
|
||||
mod generated;
|
||||
|
||||
use ra_db::FileRange;
|
||||
use test_utils::{assert_eq_text, extract_range_or_offset};
|
||||
|
||||
use crate::resolved_assists;
|
||||
|
||||
fn check(assist_id: &str, before: &str, after: &str) {
|
||||
let (selection, before) = extract_range_or_offset(before);
|
||||
let (db, file_id) = crate::helpers::with_single_file(&before);
|
||||
let frange = FileRange { file_id, range: selection.into() };
|
||||
|
||||
let assist = resolved_assists(&db, frange)
|
||||
.into_iter()
|
||||
.find(|assist| assist.label.id.0 == assist_id)
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"\n\nAssist is not applicable: {}\nAvailable assists: {}",
|
||||
assist_id,
|
||||
resolved_assists(&db, frange)
|
||||
.into_iter()
|
||||
.map(|assist| assist.label.id.0)
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)
|
||||
});
|
||||
|
||||
let actual = {
|
||||
let mut actual = before.clone();
|
||||
assist.action.edit.apply(&mut actual);
|
||||
actual
|
||||
};
|
||||
assert_eq_text!(after, &actual);
|
||||
}
|
|
@ -95,7 +95,7 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextSize> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::helpers::{check_assist, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_target};
|
||||
|
||||
#[test]
|
||||
fn add_derive_new() {
|
||||
|
|
|
@ -77,7 +77,7 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option<Assist> {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
|
||||
#[test]
|
||||
fn add_explicit_type_target() {
|
||||
|
|
|
@ -97,7 +97,7 @@ fn existing_from_impl(
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
use test_utils::covers;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -283,7 +283,7 @@ fn next_space_for_fn_in_module(
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::helpers::{check_assist, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_target};
|
||||
|
||||
#[test]
|
||||
fn test_add_impl() {
|
||||
|
|
|
@ -181,7 +181,7 @@ fn add_body(fn_def: ast::FnDef) -> ast::FnDef {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ fn has_new_fn(imp: &ast::ImplDef) -> bool {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ fn opposite_logic_op(kind: ast::BinOp) -> Option<&'static str> {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
|
||||
#[test]
|
||||
fn demorgan_turns_and_into_or() {
|
||||
|
|
|
@ -277,7 +277,7 @@ impl ImportCandidate {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
|
||||
#[test]
|
||||
fn applicable_when_found_an_import() {
|
||||
|
|
|
@ -110,7 +110,7 @@ fn change_vis(ctx: AssistCtx, vis: ast::Visibility) -> Option<Assist> {
|
|||
mod tests {
|
||||
use test_utils::covers;
|
||||
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> O
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
|
||||
use super::fill_match_arms;
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ impl From<BinOp> for FlipAction {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
|
||||
#[test]
|
||||
fn flip_binexpr_target_is_the_op() {
|
||||
|
|
|
@ -39,7 +39,7 @@ pub(crate) fn flip_comma(ctx: AssistCtx) -> Option<Assist> {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::helpers::{check_assist, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_target};
|
||||
|
||||
#[test]
|
||||
fn flip_comma_works_for_function_parameters() {
|
||||
|
|
|
@ -43,7 +43,7 @@ pub(crate) fn flip_trait_bound(ctx: AssistCtx) -> Option<Assist> {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
|
||||
#[test]
|
||||
fn flip_trait_bound_assist_available() {
|
||||
|
|
|
@ -125,7 +125,7 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> {
|
|||
mod tests {
|
||||
use test_utils::covers;
|
||||
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> {
|
|||
mod tests {
|
||||
use test_utils::covers;
|
||||
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ pub(crate) fn invert_if(ctx: AssistCtx) -> Option<Assist> {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
|
||||
#[test]
|
||||
fn invert_if_remove_inequality() {
|
||||
|
|
|
@ -125,7 +125,7 @@ fn first_path(path: &ast::Path) -> ast::Path {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::helpers::check_assist;
|
||||
use crate::tests::check_assist;
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ fn contains_placeholder(a: &ast::MatchArm) -> bool {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::helpers::check_assist;
|
||||
use crate::tests::check_assist;
|
||||
|
||||
#[test]
|
||||
fn move_bounds_to_where_clause_fn() {
|
||||
|
|
|
@ -132,7 +132,7 @@ pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
|
||||
#[test]
|
||||
fn move_guard_to_arm_body_target() {
|
||||
|
|
|
@ -138,7 +138,7 @@ fn count_hashes(s: &str) -> usize {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
|
||||
#[test]
|
||||
fn make_raw_string_target() {
|
||||
|
|
|
@ -90,7 +90,7 @@ fn is_valid_macrocall(macro_call: &ast::MacroCall, macro_name: &str) -> Option<b
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
|
||||
#[test]
|
||||
fn test_remove_dbg() {
|
||||
|
|
|
@ -109,7 +109,7 @@ fn compute_fields_ranks(path: &Path, ctx: &AssistCtx) -> Option<HashMap<String,
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ pub(crate) fn replace_if_let_with_match(ctx: AssistCtx) -> Option<Assist> {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::helpers::{check_assist, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_target};
|
||||
|
||||
#[test]
|
||||
fn test_replace_if_let_with_match_unwraps_simple_expressions() {
|
||||
|
|
|
@ -74,7 +74,7 @@ pub(crate) fn replace_let_with_if_let(ctx: AssistCtx) -> Option<Assist> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::helpers::check_assist;
|
||||
use crate::tests::check_assist;
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ pub(crate) fn replace_unwrap_with_match(ctx: AssistCtx) -> Option<Assist> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::helpers::{check_assist, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_target};
|
||||
|
||||
#[test]
|
||||
fn test_replace_result_unwrap_with_match() {
|
||||
|
|
|
@ -37,7 +37,7 @@ pub(crate) fn split_import(ctx: AssistCtx) -> Option<Assist> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ fn extract_expr(cursor_range: TextRange, block: ast::BlockExpr) -> Option<ast::E
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ macro_rules! eprintln {
|
|||
mod assist_ctx;
|
||||
mod marks;
|
||||
#[cfg(test)]
|
||||
mod doc_tests;
|
||||
mod tests;
|
||||
pub mod utils;
|
||||
pub mod ast_transform;
|
||||
|
||||
|
@ -194,150 +194,3 @@ mod handlers {
|
|||
]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod helpers {
|
||||
use std::sync::Arc;
|
||||
|
||||
use hir::Semantics;
|
||||
use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt};
|
||||
use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase};
|
||||
use test_utils::{add_cursor, assert_eq_text, extract_range_or_offset, RangeOrOffset};
|
||||
|
||||
use crate::{handlers::Handler, AssistCtx, AssistFile};
|
||||
|
||||
pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
|
||||
let (mut db, file_id) = RootDatabase::with_single_file(text);
|
||||
// FIXME: ideally, this should be done by the above `RootDatabase::with_single_file`,
|
||||
// but it looks like this might need specialization? :(
|
||||
db.set_local_roots(Arc::new(vec![db.file_source_root(file_id)]));
|
||||
(db, file_id)
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist(assist: Handler, ra_fixture_before: &str, ra_fixture_after: &str) {
|
||||
check(assist, ra_fixture_before, ExpectedResult::After(ra_fixture_after));
|
||||
}
|
||||
|
||||
// FIXME: instead of having a separate function here, maybe use
|
||||
// `extract_ranges` and mark the target as `<target> </target>` in the
|
||||
// fixuture?
|
||||
pub(crate) fn check_assist_target(assist: Handler, ra_fixture: &str, target: &str) {
|
||||
check(assist, ra_fixture, ExpectedResult::Target(target));
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist_not_applicable(assist: Handler, ra_fixture: &str) {
|
||||
check(assist, ra_fixture, ExpectedResult::NotApplicable);
|
||||
}
|
||||
|
||||
enum ExpectedResult<'a> {
|
||||
NotApplicable,
|
||||
After(&'a str),
|
||||
Target(&'a str),
|
||||
}
|
||||
|
||||
fn check(assist: Handler, before: &str, expected: ExpectedResult) {
|
||||
let (text_without_caret, file_with_caret_id, range_or_offset, db) =
|
||||
if before.contains("//-") {
|
||||
let (mut db, position) = RootDatabase::with_position(before);
|
||||
db.set_local_roots(Arc::new(vec![db.file_source_root(position.file_id)]));
|
||||
(
|
||||
db.file_text(position.file_id).as_ref().to_owned(),
|
||||
position.file_id,
|
||||
RangeOrOffset::Offset(position.offset),
|
||||
db,
|
||||
)
|
||||
} else {
|
||||
let (range_or_offset, text_without_caret) = extract_range_or_offset(before);
|
||||
let (db, file_id) = with_single_file(&text_without_caret);
|
||||
(text_without_caret, file_id, range_or_offset, db)
|
||||
};
|
||||
|
||||
let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() };
|
||||
|
||||
let sema = Semantics::new(&db);
|
||||
let assist_ctx = AssistCtx::new(&sema, frange, true);
|
||||
|
||||
match (assist(assist_ctx), expected) {
|
||||
(Some(assist), ExpectedResult::After(after)) => {
|
||||
let action = assist.0[0].action.clone().unwrap();
|
||||
|
||||
let mut actual = if let AssistFile::TargetFile(file_id) = action.file {
|
||||
db.file_text(file_id).as_ref().to_owned()
|
||||
} else {
|
||||
text_without_caret
|
||||
};
|
||||
action.edit.apply(&mut actual);
|
||||
|
||||
match action.cursor_position {
|
||||
None => {
|
||||
if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset {
|
||||
let off = action
|
||||
.edit
|
||||
.apply_to_offset(before_cursor_pos)
|
||||
.expect("cursor position is affected by the edit");
|
||||
actual = add_cursor(&actual, off)
|
||||
}
|
||||
}
|
||||
Some(off) => actual = add_cursor(&actual, off),
|
||||
};
|
||||
|
||||
assert_eq_text!(after, &actual);
|
||||
}
|
||||
(Some(assist), ExpectedResult::Target(target)) => {
|
||||
let action = assist.0[0].action.clone().unwrap();
|
||||
let range = action.target.expect("expected target on action");
|
||||
assert_eq_text!(&text_without_caret[range], target);
|
||||
}
|
||||
(Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"),
|
||||
(None, ExpectedResult::After(_)) | (None, ExpectedResult::Target(_)) => {
|
||||
panic!("code action is not applicable")
|
||||
}
|
||||
(None, ExpectedResult::NotApplicable) => (),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ra_db::FileRange;
|
||||
use ra_syntax::TextRange;
|
||||
use test_utils::{extract_offset, extract_range};
|
||||
|
||||
use crate::{helpers, resolved_assists};
|
||||
|
||||
#[test]
|
||||
fn assist_order_field_struct() {
|
||||
let before = "struct Foo { <|>bar: u32 }";
|
||||
let (before_cursor_pos, before) = extract_offset(before);
|
||||
let (db, file_id) = helpers::with_single_file(&before);
|
||||
let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) };
|
||||
let assists = resolved_assists(&db, frange);
|
||||
let mut assists = assists.iter();
|
||||
|
||||
assert_eq!(
|
||||
assists.next().expect("expected assist").label.label,
|
||||
"Change visibility to pub(crate)"
|
||||
);
|
||||
assert_eq!(assists.next().expect("expected assist").label.label, "Add `#[derive]`");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assist_order_if_expr() {
|
||||
let before = "
|
||||
pub fn test_some_range(a: int) -> bool {
|
||||
if let 2..6 = <|>5<|> {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}";
|
||||
let (range, before) = extract_range(before);
|
||||
let (db, file_id) = helpers::with_single_file(&before);
|
||||
let frange = FileRange { file_id, range };
|
||||
let assists = resolved_assists(&db, frange);
|
||||
let mut assists = assists.iter();
|
||||
|
||||
assert_eq!(assists.next().expect("expected assist").label.label, "Extract into variable");
|
||||
assert_eq!(assists.next().expect("expected assist").label.label, "Replace with match");
|
||||
}
|
||||
}
|
||||
|
|
167
crates/ra_assists/src/tests.rs
Normal file
167
crates/ra_assists/src/tests.rs
Normal file
|
@ -0,0 +1,167 @@
|
|||
mod generated;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use hir::Semantics;
|
||||
use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt};
|
||||
use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase};
|
||||
use ra_syntax::TextRange;
|
||||
use test_utils::{
|
||||
add_cursor, assert_eq_text, extract_offset, extract_range, extract_range_or_offset,
|
||||
RangeOrOffset,
|
||||
};
|
||||
|
||||
use crate::{handlers::Handler, resolved_assists, AssistCtx, AssistFile};
|
||||
|
||||
pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
|
||||
let (mut db, file_id) = RootDatabase::with_single_file(text);
|
||||
// FIXME: ideally, this should be done by the above `RootDatabase::with_single_file`,
|
||||
// but it looks like this might need specialization? :(
|
||||
db.set_local_roots(Arc::new(vec![db.file_source_root(file_id)]));
|
||||
(db, file_id)
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist(assist: Handler, ra_fixture_before: &str, ra_fixture_after: &str) {
|
||||
check(assist, ra_fixture_before, ExpectedResult::After(ra_fixture_after));
|
||||
}
|
||||
|
||||
// FIXME: instead of having a separate function here, maybe use
|
||||
// `extract_ranges` and mark the target as `<target> </target>` in the
|
||||
// fixuture?
|
||||
pub(crate) fn check_assist_target(assist: Handler, ra_fixture: &str, target: &str) {
|
||||
check(assist, ra_fixture, ExpectedResult::Target(target));
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist_not_applicable(assist: Handler, ra_fixture: &str) {
|
||||
check(assist, ra_fixture, ExpectedResult::NotApplicable);
|
||||
}
|
||||
|
||||
fn check_doc_test(assist_id: &str, before: &str, after: &str) {
|
||||
let (selection, before) = extract_range_or_offset(before);
|
||||
let (db, file_id) = crate::tests::with_single_file(&before);
|
||||
let frange = FileRange { file_id, range: selection.into() };
|
||||
|
||||
let assist = resolved_assists(&db, frange)
|
||||
.into_iter()
|
||||
.find(|assist| assist.label.id.0 == assist_id)
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"\n\nAssist is not applicable: {}\nAvailable assists: {}",
|
||||
assist_id,
|
||||
resolved_assists(&db, frange)
|
||||
.into_iter()
|
||||
.map(|assist| assist.label.id.0)
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)
|
||||
});
|
||||
|
||||
let actual = {
|
||||
let mut actual = before.clone();
|
||||
assist.action.edit.apply(&mut actual);
|
||||
actual
|
||||
};
|
||||
assert_eq_text!(after, &actual);
|
||||
}
|
||||
|
||||
enum ExpectedResult<'a> {
|
||||
NotApplicable,
|
||||
After(&'a str),
|
||||
Target(&'a str),
|
||||
}
|
||||
|
||||
fn check(assist: Handler, before: &str, expected: ExpectedResult) {
|
||||
let (text_without_caret, file_with_caret_id, range_or_offset, db) = if before.contains("//-") {
|
||||
let (mut db, position) = RootDatabase::with_position(before);
|
||||
db.set_local_roots(Arc::new(vec![db.file_source_root(position.file_id)]));
|
||||
(
|
||||
db.file_text(position.file_id).as_ref().to_owned(),
|
||||
position.file_id,
|
||||
RangeOrOffset::Offset(position.offset),
|
||||
db,
|
||||
)
|
||||
} else {
|
||||
let (range_or_offset, text_without_caret) = extract_range_or_offset(before);
|
||||
let (db, file_id) = with_single_file(&text_without_caret);
|
||||
(text_without_caret, file_id, range_or_offset, db)
|
||||
};
|
||||
|
||||
let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() };
|
||||
|
||||
let sema = Semantics::new(&db);
|
||||
let assist_ctx = AssistCtx::new(&sema, frange, true);
|
||||
|
||||
match (assist(assist_ctx), expected) {
|
||||
(Some(assist), ExpectedResult::After(after)) => {
|
||||
let action = assist.0[0].action.clone().unwrap();
|
||||
|
||||
let mut actual = if let AssistFile::TargetFile(file_id) = action.file {
|
||||
db.file_text(file_id).as_ref().to_owned()
|
||||
} else {
|
||||
text_without_caret
|
||||
};
|
||||
action.edit.apply(&mut actual);
|
||||
|
||||
match action.cursor_position {
|
||||
None => {
|
||||
if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset {
|
||||
let off = action
|
||||
.edit
|
||||
.apply_to_offset(before_cursor_pos)
|
||||
.expect("cursor position is affected by the edit");
|
||||
actual = add_cursor(&actual, off)
|
||||
}
|
||||
}
|
||||
Some(off) => actual = add_cursor(&actual, off),
|
||||
};
|
||||
|
||||
assert_eq_text!(after, &actual);
|
||||
}
|
||||
(Some(assist), ExpectedResult::Target(target)) => {
|
||||
let action = assist.0[0].action.clone().unwrap();
|
||||
let range = action.target.expect("expected target on action");
|
||||
assert_eq_text!(&text_without_caret[range], target);
|
||||
}
|
||||
(Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"),
|
||||
(None, ExpectedResult::After(_)) | (None, ExpectedResult::Target(_)) => {
|
||||
panic!("code action is not applicable")
|
||||
}
|
||||
(None, ExpectedResult::NotApplicable) => (),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assist_order_field_struct() {
|
||||
let before = "struct Foo { <|>bar: u32 }";
|
||||
let (before_cursor_pos, before) = extract_offset(before);
|
||||
let (db, file_id) = with_single_file(&before);
|
||||
let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) };
|
||||
let assists = resolved_assists(&db, frange);
|
||||
let mut assists = assists.iter();
|
||||
|
||||
assert_eq!(
|
||||
assists.next().expect("expected assist").label.label,
|
||||
"Change visibility to pub(crate)"
|
||||
);
|
||||
assert_eq!(assists.next().expect("expected assist").label.label, "Add `#[derive]`");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assist_order_if_expr() {
|
||||
let before = "
|
||||
pub fn test_some_range(a: int) -> bool {
|
||||
if let 2..6 = <|>5<|> {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}";
|
||||
let (range, before) = extract_range(before);
|
||||
let (db, file_id) = with_single_file(&before);
|
||||
let frange = FileRange { file_id, range };
|
||||
let assists = resolved_assists(&db, frange);
|
||||
let mut assists = assists.iter();
|
||||
|
||||
assert_eq!(assists.next().expect("expected assist").label.label, "Extract into variable");
|
||||
assert_eq!(assists.next().expect("expected assist").label.label, "Replace with match");
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
//! Generated file, do not edit by hand, see `xtask/src/codegen`
|
||||
|
||||
use super::check;
|
||||
use super::check_doc_test;
|
||||
|
||||
#[test]
|
||||
fn doctest_add_custom_impl() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"add_custom_impl",
|
||||
r#####"
|
||||
#[derive(Deb<|>ug, Display)]
|
||||
|
@ -23,7 +23,7 @@ impl Debug for S {
|
|||
|
||||
#[test]
|
||||
fn doctest_add_derive() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"add_derive",
|
||||
r#####"
|
||||
struct Point {
|
||||
|
@ -43,7 +43,7 @@ struct Point {
|
|||
|
||||
#[test]
|
||||
fn doctest_add_explicit_type() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"add_explicit_type",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -60,7 +60,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_add_function() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"add_function",
|
||||
r#####"
|
||||
struct Baz;
|
||||
|
@ -87,7 +87,7 @@ fn bar(arg: &str, baz: Baz) {
|
|||
|
||||
#[test]
|
||||
fn doctest_add_hash() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"add_hash",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -104,7 +104,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_add_impl() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"add_impl",
|
||||
r#####"
|
||||
struct Ctx<T: Clone> {
|
||||
|
@ -125,7 +125,7 @@ impl<T: Clone> Ctx<T> {
|
|||
|
||||
#[test]
|
||||
fn doctest_add_impl_default_members() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"add_impl_default_members",
|
||||
r#####"
|
||||
trait Trait {
|
||||
|
@ -159,7 +159,7 @@ impl Trait for () {
|
|||
|
||||
#[test]
|
||||
fn doctest_add_impl_missing_members() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"add_impl_missing_members",
|
||||
r#####"
|
||||
trait Trait<T> {
|
||||
|
@ -191,7 +191,7 @@ impl Trait<u32> for () {
|
|||
|
||||
#[test]
|
||||
fn doctest_add_new() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"add_new",
|
||||
r#####"
|
||||
struct Ctx<T: Clone> {
|
||||
|
@ -213,7 +213,7 @@ impl<T: Clone> Ctx<T> {
|
|||
|
||||
#[test]
|
||||
fn doctest_apply_demorgan() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"apply_demorgan",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -230,7 +230,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_auto_import() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"auto_import",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -251,7 +251,7 @@ pub mod std { pub mod collections { pub struct HashMap { } } }
|
|||
|
||||
#[test]
|
||||
fn doctest_change_visibility() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"change_visibility",
|
||||
r#####"
|
||||
<|>fn frobnicate() {}
|
||||
|
@ -264,7 +264,7 @@ pub(crate) fn frobnicate() {}
|
|||
|
||||
#[test]
|
||||
fn doctest_convert_to_guarded_return() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"convert_to_guarded_return",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -288,7 +288,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_fill_match_arms() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"fill_match_arms",
|
||||
r#####"
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
@ -314,7 +314,7 @@ fn handle(action: Action) {
|
|||
|
||||
#[test]
|
||||
fn doctest_flip_binexpr() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"flip_binexpr",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -331,7 +331,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_flip_comma() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"flip_comma",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -348,7 +348,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_flip_trait_bound() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"flip_trait_bound",
|
||||
r#####"
|
||||
fn foo<T: Clone +<|> Copy>() { }
|
||||
|
@ -361,7 +361,7 @@ fn foo<T: Copy + Clone>() { }
|
|||
|
||||
#[test]
|
||||
fn doctest_inline_local_variable() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"inline_local_variable",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -379,7 +379,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_introduce_variable() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"introduce_variable",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -397,7 +397,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_invert_if() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"invert_if",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -414,7 +414,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_make_raw_string() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"make_raw_string",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -431,7 +431,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_make_usual_string() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"make_usual_string",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -448,7 +448,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_merge_imports() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"merge_imports",
|
||||
r#####"
|
||||
use std::<|>fmt::Formatter;
|
||||
|
@ -462,7 +462,7 @@ use std::{fmt::Formatter, io};
|
|||
|
||||
#[test]
|
||||
fn doctest_merge_match_arms() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"merge_match_arms",
|
||||
r#####"
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
@ -488,7 +488,7 @@ fn handle(action: Action) {
|
|||
|
||||
#[test]
|
||||
fn doctest_move_arm_cond_to_match_guard() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"move_arm_cond_to_match_guard",
|
||||
r#####"
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
@ -515,7 +515,7 @@ fn handle(action: Action) {
|
|||
|
||||
#[test]
|
||||
fn doctest_move_bounds_to_where_clause() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"move_bounds_to_where_clause",
|
||||
r#####"
|
||||
fn apply<T, U, <|>F: FnOnce(T) -> U>(f: F, x: T) -> U {
|
||||
|
@ -532,7 +532,7 @@ fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U {
|
|||
|
||||
#[test]
|
||||
fn doctest_move_guard_to_arm_body() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"move_guard_to_arm_body",
|
||||
r#####"
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
@ -559,7 +559,7 @@ fn handle(action: Action) {
|
|||
|
||||
#[test]
|
||||
fn doctest_remove_dbg() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"remove_dbg",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -576,7 +576,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_remove_hash() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"remove_hash",
|
||||
r#####"
|
||||
fn main() {
|
||||
|
@ -593,7 +593,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_remove_mut() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"remove_mut",
|
||||
r#####"
|
||||
impl Walrus {
|
||||
|
@ -610,7 +610,7 @@ impl Walrus {
|
|||
|
||||
#[test]
|
||||
fn doctest_reorder_fields() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"reorder_fields",
|
||||
r#####"
|
||||
struct Foo {foo: i32, bar: i32};
|
||||
|
@ -625,7 +625,7 @@ const test: Foo = Foo {foo: 1, bar: 0}
|
|||
|
||||
#[test]
|
||||
fn doctest_replace_if_let_with_match() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"replace_if_let_with_match",
|
||||
r#####"
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
@ -653,7 +653,7 @@ fn handle(action: Action) {
|
|||
|
||||
#[test]
|
||||
fn doctest_replace_let_with_if_let() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"replace_let_with_if_let",
|
||||
r#####"
|
||||
enum Option<T> { Some(T), None }
|
||||
|
@ -679,7 +679,7 @@ fn compute() -> Option<i32> { None }
|
|||
|
||||
#[test]
|
||||
fn doctest_replace_qualified_name_with_use() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"replace_qualified_name_with_use",
|
||||
r#####"
|
||||
fn process(map: std::collections::<|>HashMap<String, String>) {}
|
||||
|
@ -694,7 +694,7 @@ fn process(map: HashMap<String, String>) {}
|
|||
|
||||
#[test]
|
||||
fn doctest_replace_unwrap_with_match() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"replace_unwrap_with_match",
|
||||
r#####"
|
||||
enum Result<T, E> { Ok(T), Err(E) }
|
||||
|
@ -718,7 +718,7 @@ fn main() {
|
|||
|
||||
#[test]
|
||||
fn doctest_split_import() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"split_import",
|
||||
r#####"
|
||||
use std::<|>collections::HashMap;
|
||||
|
@ -731,7 +731,7 @@ use std::{collections::HashMap};
|
|||
|
||||
#[test]
|
||||
fn doctest_unwrap_block() {
|
||||
check(
|
||||
check_doc_test(
|
||||
"unwrap_block",
|
||||
r#####"
|
||||
fn foo() {
|
|
@ -27,7 +27,7 @@ const AST_NODES: &str = "crates/ra_syntax/src/ast/generated/nodes.rs";
|
|||
const AST_TOKENS: &str = "crates/ra_syntax/src/ast/generated/tokens.rs";
|
||||
|
||||
const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers";
|
||||
const ASSISTS_TESTS: &str = "crates/ra_assists/src/doc_tests/generated.rs";
|
||||
const ASSISTS_TESTS: &str = "crates/ra_assists/src/tests/generated.rs";
|
||||
const ASSISTS_DOCS: &str = "docs/user/assists.md";
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
|
|
|
@ -101,14 +101,14 @@ fn collect_assists() -> Result<Vec<Assist>> {
|
|||
}
|
||||
|
||||
fn generate_tests(assists: &[Assist], mode: Mode) -> Result<()> {
|
||||
let mut buf = String::from("use super::check;\n");
|
||||
let mut buf = String::from("use super::check_doc_test;\n");
|
||||
|
||||
for assist in assists.iter() {
|
||||
let test = format!(
|
||||
r######"
|
||||
#[test]
|
||||
fn doctest_{}() {{
|
||||
check(
|
||||
check_doc_test(
|
||||
"{}",
|
||||
r#####"
|
||||
{}"#####, r#####"
|
||||
|
|
|
@ -24,7 +24,7 @@ fn check_todo(path: &Path, text: &str) {
|
|||
// This file itself is whitelisted since this test itself contains matches.
|
||||
"tests/cli.rs",
|
||||
// Some of our assists generate `todo!()` so those files are whitelisted.
|
||||
"doc_tests/generated.rs",
|
||||
"tests/generated.rs",
|
||||
"handlers/add_missing_impl_members.rs",
|
||||
"handlers/add_function.rs",
|
||||
// To support generating `todo!()` in assists, we have `expr_todo()` in ast::make.
|
||||
|
|
Loading…
Reference in a new issue