]> git.lizzy.rs Git - rust.git/commitdiff
Add **Ignore Test** assist
authorAleksey Kladov <aleksey.kladov@gmail.com>
Tue, 17 Nov 2020 13:22:04 +0000 (14:22 +0100)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Tue, 17 Nov 2020 13:22:04 +0000 (14:22 +0100)
crates/assists/src/handlers/ignore_test.rs [new file with mode: 0644]
crates/assists/src/lib.rs
crates/assists/src/tests/generated.rs
crates/assists/src/utils.rs
crates/ide/src/fn_references.rs
crates/ide/src/runnables.rs

diff --git a/crates/assists/src/handlers/ignore_test.rs b/crates/assists/src/handlers/ignore_test.rs
new file mode 100644 (file)
index 0000000..d233918
--- /dev/null
@@ -0,0 +1,34 @@
+use syntax::{ast, AstNode};
+
+use crate::{utils::test_related_attribute, AssistContext, AssistId, AssistKind, Assists};
+
+// Assist: ignore_test
+//
+// Adds `#[ignore]` attribute to the test.
+//
+// ```
+// <|>#[test]
+// fn arithmetics {
+//     assert_eq!(2 + 2, 5);
+// }
+// ```
+// ->
+// ```
+// #[test]
+// #[ignore]
+// fn arithmetics {
+//     assert_eq!(2 + 2, 5);
+// }
+// ```
+pub(crate) fn ignore_test(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
+    let attr: ast::Attr = ctx.find_node_at_offset()?;
+    let func = attr.syntax().parent().and_then(ast::Fn::cast)?;
+    let attr = test_related_attribute(&func)?;
+
+    acc.add(
+        AssistId("ignore_test", AssistKind::None),
+        "Ignore this test",
+        attr.syntax().text_range(),
+        |builder| builder.insert(attr.syntax().text_range().end(), &format!("\n#[ignore]")),
+    )
+}
index e8d81b33d76e833428d9c2215596192142466180..17e9312db2b9a34bb1627609d89696e1bf022975 100644 (file)
@@ -141,6 +141,7 @@ mod handlers {
     mod generate_function;
     mod generate_impl;
     mod generate_new;
+    mod ignore_test;
     mod infer_function_return_type;
     mod inline_local_variable;
     mod introduce_named_lifetime;
@@ -189,6 +190,7 @@ pub(crate) fn all() -> &'static [Handler] {
             generate_function::generate_function,
             generate_impl::generate_impl,
             generate_new::generate_new,
+            ignore_test::ignore_test,
             infer_function_return_type::infer_function_return_type,
             inline_local_variable::inline_local_variable,
             introduce_named_lifetime::introduce_named_lifetime,
index dbf4f21aa55e7da160b29e81ec3a4b44f6b0c036..5a9d1a01b7876a780dc9d8b24bb56ec6ffe200b4 100644 (file)
@@ -473,6 +473,26 @@ fn $0new(data: T) -> Self { Self { data } }
     )
 }
 
+#[test]
+fn doctest_ignore_test() {
+    check_doc_test(
+        "ignore_test",
+        r#####"
+<|>#[test]
+fn arithmetics {
+    assert_eq!(2 + 2, 5);
+}
+"#####,
+        r#####"
+#[test]
+#[ignore]
+fn arithmetics {
+    assert_eq!(2 + 2, 5);
+}
+"#####,
+    )
+}
+
 #[test]
 fn doctest_infer_function_return_type() {
     check_doc_test(
index 7bd338e99c750e2a548c22dfadbda13c542a807e..d1a0a99b1dd6e91872a7d9f1be21caa3b34e3eea 100644 (file)
@@ -9,6 +9,7 @@
 use itertools::Itertools;
 use syntax::{
     ast::edit::AstNodeEdit,
+    ast::AttrsOwner,
     ast::NameOwner,
     ast::{self, edit, make, ArgListOwner},
     AstNode, Direction,
@@ -82,6 +83,23 @@ pub fn extract_trivial_expression(block: &ast::BlockExpr) -> Option<ast::Expr> {
     None
 }
 
+/// This is a method with a heuristics to support test methods annotated with custom test annotations, such as
+/// `#[test_case(...)]`, `#[tokio::test]` and similar.
+/// Also a regular `#[test]` annotation is supported.
+///
+/// It may produce false positives, for example, `#[wasm_bindgen_test]` requires a different command to run the test,
+/// but it's better than not to have the runnables for the tests at all.
+pub fn test_related_attribute(fn_def: &ast::Fn) -> Option<ast::Attr> {
+    fn_def.attrs().find_map(|attr| {
+        let path = attr.path()?;
+        if path.syntax().text().to_string().contains("test") {
+            Some(attr)
+        } else {
+            None
+        }
+    })
+}
+
 #[derive(Copy, Clone, PartialEq)]
 pub enum DefaultMethods {
     Only,
index 459f201ed805a60e0f746d3af7334f9bb4ec31e8..5cbbe306e7ad551abc184b28a1dedfeac47bc24a 100644 (file)
@@ -1,11 +1,12 @@
 //! This module implements a methods and free functions search in the specified file.
 //! We have to skip tests, so cannot reuse file_structure module.
 
+use assists::utils::test_related_attribute;
 use hir::Semantics;
 use ide_db::RootDatabase;
 use syntax::{ast, ast::NameOwner, AstNode, SyntaxNode};
 
-use crate::{runnables::has_test_related_attribute, FileId, FileRange};
+use crate::{FileId, FileRange};
 
 pub(crate) fn find_all_methods(db: &RootDatabase, file_id: FileId) -> Vec<FileRange> {
     let sema = Semantics::new(db);
@@ -15,7 +16,7 @@ pub(crate) fn find_all_methods(db: &RootDatabase, file_id: FileId) -> Vec<FileRa
 
 fn method_range(item: SyntaxNode, file_id: FileId) -> Option<FileRange> {
     ast::Fn::cast(item).and_then(|fn_def| {
-        if has_test_related_attribute(&fn_def) {
+        if test_related_attribute(&fn_def).is_some() {
             None
         } else {
             fn_def.name().map(|name| FileRange { file_id, range: name.syntax().text_range() })
index 2bd0e86e5489c516954768ba762e8cab2cab2659..e154117775910acd18db6ffad37a6c16bfec316e 100644 (file)
@@ -1,5 +1,6 @@
 use std::fmt;
 
+use assists::utils::test_related_attribute;
 use cfg::CfgExpr;
 use hir::{AsAssocItem, Attrs, HirFileId, InFile, Semantics};
 use ide_db::RootDatabase;
@@ -156,7 +157,7 @@ fn runnable_fn(
             None => TestId::Name(name_string),
         };
 
-        if has_test_related_attribute(&fn_def) {
+        if test_related_attribute(&fn_def).is_some() {
             let attr = TestAttr::from_fn(&fn_def);
             RunnableKind::Test { test_id, attr }
         } else if fn_def.has_atom_attr("bench") {
@@ -235,20 +236,6 @@ fn from_fn(fn_def: &ast::Fn) -> TestAttr {
     }
 }
 
-/// This is a method with a heuristics to support test methods annotated with custom test annotations, such as
-/// `#[test_case(...)]`, `#[tokio::test]` and similar.
-/// Also a regular `#[test]` annotation is supported.
-///
-/// It may produce false positives, for example, `#[wasm_bindgen_test]` requires a different command to run the test,
-/// but it's better than not to have the runnables for the tests at all.
-pub(crate) fn has_test_related_attribute(fn_def: &ast::Fn) -> bool {
-    fn_def
-        .attrs()
-        .filter_map(|attr| attr.path())
-        .map(|path| path.syntax().to_string().to_lowercase())
-        .any(|attribute_text| attribute_text.contains("test"))
-}
-
 const RUSTDOC_FENCE: &str = "```";
 const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] =
     &["", "rust", "should_panic", "edition2015", "edition2018"];
@@ -307,7 +294,7 @@ fn has_test_function_or_multiple_test_submodules(module: &ast::Module) -> bool {
         for item in item_list.items() {
             match item {
                 ast::Item::Fn(f) => {
-                    if has_test_related_attribute(&f) {
+                    if test_related_attribute(&f).is_some() {
                         return true;
                     }
                 }