diff options
| author | bravomikekilo <[email protected]> | 2019-11-24 05:14:57 +0000 |
|---|---|---|
| committer | bravomikekilo <[email protected]> | 2019-11-24 05:14:57 +0000 |
| commit | adac4fc2f21117486356063d82d79f8c3add084a (patch) | |
| tree | 5d99ff1e3b5b0dcc19aa28633c102490454b3a89 /crates | |
| parent | 1ebfa908d50a7ef4765d2abb432531d9c98cbb58 (diff) | |
do refact and fix some issue
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/ra_assists/src/assists/apply_demorgan.rs | 40 | ||||
| -rw-r--r-- | crates/ra_assists/src/assists/invert_if.rs | 55 | ||||
| -rw-r--r-- | crates/ra_assists/src/doc_tests/generated.rs | 4 | ||||
| -rw-r--r-- | crates/ra_syntax/src/ast/edit.rs | 12 | ||||
| -rw-r--r-- | crates/ra_syntax/src/ast/expr_extensions.rs | 2 | ||||
| -rw-r--r-- | crates/ra_syntax/src/ast/make.rs | 15 |
6 files changed, 70 insertions, 58 deletions
diff --git a/crates/ra_assists/src/assists/apply_demorgan.rs b/crates/ra_assists/src/assists/apply_demorgan.rs index 0d59a0d24..7c57c0560 100644 --- a/crates/ra_assists/src/assists/apply_demorgan.rs +++ b/crates/ra_assists/src/assists/apply_demorgan.rs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | use super::invert_if::invert_boolean_expression; | ||
| 1 | use hir::db::HirDatabase; | 2 | use hir::db::HirDatabase; |
| 2 | use ra_syntax::ast::{self, AstNode}; | 3 | use ra_syntax::ast::{self, AstNode}; |
| 3 | use ra_syntax::SyntaxNode; | ||
| 4 | 4 | ||
| 5 | use crate::{Assist, AssistCtx, AssistId}; | 5 | use crate::{Assist, AssistCtx, AssistId}; |
| 6 | 6 | ||
| @@ -32,18 +32,18 @@ pub(crate) fn apply_demorgan(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> | |||
| 32 | if !cursor_in_range { | 32 | if !cursor_in_range { |
| 33 | return None; | 33 | return None; |
| 34 | } | 34 | } |
| 35 | let lhs = expr.lhs()?.syntax().clone(); | 35 | let lhs = expr.lhs()?; |
| 36 | let lhs_range = lhs.text_range(); | 36 | let lhs_range = lhs.syntax().text_range(); |
| 37 | let rhs = expr.rhs()?.syntax().clone(); | 37 | let rhs = expr.rhs()?; |
| 38 | let rhs_range = rhs.text_range(); | 38 | let rhs_range = rhs.syntax().text_range(); |
| 39 | let not_lhs = undo_negation(lhs)?; | 39 | let not_lhs = invert_boolean_expression(&lhs)?; |
| 40 | let not_rhs = undo_negation(rhs)?; | 40 | let not_rhs = invert_boolean_expression(&rhs)?; |
| 41 | 41 | ||
| 42 | ctx.add_assist(AssistId("apply_demorgan"), "apply demorgan's law", |edit| { | 42 | ctx.add_assist(AssistId("apply_demorgan"), "apply demorgan's law", |edit| { |
| 43 | edit.target(op_range); | 43 | edit.target(op_range); |
| 44 | edit.replace(op_range, opposite_op); | 44 | edit.replace(op_range, opposite_op); |
| 45 | edit.replace(lhs_range, format!("!({}", not_lhs)); | 45 | edit.replace(lhs_range, format!("!({}", not_lhs.syntax().text())); |
| 46 | edit.replace(rhs_range, format!("{})", not_rhs)); | 46 | edit.replace(rhs_range, format!("{})", not_rhs.syntax().text())); |
| 47 | }) | 47 | }) |
| 48 | } | 48 | } |
| 49 | 49 | ||
| @@ -56,28 +56,6 @@ fn opposite_logic_op(kind: ast::BinOp) -> Option<&'static str> { | |||
| 56 | } | 56 | } |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | // This function tries to undo unary negation, or inequality | ||
| 60 | pub(crate) fn undo_negation(node: SyntaxNode) -> Option<String> { | ||
| 61 | match ast::Expr::cast(node)? { | ||
| 62 | ast::Expr::BinExpr(bin) => match bin.op_kind()? { | ||
| 63 | ast::BinOp::NegatedEqualityTest => { | ||
| 64 | let lhs = bin.lhs()?.syntax().text(); | ||
| 65 | let rhs = bin.rhs()?.syntax().text(); | ||
| 66 | Some(format!("{} == {}", lhs, rhs)) | ||
| 67 | } | ||
| 68 | _ => None, | ||
| 69 | }, | ||
| 70 | ast::Expr::PrefixExpr(pe) => match pe.op_kind()? { | ||
| 71 | ast::PrefixOp::Not => { | ||
| 72 | let child = pe.expr()?.syntax().text(); | ||
| 73 | Some(String::from(child)) | ||
| 74 | } | ||
| 75 | _ => None, | ||
| 76 | }, | ||
| 77 | _ => None, | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | #[cfg(test)] | 59 | #[cfg(test)] |
| 82 | mod tests { | 60 | mod tests { |
| 83 | use super::*; | 61 | use super::*; |
diff --git a/crates/ra_assists/src/assists/invert_if.rs b/crates/ra_assists/src/assists/invert_if.rs index c2c8529fe..bababa3e2 100644 --- a/crates/ra_assists/src/assists/invert_if.rs +++ b/crates/ra_assists/src/assists/invert_if.rs | |||
| @@ -1,8 +1,7 @@ | |||
| 1 | use hir::db::HirDatabase; | 1 | use hir::db::HirDatabase; |
| 2 | use ra_syntax::ast::{self, AstNode}; | 2 | use ra_syntax::ast::{self, AstNode}; |
| 3 | use ra_syntax::{TextRange, TextUnit}; | 3 | use ra_syntax::T; |
| 4 | 4 | ||
| 5 | use super::apply_demorgan::undo_negation; | ||
| 6 | use crate::{Assist, AssistCtx, AssistId}; | 5 | use crate::{Assist, AssistCtx, AssistId}; |
| 7 | 6 | ||
| 8 | // Assist: invert_if | 7 | // Assist: invert_if |
| @@ -14,42 +13,56 @@ use crate::{Assist, AssistCtx, AssistId}; | |||
| 14 | // | 13 | // |
| 15 | // ``` | 14 | // ``` |
| 16 | // fn main() { | 15 | // fn main() { |
| 17 | // if<|> !y {A} else {B} | 16 | // if<|> !y { A } else { B } |
| 18 | // } | 17 | // } |
| 19 | // ``` | 18 | // ``` |
| 20 | // -> | 19 | // -> |
| 21 | // ``` | 20 | // ``` |
| 22 | // fn main() { | 21 | // fn main() { |
| 23 | // if y {B} else {A} | 22 | // if y { B } else { A } |
| 24 | // } | 23 | // } |
| 25 | // ``` | 24 | // ``` |
| 26 | 25 | ||
| 27 | pub(crate) fn invert_if(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 26 | pub(crate) fn invert_if(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
| 28 | let expr = ctx.find_node_at_offset::<ast::IfExpr>()?; | 27 | let if_keyword = ctx.find_token_at_offset(T![if])?; |
| 29 | let expr_range = expr.syntax().text_range(); | 28 | let expr = ast::IfExpr::cast(if_keyword.parent())?; |
| 30 | let if_range = TextRange::offset_len(expr_range.start(), TextUnit::from_usize(2)); | 29 | let if_range = if_keyword.text_range(); |
| 31 | let cursor_in_range = ctx.frange.range.is_subrange(&if_range); | 30 | let cursor_in_range = ctx.frange.range.is_subrange(&if_range); |
| 32 | if !cursor_in_range { | 31 | if !cursor_in_range { |
| 33 | return None; | 32 | return None; |
| 34 | } | 33 | } |
| 35 | 34 | ||
| 36 | let cond = expr.condition()?.expr()?.syntax().clone(); | 35 | let cond = expr.condition()?.expr()?; |
| 37 | let then_node = expr.then_branch()?.syntax().clone(); | 36 | let then_node = expr.then_branch()?.syntax().clone(); |
| 38 | 37 | ||
| 39 | if let ast::ElseBranch::Block(else_block) = expr.else_branch()? { | 38 | if let ast::ElseBranch::Block(else_block) = expr.else_branch()? { |
| 40 | let flip_cond = undo_negation(cond.clone())?; | 39 | let flip_cond = invert_boolean_expression(&cond)?; |
| 41 | let cond_range = cond.text_range(); | 40 | let cond_range = cond.syntax().text_range(); |
| 42 | let else_node = else_block.syntax(); | 41 | let else_node = else_block.syntax(); |
| 43 | let else_range = else_node.text_range(); | 42 | let else_range = else_node.text_range(); |
| 44 | let then_range = then_node.text_range(); | 43 | let then_range = then_node.text_range(); |
| 45 | ctx.add_assist(AssistId("invert_if"), "invert if branches", |edit| { | 44 | return ctx.add_assist(AssistId("invert_if"), "invert if branches", |edit| { |
| 46 | edit.target(if_range); | 45 | edit.target(if_range); |
| 47 | edit.replace(cond_range, flip_cond); | 46 | edit.replace(cond_range, flip_cond.syntax().text()); |
| 48 | edit.replace(else_range, then_node.text()); | 47 | edit.replace(else_range, then_node.text()); |
| 49 | edit.replace(then_range, else_node.text()); | 48 | edit.replace(then_range, else_node.text()); |
| 50 | }) | 49 | }); |
| 51 | } else { | 50 | } |
| 52 | None | 51 | |
| 52 | None | ||
| 53 | } | ||
| 54 | |||
| 55 | pub(crate) fn invert_boolean_expression(expr: &ast::Expr) -> Option<ast::Expr> { | ||
| 56 | match expr { | ||
| 57 | ast::Expr::BinExpr(bin) => match bin.op_kind()? { | ||
| 58 | ast::BinOp::NegatedEqualityTest => bin.replace_op(T![==]).map(|it| it.into()), | ||
| 59 | _ => None, | ||
| 60 | }, | ||
| 61 | ast::Expr::PrefixExpr(pe) => match pe.op_kind()? { | ||
| 62 | ast::PrefixOp::Not => pe.expr(), | ||
| 63 | _ => None, | ||
| 64 | }, | ||
| 65 | _ => None, | ||
| 53 | } | 66 | } |
| 54 | } | 67 | } |
| 55 | 68 | ||
| @@ -63,8 +76,8 @@ mod tests { | |||
| 63 | fn invert_if_remove_inequality() { | 76 | fn invert_if_remove_inequality() { |
| 64 | check_assist( | 77 | check_assist( |
| 65 | invert_if, | 78 | invert_if, |
| 66 | "fn f() { i<|>f x != 3 {1} else {3 + 2} }", | 79 | "fn f() { i<|>f x != 3 { 1 } else { 3 + 2 } }", |
| 67 | "fn f() { i<|>f x == 3 {3 + 2} else {1} }", | 80 | "fn f() { i<|>f x == 3 { 3 + 2 } else { 1 } }", |
| 68 | ) | 81 | ) |
| 69 | } | 82 | } |
| 70 | 83 | ||
| @@ -72,18 +85,18 @@ mod tests { | |||
| 72 | fn invert_if_remove_not() { | 85 | fn invert_if_remove_not() { |
| 73 | check_assist( | 86 | check_assist( |
| 74 | invert_if, | 87 | invert_if, |
| 75 | "fn f() { <|>if !cond {3 * 2} else {1} }", | 88 | "fn f() { <|>if !cond { 3 * 2 } else { 1 } }", |
| 76 | "fn f() { <|>if cond {1} else {3 * 2} }", | 89 | "fn f() { <|>if cond { 1 } else { 3 * 2 } }", |
| 77 | ) | 90 | ) |
| 78 | } | 91 | } |
| 79 | 92 | ||
| 80 | #[test] | 93 | #[test] |
| 81 | fn invert_if_doesnt_apply_with_cursor_not_on_if() { | 94 | fn invert_if_doesnt_apply_with_cursor_not_on_if() { |
| 82 | check_assist_not_applicable(invert_if, "fn f() { if !<|>cond {3 * 2} else {1} }") | 95 | check_assist_not_applicable(invert_if, "fn f() { if !<|>cond { 3 * 2 } else { 1 } }") |
| 83 | } | 96 | } |
| 84 | 97 | ||
| 85 | #[test] | 98 | #[test] |
| 86 | fn invert_if_doesnt_apply_without_negated() { | 99 | fn invert_if_doesnt_apply_without_negated() { |
| 87 | check_assist_not_applicable(invert_if, "fn f() { i<|>f cond {3 * 2} else {1} }") | 100 | check_assist_not_applicable(invert_if, "fn f() { i<|>f cond { 3 * 2 } else { 1 } }") |
| 88 | } | 101 | } |
| 89 | } | 102 | } |
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index 1ccc016d3..3c716c2d1 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs | |||
| @@ -347,12 +347,12 @@ fn doctest_invert_if() { | |||
| 347 | "invert_if", | 347 | "invert_if", |
| 348 | r#####" | 348 | r#####" |
| 349 | fn main() { | 349 | fn main() { |
| 350 | if<|> !y {A} else {B} | 350 | if<|> !y { A } else { B } |
| 351 | } | 351 | } |
| 352 | "#####, | 352 | "#####, |
| 353 | r#####" | 353 | r#####" |
| 354 | fn main() { | 354 | fn main() { |
| 355 | if y {B} else {A} | 355 | if y { B } else { A } |
| 356 | } | 356 | } |
| 357 | "#####, | 357 | "#####, |
| 358 | ) | 358 | ) |
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs index 6f005a2d8..95bf9db14 100644 --- a/crates/ra_syntax/src/ast/edit.rs +++ b/crates/ra_syntax/src/ast/edit.rs | |||
| @@ -13,11 +13,21 @@ use crate::{ | |||
| 13 | make::{self, tokens}, | 13 | make::{self, tokens}, |
| 14 | AstNode, TypeBoundsOwner, | 14 | AstNode, TypeBoundsOwner, |
| 15 | }, | 15 | }, |
| 16 | AstToken, Direction, InsertPosition, SmolStr, SyntaxElement, | 16 | AstToken, Direction, InsertPosition, SmolStr, SyntaxElement, SyntaxKind, |
| 17 | SyntaxKind::{ATTR, COMMENT, WHITESPACE}, | 17 | SyntaxKind::{ATTR, COMMENT, WHITESPACE}, |
| 18 | SyntaxNode, SyntaxToken, T, | 18 | SyntaxNode, SyntaxToken, T, |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | impl ast::BinExpr { | ||
| 22 | #[must_use] | ||
| 23 | pub fn replace_op(&self, op: SyntaxKind) -> Option<ast::BinExpr> { | ||
| 24 | let op_node: SyntaxElement = self.op_details()?.0.into(); | ||
| 25 | let to_insert: Option<SyntaxElement> = Some(tokens::op(op).into()); | ||
| 26 | let replace_range = RangeInclusive::new(op_node.clone(), op_node); | ||
| 27 | Some(replace_children(self, replace_range, to_insert.into_iter())) | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 21 | impl ast::FnDef { | 31 | impl ast::FnDef { |
| 22 | #[must_use] | 32 | #[must_use] |
| 23 | pub fn with_body(&self, body: ast::Block) -> ast::FnDef { | 33 | pub fn with_body(&self, body: ast::Block) -> ast::FnDef { |
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs index 7c53aa934..2fd039837 100644 --- a/crates/ra_syntax/src/ast/expr_extensions.rs +++ b/crates/ra_syntax/src/ast/expr_extensions.rs | |||
| @@ -127,7 +127,7 @@ pub enum BinOp { | |||
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | impl ast::BinExpr { | 129 | impl ast::BinExpr { |
| 130 | fn op_details(&self) -> Option<(SyntaxToken, BinOp)> { | 130 | pub fn op_details(&self) -> Option<(SyntaxToken, BinOp)> { |
| 131 | self.syntax().children_with_tokens().filter_map(|it| it.into_token()).find_map(|c| { | 131 | self.syntax().children_with_tokens().filter_map(|it| it.into_token()).find_map(|c| { |
| 132 | let bin_op = match c.kind() { | 132 | let bin_op = match c.kind() { |
| 133 | T![||] => BinOp::BooleanOr, | 133 | T![||] => BinOp::BooleanOr, |
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 9749327fa..40db570da 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
| @@ -173,10 +173,21 @@ fn ast_from_text<N: AstNode>(text: &str) -> N { | |||
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | pub mod tokens { | 175 | pub mod tokens { |
| 176 | use crate::{AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken, T}; | 176 | use crate::{AstNode, Parse, SourceFile, SyntaxKind, SyntaxKind::*, SyntaxToken, T}; |
| 177 | use once_cell::sync::Lazy; | 177 | use once_cell::sync::Lazy; |
| 178 | 178 | ||
| 179 | static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| SourceFile::parse(",\n; ;")); | 179 | static SOURCE_FILE: Lazy<Parse<SourceFile>> = |
| 180 | Lazy::new(|| SourceFile::parse("const C: () = (1 != 1, 2 == 2)\n;")); | ||
| 181 | |||
| 182 | pub fn op(op: SyntaxKind) -> SyntaxToken { | ||
| 183 | SOURCE_FILE | ||
| 184 | .tree() | ||
| 185 | .syntax() | ||
| 186 | .descendants_with_tokens() | ||
| 187 | .filter_map(|it| it.into_token()) | ||
| 188 | .find(|it| it.kind() == op) | ||
| 189 | .unwrap() | ||
| 190 | } | ||
| 180 | 191 | ||
| 181 | pub fn comma() -> SyntaxToken { | 192 | pub fn comma() -> SyntaxToken { |
| 182 | SOURCE_FILE | 193 | SOURCE_FILE |
