mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-08-31 07:37:30 +00:00
Merge f2ba087170
into 1f4e5e82ff
This commit is contained in:
commit
5bb30ad8b7
3 changed files with 892 additions and 0 deletions
845
crates/ide-assists/src/handlers/convert_attr_cfg_to_if.rs
Normal file
845
crates/ide-assists/src/handlers/convert_attr_cfg_to_if.rs
Normal file
|
@ -0,0 +1,845 @@
|
|||
use either::Either::{self, Left, Right};
|
||||
use ide_db::assists::AssistId;
|
||||
use itertools::Itertools;
|
||||
use syntax::{
|
||||
AstNode,
|
||||
NodeOrToken::{self, Node, Token},
|
||||
SyntaxKind, SyntaxNode, SyntaxToken, T,
|
||||
ast::{self, HasAttrs, edit_in_place::Indent, make},
|
||||
syntax_editor::{Position, SyntaxEditor},
|
||||
};
|
||||
|
||||
use crate::assist_context::{AssistContext, Assists};
|
||||
|
||||
// Assist: convert_attr_cfg_to_if
|
||||
//
|
||||
// Convert `#[cfg(...)] {}` to `if cfg!(...) {}`.
|
||||
//
|
||||
// ```
|
||||
// fn foo() {
|
||||
// $0#[cfg(feature = "foo")]
|
||||
// {
|
||||
// let _x = 2;
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
// ->
|
||||
// ```
|
||||
// fn foo() {
|
||||
// if cfg!(feature = "foo") {
|
||||
// let _x = 2;
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn convert_attr_cfg_to_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
|
||||
let cfg = ctx.find_node_at_offset::<ast::Attr>()?;
|
||||
let target = cfg.syntax().text_range();
|
||||
let (origin, cfg, stmt) = find_stmt(cfg)?;
|
||||
|
||||
if !is_cfg(&cfg) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let cfg_tt = cfg.token_tree()?;
|
||||
let cfg_expr = make::expr_macro(cfg.path()?, cfg_tt.clone()).into();
|
||||
|
||||
acc.add(
|
||||
AssistId::refactor_rewrite("convert_attr_cfg_to_if"),
|
||||
"Convert `#[cfg()]` to `if cfg!()`",
|
||||
target,
|
||||
|builder| {
|
||||
let mut edit = builder.make_editor(origin.syntax());
|
||||
|
||||
let block = process_stmt(&cfg, stmt, &mut edit);
|
||||
let else_branch = take_else_branch(&origin, cfg_tt, &mut edit);
|
||||
let if_expr = make::expr_if(cfg_expr, block, else_branch).clone_for_update();
|
||||
|
||||
if_expr.indent(origin.indent_level());
|
||||
edit.replace(origin.syntax(), if_expr.syntax());
|
||||
|
||||
builder.add_file_edits(ctx.vfs_file_id(), edit);
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// Assist: convert_if_cfg_to_attr
|
||||
//
|
||||
// Convert `if cfg!(...) {}` to `#[cfg(...)] {}`.
|
||||
//
|
||||
// ```
|
||||
// fn foo() {
|
||||
// if $0cfg!(feature = "foo") {
|
||||
// let _x = 2;
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
// ->
|
||||
// ```
|
||||
// fn foo() {
|
||||
// #[cfg(feature = "foo")]
|
||||
// {
|
||||
// let _x = 2;
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn convert_if_cfg_to_attr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
|
||||
let if_ = ctx.find_node_at_offset::<ast::IfExpr>()?;
|
||||
let ast::Expr::MacroExpr(cfg) = if_.condition()? else {
|
||||
return None;
|
||||
};
|
||||
let macro_call = cfg.macro_call()?;
|
||||
|
||||
let block_expr = if_.then_branch()?;
|
||||
let else_block = match if_.else_branch() {
|
||||
Some(ast::ElseBranch::Block(block)) => Some(block),
|
||||
None => None,
|
||||
Some(ast::ElseBranch::IfExpr(_)) => return None,
|
||||
};
|
||||
if macro_call.path()?.segment()?.name_ref()?.text() != "cfg"
|
||||
|| ctx.offset() > block_expr.stmt_list()?.l_curly_token()?.text_range().end()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let cfg_cond = macro_call.token_tree()?;
|
||||
|
||||
acc.add(
|
||||
AssistId::refactor_rewrite("convert_if_cfg_to_attr"),
|
||||
"Convert `if cfg!()` to `#[cfg()]`",
|
||||
macro_call.syntax().text_range(),
|
||||
|builder| {
|
||||
let mut edit = builder.make_editor(if_.syntax());
|
||||
|
||||
let indent = format!("\n{}", if_.indent_level());
|
||||
if let Some(else_block) = else_block {
|
||||
let attr_cfg_not = make_cfg(make::token_tree(
|
||||
T!['('],
|
||||
[Token(make::tokens::ident("not")), Node(cfg_cond.clone())],
|
||||
));
|
||||
edit.insert_all(
|
||||
Position::before(if_.syntax()),
|
||||
vec![
|
||||
make::tokens::whitespace(&indent).into(),
|
||||
attr_cfg_not.syntax().clone_for_update().into(),
|
||||
make::tokens::whitespace(&indent).into(),
|
||||
else_block.syntax().clone_for_update().into(),
|
||||
],
|
||||
);
|
||||
edit.insert_all(
|
||||
Position::before(if_.syntax()),
|
||||
indent_attributes(&if_, &indent, false).clone(),
|
||||
);
|
||||
}
|
||||
|
||||
let attr_cfg = make_cfg(cfg_cond);
|
||||
edit.insert_all(
|
||||
Position::before(if_.syntax()),
|
||||
vec![
|
||||
attr_cfg.syntax().clone_for_update().into(),
|
||||
make::tokens::whitespace(&indent).into(),
|
||||
block_expr.syntax().clone_for_update().into(),
|
||||
],
|
||||
);
|
||||
edit.insert_all(Position::before(if_.syntax()), indent_attributes(&if_, &indent, true));
|
||||
|
||||
edit.delete(if_.syntax());
|
||||
builder.add_file_edits(ctx.vfs_file_id(), edit);
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn take_else_branch(
|
||||
origin: &impl AstNode,
|
||||
cfg_tt: ast::TokenTree,
|
||||
edit: &mut SyntaxEditor,
|
||||
) -> Option<ast::ElseBranch> {
|
||||
let attr_cfg_not = next_attr_cfg_not(origin, &cfg_tt)?;
|
||||
let (else_origin, else_cfg, else_stmt) = find_stmt(attr_cfg_not)?;
|
||||
let block = process_stmt(&else_cfg, else_stmt, edit);
|
||||
|
||||
remove_next_ws(origin.syntax(), edit);
|
||||
edit.delete(else_origin.syntax());
|
||||
|
||||
Some(ast::ElseBranch::Block(block))
|
||||
}
|
||||
|
||||
fn make_block(
|
||||
stmts: impl IntoIterator<Item = ast::Stmt>,
|
||||
tail_expr: Option<ast::Expr>,
|
||||
) -> ast::BlockExpr {
|
||||
let tail_expr = tail_expr.inspect(|expr| expr.reindent_to(1.into()));
|
||||
let stmts = stmts.into_iter().inspect(|stmt| stmt.reindent_to(1.into()));
|
||||
|
||||
make::block_expr(stmts, tail_expr)
|
||||
}
|
||||
|
||||
fn process_stmt(
|
||||
cfg: &ast::Attr,
|
||||
stmt: Either<ast::StmtList, ast::Stmt>,
|
||||
edit: &mut SyntaxEditor,
|
||||
) -> ast::BlockExpr {
|
||||
match stmt {
|
||||
Left(stmt_list) => {
|
||||
remove_cfg(cfg, edit);
|
||||
make_block(stmt_list.statements(), stmt_list.tail_expr())
|
||||
}
|
||||
Right(stmt) => make_block([stmt], None),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_stmt(
|
||||
attr: ast::Attr,
|
||||
) -> Option<(impl Indent, ast::Attr, Either<ast::StmtList, ast::Stmt>)> {
|
||||
if let Some(stmt_list) = find_stmt_list(&attr) {
|
||||
let new_stmt_list = stmt_list.clone_for_update();
|
||||
new_stmt_list.dedent(stmt_list.indent_level());
|
||||
return Some((Left(stmt_list), attr.clone(), Left(new_stmt_list)));
|
||||
}
|
||||
|
||||
let node =
|
||||
match attr.syntax().ancestors().find_map(Either::<ast::ExprStmt, ast::StmtList>::cast)? {
|
||||
Left(expr_stmt) => Left(expr_stmt),
|
||||
Right(list) => Right(list.tail_expr()?),
|
||||
};
|
||||
|
||||
let new_node = node.syntax().clone_subtree();
|
||||
let attr = new_node
|
||||
.descendants()
|
||||
.filter(|node| node.text() == attr.syntax().text())
|
||||
.find_map(ast::Attr::cast)?;
|
||||
|
||||
let mut edit = SyntaxEditor::new(new_node);
|
||||
remove_cfg(&attr, &mut edit);
|
||||
let new_node = edit.finish().new_root().clone();
|
||||
let new_stmt = match Either::<ast::ExprStmt, ast::Expr>::cast(new_node)? {
|
||||
Left(expr_stmt) => ast::Stmt::from(expr_stmt),
|
||||
Right(expr) => make::expr_stmt(expr).clone_for_update().into(),
|
||||
};
|
||||
new_stmt.dedent(node.indent_level());
|
||||
Some((Right(node), attr, Right(new_stmt)))
|
||||
}
|
||||
|
||||
fn find_stmt_list(attr: &ast::Attr) -> Option<ast::StmtList> {
|
||||
let mut node = attr.syntax().clone();
|
||||
|
||||
while node.kind().is_trivia() || node.kind() == SyntaxKind::ATTR {
|
||||
node = node.next_sibling()?;
|
||||
}
|
||||
|
||||
AstNode::cast(node)
|
||||
}
|
||||
|
||||
fn next_attr_cfg_not(node: &impl AstNode, cond: &ast::TokenTree) -> Option<ast::Attr> {
|
||||
let attr = node
|
||||
.syntax()
|
||||
.ancestors()
|
||||
.filter_map(|node| node.next_sibling())
|
||||
.flat_map(|x| x.descendants())
|
||||
.filter_map(ast::Attr::cast)
|
||||
.find(is_cfg)?;
|
||||
|
||||
let tts = attr
|
||||
.token_tree()?
|
||||
.token_trees_and_tokens()
|
||||
.filter(|tt| tt.as_token().is_none_or(|t| !t.kind().is_trivia()))
|
||||
.collect_array()?;
|
||||
if let [Token(_lparen), Token(not), Node(not_cond), Token(_rparen)] = tts
|
||||
&& not.text() == "not"
|
||||
&& not_cond.syntax().text() == cond.syntax().text()
|
||||
{
|
||||
Some(attr)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_cfg(cfg: &ast::Attr, edit: &mut SyntaxEditor) {
|
||||
remove_next_ws(cfg.syntax(), edit);
|
||||
edit.delete(cfg.syntax());
|
||||
}
|
||||
|
||||
fn remove_next_ws(node: &SyntaxNode, edit: &mut SyntaxEditor) {
|
||||
if let Some(Token(next)) = node.next_sibling_or_token()
|
||||
&& next.kind() == SyntaxKind::WHITESPACE
|
||||
{
|
||||
edit.delete(next);
|
||||
} else if let Some(parent) = node.parent()
|
||||
&& parent.last_child().is_some_and(|it| it == *node)
|
||||
{
|
||||
remove_next_ws(&parent, edit);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_cfg(attr: &ast::Attr) -> bool {
|
||||
attr.path().and_then(|p| p.as_single_name_ref()).is_some_and(|name| name.text() == "cfg")
|
||||
}
|
||||
|
||||
fn make_cfg(tt: ast::TokenTree) -> ast::Attr {
|
||||
let cfg_path = make::ext::ident_path("cfg");
|
||||
make::attr_outer(make::meta_token_tree(cfg_path, tt))
|
||||
}
|
||||
|
||||
fn indent_attributes(
|
||||
if_: &ast::IfExpr,
|
||||
indent: &str,
|
||||
before: bool,
|
||||
) -> Vec<NodeOrToken<SyntaxNode, SyntaxToken>> {
|
||||
if_.attrs()
|
||||
.flat_map(|attr| {
|
||||
let mut tts =
|
||||
[Token(make::tokens::whitespace(indent)), Node(attr.syntax().clone_for_update())];
|
||||
if before {
|
||||
tts.reverse();
|
||||
}
|
||||
tts
|
||||
})
|
||||
.collect_vec()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_stmt_list() {
|
||||
check_assist(
|
||||
convert_attr_cfg_to_if,
|
||||
r#"
|
||||
fn foo() {
|
||||
$0#[cfg(feature = "foo")]
|
||||
{
|
||||
let x = 2;
|
||||
let _ = x+1;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn foo() {
|
||||
if cfg!(feature = "foo") {
|
||||
let x = 2;
|
||||
let _ = x+1;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stmt_list_else() {
|
||||
check_assist(
|
||||
convert_attr_cfg_to_if,
|
||||
r#"
|
||||
fn foo() {
|
||||
$0#[cfg(feature = "foo")]
|
||||
{
|
||||
let x = 2;
|
||||
let _ = x+1;
|
||||
}
|
||||
#[cfg(not(feature = "foo"))]
|
||||
{
|
||||
let _ = 3;
|
||||
}
|
||||
// needless comment
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn foo() {
|
||||
if cfg!(feature = "foo") {
|
||||
let x = 2;
|
||||
let _ = x+1;
|
||||
} else {
|
||||
let _ = 3;
|
||||
}
|
||||
// needless comment
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expr_stmt() {
|
||||
check_assist(
|
||||
convert_attr_cfg_to_if,
|
||||
r#"
|
||||
fn bar() {}
|
||||
fn foo() {
|
||||
$0#[cfg(feature = "foo")]
|
||||
bar();
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn bar() {}
|
||||
fn foo() {
|
||||
if cfg!(feature = "foo") {
|
||||
bar();
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_other_attr() {
|
||||
check_assist(
|
||||
convert_attr_cfg_to_if,
|
||||
r#"
|
||||
fn foo() {
|
||||
$0#[cfg(feature = "foo")]
|
||||
#[allow(unused)]
|
||||
{
|
||||
let x = 2;
|
||||
let _ = x+1;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn foo() {
|
||||
#[allow(unused)]
|
||||
if cfg!(feature = "foo") {
|
||||
let x = 2;
|
||||
let _ = x+1;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_assist(
|
||||
convert_attr_cfg_to_if,
|
||||
r#"
|
||||
fn bar() {}
|
||||
fn foo() {
|
||||
#[allow(unused)]
|
||||
$0#[cfg(feature = "foo")]
|
||||
bar();
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn bar() {}
|
||||
fn foo() {
|
||||
if cfg!(feature = "foo") {
|
||||
#[allow(unused)]
|
||||
bar();
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_assist(
|
||||
convert_attr_cfg_to_if,
|
||||
r#"
|
||||
fn bar() {}
|
||||
fn baz() {}
|
||||
fn foo() {
|
||||
#[allow(unused)]
|
||||
$0#[cfg(feature = "foo")]
|
||||
bar();
|
||||
#[allow(unused)]
|
||||
#[cfg(not(feature = "foo"))]
|
||||
baz();
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn bar() {}
|
||||
fn baz() {}
|
||||
fn foo() {
|
||||
if cfg!(feature = "foo") {
|
||||
#[allow(unused)]
|
||||
bar();
|
||||
} else {
|
||||
#[allow(unused)]
|
||||
baz();
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stmt_list_indent() {
|
||||
check_assist(
|
||||
convert_attr_cfg_to_if,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
#[allow(unused)]
|
||||
$0#[cfg(feature = "foo")]
|
||||
{
|
||||
let _ = match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
};
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
#[allow(unused)]
|
||||
if cfg!(feature = "foo") {
|
||||
let _ = match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
};
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_assist(
|
||||
convert_attr_cfg_to_if,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
#[allow(unused)]
|
||||
$0#[cfg(feature = "foo")]
|
||||
{
|
||||
let _ = match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
};
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "foo"))]
|
||||
{
|
||||
let _ = match () {
|
||||
() => {
|
||||
todo!("")
|
||||
},
|
||||
};
|
||||
match () {
|
||||
() => {
|
||||
todo!("")
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
#[allow(unused)]
|
||||
if cfg!(feature = "foo") {
|
||||
let _ = match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
};
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
}
|
||||
} else {
|
||||
let _ = match () {
|
||||
() => {
|
||||
todo!("")
|
||||
},
|
||||
};
|
||||
match () {
|
||||
() => {
|
||||
todo!("")
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expr_indent() {
|
||||
check_assist(
|
||||
convert_attr_cfg_to_if,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
#[allow(unused)]
|
||||
$0#[cfg(feature = "foo")]
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
if cfg!(feature = "foo") {
|
||||
#[allow(unused)]
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_assist(
|
||||
convert_attr_cfg_to_if,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
$0#[cfg(feature = "foo")]
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
if cfg!(feature = "foo") {
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_assist(
|
||||
convert_attr_cfg_to_if,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
$0#[cfg(feature = "foo")]
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
};
|
||||
#[cfg(not(feature = "foo"))]
|
||||
match () {
|
||||
() => {
|
||||
todo!("")
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
if cfg!(feature = "foo") {
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
};
|
||||
} else {
|
||||
match () {
|
||||
() => {
|
||||
todo!("")
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_convert_if_cfg_to_attr_else_block() {
|
||||
check_assist(
|
||||
convert_if_cfg_to_attr,
|
||||
r#"
|
||||
fn foo() {
|
||||
$0if cfg!(feature = "foo") {
|
||||
let x = 2;
|
||||
let _ = x+1;
|
||||
} else {
|
||||
let _ = 3;
|
||||
}
|
||||
// needless comment
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn foo() {
|
||||
#[cfg(feature = "foo")]
|
||||
{
|
||||
let x = 2;
|
||||
let _ = x+1;
|
||||
}
|
||||
#[cfg(not(feature = "foo"))]
|
||||
{
|
||||
let _ = 3;
|
||||
}
|
||||
// needless comment
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_convert_if_cfg_to_attr_not_applicable_after_curly() {
|
||||
check_assist_not_applicable(
|
||||
convert_if_cfg_to_attr,
|
||||
r#"
|
||||
fn foo() {
|
||||
if cfg!(feature = "foo") {
|
||||
$0let x = 2;
|
||||
let _ = x+1;
|
||||
} else {
|
||||
let _ = 3;
|
||||
}
|
||||
// needless comment
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_convert_if_cfg_to_attr_indent() {
|
||||
check_assist(
|
||||
convert_if_cfg_to_attr,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
$0if cfg!(feature = "foo") {
|
||||
#[allow(unused)]
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
#[cfg(feature = "foo")]
|
||||
{
|
||||
#[allow(unused)]
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_assist(
|
||||
convert_if_cfg_to_attr,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
$0if cfg!(feature = "foo") {
|
||||
#[allow(unused)]
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
}
|
||||
} else {
|
||||
#[allow(unused)]
|
||||
match () {
|
||||
() => {
|
||||
todo!("")
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
mod a {
|
||||
fn foo() {
|
||||
#[cfg(feature = "foo")]
|
||||
{
|
||||
#[allow(unused)]
|
||||
match () {
|
||||
() => {
|
||||
todo!()
|
||||
},
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "foo"))]
|
||||
{
|
||||
#[allow(unused)]
|
||||
match () {
|
||||
() => {
|
||||
todo!("")
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_convert_if_cfg_to_attr_attributes() {
|
||||
check_assist(
|
||||
convert_if_cfg_to_attr,
|
||||
r#"
|
||||
fn foo() {
|
||||
#[foo]
|
||||
#[allow(unused)]
|
||||
$0if cfg!(feature = "foo") {
|
||||
let x = 2;
|
||||
let _ = x+1;
|
||||
} else {
|
||||
let _ = 3;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn foo() {
|
||||
#[foo]
|
||||
#[allow(unused)]
|
||||
#[cfg(feature = "foo")]
|
||||
{
|
||||
let x = 2;
|
||||
let _ = x+1;
|
||||
}
|
||||
#[foo]
|
||||
#[allow(unused)]
|
||||
#[cfg(not(feature = "foo"))]
|
||||
{
|
||||
let _ = 3;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -117,6 +117,7 @@ mod handlers {
|
|||
mod auto_import;
|
||||
mod bind_unused_param;
|
||||
mod change_visibility;
|
||||
mod convert_attr_cfg_to_if;
|
||||
mod convert_bool_then;
|
||||
mod convert_bool_to_enum;
|
||||
mod convert_closure_to_fn;
|
||||
|
@ -254,6 +255,8 @@ mod handlers {
|
|||
convert_bool_then::convert_if_to_bool_then,
|
||||
convert_bool_to_enum::convert_bool_to_enum,
|
||||
convert_closure_to_fn::convert_closure_to_fn,
|
||||
convert_attr_cfg_to_if::convert_attr_cfg_to_if,
|
||||
convert_attr_cfg_to_if::convert_if_cfg_to_attr,
|
||||
convert_comment_block::convert_comment_block,
|
||||
convert_comment_from_or_to_doc::convert_comment_from_or_to_doc,
|
||||
convert_for_to_while_let::convert_for_loop_to_while_let,
|
||||
|
|
|
@ -355,6 +355,28 @@ fn doctest_comment_to_doc() {
|
|||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doctest_convert_attr_cfg_to_if() {
|
||||
check_doc_test(
|
||||
"convert_attr_cfg_to_if",
|
||||
r#####"
|
||||
fn foo() {
|
||||
$0#[cfg(feature = "foo")]
|
||||
{
|
||||
let _x = 2;
|
||||
}
|
||||
}
|
||||
"#####,
|
||||
r#####"
|
||||
fn foo() {
|
||||
if cfg!(feature = "foo") {
|
||||
let _x = 2;
|
||||
}
|
||||
}
|
||||
"#####,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doctest_convert_bool_then_to_if() {
|
||||
check_doc_test(
|
||||
|
@ -516,6 +538,28 @@ impl TryFrom<usize> for Thing {
|
|||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doctest_convert_if_cfg_to_attr() {
|
||||
check_doc_test(
|
||||
"convert_if_cfg_to_attr",
|
||||
r#####"
|
||||
fn foo() {
|
||||
if $0cfg!(feature = "foo") {
|
||||
let _x = 2;
|
||||
}
|
||||
}
|
||||
"#####,
|
||||
r#####"
|
||||
fn foo() {
|
||||
#[cfg(feature = "foo")]
|
||||
{
|
||||
let _x = 2;
|
||||
}
|
||||
}
|
||||
"#####,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doctest_convert_if_to_bool_then() {
|
||||
check_doc_test(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue