1 use syntax::{
2 ast::{self, HasAttrs},
3 AstNode, AstToken,
4 };
5
6 use crate::{utils::test_related_attribute, AssistContext, AssistId, AssistKind, Assists};
7
8 // Assist: toggle_ignore
9 //
10 // Adds `#[ignore]` attribute to the test.
11 //
12 // ```
13 // $0#[test]
14 // fn arithmetics {
15 // assert_eq!(2 + 2, 5);
16 // }
17 // ```
18 // ->
19 // ```
20 // #[test]
21 // #[ignore]
22 // fn arithmetics {
23 // assert_eq!(2 + 2, 5);
24 // }
25 // ```
toggle_ignore(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()>26 pub(crate) fn toggle_ignore(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
27 let attr: ast::Attr = ctx.find_node_at_offset()?;
28 let func = attr.syntax().parent().and_then(ast::Fn::cast)?;
29 let attr = test_related_attribute(&func)?;
30
31 match has_ignore_attribute(&func) {
32 None => acc.add(
33 AssistId("toggle_ignore", AssistKind::None),
34 "Ignore this test",
35 attr.syntax().text_range(),
36 |builder| builder.insert(attr.syntax().text_range().end(), "\n#[ignore]"),
37 ),
38 Some(ignore_attr) => acc.add(
39 AssistId("toggle_ignore", AssistKind::None),
40 "Re-enable this test",
41 ignore_attr.syntax().text_range(),
42 |builder| {
43 builder.delete(ignore_attr.syntax().text_range());
44 let whitespace = ignore_attr
45 .syntax()
46 .next_sibling_or_token()
47 .and_then(|x| x.into_token())
48 .and_then(ast::Whitespace::cast);
49 if let Some(whitespace) = whitespace {
50 builder.delete(whitespace.syntax().text_range());
51 }
52 },
53 ),
54 }
55 }
56
has_ignore_attribute(fn_def: &ast::Fn) -> Option<ast::Attr>57 fn has_ignore_attribute(fn_def: &ast::Fn) -> Option<ast::Attr> {
58 fn_def.attrs().find(|attr| attr.path().map(|it| it.syntax().text() == "ignore") == Some(true))
59 }
60
61 #[cfg(test)]
62 mod tests {
63 use crate::tests::check_assist;
64
65 use super::*;
66
67 #[test]
test_base_case()68 fn test_base_case() {
69 check_assist(
70 toggle_ignore,
71 r#"
72 #[test$0]
73 fn test() {}
74 "#,
75 r#"
76 #[test]
77 #[ignore]
78 fn test() {}
79 "#,
80 )
81 }
82
83 #[test]
test_unignore()84 fn test_unignore() {
85 check_assist(
86 toggle_ignore,
87 r#"
88 #[test$0]
89 #[ignore]
90 fn test() {}
91 "#,
92 r#"
93 #[test]
94 fn test() {}
95 "#,
96 )
97 }
98 }
99