diff options
author | dragfire <[email protected]> | 2020-08-23 21:30:07 +0100 |
---|---|---|
committer | dragfire <[email protected]> | 2020-08-24 05:30:34 +0100 |
commit | 1d129a7172bbe502182be6cc3b50b3250cb6f3a9 (patch) | |
tree | 7b9e694ab43ffebde2a39c4e99d5b2a6c774a005 | |
parent | e65d48d1fb3d4d91d9dc1148a7a836ff5c9a3c87 (diff) |
Invert if should be smart about is_some, is_none, is_ok, is_err
-rw-r--r-- | crates/assists/src/handlers/invert_if.rs | 18 | ||||
-rw-r--r-- | crates/assists/src/utils.rs | 21 | ||||
-rw-r--r-- | crates/syntax/src/ast/make.rs | 8 |
3 files changed, 45 insertions, 2 deletions
diff --git a/crates/assists/src/handlers/invert_if.rs b/crates/assists/src/handlers/invert_if.rs index f0e047538..294256297 100644 --- a/crates/assists/src/handlers/invert_if.rs +++ b/crates/assists/src/handlers/invert_if.rs | |||
@@ -106,4 +106,22 @@ mod tests { | |||
106 | "fn f() { i<|>f let Some(_) = Some(1) { 1 } else { 0 } }", | 106 | "fn f() { i<|>f let Some(_) = Some(1) { 1 } else { 0 } }", |
107 | ) | 107 | ) |
108 | } | 108 | } |
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 | } | ||
109 | } | 127 | } |
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs index d071d6502..e15c982e7 100644 --- a/crates/assists/src/utils.rs +++ b/crates/assists/src/utils.rs | |||
@@ -11,7 +11,7 @@ use syntax::{ | |||
11 | ast::{self, make, NameOwner}, | 11 | ast::{self, make, NameOwner}, |
12 | AstNode, Direction, | 12 | AstNode, Direction, |
13 | SyntaxKind::*, | 13 | SyntaxKind::*, |
14 | SyntaxNode, TextSize, T, | 14 | SyntaxNode, SyntaxText, TextSize, T, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | use crate::assist_config::SnippetCap; | 17 | use crate::assist_config::SnippetCap; |
@@ -179,6 +179,25 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> { | |||
179 | ast::BinOp::EqualityTest => bin.replace_op(T![!=]).map(|it| it.into()), | 179 | ast::BinOp::EqualityTest => bin.replace_op(T![!=]).map(|it| it.into()), |
180 | _ => None, | 180 | _ => None, |
181 | }, | 181 | }, |
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 | } | ||
182 | ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::PrefixOp::Not => pe.expr(), | 201 | ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::PrefixOp::Not => pe.expr(), |
183 | // FIXME: | 202 | // FIXME: |
184 | // ast::Expr::Literal(true | false ) | 203 | // ast::Expr::Literal(true | false ) |
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index d20c085aa..7958721e2 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs | |||
@@ -7,7 +7,7 @@ | |||
7 | use itertools::Itertools; | 7 | use itertools::Itertools; |
8 | use stdx::format_to; | 8 | use stdx::format_to; |
9 | 9 | ||
10 | use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken}; | 10 | use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxText, SyntaxToken}; |
11 | 11 | ||
12 | pub fn name(text: &str) -> ast::Name { | 12 | pub fn name(text: &str) -> ast::Name { |
13 | ast_from_text(&format!("mod {};", text)) | 13 | ast_from_text(&format!("mod {};", text)) |
@@ -137,6 +137,12 @@ pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr { | |||
137 | pub fn expr_call(f: ast::Expr, arg_list: ast::ArgList) -> ast::Expr { | 137 | pub fn expr_call(f: ast::Expr, arg_list: ast::ArgList) -> ast::Expr { |
138 | expr_from_text(&format!("{}{}", f, arg_list)) | 138 | expr_from_text(&format!("{}{}", f, arg_list)) |
139 | } | 139 | } |
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 | } | ||
140 | fn expr_from_text(text: &str) -> ast::Expr { | 146 | fn expr_from_text(text: &str) -> ast::Expr { |
141 | ast_from_text(&format!("const C: () = {};", text)) | 147 | ast_from_text(&format!("const C: () = {};", text)) |
142 | } | 148 | } |