Skip to content

Commit b00702b

Browse files
bors[bot]dragfire
andauthored
Merge #5851
5851: Invert if should be smart about is_some, is_none, is_ok, is_err r=matklad a=dragfire Fixes #5827 Co-authored-by: dragfire <[email protected]>
2 parents 951c7c1 + 1d129a7 commit b00702b

File tree

3 files changed

+45
-2
lines changed

3 files changed

+45
-2
lines changed

crates/assists/src/handlers/invert_if.rs

+18
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,22 @@ mod tests {
106106
"fn f() { i<|>f let Some(_) = Some(1) { 1 } else { 0 } }",
107107
)
108108
}
109+
110+
#[test]
111+
fn invert_if_option_case() {
112+
check_assist(
113+
invert_if,
114+
"fn f() { if<|> doc_style.is_some() { Class::DocComment } else { Class::Comment } }",
115+
"fn f() { if doc_style.is_none() { Class::Comment } else { Class::DocComment } }",
116+
)
117+
}
118+
119+
#[test]
120+
fn invert_if_result_case() {
121+
check_assist(
122+
invert_if,
123+
"fn f() { i<|>f doc_style.is_err() { Class::Err } else { Class::Ok } }",
124+
"fn f() { if doc_style.is_ok() { Class::Ok } else { Class::Err } }",
125+
)
126+
}
109127
}

crates/assists/src/utils.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use syntax::{
1111
ast::{self, make, NameOwner},
1212
AstNode, Direction,
1313
SyntaxKind::*,
14-
SyntaxNode, TextSize, T,
14+
SyntaxNode, SyntaxText, TextSize, T,
1515
};
1616

1717
use crate::assist_config::SnippetCap;
@@ -179,6 +179,25 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
179179
ast::BinOp::EqualityTest => bin.replace_op(T![!=]).map(|it| it.into()),
180180
_ => None,
181181
},
182+
ast::Expr::MethodCallExpr(mce) => {
183+
const IS_SOME_TEXT: &str = "is_some";
184+
const IS_NONE_TEXT: &str = "is_none";
185+
const IS_OK_TEXT: &str = "is_ok";
186+
const IS_ERR_TEXT: &str = "is_err";
187+
188+
let name = mce.name_ref()?;
189+
let name_text = name.text();
190+
191+
let caller = || -> Option<SyntaxText> { Some(mce.receiver()?.syntax().text()) };
192+
193+
match name_text {
194+
x if x == IS_SOME_TEXT => make::expr_method_call(IS_NONE_TEXT, caller),
195+
x if x == IS_NONE_TEXT => make::expr_method_call(IS_SOME_TEXT, caller),
196+
x if x == IS_OK_TEXT => make::expr_method_call(IS_ERR_TEXT, caller),
197+
x if x == IS_ERR_TEXT => make::expr_method_call(IS_OK_TEXT, caller),
198+
_ => None,
199+
}
200+
}
182201
ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::PrefixOp::Not => pe.expr(),
183202
// FIXME:
184203
// ast::Expr::Literal(true | false )

crates/syntax/src/ast/make.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use itertools::Itertools;
88
use stdx::format_to;
99

10-
use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken};
10+
use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxText, SyntaxToken};
1111

1212
pub fn name(text: &str) -> ast::Name {
1313
ast_from_text(&format!("mod {};", text))
@@ -137,6 +137,12 @@ pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr {
137137
pub fn expr_call(f: ast::Expr, arg_list: ast::ArgList) -> ast::Expr {
138138
expr_from_text(&format!("{}{}", f, arg_list))
139139
}
140+
pub fn expr_method_call<F>(text: &str, caller: F) -> Option<ast::Expr>
141+
where
142+
F: FnOnce() -> Option<SyntaxText>,
143+
{
144+
try_expr_from_text(&format!("{}.{}()", caller()?, text))
145+
}
140146
fn expr_from_text(text: &str) -> ast::Expr {
141147
ast_from_text(&format!("const C: () = {};", text))
142148
}

0 commit comments

Comments
 (0)