Skip to content

Commit 9a30707

Browse files
committed
Add **Ignore Test** assist
1 parent 10e3a98 commit 9a30707

File tree

6 files changed

+80
-18
lines changed

6 files changed

+80
-18
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use syntax::{ast, AstNode};
2+
3+
use crate::{utils::test_related_attribute, AssistContext, AssistId, AssistKind, Assists};
4+
5+
// Assist: ignore_test
6+
//
7+
// Adds `#[ignore]` attribute to the test.
8+
//
9+
// ```
10+
// <|>#[test]
11+
// fn arithmetics {
12+
// assert_eq!(2 + 2, 5);
13+
// }
14+
// ```
15+
// ->
16+
// ```
17+
// #[test]
18+
// #[ignore]
19+
// fn arithmetics {
20+
// assert_eq!(2 + 2, 5);
21+
// }
22+
// ```
23+
pub(crate) fn ignore_test(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
24+
let attr: ast::Attr = ctx.find_node_at_offset()?;
25+
let func = attr.syntax().parent().and_then(ast::Fn::cast)?;
26+
let attr = test_related_attribute(&func)?;
27+
28+
acc.add(
29+
AssistId("ignore_test", AssistKind::None),
30+
"Ignore this test",
31+
attr.syntax().text_range(),
32+
|builder| builder.insert(attr.syntax().text_range().end(), &format!("\n#[ignore]")),
33+
)
34+
}

crates/assists/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ mod handlers {
141141
mod generate_function;
142142
mod generate_impl;
143143
mod generate_new;
144+
mod ignore_test;
144145
mod infer_function_return_type;
145146
mod inline_local_variable;
146147
mod introduce_named_lifetime;
@@ -189,6 +190,7 @@ mod handlers {
189190
generate_function::generate_function,
190191
generate_impl::generate_impl,
191192
generate_new::generate_new,
193+
ignore_test::ignore_test,
192194
infer_function_return_type::infer_function_return_type,
193195
inline_local_variable::inline_local_variable,
194196
introduce_named_lifetime::introduce_named_lifetime,

crates/assists/src/tests/generated.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,26 @@ impl<T: Clone> Ctx<T> {
473473
)
474474
}
475475

476+
#[test]
477+
fn doctest_ignore_test() {
478+
check_doc_test(
479+
"ignore_test",
480+
r#####"
481+
<|>#[test]
482+
fn arithmetics {
483+
assert_eq!(2 + 2, 5);
484+
}
485+
"#####,
486+
r#####"
487+
#[test]
488+
#[ignore]
489+
fn arithmetics {
490+
assert_eq!(2 + 2, 5);
491+
}
492+
"#####,
493+
)
494+
}
495+
476496
#[test]
477497
fn doctest_infer_function_return_type() {
478498
check_doc_test(

crates/assists/src/utils.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use ide_db::RootDatabase;
99
use itertools::Itertools;
1010
use syntax::{
1111
ast::edit::AstNodeEdit,
12+
ast::AttrsOwner,
1213
ast::NameOwner,
1314
ast::{self, edit, make, ArgListOwner},
1415
AstNode, Direction,
@@ -82,6 +83,23 @@ pub fn extract_trivial_expression(block: &ast::BlockExpr) -> Option<ast::Expr> {
8283
None
8384
}
8485

86+
/// This is a method with a heuristics to support test methods annotated with custom test annotations, such as
87+
/// `#[test_case(...)]`, `#[tokio::test]` and similar.
88+
/// Also a regular `#[test]` annotation is supported.
89+
///
90+
/// It may produce false positives, for example, `#[wasm_bindgen_test]` requires a different command to run the test,
91+
/// but it's better than not to have the runnables for the tests at all.
92+
pub fn test_related_attribute(fn_def: &ast::Fn) -> Option<ast::Attr> {
93+
fn_def.attrs().find_map(|attr| {
94+
let path = attr.path()?;
95+
if path.syntax().text().to_string().contains("test") {
96+
Some(attr)
97+
} else {
98+
None
99+
}
100+
})
101+
}
102+
85103
#[derive(Copy, Clone, PartialEq)]
86104
pub enum DefaultMethods {
87105
Only,

crates/ide/src/fn_references.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
//! This module implements a methods and free functions search in the specified file.
22
//! We have to skip tests, so cannot reuse file_structure module.
33
4+
use assists::utils::test_related_attribute;
45
use hir::Semantics;
56
use ide_db::RootDatabase;
67
use syntax::{ast, ast::NameOwner, AstNode, SyntaxNode};
78

8-
use crate::{runnables::has_test_related_attribute, FileId, FileRange};
9+
use crate::{FileId, FileRange};
910

1011
pub(crate) fn find_all_methods(db: &RootDatabase, file_id: FileId) -> Vec<FileRange> {
1112
let sema = Semantics::new(db);
@@ -15,7 +16,7 @@ pub(crate) fn find_all_methods(db: &RootDatabase, file_id: FileId) -> Vec<FileRa
1516

1617
fn method_range(item: SyntaxNode, file_id: FileId) -> Option<FileRange> {
1718
ast::Fn::cast(item).and_then(|fn_def| {
18-
if has_test_related_attribute(&fn_def) {
19+
if test_related_attribute(&fn_def).is_some() {
1920
None
2021
} else {
2122
fn_def.name().map(|name| FileRange { file_id, range: name.syntax().text_range() })

crates/ide/src/runnables.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::fmt;
22

3+
use assists::utils::test_related_attribute;
34
use cfg::CfgExpr;
45
use hir::{AsAssocItem, Attrs, HirFileId, InFile, Semantics};
56
use ide_db::RootDatabase;
@@ -156,7 +157,7 @@ fn runnable_fn(
156157
None => TestId::Name(name_string),
157158
};
158159

159-
if has_test_related_attribute(&fn_def) {
160+
if test_related_attribute(&fn_def).is_some() {
160161
let attr = TestAttr::from_fn(&fn_def);
161162
RunnableKind::Test { test_id, attr }
162163
} else if fn_def.has_atom_attr("bench") {
@@ -235,20 +236,6 @@ impl TestAttr {
235236
}
236237
}
237238

238-
/// This is a method with a heuristics to support test methods annotated with custom test annotations, such as
239-
/// `#[test_case(...)]`, `#[tokio::test]` and similar.
240-
/// Also a regular `#[test]` annotation is supported.
241-
///
242-
/// It may produce false positives, for example, `#[wasm_bindgen_test]` requires a different command to run the test,
243-
/// but it's better than not to have the runnables for the tests at all.
244-
pub(crate) fn has_test_related_attribute(fn_def: &ast::Fn) -> bool {
245-
fn_def
246-
.attrs()
247-
.filter_map(|attr| attr.path())
248-
.map(|path| path.syntax().to_string().to_lowercase())
249-
.any(|attribute_text| attribute_text.contains("test"))
250-
}
251-
252239
const RUSTDOC_FENCE: &str = "```";
253240
const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] =
254241
&["", "rust", "should_panic", "edition2015", "edition2018"];
@@ -307,7 +294,7 @@ fn has_test_function_or_multiple_test_submodules(module: &ast::Module) -> bool {
307294
for item in item_list.items() {
308295
match item {
309296
ast::Item::Fn(f) => {
310-
if has_test_related_attribute(&f) {
297+
if test_related_attribute(&f).is_some() {
311298
return true;
312299
}
313300
}

0 commit comments

Comments
 (0)