]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs
Auto merge of #103913 - Neutron3529:patch-1, r=thomcc
[rust.git] / src / tools / rust-analyzer / crates / ide-assists / src / handlers / toggle_ignore.rs
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 // ```
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
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]
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]
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 }