mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 14:21:44 +00:00
Merge #6573
6573: Add **Ignore Test** assist r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
d4c970d1f2
6 changed files with 80 additions and 18 deletions
34
crates/assists/src/handlers/ignore_test.rs
Normal file
34
crates/assists/src/handlers/ignore_test.rs
Normal file
|
@ -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]")),
|
||||||
|
)
|
||||||
|
}
|
|
@ -141,6 +141,7 @@ mod handlers {
|
||||||
mod generate_function;
|
mod generate_function;
|
||||||
mod generate_impl;
|
mod generate_impl;
|
||||||
mod generate_new;
|
mod generate_new;
|
||||||
|
mod ignore_test;
|
||||||
mod infer_function_return_type;
|
mod infer_function_return_type;
|
||||||
mod inline_local_variable;
|
mod inline_local_variable;
|
||||||
mod introduce_named_lifetime;
|
mod introduce_named_lifetime;
|
||||||
|
@ -189,6 +190,7 @@ mod handlers {
|
||||||
generate_function::generate_function,
|
generate_function::generate_function,
|
||||||
generate_impl::generate_impl,
|
generate_impl::generate_impl,
|
||||||
generate_new::generate_new,
|
generate_new::generate_new,
|
||||||
|
ignore_test::ignore_test,
|
||||||
infer_function_return_type::infer_function_return_type,
|
infer_function_return_type::infer_function_return_type,
|
||||||
inline_local_variable::inline_local_variable,
|
inline_local_variable::inline_local_variable,
|
||||||
introduce_named_lifetime::introduce_named_lifetime,
|
introduce_named_lifetime::introduce_named_lifetime,
|
||||||
|
|
|
@ -473,6 +473,26 @@ impl<T: Clone> Ctx<T> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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]
|
#[test]
|
||||||
fn doctest_infer_function_return_type() {
|
fn doctest_infer_function_return_type() {
|
||||||
check_doc_test(
|
check_doc_test(
|
||||||
|
|
|
@ -9,6 +9,7 @@ use ide_db::RootDatabase;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::edit::AstNodeEdit,
|
ast::edit::AstNodeEdit,
|
||||||
|
ast::AttrsOwner,
|
||||||
ast::NameOwner,
|
ast::NameOwner,
|
||||||
ast::{self, edit, make, ArgListOwner},
|
ast::{self, edit, make, ArgListOwner},
|
||||||
AstNode, Direction,
|
AstNode, Direction,
|
||||||
|
@ -82,6 +83,23 @@ pub fn extract_trivial_expression(block: &ast::BlockExpr) -> Option<ast::Expr> {
|
||||||
None
|
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)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub enum DefaultMethods {
|
pub enum DefaultMethods {
|
||||||
Only,
|
Only,
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
//! This module implements a methods and free functions search in the specified file.
|
//! This module implements a methods and free functions search in the specified file.
|
||||||
//! We have to skip tests, so cannot reuse file_structure module.
|
//! We have to skip tests, so cannot reuse file_structure module.
|
||||||
|
|
||||||
|
use assists::utils::test_related_attribute;
|
||||||
use hir::Semantics;
|
use hir::Semantics;
|
||||||
use ide_db::RootDatabase;
|
use ide_db::RootDatabase;
|
||||||
use syntax::{ast, ast::NameOwner, AstNode, SyntaxNode};
|
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> {
|
pub(crate) fn find_all_methods(db: &RootDatabase, file_id: FileId) -> Vec<FileRange> {
|
||||||
let sema = Semantics::new(db);
|
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> {
|
fn method_range(item: SyntaxNode, file_id: FileId) -> Option<FileRange> {
|
||||||
ast::Fn::cast(item).and_then(|fn_def| {
|
ast::Fn::cast(item).and_then(|fn_def| {
|
||||||
if has_test_related_attribute(&fn_def) {
|
if test_related_attribute(&fn_def).is_some() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
fn_def.name().map(|name| FileRange { file_id, range: name.syntax().text_range() })
|
fn_def.name().map(|name| FileRange { file_id, range: name.syntax().text_range() })
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use assists::utils::test_related_attribute;
|
||||||
use cfg::CfgExpr;
|
use cfg::CfgExpr;
|
||||||
use hir::{AsAssocItem, Attrs, HirFileId, InFile, Semantics};
|
use hir::{AsAssocItem, Attrs, HirFileId, InFile, Semantics};
|
||||||
use ide_db::RootDatabase;
|
use ide_db::RootDatabase;
|
||||||
|
@ -156,7 +157,7 @@ fn runnable_fn(
|
||||||
None => TestId::Name(name_string),
|
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);
|
let attr = TestAttr::from_fn(&fn_def);
|
||||||
RunnableKind::Test { test_id, attr }
|
RunnableKind::Test { test_id, attr }
|
||||||
} else if fn_def.has_atom_attr("bench") {
|
} else if fn_def.has_atom_attr("bench") {
|
||||||
|
@ -235,20 +236,6 @@ impl 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_FENCE: &str = "```";
|
||||||
const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] =
|
const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] =
|
||||||
&["", "rust", "should_panic", "edition2015", "edition2018"];
|
&["", "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() {
|
for item in item_list.items() {
|
||||||
match item {
|
match item {
|
||||||
ast::Item::Fn(f) => {
|
ast::Item::Fn(f) => {
|
||||||
if has_test_related_attribute(&f) {
|
if test_related_attribute(&f).is_some() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue