diff options
Diffstat (limited to 'crates/ra_assists')
-rw-r--r-- | crates/ra_assists/src/add_derive.rs | 6 | ||||
-rw-r--r-- | crates/ra_assists/src/add_impl.rs | 8 | ||||
-rw-r--r-- | crates/ra_assists/src/add_missing_impl_members.rs | 15 | ||||
-rw-r--r-- | crates/ra_assists/src/assist_ctx.rs | 16 | ||||
-rw-r--r-- | crates/ra_assists/src/auto_import.rs | 13 | ||||
-rw-r--r-- | crates/ra_assists/src/change_visibility.rs | 10 | ||||
-rw-r--r-- | crates/ra_assists/src/flip_binexpr.rs | 2 | ||||
-rw-r--r-- | crates/ra_assists/src/flip_comma.rs | 10 | ||||
-rw-r--r-- | crates/ra_assists/src/inline_local_variable.rs | 432 | ||||
-rw-r--r-- | crates/ra_assists/src/introduce_variable.rs | 28 | ||||
-rw-r--r-- | crates/ra_assists/src/remove_dbg.rs | 6 | ||||
-rw-r--r-- | crates/ra_assists/src/replace_if_let_with_match.rs | 4 | ||||
-rw-r--r-- | crates/ra_assists/src/split_import.rs | 4 |
13 files changed, 451 insertions, 103 deletions
diff --git a/crates/ra_assists/src/add_derive.rs b/crates/ra_assists/src/add_derive.rs index e91b5eb8d..0c4cf2615 100644 --- a/crates/ra_assists/src/add_derive.rs +++ b/crates/ra_assists/src/add_derive.rs | |||
@@ -33,8 +33,10 @@ pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> | |||
33 | 33 | ||
34 | // Insert `derive` after doc comments. | 34 | // Insert `derive` after doc comments. |
35 | fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextUnit> { | 35 | fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextUnit> { |
36 | let non_ws_child = | 36 | let non_ws_child = nominal |
37 | nominal.syntax().children().find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?; | 37 | .syntax() |
38 | .children_with_tokens() | ||
39 | .find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?; | ||
38 | Some(non_ws_child.range().start()) | 40 | Some(non_ws_child.range().start()) |
39 | } | 41 | } |
40 | 42 | ||
diff --git a/crates/ra_assists/src/add_impl.rs b/crates/ra_assists/src/add_impl.rs index b292f188d..fa1c85890 100644 --- a/crates/ra_assists/src/add_impl.rs +++ b/crates/ra_assists/src/add_impl.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use join_to_string::join; | 1 | use join_to_string::join; |
2 | use hir::db::HirDatabase; | 2 | use hir::db::HirDatabase; |
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | ast::{self, AstNode, AstToken, NameOwner, TypeParamsOwner}, | 4 | ast::{self, AstNode, NameOwner, TypeParamsOwner}, |
5 | TextUnit, | 5 | TextUnit, |
6 | }; | 6 | }; |
7 | 7 | ||
@@ -22,8 +22,10 @@ pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | |||
22 | buf.push_str(" "); | 22 | buf.push_str(" "); |
23 | buf.push_str(name.text().as_str()); | 23 | buf.push_str(name.text().as_str()); |
24 | if let Some(type_params) = type_params { | 24 | if let Some(type_params) = type_params { |
25 | let lifetime_params = | 25 | let lifetime_params = type_params |
26 | type_params.lifetime_params().filter_map(|it| it.lifetime()).map(|it| it.text()); | 26 | .lifetime_params() |
27 | .filter_map(|it| it.lifetime_token()) | ||
28 | .map(|it| it.text()); | ||
27 | let type_params = | 29 | let type_params = |
28 | type_params.type_params().filter_map(|it| it.name()).map(|it| it.text()); | 30 | type_params.type_params().filter_map(|it| it.name()).map(|it| it.text()); |
29 | join(lifetime_params.chain(type_params)).surround_with("<", ">").to_buf(&mut buf); | 31 | join(lifetime_params.chain(type_params)).surround_with("<", ">").to_buf(&mut buf); |
diff --git a/crates/ra_assists/src/add_missing_impl_members.rs b/crates/ra_assists/src/add_missing_impl_members.rs index e13f54c4f..19a2d05bc 100644 --- a/crates/ra_assists/src/add_missing_impl_members.rs +++ b/crates/ra_assists/src/add_missing_impl_members.rs | |||
@@ -1,9 +1,11 @@ | |||
1 | use std::fmt::Write; | ||
2 | |||
1 | use crate::{Assist, AssistId, AssistCtx}; | 3 | use crate::{Assist, AssistId, AssistCtx}; |
2 | 4 | ||
3 | use hir::Resolver; | 5 | use hir::Resolver; |
4 | use hir::db::HirDatabase; | 6 | use hir::db::HirDatabase; |
5 | use ra_syntax::{SmolStr, SyntaxKind, TextRange, TextUnit, TreeArc}; | 7 | use ra_syntax::{SmolStr, SyntaxKind, TextRange, TextUnit, TreeArc}; |
6 | use ra_syntax::ast::{self, AstNode, FnDef, ImplItem, ImplItemKind, NameOwner}; | 8 | use ra_syntax::ast::{self, AstNode, AstToken, FnDef, ImplItem, ImplItemKind, NameOwner}; |
7 | use ra_db::FilePosition; | 9 | use ra_db::FilePosition; |
8 | use ra_fmt::{leading_indent, reindent}; | 10 | use ra_fmt::{leading_indent, reindent}; |
9 | 11 | ||
@@ -91,8 +93,9 @@ fn add_missing_impl_members_inner( | |||
91 | }; | 93 | }; |
92 | 94 | ||
93 | let changed_range = { | 95 | let changed_range = { |
94 | let children = impl_item_list.syntax().children(); | 96 | let children = impl_item_list.syntax().children_with_tokens(); |
95 | let last_whitespace = children.filter_map(ast::Whitespace::cast).last(); | 97 | let last_whitespace = |
98 | children.filter_map(|it| ast::Whitespace::cast(it.as_token()?)).last(); | ||
96 | 99 | ||
97 | last_whitespace.map(|w| w.syntax().range()).unwrap_or_else(|| { | 100 | last_whitespace.map(|w| w.syntax().range()).unwrap_or_else(|| { |
98 | let in_brackets = impl_item_list.syntax().range().end() - TextUnit::of_str("}"); | 101 | let in_brackets = impl_item_list.syntax().range().end() - TextUnit::of_str("}"); |
@@ -134,13 +137,13 @@ fn resolve_target_trait_def( | |||
134 | fn build_func_body(def: &ast::FnDef) -> String { | 137 | fn build_func_body(def: &ast::FnDef) -> String { |
135 | let mut buf = String::new(); | 138 | let mut buf = String::new(); |
136 | 139 | ||
137 | for child in def.syntax().children() { | 140 | for child in def.syntax().children_with_tokens() { |
138 | match (child.prev_sibling().map(|c| c.kind()), child.kind()) { | 141 | match (child.prev_sibling_or_token().map(|c| c.kind()), child.kind()) { |
139 | (_, SyntaxKind::SEMI) => buf.push_str(" { unimplemented!() }"), | 142 | (_, SyntaxKind::SEMI) => buf.push_str(" { unimplemented!() }"), |
140 | (_, SyntaxKind::ATTR) | (_, SyntaxKind::COMMENT) => {} | 143 | (_, SyntaxKind::ATTR) | (_, SyntaxKind::COMMENT) => {} |
141 | (Some(SyntaxKind::ATTR), SyntaxKind::WHITESPACE) | 144 | (Some(SyntaxKind::ATTR), SyntaxKind::WHITESPACE) |
142 | | (Some(SyntaxKind::COMMENT), SyntaxKind::WHITESPACE) => {} | 145 | | (Some(SyntaxKind::COMMENT), SyntaxKind::WHITESPACE) => {} |
143 | _ => child.text().push_to(&mut buf), | 146 | _ => write!(buf, "{}", child).unwrap(), |
144 | }; | 147 | }; |
145 | } | 148 | } |
146 | 149 | ||
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 4ad21c74b..e80e35738 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs | |||
@@ -2,8 +2,8 @@ use hir::db::HirDatabase; | |||
2 | use ra_text_edit::TextEditBuilder; | 2 | use ra_text_edit::TextEditBuilder; |
3 | use ra_db::FileRange; | 3 | use ra_db::FileRange; |
4 | use ra_syntax::{ | 4 | use ra_syntax::{ |
5 | SourceFile, TextRange, AstNode, TextUnit, SyntaxNode, | 5 | SourceFile, TextRange, AstNode, TextUnit, SyntaxNode, SyntaxElement, SyntaxToken, |
6 | algo::{find_leaf_at_offset, find_node_at_offset, find_covering_node, LeafAtOffset}, | 6 | algo::{find_token_at_offset, find_node_at_offset, find_covering_element, TokenAtOffset}, |
7 | }; | 7 | }; |
8 | use ra_fmt::{leading_indent, reindent}; | 8 | use ra_fmt::{leading_indent, reindent}; |
9 | 9 | ||
@@ -104,15 +104,19 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> { | |||
104 | Some(self.assist) | 104 | Some(self.assist) |
105 | } | 105 | } |
106 | 106 | ||
107 | pub(crate) fn leaf_at_offset(&self) -> LeafAtOffset<&'a SyntaxNode> { | 107 | pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken<'a>> { |
108 | find_leaf_at_offset(self.source_file.syntax(), self.frange.range.start()) | 108 | find_token_at_offset(self.source_file.syntax(), self.frange.range.start()) |
109 | } | 109 | } |
110 | 110 | ||
111 | pub(crate) fn node_at_offset<N: AstNode>(&self) -> Option<&'a N> { | 111 | pub(crate) fn node_at_offset<N: AstNode>(&self) -> Option<&'a N> { |
112 | find_node_at_offset(self.source_file.syntax(), self.frange.range.start()) | 112 | find_node_at_offset(self.source_file.syntax(), self.frange.range.start()) |
113 | } | 113 | } |
114 | pub(crate) fn covering_node(&self) -> &'a SyntaxNode { | 114 | pub(crate) fn covering_element(&self) -> SyntaxElement<'a> { |
115 | find_covering_node(self.source_file.syntax(), self.frange.range) | 115 | find_covering_element(self.source_file.syntax(), self.frange.range) |
116 | } | ||
117 | |||
118 | pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement<'a> { | ||
119 | find_covering_element(self.source_file.syntax(), range) | ||
116 | } | 120 | } |
117 | } | 121 | } |
118 | 122 | ||
diff --git a/crates/ra_assists/src/auto_import.rs b/crates/ra_assists/src/auto_import.rs index 685dbed06..3fdf6b0d9 100644 --- a/crates/ra_assists/src/auto_import.rs +++ b/crates/ra_assists/src/auto_import.rs | |||
@@ -21,7 +21,7 @@ fn collect_path_segments_raw<'a>( | |||
21 | ) -> Option<usize> { | 21 | ) -> Option<usize> { |
22 | let oldlen = segments.len(); | 22 | let oldlen = segments.len(); |
23 | loop { | 23 | loop { |
24 | let mut children = path.syntax().children(); | 24 | let mut children = path.syntax().children_with_tokens(); |
25 | let (first, second, third) = ( | 25 | let (first, second, third) = ( |
26 | children.next().map(|n| (n, n.kind())), | 26 | children.next().map(|n| (n, n.kind())), |
27 | children.next().map(|n| (n, n.kind())), | 27 | children.next().map(|n| (n, n.kind())), |
@@ -29,11 +29,11 @@ fn collect_path_segments_raw<'a>( | |||
29 | ); | 29 | ); |
30 | match (first, second, third) { | 30 | match (first, second, third) { |
31 | (Some((subpath, PATH)), Some((_, COLONCOLON)), Some((segment, PATH_SEGMENT))) => { | 31 | (Some((subpath, PATH)), Some((_, COLONCOLON)), Some((segment, PATH_SEGMENT))) => { |
32 | path = ast::Path::cast(subpath)?; | 32 | path = ast::Path::cast(subpath.as_node()?)?; |
33 | segments.push(ast::PathSegment::cast(segment)?); | 33 | segments.push(ast::PathSegment::cast(segment.as_node()?)?); |
34 | } | 34 | } |
35 | (Some((segment, PATH_SEGMENT)), _, _) => { | 35 | (Some((segment, PATH_SEGMENT)), _, _) => { |
36 | segments.push(ast::PathSegment::cast(segment)?); | 36 | segments.push(ast::PathSegment::cast(segment.as_node()?)?); |
37 | break; | 37 | break; |
38 | } | 38 | } |
39 | (_, _, _) => return None, | 39 | (_, _, _) => return None, |
@@ -514,8 +514,7 @@ fn apply_auto_import<'a>( | |||
514 | } | 514 | } |
515 | 515 | ||
516 | pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 516 | pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
517 | let node = ctx.covering_node(); | 517 | let path: &ast::Path = ctx.node_at_offset()?; |
518 | let path = node.ancestors().find_map(ast::Path::cast)?; | ||
519 | // We don't want to mess with use statements | 518 | // We don't want to mess with use statements |
520 | if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() { | 519 | if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() { |
521 | return None; | 520 | return None; |
@@ -537,7 +536,7 @@ pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist | |||
537 | ); | 536 | ); |
538 | } | 537 | } |
539 | } else { | 538 | } else { |
540 | let current_file = node.ancestors().find_map(ast::SourceFile::cast)?; | 539 | let current_file = path.syntax().ancestors().find_map(ast::SourceFile::cast)?; |
541 | ctx.add_action( | 540 | ctx.add_action( |
542 | AssistId("auto_import"), | 541 | AssistId("auto_import"), |
543 | format!("import {} in the current file", fmt_segments(&segments)), | 542 | format!("import {} in the current file", fmt_segments(&segments)), |
diff --git a/crates/ra_assists/src/change_visibility.rs b/crates/ra_assists/src/change_visibility.rs index 50c1be5ae..c63470726 100644 --- a/crates/ra_assists/src/change_visibility.rs +++ b/crates/ra_assists/src/change_visibility.rs | |||
@@ -15,13 +15,13 @@ pub(crate) fn change_visibility(ctx: AssistCtx<impl HirDatabase>) -> Option<Assi | |||
15 | } | 15 | } |
16 | 16 | ||
17 | fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 17 | fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
18 | let item_keyword = ctx.leaf_at_offset().find(|leaf| match leaf.kind() { | 18 | let item_keyword = ctx.token_at_offset().find(|leaf| match leaf.kind() { |
19 | FN_KW | MOD_KW | STRUCT_KW | ENUM_KW | TRAIT_KW => true, | 19 | FN_KW | MOD_KW | STRUCT_KW | ENUM_KW | TRAIT_KW => true, |
20 | _ => false, | 20 | _ => false, |
21 | }); | 21 | }); |
22 | 22 | ||
23 | let (offset, target) = if let Some(keyword) = item_keyword { | 23 | let (offset, target) = if let Some(keyword) = item_keyword { |
24 | let parent = keyword.parent()?; | 24 | let parent = keyword.parent(); |
25 | let def_kws = vec![FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF]; | 25 | let def_kws = vec![FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF]; |
26 | // Parent is not a definition, can't add visibility | 26 | // Parent is not a definition, can't add visibility |
27 | if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) { | 27 | if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) { |
@@ -33,8 +33,8 @@ fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | |||
33 | } | 33 | } |
34 | (vis_offset(parent), keyword.range()) | 34 | (vis_offset(parent), keyword.range()) |
35 | } else { | 35 | } else { |
36 | let ident = ctx.leaf_at_offset().find(|leaf| leaf.kind() == IDENT)?; | 36 | let ident = ctx.token_at_offset().find(|leaf| leaf.kind() == IDENT)?; |
37 | let field = ident.ancestors().find_map(ast::NamedFieldDef::cast)?; | 37 | let field = ident.parent().ancestors().find_map(ast::NamedFieldDef::cast)?; |
38 | if field.name()?.syntax().range() != ident.range() && field.visibility().is_some() { | 38 | if field.name()?.syntax().range() != ident.range() && field.visibility().is_some() { |
39 | return None; | 39 | return None; |
40 | } | 40 | } |
@@ -51,7 +51,7 @@ fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | |||
51 | } | 51 | } |
52 | 52 | ||
53 | fn vis_offset(node: &SyntaxNode) -> TextUnit { | 53 | fn vis_offset(node: &SyntaxNode) -> TextUnit { |
54 | node.children() | 54 | node.children_with_tokens() |
55 | .skip_while(|it| match it.kind() { | 55 | .skip_while(|it| match it.kind() { |
56 | WHITESPACE | COMMENT | ATTR => true, | 56 | WHITESPACE | COMMENT | ATTR => true, |
57 | _ => false, | 57 | _ => false, |
diff --git a/crates/ra_assists/src/flip_binexpr.rs b/crates/ra_assists/src/flip_binexpr.rs index ec377642e..02d27f66d 100644 --- a/crates/ra_assists/src/flip_binexpr.rs +++ b/crates/ra_assists/src/flip_binexpr.rs | |||
@@ -8,7 +8,7 @@ pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assis | |||
8 | let expr = ctx.node_at_offset::<BinExpr>()?; | 8 | let expr = ctx.node_at_offset::<BinExpr>()?; |
9 | let lhs = expr.lhs()?.syntax(); | 9 | let lhs = expr.lhs()?.syntax(); |
10 | let rhs = expr.rhs()?.syntax(); | 10 | let rhs = expr.rhs()?.syntax(); |
11 | let op_range = expr.op()?.range(); | 11 | let op_range = expr.op_token()?.range(); |
12 | // The assist should be applied only if the cursor is on the operator | 12 | // The assist should be applied only if the cursor is on the operator |
13 | let cursor_in_range = ctx.frange.range.is_subrange(&op_range); | 13 | let cursor_in_range = ctx.frange.range.is_subrange(&op_range); |
14 | if !cursor_in_range { | 14 | if !cursor_in_range { |
diff --git a/crates/ra_assists/src/flip_comma.rs b/crates/ra_assists/src/flip_comma.rs index 6b98cac68..a9b108111 100644 --- a/crates/ra_assists/src/flip_comma.rs +++ b/crates/ra_assists/src/flip_comma.rs | |||
@@ -8,13 +8,13 @@ use ra_syntax::{ | |||
8 | use crate::{AssistCtx, Assist, AssistId}; | 8 | use crate::{AssistCtx, Assist, AssistId}; |
9 | 9 | ||
10 | pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 10 | pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
11 | let comma = ctx.leaf_at_offset().find(|leaf| leaf.kind() == COMMA)?; | 11 | let comma = ctx.token_at_offset().find(|leaf| leaf.kind() == COMMA)?; |
12 | let prev = non_trivia_sibling(comma, Direction::Prev)?; | 12 | let prev = non_trivia_sibling(comma.into(), Direction::Prev)?; |
13 | let next = non_trivia_sibling(comma, Direction::Next)?; | 13 | let next = non_trivia_sibling(comma.into(), Direction::Next)?; |
14 | ctx.add_action(AssistId("flip_comma"), "flip comma", |edit| { | 14 | ctx.add_action(AssistId("flip_comma"), "flip comma", |edit| { |
15 | edit.target(comma.range()); | 15 | edit.target(comma.range()); |
16 | edit.replace(prev.range(), next.text()); | 16 | edit.replace(prev.range(), next.to_string()); |
17 | edit.replace(next.range(), prev.text()); | 17 | edit.replace(next.range(), prev.to_string()); |
18 | }); | 18 | }); |
19 | 19 | ||
20 | ctx.build() | 20 | ctx.build() |
diff --git a/crates/ra_assists/src/inline_local_variable.rs b/crates/ra_assists/src/inline_local_variable.rs index bd3cdb970..950c2910b 100644 --- a/crates/ra_assists/src/inline_local_variable.rs +++ b/crates/ra_assists/src/inline_local_variable.rs | |||
@@ -1,7 +1,11 @@ | |||
1 | use hir::db::HirDatabase; | 1 | use hir::{ |
2 | use hir::source_binder::function_from_child_node; | 2 | db::HirDatabase, |
3 | use ra_syntax::{ast::{self, AstNode}, TextRange}; | 3 | source_binder::function_from_child_node, |
4 | use ra_syntax::ast::{PatKind, ExprKind}; | 4 | }; |
5 | use ra_syntax::{ | ||
6 | ast::{self, AstNode, AstToken, PatKind, ExprKind}, | ||
7 | TextRange, | ||
8 | }; | ||
5 | 9 | ||
6 | use crate::{Assist, AssistCtx, AssistId}; | 10 | use crate::{Assist, AssistCtx, AssistId}; |
7 | use crate::assist_ctx::AssistBuilder; | 11 | use crate::assist_ctx::AssistBuilder; |
@@ -15,61 +19,77 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt | |||
15 | if bind_pat.is_mutable() { | 19 | if bind_pat.is_mutable() { |
16 | return None; | 20 | return None; |
17 | } | 21 | } |
18 | let initializer = let_stmt.initializer()?; | 22 | let initializer_expr = let_stmt.initializer(); |
19 | let wrap_in_parens = match initializer.kind() { | 23 | let delete_range = if let Some(whitespace) = let_stmt |
20 | ExprKind::LambdaExpr(_) | 24 | .syntax() |
21 | | ExprKind::IfExpr(_) | 25 | .next_sibling_or_token() |
22 | | ExprKind::LoopExpr(_) | 26 | .and_then(|it| ast::Whitespace::cast(it.as_token()?)) |
23 | | ExprKind::ForExpr(_) | ||
24 | | ExprKind::WhileExpr(_) | ||
25 | | ExprKind::ContinueExpr(_) | ||
26 | | ExprKind::BreakExpr(_) | ||
27 | | ExprKind::Label(_) | ||
28 | | ExprKind::ReturnExpr(_) | ||
29 | | ExprKind::MatchExpr(_) | ||
30 | | ExprKind::StructLit(_) | ||
31 | | ExprKind::CastExpr(_) | ||
32 | | ExprKind::PrefixExpr(_) | ||
33 | | ExprKind::RangeExpr(_) | ||
34 | | ExprKind::BinExpr(_) => true, | ||
35 | ExprKind::CallExpr(_) | ||
36 | | ExprKind::IndexExpr(_) | ||
37 | | ExprKind::MethodCallExpr(_) | ||
38 | | ExprKind::FieldExpr(_) | ||
39 | | ExprKind::TryExpr(_) | ||
40 | | ExprKind::RefExpr(_) | ||
41 | | ExprKind::Literal(_) | ||
42 | | ExprKind::TupleExpr(_) | ||
43 | | ExprKind::ArrayExpr(_) | ||
44 | | ExprKind::ParenExpr(_) | ||
45 | | ExprKind::PathExpr(_) | ||
46 | | ExprKind::BlockExpr(_) => false, | ||
47 | }; | ||
48 | |||
49 | let delete_range = if let Some(whitespace) = | ||
50 | let_stmt.syntax().next_sibling().and_then(ast::Whitespace::cast) | ||
51 | { | 27 | { |
52 | TextRange::from_to(let_stmt.syntax().range().start(), whitespace.syntax().range().end()) | 28 | TextRange::from_to(let_stmt.syntax().range().start(), whitespace.syntax().range().end()) |
53 | } else { | 29 | } else { |
54 | let_stmt.syntax().range() | 30 | let_stmt.syntax().range() |
55 | }; | 31 | }; |
56 | 32 | ||
57 | let init_str = if wrap_in_parens { | ||
58 | format!("({})", initializer.syntax().text().to_string()) | ||
59 | } else { | ||
60 | initializer.syntax().text().to_string() | ||
61 | }; | ||
62 | let function = function_from_child_node(ctx.db, ctx.frange.file_id, bind_pat.syntax())?; | 33 | let function = function_from_child_node(ctx.db, ctx.frange.file_id, bind_pat.syntax())?; |
63 | let scope = function.scopes(ctx.db); | 34 | let scope = function.scopes(ctx.db); |
64 | let refs = scope.find_all_refs(bind_pat); | 35 | let refs = scope.find_all_refs(bind_pat); |
65 | 36 | ||
37 | let mut wrap_in_parens = vec![true; refs.len()]; | ||
38 | |||
39 | for (i, desc) in refs.iter().enumerate() { | ||
40 | let usage_node = ctx | ||
41 | .covering_node_for_range(desc.range) | ||
42 | .ancestors() | ||
43 | .find_map(|node| ast::PathExpr::cast(node))?; | ||
44 | let usage_parent_option = usage_node.syntax().parent().and_then(ast::Expr::cast); | ||
45 | let usage_parent = match usage_parent_option { | ||
46 | Some(u) => u, | ||
47 | None => { | ||
48 | wrap_in_parens[i] = false; | ||
49 | continue; | ||
50 | } | ||
51 | }; | ||
52 | |||
53 | wrap_in_parens[i] = match (initializer_expr?.kind(), usage_parent.kind()) { | ||
54 | (ExprKind::CallExpr(_), _) | ||
55 | | (ExprKind::IndexExpr(_), _) | ||
56 | | (ExprKind::MethodCallExpr(_), _) | ||
57 | | (ExprKind::FieldExpr(_), _) | ||
58 | | (ExprKind::TryExpr(_), _) | ||
59 | | (ExprKind::RefExpr(_), _) | ||
60 | | (ExprKind::Literal(_), _) | ||
61 | | (ExprKind::TupleExpr(_), _) | ||
62 | | (ExprKind::ArrayExpr(_), _) | ||
63 | | (ExprKind::ParenExpr(_), _) | ||
64 | | (ExprKind::PathExpr(_), _) | ||
65 | | (ExprKind::BlockExpr(_), _) | ||
66 | | (_, ExprKind::CallExpr(_)) | ||
67 | | (_, ExprKind::TupleExpr(_)) | ||
68 | | (_, ExprKind::ArrayExpr(_)) | ||
69 | | (_, ExprKind::ParenExpr(_)) | ||
70 | | (_, ExprKind::ForExpr(_)) | ||
71 | | (_, ExprKind::WhileExpr(_)) | ||
72 | | (_, ExprKind::BreakExpr(_)) | ||
73 | | (_, ExprKind::ReturnExpr(_)) | ||
74 | | (_, ExprKind::MatchExpr(_)) => false, | ||
75 | _ => true, | ||
76 | }; | ||
77 | } | ||
78 | |||
79 | let init_str = initializer_expr?.syntax().text().to_string(); | ||
80 | let init_in_paren = format!("({})", &init_str); | ||
81 | |||
66 | ctx.add_action( | 82 | ctx.add_action( |
67 | AssistId("inline_local_variable"), | 83 | AssistId("inline_local_variable"), |
68 | "inline local variable", | 84 | "inline local variable", |
69 | move |edit: &mut AssistBuilder| { | 85 | move |edit: &mut AssistBuilder| { |
70 | edit.delete(delete_range); | 86 | edit.delete(delete_range); |
71 | for desc in refs { | 87 | for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) { |
72 | edit.replace(desc.range, init_str.clone()) | 88 | if should_wrap { |
89 | edit.replace(desc.range, init_in_paren.clone()) | ||
90 | } else { | ||
91 | edit.replace(desc.range, init_str.clone()) | ||
92 | } | ||
73 | } | 93 | } |
74 | edit.set_cursor(delete_range.start()) | 94 | edit.set_cursor(delete_range.start()) |
75 | }, | 95 | }, |
@@ -147,7 +167,7 @@ fn foo() { | |||
147 | 167 | ||
148 | } | 168 | } |
149 | let b = (1 + 1) * 10; | 169 | let b = (1 + 1) * 10; |
150 | bar((1 + 1)); | 170 | bar(1 + 1); |
151 | }", | 171 | }", |
152 | ); | 172 | ); |
153 | } | 173 | } |
@@ -215,7 +235,7 @@ fn foo() { | |||
215 | 235 | ||
216 | } | 236 | } |
217 | let b = (bar(1) as u64) * 10; | 237 | let b = (bar(1) as u64) * 10; |
218 | bar((bar(1) as u64)); | 238 | bar(bar(1) as u64); |
219 | }", | 239 | }", |
220 | ); | 240 | ); |
221 | } | 241 | } |
@@ -295,4 +315,324 @@ fn foo() { | |||
295 | }", | 315 | }", |
296 | ); | 316 | ); |
297 | } | 317 | } |
318 | |||
319 | #[test] | ||
320 | fn test_call_expr() { | ||
321 | check_assist( | ||
322 | inline_local_varialbe, | ||
323 | " | ||
324 | fn foo() { | ||
325 | let a<|> = bar(10 + 1); | ||
326 | let b = a * 10; | ||
327 | let c = a as usize; | ||
328 | }", | ||
329 | " | ||
330 | fn foo() { | ||
331 | <|>let b = bar(10 + 1) * 10; | ||
332 | let c = bar(10 + 1) as usize; | ||
333 | }", | ||
334 | ); | ||
335 | } | ||
336 | |||
337 | #[test] | ||
338 | fn test_index_expr() { | ||
339 | check_assist( | ||
340 | inline_local_varialbe, | ||
341 | " | ||
342 | fn foo() { | ||
343 | let x = vec![1, 2, 3]; | ||
344 | let a<|> = x[0]; | ||
345 | let b = a * 10; | ||
346 | let c = a as usize; | ||
347 | }", | ||
348 | " | ||
349 | fn foo() { | ||
350 | let x = vec![1, 2, 3]; | ||
351 | <|>let b = x[0] * 10; | ||
352 | let c = x[0] as usize; | ||
353 | }", | ||
354 | ); | ||
355 | } | ||
356 | |||
357 | #[test] | ||
358 | fn test_method_call_expr() { | ||
359 | check_assist( | ||
360 | inline_local_varialbe, | ||
361 | " | ||
362 | fn foo() { | ||
363 | let bar = vec![1]; | ||
364 | let a<|> = bar.len(); | ||
365 | let b = a * 10; | ||
366 | let c = a as usize; | ||
367 | }", | ||
368 | " | ||
369 | fn foo() { | ||
370 | let bar = vec![1]; | ||
371 | <|>let b = bar.len() * 10; | ||
372 | let c = bar.len() as usize; | ||
373 | }", | ||
374 | ); | ||
375 | } | ||
376 | |||
377 | #[test] | ||
378 | fn test_field_expr() { | ||
379 | check_assist( | ||
380 | inline_local_varialbe, | ||
381 | " | ||
382 | struct Bar { | ||
383 | foo: usize | ||
384 | } | ||
385 | |||
386 | fn foo() { | ||
387 | let bar = Bar { foo: 1 }; | ||
388 | let a<|> = bar.foo; | ||
389 | let b = a * 10; | ||
390 | let c = a as usize; | ||
391 | }", | ||
392 | " | ||
393 | struct Bar { | ||
394 | foo: usize | ||
395 | } | ||
396 | |||
397 | fn foo() { | ||
398 | let bar = Bar { foo: 1 }; | ||
399 | <|>let b = bar.foo * 10; | ||
400 | let c = bar.foo as usize; | ||
401 | }", | ||
402 | ); | ||
403 | } | ||
404 | |||
405 | #[test] | ||
406 | fn test_try_expr() { | ||
407 | check_assist( | ||
408 | inline_local_varialbe, | ||
409 | " | ||
410 | fn foo() -> Option<usize> { | ||
411 | let bar = Some(1); | ||
412 | let a<|> = bar?; | ||
413 | let b = a * 10; | ||
414 | let c = a as usize; | ||
415 | None | ||
416 | }", | ||
417 | " | ||
418 | fn foo() -> Option<usize> { | ||
419 | let bar = Some(1); | ||
420 | <|>let b = bar? * 10; | ||
421 | let c = bar? as usize; | ||
422 | None | ||
423 | }", | ||
424 | ); | ||
425 | } | ||
426 | |||
427 | #[test] | ||
428 | fn test_ref_expr() { | ||
429 | check_assist( | ||
430 | inline_local_varialbe, | ||
431 | " | ||
432 | fn foo() { | ||
433 | let bar = 10; | ||
434 | let a<|> = &bar; | ||
435 | let b = a * 10; | ||
436 | }", | ||
437 | " | ||
438 | fn foo() { | ||
439 | let bar = 10; | ||
440 | <|>let b = &bar * 10; | ||
441 | }", | ||
442 | ); | ||
443 | } | ||
444 | |||
445 | #[test] | ||
446 | fn test_tuple_expr() { | ||
447 | check_assist( | ||
448 | inline_local_varialbe, | ||
449 | " | ||
450 | fn foo() { | ||
451 | let a<|> = (10, 20); | ||
452 | let b = a[0]; | ||
453 | }", | ||
454 | " | ||
455 | fn foo() { | ||
456 | <|>let b = (10, 20)[0]; | ||
457 | }", | ||
458 | ); | ||
459 | } | ||
460 | |||
461 | #[test] | ||
462 | fn test_array_expr() { | ||
463 | check_assist( | ||
464 | inline_local_varialbe, | ||
465 | " | ||
466 | fn foo() { | ||
467 | let a<|> = [1, 2, 3]; | ||
468 | let b = a.len(); | ||
469 | }", | ||
470 | " | ||
471 | fn foo() { | ||
472 | <|>let b = [1, 2, 3].len(); | ||
473 | }", | ||
474 | ); | ||
475 | } | ||
476 | |||
477 | #[test] | ||
478 | fn test_paren() { | ||
479 | check_assist( | ||
480 | inline_local_varialbe, | ||
481 | " | ||
482 | fn foo() { | ||
483 | let a<|> = (10 + 20); | ||
484 | let b = a * 10; | ||
485 | let c = a as usize; | ||
486 | }", | ||
487 | " | ||
488 | fn foo() { | ||
489 | <|>let b = (10 + 20) * 10; | ||
490 | let c = (10 + 20) as usize; | ||
491 | }", | ||
492 | ); | ||
493 | } | ||
494 | |||
495 | #[test] | ||
496 | fn test_path_expr() { | ||
497 | check_assist( | ||
498 | inline_local_varialbe, | ||
499 | " | ||
500 | fn foo() { | ||
501 | let d = 10; | ||
502 | let a<|> = d; | ||
503 | let b = a * 10; | ||
504 | let c = a as usize; | ||
505 | }", | ||
506 | " | ||
507 | fn foo() { | ||
508 | let d = 10; | ||
509 | <|>let b = d * 10; | ||
510 | let c = d as usize; | ||
511 | }", | ||
512 | ); | ||
513 | } | ||
514 | |||
515 | #[test] | ||
516 | fn test_block_expr() { | ||
517 | check_assist( | ||
518 | inline_local_varialbe, | ||
519 | " | ||
520 | fn foo() { | ||
521 | let a<|> = { 10 }; | ||
522 | let b = a * 10; | ||
523 | let c = a as usize; | ||
524 | }", | ||
525 | " | ||
526 | fn foo() { | ||
527 | <|>let b = { 10 } * 10; | ||
528 | let c = { 10 } as usize; | ||
529 | }", | ||
530 | ); | ||
531 | } | ||
532 | |||
533 | #[test] | ||
534 | fn test_used_in_different_expr1() { | ||
535 | check_assist( | ||
536 | inline_local_varialbe, | ||
537 | " | ||
538 | fn foo() { | ||
539 | let a<|> = 10 + 20; | ||
540 | let b = a * 10; | ||
541 | let c = (a, 20); | ||
542 | let d = [a, 10]; | ||
543 | let e = (a); | ||
544 | }", | ||
545 | " | ||
546 | fn foo() { | ||
547 | <|>let b = (10 + 20) * 10; | ||
548 | let c = (10 + 20, 20); | ||
549 | let d = [10 + 20, 10]; | ||
550 | let e = (10 + 20); | ||
551 | }", | ||
552 | ); | ||
553 | } | ||
554 | |||
555 | #[test] | ||
556 | fn test_used_in_for_expr() { | ||
557 | check_assist( | ||
558 | inline_local_varialbe, | ||
559 | " | ||
560 | fn foo() { | ||
561 | let a<|> = vec![10, 20]; | ||
562 | for i in a {} | ||
563 | }", | ||
564 | " | ||
565 | fn foo() { | ||
566 | <|>for i in vec![10, 20] {} | ||
567 | }", | ||
568 | ); | ||
569 | } | ||
570 | |||
571 | #[test] | ||
572 | fn test_used_in_while_expr() { | ||
573 | check_assist( | ||
574 | inline_local_varialbe, | ||
575 | " | ||
576 | fn foo() { | ||
577 | let a<|> = 1 > 0; | ||
578 | while a {} | ||
579 | }", | ||
580 | " | ||
581 | fn foo() { | ||
582 | <|>while 1 > 0 {} | ||
583 | }", | ||
584 | ); | ||
585 | } | ||
586 | |||
587 | #[test] | ||
588 | fn test_used_in_break_expr() { | ||
589 | check_assist( | ||
590 | inline_local_varialbe, | ||
591 | " | ||
592 | fn foo() { | ||
593 | let a<|> = 1 + 1; | ||
594 | loop { | ||
595 | break a; | ||
596 | } | ||
597 | }", | ||
598 | " | ||
599 | fn foo() { | ||
600 | <|>loop { | ||
601 | break 1 + 1; | ||
602 | } | ||
603 | }", | ||
604 | ); | ||
605 | } | ||
606 | |||
607 | #[test] | ||
608 | fn test_used_in_return_expr() { | ||
609 | check_assist( | ||
610 | inline_local_varialbe, | ||
611 | " | ||
612 | fn foo() { | ||
613 | let a<|> = 1 > 0; | ||
614 | return a; | ||
615 | }", | ||
616 | " | ||
617 | fn foo() { | ||
618 | <|>return 1 > 0; | ||
619 | }", | ||
620 | ); | ||
621 | } | ||
622 | |||
623 | #[test] | ||
624 | fn test_used_in_match_expr() { | ||
625 | check_assist( | ||
626 | inline_local_varialbe, | ||
627 | " | ||
628 | fn foo() { | ||
629 | let a<|> = 1 > 0; | ||
630 | match a {} | ||
631 | }", | ||
632 | " | ||
633 | fn foo() { | ||
634 | <|>match 1 > 0 {} | ||
635 | }", | ||
636 | ); | ||
637 | } | ||
298 | } | 638 | } |
diff --git a/crates/ra_assists/src/introduce_variable.rs b/crates/ra_assists/src/introduce_variable.rs index 353bc4105..fb7333c8c 100644 --- a/crates/ra_assists/src/introduce_variable.rs +++ b/crates/ra_assists/src/introduce_variable.rs | |||
@@ -2,9 +2,8 @@ use test_utils::tested_by; | |||
2 | use hir::db::HirDatabase; | 2 | use hir::db::HirDatabase; |
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | ast::{self, AstNode}, | 4 | ast::{self, AstNode}, |
5 | SyntaxKind::{ | 5 | SyntaxNode, TextUnit, |
6 | WHITESPACE, MATCH_ARM, LAMBDA_EXPR, PATH_EXPR, BREAK_EXPR, LOOP_EXPR, RETURN_EXPR, COMMENT | 6 | SyntaxKind::{WHITESPACE, MATCH_ARM, LAMBDA_EXPR, PATH_EXPR, BREAK_EXPR, LOOP_EXPR, RETURN_EXPR, COMMENT}, |
7 | }, SyntaxNode, TextUnit, | ||
8 | }; | 7 | }; |
9 | 8 | ||
10 | use crate::{AssistCtx, Assist, AssistId}; | 9 | use crate::{AssistCtx, Assist, AssistId}; |
@@ -13,14 +12,14 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option | |||
13 | if ctx.frange.range.is_empty() { | 12 | if ctx.frange.range.is_empty() { |
14 | return None; | 13 | return None; |
15 | } | 14 | } |
16 | let node = ctx.covering_node(); | 15 | let node = ctx.covering_element(); |
17 | if node.kind() == COMMENT { | 16 | if node.kind() == COMMENT { |
18 | tested_by!(introduce_var_in_comment_is_not_applicable); | 17 | tested_by!(introduce_var_in_comment_is_not_applicable); |
19 | return None; | 18 | return None; |
20 | } | 19 | } |
21 | let expr = node.ancestors().find_map(valid_target_expr)?; | 20 | let expr = node.ancestors().find_map(valid_target_expr)?; |
22 | let (anchor_stmt, wrap_in_block) = anchor_stmt(expr)?; | 21 | let (anchor_stmt, wrap_in_block) = anchor_stmt(expr)?; |
23 | let indent = anchor_stmt.prev_sibling()?; | 22 | let indent = anchor_stmt.prev_sibling_or_token()?.as_token()?; |
24 | if indent.kind() != WHITESPACE { | 23 | if indent.kind() != WHITESPACE { |
25 | return None; | 24 | return None; |
26 | } | 25 | } |
@@ -54,16 +53,15 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option | |||
54 | // We want to maintain the indent level, | 53 | // We want to maintain the indent level, |
55 | // but we do not want to duplicate possible | 54 | // but we do not want to duplicate possible |
56 | // extra newlines in the indent block | 55 | // extra newlines in the indent block |
57 | for chunk in indent.text().chunks() { | 56 | let text = indent.text(); |
58 | if chunk.starts_with("\r\n") { | 57 | if text.starts_with("\r\n") { |
59 | buf.push_str("\r\n"); | 58 | buf.push_str("\r\n"); |
60 | buf.push_str(chunk.trim_start_matches("\r\n")); | 59 | buf.push_str(text.trim_start_matches("\r\n")); |
61 | } else if chunk.starts_with("\n") { | 60 | } else if text.starts_with("\n") { |
62 | buf.push_str("\n"); | 61 | buf.push_str("\n"); |
63 | buf.push_str(chunk.trim_start_matches("\n")); | 62 | buf.push_str(text.trim_start_matches("\n")); |
64 | } else { | 63 | } else { |
65 | buf.push_str(chunk); | 64 | buf.push_str(text); |
66 | } | ||
67 | } | 65 | } |
68 | 66 | ||
69 | edit.target(expr.syntax().range()); | 67 | edit.target(expr.syntax().range()); |
diff --git a/crates/ra_assists/src/remove_dbg.rs b/crates/ra_assists/src/remove_dbg.rs index 6ea48d909..ae9958f11 100644 --- a/crates/ra_assists/src/remove_dbg.rs +++ b/crates/ra_assists/src/remove_dbg.rs | |||
@@ -62,15 +62,15 @@ fn is_valid_macrocall(macro_call: &ast::MacroCall, macro_name: &str) -> Option<b | |||
62 | let name_ref = path.segment()?.name_ref()?; | 62 | let name_ref = path.segment()?.name_ref()?; |
63 | 63 | ||
64 | // Make sure it is actually a dbg-macro call, dbg followed by ! | 64 | // Make sure it is actually a dbg-macro call, dbg followed by ! |
65 | let excl = path.syntax().next_sibling()?; | 65 | let excl = path.syntax().next_sibling_or_token()?; |
66 | 66 | ||
67 | if name_ref.text() != macro_name || excl.kind() != EXCL { | 67 | if name_ref.text() != macro_name || excl.kind() != EXCL { |
68 | return None; | 68 | return None; |
69 | } | 69 | } |
70 | 70 | ||
71 | let node = macro_call.token_tree()?.syntax(); | 71 | let node = macro_call.token_tree()?.syntax(); |
72 | let first_child = node.first_child()?; | 72 | let first_child = node.first_child_or_token()?; |
73 | let last_child = node.last_child()?; | 73 | let last_child = node.last_child_or_token()?; |
74 | 74 | ||
75 | match (first_child.kind(), last_child.kind()) { | 75 | match (first_child.kind(), last_child.kind()) { |
76 | (L_PAREN, R_PAREN) | (L_BRACK, R_BRACK) | (L_CURLY, R_CURLY) => Some(true), | 76 | (L_PAREN, R_PAREN) | (L_BRACK, R_BRACK) | (L_CURLY, R_CURLY) => Some(true), |
diff --git a/crates/ra_assists/src/replace_if_let_with_match.rs b/crates/ra_assists/src/replace_if_let_with_match.rs index 230573499..2b451f08d 100644 --- a/crates/ra_assists/src/replace_if_let_with_match.rs +++ b/crates/ra_assists/src/replace_if_let_with_match.rs | |||
@@ -11,8 +11,8 @@ pub(crate) fn replace_if_let_with_match(mut ctx: AssistCtx<impl HirDatabase>) -> | |||
11 | let expr = cond.expr()?; | 11 | let expr = cond.expr()?; |
12 | let then_block = if_expr.then_branch()?; | 12 | let then_block = if_expr.then_branch()?; |
13 | let else_block = match if_expr.else_branch()? { | 13 | let else_block = match if_expr.else_branch()? { |
14 | ast::ElseBranchFlavor::Block(it) => it, | 14 | ast::ElseBranch::Block(it) => it, |
15 | ast::ElseBranchFlavor::IfExpr(_) => return None, | 15 | ast::ElseBranch::IfExpr(_) => return None, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | ctx.add_action(AssistId("replace_if_let_with_match"), "replace with match", |edit| { | 18 | ctx.add_action(AssistId("replace_if_let_with_match"), "replace with match", |edit| { |
diff --git a/crates/ra_assists/src/split_import.rs b/crates/ra_assists/src/split_import.rs index dd5be4e91..4bf1852db 100644 --- a/crates/ra_assists/src/split_import.rs +++ b/crates/ra_assists/src/split_import.rs | |||
@@ -8,8 +8,8 @@ use ra_syntax::{ | |||
8 | use crate::{AssistCtx, Assist, AssistId}; | 8 | use crate::{AssistCtx, Assist, AssistId}; |
9 | 9 | ||
10 | pub(crate) fn split_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 10 | pub(crate) fn split_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
11 | let colon_colon = ctx.leaf_at_offset().find(|leaf| leaf.kind() == COLONCOLON)?; | 11 | let colon_colon = ctx.token_at_offset().find(|leaf| leaf.kind() == COLONCOLON)?; |
12 | let path = colon_colon.parent().and_then(ast::Path::cast)?; | 12 | let path = ast::Path::cast(colon_colon.parent())?; |
13 | let top_path = generate(Some(path), |it| it.parent_path()).last()?; | 13 | let top_path = generate(Some(path), |it| it.parent_path()).last()?; |
14 | 14 | ||
15 | let use_tree = top_path.syntax().ancestors().find_map(ast::UseTree::cast); | 15 | let use_tree = top_path.syntax().ancestors().find_map(ast::UseTree::cast); |