aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbravomikekilo <[email protected]>2019-11-24 05:14:57 +0000
committerbravomikekilo <[email protected]>2019-11-24 05:14:57 +0000
commitadac4fc2f21117486356063d82d79f8c3add084a (patch)
tree5d99ff1e3b5b0dcc19aa28633c102490454b3a89 /crates
parent1ebfa908d50a7ef4765d2abb432531d9c98cbb58 (diff)
do refact and fix some issue
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/assists/apply_demorgan.rs40
-rw-r--r--crates/ra_assists/src/assists/invert_if.rs55
-rw-r--r--crates/ra_assists/src/doc_tests/generated.rs4
-rw-r--r--crates/ra_syntax/src/ast/edit.rs12
-rw-r--r--crates/ra_syntax/src/ast/expr_extensions.rs2
-rw-r--r--crates/ra_syntax/src/ast/make.rs15
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 @@
1use super::invert_if::invert_boolean_expression;
1use hir::db::HirDatabase; 2use hir::db::HirDatabase;
2use ra_syntax::ast::{self, AstNode}; 3use ra_syntax::ast::{self, AstNode};
3use ra_syntax::SyntaxNode;
4 4
5use crate::{Assist, AssistCtx, AssistId}; 5use 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
60pub(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)]
82mod tests { 60mod 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 @@
1use hir::db::HirDatabase; 1use hir::db::HirDatabase;
2use ra_syntax::ast::{self, AstNode}; 2use ra_syntax::ast::{self, AstNode};
3use ra_syntax::{TextRange, TextUnit}; 3use ra_syntax::T;
4 4
5use super::apply_demorgan::undo_negation;
6use crate::{Assist, AssistCtx, AssistId}; 5use 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
27pub(crate) fn invert_if(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 26pub(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
55pub(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#####"
349fn main() { 349fn main() {
350 if<|> !y {A} else {B} 350 if<|> !y { A } else { B }
351} 351}
352"#####, 352"#####,
353 r#####" 353 r#####"
354fn main() { 354fn 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
21impl 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
21impl ast::FnDef { 31impl 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
129impl ast::BinExpr { 129impl 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
175pub mod tokens { 175pub 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