diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_assists/src/add_derive.rs | 2 | ||||
-rw-r--r-- | crates/ra_assists/src/add_explicit_type.rs | 2 | ||||
-rw-r--r-- | crates/ra_assists/src/add_impl.rs | 6 | ||||
-rw-r--r-- | crates/ra_assists/src/add_missing_impl_members.rs | 46 | ||||
-rw-r--r-- | crates/ra_assists/src/assist_ctx.rs | 14 | ||||
-rw-r--r-- | crates/ra_assists/src/ast_editor.rs | 123 | ||||
-rw-r--r-- | crates/ra_assists/src/auto_import.rs | 143 | ||||
-rw-r--r-- | crates/ra_assists/src/change_visibility.rs | 4 | ||||
-rw-r--r-- | crates/ra_assists/src/fill_match_arms.rs | 4 | ||||
-rw-r--r-- | crates/ra_assists/src/flip_binexpr.rs | 4 | ||||
-rw-r--r-- | crates/ra_assists/src/flip_comma.rs | 4 | ||||
-rw-r--r-- | crates/ra_assists/src/inline_local_variable.rs | 10 | ||||
-rw-r--r-- | crates/ra_assists/src/introduce_variable.rs | 24 | ||||
-rw-r--r-- | crates/ra_assists/src/move_guard.rs | 10 | ||||
-rw-r--r-- | crates/ra_assists/src/remove_dbg.rs | 6 | ||||
-rw-r--r-- | crates/ra_assists/src/replace_if_let_with_match.rs | 13 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 2 |
17 files changed, 213 insertions, 204 deletions
diff --git a/crates/ra_assists/src/add_derive.rs b/crates/ra_assists/src/add_derive.rs index bf7d55d6d..f19196f53 100644 --- a/crates/ra_assists/src/add_derive.rs +++ b/crates/ra_assists/src/add_derive.rs | |||
@@ -9,7 +9,7 @@ use crate::{Assist, AssistCtx, AssistId}; | |||
9 | 9 | ||
10 | pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 10 | pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
11 | let nominal = ctx.node_at_offset::<ast::NominalDef>()?; | 11 | let nominal = ctx.node_at_offset::<ast::NominalDef>()?; |
12 | let node_start = derive_insertion_offset(nominal)?; | 12 | let node_start = derive_insertion_offset(&nominal)?; |
13 | ctx.add_action(AssistId("add_derive"), "add `#[derive]`", |edit| { | 13 | ctx.add_action(AssistId("add_derive"), "add `#[derive]`", |edit| { |
14 | let derive_attr = nominal | 14 | let derive_attr = nominal |
15 | .attrs() | 15 | .attrs() |
diff --git a/crates/ra_assists/src/add_explicit_type.rs b/crates/ra_assists/src/add_explicit_type.rs index bb47a32f0..a69cfc8e3 100644 --- a/crates/ra_assists/src/add_explicit_type.rs +++ b/crates/ra_assists/src/add_explicit_type.rs | |||
@@ -27,7 +27,7 @@ pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option< | |||
27 | // Infer type | 27 | // Infer type |
28 | let db = ctx.db; | 28 | let db = ctx.db; |
29 | let analyzer = hir::SourceAnalyzer::new(db, ctx.frange.file_id, stmt.syntax(), None); | 29 | let analyzer = hir::SourceAnalyzer::new(db, ctx.frange.file_id, stmt.syntax(), None); |
30 | let ty = analyzer.type_of(db, expr)?; | 30 | let ty = analyzer.type_of(db, &expr)?; |
31 | // Assist not applicable if the type is unknown | 31 | // Assist not applicable if the type is unknown |
32 | if is_unknown(&ty) { | 32 | if is_unknown(&ty) { |
33 | return None; | 33 | return None; |
diff --git a/crates/ra_assists/src/add_impl.rs b/crates/ra_assists/src/add_impl.rs index b81922c1d..cebc19539 100644 --- a/crates/ra_assists/src/add_impl.rs +++ b/crates/ra_assists/src/add_impl.rs | |||
@@ -16,7 +16,7 @@ pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | |||
16 | let start_offset = nominal.syntax().range().end(); | 16 | let start_offset = nominal.syntax().range().end(); |
17 | let mut buf = String::new(); | 17 | let mut buf = String::new(); |
18 | buf.push_str("\n\nimpl"); | 18 | buf.push_str("\n\nimpl"); |
19 | if let Some(type_params) = type_params { | 19 | if let Some(type_params) = &type_params { |
20 | type_params.syntax().text().push_to(&mut buf); | 20 | type_params.syntax().text().push_to(&mut buf); |
21 | } | 21 | } |
22 | buf.push_str(" "); | 22 | buf.push_str(" "); |
@@ -25,9 +25,9 @@ pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | |||
25 | let lifetime_params = type_params | 25 | let lifetime_params = type_params |
26 | .lifetime_params() | 26 | .lifetime_params() |
27 | .filter_map(|it| it.lifetime_token()) | 27 | .filter_map(|it| it.lifetime_token()) |
28 | .map(|it| it.text()); | 28 | .map(|it| it.text().clone()); |
29 | let type_params = | 29 | let type_params = |
30 | 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().clone()); |
31 | 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); |
32 | } | 32 | } |
33 | buf.push_str(" {\n"); | 33 | buf.push_str(" {\n"); |
diff --git a/crates/ra_assists/src/add_missing_impl_members.rs b/crates/ra_assists/src/add_missing_impl_members.rs index 6ffdad0b1..b992a4dc8 100644 --- a/crates/ra_assists/src/add_missing_impl_members.rs +++ b/crates/ra_assists/src/add_missing_impl_members.rs | |||
@@ -5,8 +5,8 @@ use crate::{ | |||
5 | 5 | ||
6 | use hir::{db::HirDatabase, HasSource}; | 6 | use hir::{db::HirDatabase, HasSource}; |
7 | use ra_db::FilePosition; | 7 | use ra_db::FilePosition; |
8 | use ra_syntax::ast::{self, AstNode, ImplItem, ImplItemKind, NameOwner}; | 8 | use ra_syntax::ast::{self, AstNode, ImplItemKind, NameOwner}; |
9 | use ra_syntax::{SmolStr, TreeArc}; | 9 | use ra_syntax::SmolStr; |
10 | 10 | ||
11 | #[derive(PartialEq)] | 11 | #[derive(PartialEq)] |
12 | enum AddMissingImplMembersMode { | 12 | enum AddMissingImplMembersMode { |
@@ -46,16 +46,16 @@ fn add_missing_impl_members_inner( | |||
46 | let position = FilePosition { file_id, offset: impl_node.syntax().range().start() }; | 46 | let position = FilePosition { file_id, offset: impl_node.syntax().range().start() }; |
47 | let analyzer = hir::SourceAnalyzer::new(ctx.db, position.file_id, impl_node.syntax(), None); | 47 | let analyzer = hir::SourceAnalyzer::new(ctx.db, position.file_id, impl_node.syntax(), None); |
48 | 48 | ||
49 | resolve_target_trait_def(ctx.db, &analyzer, impl_node)? | 49 | resolve_target_trait_def(ctx.db, &analyzer, &impl_node)? |
50 | }; | 50 | }; |
51 | 51 | ||
52 | let def_name = |kind| -> Option<&SmolStr> { | 52 | let def_name = |kind| -> Option<SmolStr> { |
53 | match kind { | 53 | match kind { |
54 | ImplItemKind::FnDef(def) => def.name(), | 54 | ast::ImplItemKind::FnDef(def) => def.name(), |
55 | ImplItemKind::TypeAliasDef(def) => def.name(), | 55 | ast::ImplItemKind::TypeAliasDef(def) => def.name(), |
56 | ImplItemKind::ConstDef(def) => def.name(), | 56 | ast::ImplItemKind::ConstDef(def) => def.name(), |
57 | } | 57 | } |
58 | .map(ast::Name::text) | 58 | .map(|it| it.text().clone()) |
59 | }; | 59 | }; |
60 | 60 | ||
61 | let trait_items = trait_def.item_list()?.impl_items(); | 61 | let trait_items = trait_def.item_list()?.impl_items(); |
@@ -78,18 +78,13 @@ fn add_missing_impl_members_inner( | |||
78 | 78 | ||
79 | ctx.add_action(AssistId(assist_id), label, |edit| { | 79 | ctx.add_action(AssistId(assist_id), label, |edit| { |
80 | let n_existing_items = impl_item_list.impl_items().count(); | 80 | let n_existing_items = impl_item_list.impl_items().count(); |
81 | let items: Vec<_> = missing_items | 81 | let items = missing_items.into_iter().map(|it| match it.kind() { |
82 | .into_iter() | 82 | ImplItemKind::FnDef(def) => strip_docstring(add_body(def).into()), |
83 | .map(|it| match it.kind() { | 83 | _ => strip_docstring(it), |
84 | ImplItemKind::FnDef(def) => { | 84 | }); |
85 | strip_docstring(ImplItem::cast(add_body(def).syntax()).unwrap()) | ||
86 | } | ||
87 | _ => strip_docstring(it), | ||
88 | }) | ||
89 | .collect(); | ||
90 | let mut ast_editor = AstEditor::new(impl_item_list); | 85 | let mut ast_editor = AstEditor::new(impl_item_list); |
91 | 86 | ||
92 | ast_editor.append_items(items.iter().map(|it| &**it)); | 87 | ast_editor.append_items(items); |
93 | 88 | ||
94 | let first_new_item = ast_editor.ast().impl_items().nth(n_existing_items).unwrap(); | 89 | let first_new_item = ast_editor.ast().impl_items().nth(n_existing_items).unwrap(); |
95 | let cursor_position = first_new_item.syntax().range().start(); | 90 | let cursor_position = first_new_item.syntax().range().start(); |
@@ -101,14 +96,14 @@ fn add_missing_impl_members_inner( | |||
101 | ctx.build() | 96 | ctx.build() |
102 | } | 97 | } |
103 | 98 | ||
104 | fn strip_docstring(item: &ast::ImplItem) -> TreeArc<ast::ImplItem> { | 99 | fn strip_docstring(item: ast::ImplItem) -> ast::ImplItem { |
105 | let mut ast_editor = AstEditor::new(item); | 100 | let mut ast_editor = AstEditor::new(item); |
106 | ast_editor.strip_attrs_and_docs(); | 101 | ast_editor.strip_attrs_and_docs(); |
107 | ast_editor.ast().to_owned() | 102 | ast_editor.ast().to_owned() |
108 | } | 103 | } |
109 | 104 | ||
110 | fn add_body(fn_def: &ast::FnDef) -> TreeArc<ast::FnDef> { | 105 | fn add_body(fn_def: ast::FnDef) -> ast::FnDef { |
111 | let mut ast_editor = AstEditor::new(fn_def); | 106 | let mut ast_editor = AstEditor::new(fn_def.clone()); |
112 | if fn_def.body().is_none() { | 107 | if fn_def.body().is_none() { |
113 | ast_editor.set_body(&AstBuilder::<ast::Block>::single_expr( | 108 | ast_editor.set_body(&AstBuilder::<ast::Block>::single_expr( |
114 | &AstBuilder::<ast::Expr>::unimplemented(), | 109 | &AstBuilder::<ast::Expr>::unimplemented(), |
@@ -123,9 +118,12 @@ fn resolve_target_trait_def( | |||
123 | db: &impl HirDatabase, | 118 | db: &impl HirDatabase, |
124 | analyzer: &hir::SourceAnalyzer, | 119 | analyzer: &hir::SourceAnalyzer, |
125 | impl_block: &ast::ImplBlock, | 120 | impl_block: &ast::ImplBlock, |
126 | ) -> Option<TreeArc<ast::TraitDef>> { | 121 | ) -> Option<ast::TraitDef> { |
127 | let ast_path = | 122 | let ast_path = impl_block |
128 | impl_block.target_trait().map(AstNode::syntax).and_then(ast::PathType::cast)?.path()?; | 123 | .target_trait() |
124 | .map(|it| it.syntax().clone()) | ||
125 | .and_then(ast::PathType::cast)? | ||
126 | .path()?; | ||
129 | 127 | ||
130 | match analyzer.resolve_path(db, &ast_path) { | 128 | match analyzer.resolve_path(db, &ast_path) { |
131 | Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).ast), | 129 | Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).ast), |
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 34b207154..e52085f85 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs | |||
@@ -49,7 +49,7 @@ pub(crate) enum Assist { | |||
49 | pub(crate) struct AssistCtx<'a, DB> { | 49 | pub(crate) struct AssistCtx<'a, DB> { |
50 | pub(crate) db: &'a DB, | 50 | pub(crate) db: &'a DB, |
51 | pub(crate) frange: FileRange, | 51 | pub(crate) frange: FileRange, |
52 | source_file: &'a SourceFile, | 52 | source_file: SourceFile, |
53 | should_compute_edit: bool, | 53 | should_compute_edit: bool, |
54 | assist: Assist, | 54 | assist: Assist, |
55 | } | 55 | } |
@@ -59,7 +59,7 @@ impl<'a, DB> Clone for AssistCtx<'a, DB> { | |||
59 | AssistCtx { | 59 | AssistCtx { |
60 | db: self.db, | 60 | db: self.db, |
61 | frange: self.frange, | 61 | frange: self.frange, |
62 | source_file: self.source_file, | 62 | source_file: self.source_file.clone(), |
63 | should_compute_edit: self.should_compute_edit, | 63 | should_compute_edit: self.should_compute_edit, |
64 | assist: self.assist.clone(), | 64 | assist: self.assist.clone(), |
65 | } | 65 | } |
@@ -104,18 +104,18 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> { | |||
104 | Some(self.assist) | 104 | Some(self.assist) |
105 | } | 105 | } |
106 | 106 | ||
107 | pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken<'a>> { | 107 | pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> { |
108 | find_token_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<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_element(&self) -> SyntaxElement<'a> { | 114 | pub(crate) fn covering_element(&self) -> SyntaxElement { |
115 | find_covering_element(self.source_file.syntax(), self.frange.range) | 115 | find_covering_element(self.source_file.syntax(), self.frange.range) |
116 | } | 116 | } |
117 | 117 | ||
118 | pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement<'a> { | 118 | pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement { |
119 | find_covering_element(self.source_file.syntax(), range) | 119 | find_covering_element(self.source_file.syntax(), range) |
120 | } | 120 | } |
121 | } | 121 | } |
@@ -139,7 +139,7 @@ impl AssistBuilder { | |||
139 | ) { | 139 | ) { |
140 | let mut replace_with = replace_with.into(); | 140 | let mut replace_with = replace_with.into(); |
141 | if let Some(indent) = leading_indent(node) { | 141 | if let Some(indent) = leading_indent(node) { |
142 | replace_with = reindent(&replace_with, indent) | 142 | replace_with = reindent(&replace_with, &indent) |
143 | } | 143 | } |
144 | self.replace(node.range(), replace_with) | 144 | self.replace(node.range(), replace_with) |
145 | } | 145 | } |
diff --git a/crates/ra_assists/src/ast_editor.rs b/crates/ra_assists/src/ast_editor.rs index 7b743c9f0..5fbcadfee 100644 --- a/crates/ra_assists/src/ast_editor.rs +++ b/crates/ra_assists/src/ast_editor.rs | |||
@@ -4,18 +4,18 @@ use arrayvec::ArrayVec; | |||
4 | use hir::Name; | 4 | use hir::Name; |
5 | use ra_fmt::leading_indent; | 5 | use ra_fmt::leading_indent; |
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
7 | ast, AstNode, Direction, InsertPosition, SourceFile, SyntaxElement, SyntaxKind::*, TreeArc, T, | 7 | ast, AstNode, Direction, InsertPosition, SourceFile, SyntaxElement, SyntaxKind::*, T, |
8 | }; | 8 | }; |
9 | use ra_text_edit::TextEditBuilder; | 9 | use ra_text_edit::TextEditBuilder; |
10 | 10 | ||
11 | pub struct AstEditor<N: AstNode> { | 11 | pub struct AstEditor<N: AstNode> { |
12 | original_ast: TreeArc<N>, | 12 | original_ast: N, |
13 | ast: TreeArc<N>, | 13 | ast: N, |
14 | } | 14 | } |
15 | 15 | ||
16 | impl<N: AstNode> AstEditor<N> { | 16 | impl<N: AstNode> AstEditor<N> { |
17 | pub fn new(node: &N) -> AstEditor<N> { | 17 | pub fn new(node: N) -> AstEditor<N> { |
18 | AstEditor { original_ast: node.to_owned(), ast: node.to_owned() } | 18 | AstEditor { original_ast: node.clone(), ast: node } |
19 | } | 19 | } |
20 | 20 | ||
21 | pub fn into_text_edit(self, builder: &mut TextEditBuilder) { | 21 | pub fn into_text_edit(self, builder: &mut TextEditBuilder) { |
@@ -26,27 +26,27 @@ impl<N: AstNode> AstEditor<N> { | |||
26 | } | 26 | } |
27 | 27 | ||
28 | pub fn ast(&self) -> &N { | 28 | pub fn ast(&self) -> &N { |
29 | &*self.ast | 29 | &self.ast |
30 | } | 30 | } |
31 | 31 | ||
32 | #[must_use] | 32 | #[must_use] |
33 | fn insert_children<'a>( | 33 | fn insert_children( |
34 | &self, | 34 | &self, |
35 | position: InsertPosition<SyntaxElement<'_>>, | 35 | position: InsertPosition<SyntaxElement>, |
36 | to_insert: impl Iterator<Item = SyntaxElement<'a>>, | 36 | to_insert: impl Iterator<Item = SyntaxElement>, |
37 | ) -> TreeArc<N> { | 37 | ) -> N { |
38 | let new_syntax = self.ast().syntax().insert_children(position, to_insert); | 38 | let new_syntax = self.ast().syntax().insert_children(position, to_insert); |
39 | N::cast(&new_syntax).unwrap().to_owned() | 39 | N::cast(new_syntax).unwrap() |
40 | } | 40 | } |
41 | 41 | ||
42 | #[must_use] | 42 | #[must_use] |
43 | fn replace_children<'a>( | 43 | fn replace_children( |
44 | &self, | 44 | &self, |
45 | to_delete: RangeInclusive<SyntaxElement<'_>>, | 45 | to_delete: RangeInclusive<SyntaxElement>, |
46 | to_insert: impl Iterator<Item = SyntaxElement<'a>>, | 46 | to_insert: impl Iterator<Item = SyntaxElement>, |
47 | ) -> TreeArc<N> { | 47 | ) -> N { |
48 | let new_syntax = self.ast().syntax().replace_children(to_delete, to_insert); | 48 | let new_syntax = self.ast().syntax().replace_children(to_delete, to_insert); |
49 | N::cast(&new_syntax).unwrap().to_owned() | 49 | N::cast(new_syntax).unwrap() |
50 | } | 50 | } |
51 | 51 | ||
52 | fn do_make_multiline(&mut self) { | 52 | fn do_make_multiline(&mut self) { |
@@ -66,16 +66,18 @@ impl<N: AstNode> AstEditor<N> { | |||
66 | if ws.text().contains('\n') { | 66 | if ws.text().contains('\n') { |
67 | return; | 67 | return; |
68 | } | 68 | } |
69 | Some(ws) | 69 | Some(ws.clone()) |
70 | } | 70 | } |
71 | }; | 71 | }; |
72 | 72 | ||
73 | let indent = leading_indent(self.ast().syntax()).unwrap_or(""); | 73 | let indent = leading_indent(self.ast().syntax()).unwrap_or("".into()); |
74 | let ws = tokens::WsBuilder::new(&format!("\n{}", indent)); | 74 | let ws = tokens::WsBuilder::new(&format!("\n{}", indent)); |
75 | let to_insert = iter::once(ws.ws().into()); | 75 | let to_insert = iter::once(ws.ws().into()); |
76 | self.ast = match existing_ws { | 76 | self.ast = match existing_ws { |
77 | None => self.insert_children(InsertPosition::After(l_curly), to_insert), | 77 | None => self.insert_children(InsertPosition::After(l_curly), to_insert), |
78 | Some(ws) => self.replace_children(RangeInclusive::new(ws.into(), ws.into()), to_insert), | 78 | Some(ws) => { |
79 | self.replace_children(RangeInclusive::new(ws.clone().into(), ws.into()), to_insert) | ||
80 | } | ||
79 | }; | 81 | }; |
80 | } | 82 | } |
81 | } | 83 | } |
@@ -95,7 +97,7 @@ impl AstEditor<ast::NamedFieldList> { | |||
95 | let space = if is_multiline { | 97 | let space = if is_multiline { |
96 | ws = tokens::WsBuilder::new(&format!( | 98 | ws = tokens::WsBuilder::new(&format!( |
97 | "\n{} ", | 99 | "\n{} ", |
98 | leading_indent(self.ast().syntax()).unwrap_or("") | 100 | leading_indent(self.ast().syntax()).unwrap_or("".into()) |
99 | )); | 101 | )); |
100 | ws.ws() | 102 | ws.ws() |
101 | } else { | 103 | } else { |
@@ -104,7 +106,7 @@ impl AstEditor<ast::NamedFieldList> { | |||
104 | 106 | ||
105 | let mut to_insert: ArrayVec<[SyntaxElement; 4]> = ArrayVec::new(); | 107 | let mut to_insert: ArrayVec<[SyntaxElement; 4]> = ArrayVec::new(); |
106 | to_insert.push(space.into()); | 108 | to_insert.push(space.into()); |
107 | to_insert.push(field.syntax().into()); | 109 | to_insert.push(field.syntax().clone().into()); |
108 | to_insert.push(tokens::comma().into()); | 110 | to_insert.push(tokens::comma().into()); |
109 | 111 | ||
110 | macro_rules! after_l_curly { | 112 | macro_rules! after_l_curly { |
@@ -127,7 +129,7 @@ impl AstEditor<ast::NamedFieldList> { | |||
127 | InsertPosition::After(comma) | 129 | InsertPosition::After(comma) |
128 | } else { | 130 | } else { |
129 | to_insert.insert(0, tokens::comma().into()); | 131 | to_insert.insert(0, tokens::comma().into()); |
130 | InsertPosition::After($anchor.syntax().into()) | 132 | InsertPosition::After($anchor.syntax().clone().into()) |
131 | } | 133 | } |
132 | }; | 134 | }; |
133 | }; | 135 | }; |
@@ -144,7 +146,9 @@ impl AstEditor<ast::NamedFieldList> { | |||
144 | None => after_l_curly!(), | 146 | None => after_l_curly!(), |
145 | } | 147 | } |
146 | } | 148 | } |
147 | InsertPosition::Before(anchor) => InsertPosition::Before(anchor.syntax().into()), | 149 | InsertPosition::Before(anchor) => { |
150 | InsertPosition::Before(anchor.syntax().clone().into()) | ||
151 | } | ||
148 | InsertPosition::After(anchor) => after_field!(anchor), | 152 | InsertPosition::After(anchor) => after_field!(anchor), |
149 | }; | 153 | }; |
150 | 154 | ||
@@ -157,7 +161,7 @@ impl AstEditor<ast::NamedFieldList> { | |||
157 | } | 161 | } |
158 | 162 | ||
159 | impl AstEditor<ast::ItemList> { | 163 | impl AstEditor<ast::ItemList> { |
160 | pub fn append_items<'a>(&mut self, items: impl Iterator<Item = &'a ast::ImplItem>) { | 164 | pub fn append_items(&mut self, items: impl Iterator<Item = ast::ImplItem>) { |
161 | let n_existing_items = self.ast().impl_items().count(); | 165 | let n_existing_items = self.ast().impl_items().count(); |
162 | if n_existing_items == 0 { | 166 | if n_existing_items == 0 { |
163 | self.do_make_multiline(); | 167 | self.do_make_multiline(); |
@@ -165,22 +169,23 @@ impl AstEditor<ast::ItemList> { | |||
165 | items.for_each(|it| self.append_item(it)); | 169 | items.for_each(|it| self.append_item(it)); |
166 | } | 170 | } |
167 | 171 | ||
168 | pub fn append_item(&mut self, item: &ast::ImplItem) { | 172 | pub fn append_item(&mut self, item: ast::ImplItem) { |
169 | let (indent, position) = match self.ast().impl_items().last() { | 173 | let (indent, position) = match self.ast().impl_items().last() { |
170 | Some(it) => ( | 174 | Some(it) => ( |
171 | leading_indent(it.syntax()).unwrap_or("").to_string(), | 175 | leading_indent(it.syntax()).unwrap_or_default().to_string(), |
172 | InsertPosition::After(it.syntax().into()), | 176 | InsertPosition::After(it.syntax().clone().into()), |
173 | ), | 177 | ), |
174 | None => match self.l_curly() { | 178 | None => match self.l_curly() { |
175 | Some(it) => ( | 179 | Some(it) => ( |
176 | " ".to_string() + leading_indent(self.ast().syntax()).unwrap_or(""), | 180 | " ".to_string() + &leading_indent(self.ast().syntax()).unwrap_or_default(), |
177 | InsertPosition::After(it), | 181 | InsertPosition::After(it), |
178 | ), | 182 | ), |
179 | None => return, | 183 | None => return, |
180 | }, | 184 | }, |
181 | }; | 185 | }; |
182 | let ws = tokens::WsBuilder::new(&format!("\n{}", indent)); | 186 | let ws = tokens::WsBuilder::new(&format!("\n{}", indent)); |
183 | let to_insert: ArrayVec<[SyntaxElement; 2]> = [ws.ws().into(), item.syntax().into()].into(); | 187 | let to_insert: ArrayVec<[SyntaxElement; 2]> = |
188 | [ws.ws().into(), item.syntax().clone().into()].into(); | ||
184 | self.ast = self.insert_children(position, to_insert.into_iter()); | 189 | self.ast = self.insert_children(position, to_insert.into_iter()); |
185 | } | 190 | } |
186 | 191 | ||
@@ -197,9 +202,9 @@ impl AstEditor<ast::ImplItem> { | |||
197 | .children_with_tokens() | 202 | .children_with_tokens() |
198 | .find(|it| it.kind() == ATTR || it.kind() == COMMENT) | 203 | .find(|it| it.kind() == ATTR || it.kind() == COMMENT) |
199 | { | 204 | { |
200 | let end = match start.next_sibling_or_token() { | 205 | let end = match &start.next_sibling_or_token() { |
201 | Some(el) if el.kind() == WHITESPACE => el, | 206 | Some(el) if el.kind() == WHITESPACE => el.clone(), |
202 | Some(_) | None => start, | 207 | Some(_) | None => start.clone(), |
203 | }; | 208 | }; |
204 | self.ast = self.replace_children(RangeInclusive::new(start, end), iter::empty()); | 209 | self.ast = self.replace_children(RangeInclusive::new(start, end), iter::empty()); |
205 | } | 210 | } |
@@ -210,18 +215,18 @@ impl AstEditor<ast::FnDef> { | |||
210 | pub fn set_body(&mut self, body: &ast::Block) { | 215 | pub fn set_body(&mut self, body: &ast::Block) { |
211 | let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); | 216 | let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); |
212 | let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.ast().body() { | 217 | let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.ast().body() { |
213 | old_body.syntax().into() | 218 | old_body.syntax().clone().into() |
214 | } else if let Some(semi) = self.ast().semicolon_token() { | 219 | } else if let Some(semi) = self.ast().semicolon_token() { |
215 | to_insert.push(tokens::single_space().into()); | 220 | to_insert.push(tokens::single_space().into()); |
216 | semi.into() | 221 | semi.into() |
217 | } else { | 222 | } else { |
218 | to_insert.push(tokens::single_space().into()); | 223 | to_insert.push(tokens::single_space().into()); |
219 | to_insert.push(body.syntax().into()); | 224 | to_insert.push(body.syntax().clone().into()); |
220 | self.ast = self.insert_children(InsertPosition::Last, to_insert.into_iter()); | 225 | self.ast = self.insert_children(InsertPosition::Last, to_insert.into_iter()); |
221 | return; | 226 | return; |
222 | }; | 227 | }; |
223 | to_insert.push(body.syntax().into()); | 228 | to_insert.push(body.syntax().clone().into()); |
224 | let replace_range = RangeInclusive::new(old_body_or_semi, old_body_or_semi); | 229 | let replace_range = RangeInclusive::new(old_body_or_semi.clone(), old_body_or_semi); |
225 | self.ast = self.replace_children(replace_range, to_insert.into_iter()) | 230 | self.ast = self.replace_children(replace_range, to_insert.into_iter()) |
226 | } | 231 | } |
227 | } | 232 | } |
@@ -231,15 +236,15 @@ pub struct AstBuilder<N: AstNode> { | |||
231 | } | 236 | } |
232 | 237 | ||
233 | impl AstBuilder<ast::NamedField> { | 238 | impl AstBuilder<ast::NamedField> { |
234 | pub fn from_name(name: &Name) -> TreeArc<ast::NamedField> { | 239 | pub fn from_name(name: &Name) -> ast::NamedField { |
235 | ast_node_from_file_text(&format!("fn f() {{ S {{ {}: (), }} }}", name)) | 240 | ast_node_from_file_text(&format!("fn f() {{ S {{ {}: (), }} }}", name)) |
236 | } | 241 | } |
237 | 242 | ||
238 | fn from_text(text: &str) -> TreeArc<ast::NamedField> { | 243 | fn from_text(text: &str) -> ast::NamedField { |
239 | ast_node_from_file_text(&format!("fn f() {{ S {{ {}, }} }}", text)) | 244 | ast_node_from_file_text(&format!("fn f() {{ S {{ {}, }} }}", text)) |
240 | } | 245 | } |
241 | 246 | ||
242 | pub fn from_pieces(name: &ast::NameRef, expr: Option<&ast::Expr>) -> TreeArc<ast::NamedField> { | 247 | pub fn from_pieces(name: &ast::NameRef, expr: Option<&ast::Expr>) -> ast::NamedField { |
243 | match expr { | 248 | match expr { |
244 | Some(expr) => Self::from_text(&format!("{}: {}", name.syntax(), expr.syntax())), | 249 | Some(expr) => Self::from_text(&format!("{}: {}", name.syntax(), expr.syntax())), |
245 | None => Self::from_text(&name.syntax().to_string()), | 250 | None => Self::from_text(&name.syntax().to_string()), |
@@ -248,36 +253,36 @@ impl AstBuilder<ast::NamedField> { | |||
248 | } | 253 | } |
249 | 254 | ||
250 | impl AstBuilder<ast::Block> { | 255 | impl AstBuilder<ast::Block> { |
251 | fn from_text(text: &str) -> TreeArc<ast::Block> { | 256 | fn from_text(text: &str) -> ast::Block { |
252 | ast_node_from_file_text(&format!("fn f() {}", text)) | 257 | ast_node_from_file_text(&format!("fn f() {}", text)) |
253 | } | 258 | } |
254 | 259 | ||
255 | pub fn single_expr(e: &ast::Expr) -> TreeArc<ast::Block> { | 260 | pub fn single_expr(e: &ast::Expr) -> ast::Block { |
256 | Self::from_text(&format!("{{ {} }}", e.syntax())) | 261 | Self::from_text(&format!("{{ {} }}", e.syntax())) |
257 | } | 262 | } |
258 | } | 263 | } |
259 | 264 | ||
260 | impl AstBuilder<ast::Expr> { | 265 | impl AstBuilder<ast::Expr> { |
261 | fn from_text(text: &str) -> TreeArc<ast::Expr> { | 266 | fn from_text(text: &str) -> ast::Expr { |
262 | ast_node_from_file_text(&format!("fn f() {{ {}; }}", text)) | 267 | ast_node_from_file_text(&format!("fn f() {{ {}; }}", text)) |
263 | } | 268 | } |
264 | 269 | ||
265 | pub fn unit() -> TreeArc<ast::Expr> { | 270 | pub fn unit() -> ast::Expr { |
266 | Self::from_text("()") | 271 | Self::from_text("()") |
267 | } | 272 | } |
268 | 273 | ||
269 | pub fn unimplemented() -> TreeArc<ast::Expr> { | 274 | pub fn unimplemented() -> ast::Expr { |
270 | Self::from_text("unimplemented!()") | 275 | Self::from_text("unimplemented!()") |
271 | } | 276 | } |
272 | } | 277 | } |
273 | 278 | ||
274 | impl AstBuilder<ast::NameRef> { | 279 | impl AstBuilder<ast::NameRef> { |
275 | pub fn new(text: &str) -> TreeArc<ast::NameRef> { | 280 | pub fn new(text: &str) -> ast::NameRef { |
276 | ast_node_from_file_text(&format!("fn f() {{ {}; }}", text)) | 281 | ast_node_from_file_text(&format!("fn f() {{ {}; }}", text)) |
277 | } | 282 | } |
278 | } | 283 | } |
279 | 284 | ||
280 | fn ast_node_from_file_text<N: AstNode>(text: &str) -> TreeArc<N> { | 285 | fn ast_node_from_file_text<N: AstNode>(text: &str) -> N { |
281 | let parse = SourceFile::parse(text); | 286 | let parse = SourceFile::parse(text); |
282 | let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap().to_owned(); | 287 | let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap().to_owned(); |
283 | res | 288 | res |
@@ -285,47 +290,49 @@ fn ast_node_from_file_text<N: AstNode>(text: &str) -> TreeArc<N> { | |||
285 | 290 | ||
286 | mod tokens { | 291 | mod tokens { |
287 | use once_cell::sync::Lazy; | 292 | use once_cell::sync::Lazy; |
288 | use ra_syntax::{AstNode, SourceFile, SyntaxKind::*, SyntaxToken, TreeArc, T}; | 293 | use ra_syntax::{AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken, T}; |
289 | 294 | ||
290 | static SOURCE_FILE: Lazy<TreeArc<SourceFile>> = | 295 | static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| SourceFile::parse(",\n; ;")); |
291 | Lazy::new(|| SourceFile::parse(",\n; ;").tree().to_owned()); | ||
292 | 296 | ||
293 | pub(crate) fn comma() -> SyntaxToken<'static> { | 297 | pub(crate) fn comma() -> SyntaxToken { |
294 | SOURCE_FILE | 298 | SOURCE_FILE |
299 | .tree() | ||
295 | .syntax() | 300 | .syntax() |
296 | .descendants_with_tokens() | 301 | .descendants_with_tokens() |
297 | .filter_map(|it| it.as_token()) | 302 | .filter_map(|it| it.as_token().cloned()) |
298 | .find(|it| it.kind() == T![,]) | 303 | .find(|it| it.kind() == T![,]) |
299 | .unwrap() | 304 | .unwrap() |
300 | } | 305 | } |
301 | 306 | ||
302 | pub(crate) fn single_space() -> SyntaxToken<'static> { | 307 | pub(crate) fn single_space() -> SyntaxToken { |
303 | SOURCE_FILE | 308 | SOURCE_FILE |
309 | .tree() | ||
304 | .syntax() | 310 | .syntax() |
305 | .descendants_with_tokens() | 311 | .descendants_with_tokens() |
306 | .filter_map(|it| it.as_token()) | 312 | .filter_map(|it| it.as_token().cloned()) |
307 | .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ") | 313 | .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ") |
308 | .unwrap() | 314 | .unwrap() |
309 | } | 315 | } |
310 | 316 | ||
311 | #[allow(unused)] | 317 | #[allow(unused)] |
312 | pub(crate) fn single_newline() -> SyntaxToken<'static> { | 318 | pub(crate) fn single_newline() -> SyntaxToken { |
313 | SOURCE_FILE | 319 | SOURCE_FILE |
320 | .tree() | ||
314 | .syntax() | 321 | .syntax() |
315 | .descendants_with_tokens() | 322 | .descendants_with_tokens() |
316 | .filter_map(|it| it.as_token()) | 323 | .filter_map(|it| it.as_token().cloned()) |
317 | .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n") | 324 | .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n") |
318 | .unwrap() | 325 | .unwrap() |
319 | } | 326 | } |
320 | 327 | ||
321 | pub(crate) struct WsBuilder(TreeArc<SourceFile>); | 328 | pub(crate) struct WsBuilder(SourceFile); |
322 | 329 | ||
323 | impl WsBuilder { | 330 | impl WsBuilder { |
324 | pub(crate) fn new(text: &str) -> WsBuilder { | 331 | pub(crate) fn new(text: &str) -> WsBuilder { |
325 | WsBuilder(SourceFile::parse(text).ok().unwrap()) | 332 | WsBuilder(SourceFile::parse(text).ok().unwrap()) |
326 | } | 333 | } |
327 | pub(crate) fn ws(&self) -> SyntaxToken<'_> { | 334 | pub(crate) fn ws(&self) -> SyntaxToken { |
328 | self.0.syntax().first_child_or_token().unwrap().as_token().unwrap() | 335 | self.0.syntax().first_child_or_token().unwrap().as_token().cloned().unwrap() |
329 | } | 336 | } |
330 | } | 337 | } |
331 | 338 | ||
diff --git a/crates/ra_assists/src/auto_import.rs b/crates/ra_assists/src/auto_import.rs index f8f37e852..0eb4bdb62 100644 --- a/crates/ra_assists/src/auto_import.rs +++ b/crates/ra_assists/src/auto_import.rs | |||
@@ -12,25 +12,25 @@ use ra_syntax::{ | |||
12 | SyntaxNode, TextRange, T, | 12 | SyntaxNode, TextRange, T, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | fn collect_path_segments_raw<'a>( | 15 | fn collect_path_segments_raw( |
16 | segments: &mut Vec<&'a ast::PathSegment>, | 16 | segments: &mut Vec<ast::PathSegment>, |
17 | mut path: &'a ast::Path, | 17 | mut path: ast::Path, |
18 | ) -> Option<usize> { | 18 | ) -> Option<usize> { |
19 | let oldlen = segments.len(); | 19 | let oldlen = segments.len(); |
20 | loop { | 20 | loop { |
21 | let mut children = path.syntax().children_with_tokens(); | 21 | let mut children = path.syntax().children_with_tokens(); |
22 | let (first, second, third) = ( | 22 | let (first, second, third) = ( |
23 | children.next().map(|n| (n, n.kind())), | 23 | children.next().map(|n| (n.clone(), n.kind())), |
24 | children.next().map(|n| (n, n.kind())), | 24 | children.next().map(|n| (n.clone(), n.kind())), |
25 | children.next().map(|n| (n, n.kind())), | 25 | children.next().map(|n| (n.clone(), n.kind())), |
26 | ); | 26 | ); |
27 | match (first, second, third) { | 27 | match (first, second, third) { |
28 | (Some((subpath, PATH)), Some((_, T![::])), Some((segment, PATH_SEGMENT))) => { | 28 | (Some((subpath, PATH)), Some((_, T![::])), Some((segment, PATH_SEGMENT))) => { |
29 | path = ast::Path::cast(subpath.as_node()?)?; | 29 | path = ast::Path::cast(subpath.as_node()?.clone())?; |
30 | segments.push(ast::PathSegment::cast(segment.as_node()?)?); | 30 | segments.push(ast::PathSegment::cast(segment.as_node()?.clone())?); |
31 | } | 31 | } |
32 | (Some((segment, PATH_SEGMENT)), _, _) => { | 32 | (Some((segment, PATH_SEGMENT)), _, _) => { |
33 | segments.push(ast::PathSegment::cast(segment.as_node()?)?); | 33 | segments.push(ast::PathSegment::cast(segment.as_node()?.clone())?); |
34 | break; | 34 | break; |
35 | } | 35 | } |
36 | (_, _, _) => return None, | 36 | (_, _, _) => return None, |
@@ -60,7 +60,7 @@ fn fmt_segments_raw(segments: &[SmolStr], buf: &mut String) { | |||
60 | } | 60 | } |
61 | 61 | ||
62 | // Returns the numeber of common segments. | 62 | // Returns the numeber of common segments. |
63 | fn compare_path_segments(left: &[SmolStr], right: &[&ast::PathSegment]) -> usize { | 63 | fn compare_path_segments(left: &[SmolStr], right: &[ast::PathSegment]) -> usize { |
64 | left.iter().zip(right).filter(|(l, r)| compare_path_segment(l, r)).count() | 64 | left.iter().zip(right).filter(|(l, r)| compare_path_segment(l, r)).count() |
65 | } | 65 | } |
66 | 66 | ||
@@ -81,12 +81,12 @@ fn compare_path_segment_with_name(a: &SmolStr, b: &ast::Name) -> bool { | |||
81 | a == b.text() | 81 | a == b.text() |
82 | } | 82 | } |
83 | 83 | ||
84 | #[derive(Copy, Clone)] | 84 | #[derive(Clone)] |
85 | enum ImportAction<'a> { | 85 | enum ImportAction { |
86 | Nothing, | 86 | Nothing, |
87 | // Add a brand new use statement. | 87 | // Add a brand new use statement. |
88 | AddNewUse { | 88 | AddNewUse { |
89 | anchor: Option<&'a SyntaxNode>, // anchor node | 89 | anchor: Option<SyntaxNode>, // anchor node |
90 | add_after_anchor: bool, | 90 | add_after_anchor: bool, |
91 | }, | 91 | }, |
92 | 92 | ||
@@ -94,9 +94,9 @@ enum ImportAction<'a> { | |||
94 | AddNestedImport { | 94 | AddNestedImport { |
95 | // how may segments matched with the target path | 95 | // how may segments matched with the target path |
96 | common_segments: usize, | 96 | common_segments: usize, |
97 | path_to_split: &'a ast::Path, | 97 | path_to_split: ast::Path, |
98 | // the first segment of path_to_split we want to add into the new nested list | 98 | // the first segment of path_to_split we want to add into the new nested list |
99 | first_segment_to_split: Option<&'a ast::PathSegment>, | 99 | first_segment_to_split: Option<ast::PathSegment>, |
100 | // Wether to add 'self' in addition to the target path | 100 | // Wether to add 'self' in addition to the target path |
101 | add_self: bool, | 101 | add_self: bool, |
102 | }, | 102 | }, |
@@ -104,20 +104,20 @@ enum ImportAction<'a> { | |||
104 | AddInTreeList { | 104 | AddInTreeList { |
105 | common_segments: usize, | 105 | common_segments: usize, |
106 | // The UseTreeList where to add the target path | 106 | // The UseTreeList where to add the target path |
107 | tree_list: &'a ast::UseTreeList, | 107 | tree_list: ast::UseTreeList, |
108 | add_self: bool, | 108 | add_self: bool, |
109 | }, | 109 | }, |
110 | } | 110 | } |
111 | 111 | ||
112 | impl<'a> ImportAction<'a> { | 112 | impl ImportAction { |
113 | fn add_new_use(anchor: Option<&'a SyntaxNode>, add_after_anchor: bool) -> Self { | 113 | fn add_new_use(anchor: Option<SyntaxNode>, add_after_anchor: bool) -> Self { |
114 | ImportAction::AddNewUse { anchor, add_after_anchor } | 114 | ImportAction::AddNewUse { anchor, add_after_anchor } |
115 | } | 115 | } |
116 | 116 | ||
117 | fn add_nested_import( | 117 | fn add_nested_import( |
118 | common_segments: usize, | 118 | common_segments: usize, |
119 | path_to_split: &'a ast::Path, | 119 | path_to_split: ast::Path, |
120 | first_segment_to_split: Option<&'a ast::PathSegment>, | 120 | first_segment_to_split: Option<ast::PathSegment>, |
121 | add_self: bool, | 121 | add_self: bool, |
122 | ) -> Self { | 122 | ) -> Self { |
123 | ImportAction::AddNestedImport { | 123 | ImportAction::AddNestedImport { |
@@ -130,14 +130,14 @@ impl<'a> ImportAction<'a> { | |||
130 | 130 | ||
131 | fn add_in_tree_list( | 131 | fn add_in_tree_list( |
132 | common_segments: usize, | 132 | common_segments: usize, |
133 | tree_list: &'a ast::UseTreeList, | 133 | tree_list: ast::UseTreeList, |
134 | add_self: bool, | 134 | add_self: bool, |
135 | ) -> Self { | 135 | ) -> Self { |
136 | ImportAction::AddInTreeList { common_segments, tree_list, add_self } | 136 | ImportAction::AddInTreeList { common_segments, tree_list, add_self } |
137 | } | 137 | } |
138 | 138 | ||
139 | fn better<'b>(left: &'b ImportAction<'a>, right: &'b ImportAction<'a>) -> &'b ImportAction<'a> { | 139 | fn better(left: ImportAction, right: ImportAction) -> ImportAction { |
140 | if left.is_better(right) { | 140 | if left.is_better(&right) { |
141 | left | 141 | left |
142 | } else { | 142 | } else { |
143 | right | 143 | right |
@@ -166,12 +166,12 @@ impl<'a> ImportAction<'a> { | |||
166 | 166 | ||
167 | // Find out the best ImportAction to import target path against current_use_tree. | 167 | // Find out the best ImportAction to import target path against current_use_tree. |
168 | // If current_use_tree has a nested import the function gets called recursively on every UseTree inside a UseTreeList. | 168 | // If current_use_tree has a nested import the function gets called recursively on every UseTree inside a UseTreeList. |
169 | fn walk_use_tree_for_best_action<'a>( | 169 | fn walk_use_tree_for_best_action( |
170 | current_path_segments: &mut Vec<&'a ast::PathSegment>, // buffer containing path segments | 170 | current_path_segments: &mut Vec<ast::PathSegment>, // buffer containing path segments |
171 | current_parent_use_tree_list: Option<&'a ast::UseTreeList>, // will be Some value if we are in a nested import | 171 | current_parent_use_tree_list: Option<ast::UseTreeList>, // will be Some value if we are in a nested import |
172 | current_use_tree: &'a ast::UseTree, // the use tree we are currently examinating | 172 | current_use_tree: ast::UseTree, // the use tree we are currently examinating |
173 | target: &[SmolStr], // the path we want to import | 173 | target: &[SmolStr], // the path we want to import |
174 | ) -> ImportAction<'a> { | 174 | ) -> ImportAction { |
175 | // We save the number of segments in the buffer so we can restore the correct segments | 175 | // We save the number of segments in the buffer so we can restore the correct segments |
176 | // before returning. Recursive call will add segments so we need to delete them. | 176 | // before returning. Recursive call will add segments so we need to delete them. |
177 | let prev_len = current_path_segments.len(); | 177 | let prev_len = current_path_segments.len(); |
@@ -188,32 +188,36 @@ fn walk_use_tree_for_best_action<'a>( | |||
188 | .syntax() | 188 | .syntax() |
189 | .ancestors() | 189 | .ancestors() |
190 | .find_map(ast::UseItem::cast) | 190 | .find_map(ast::UseItem::cast) |
191 | .map(AstNode::syntax), | 191 | .map(|it| it.syntax().clone()), |
192 | true, | 192 | true, |
193 | ); | 193 | ); |
194 | } | 194 | } |
195 | }; | 195 | }; |
196 | 196 | ||
197 | // This can happen only if current_use_tree is a direct child of a UseItem | 197 | // This can happen only if current_use_tree is a direct child of a UseItem |
198 | if let Some(name) = alias.and_then(ast::NameOwner::name) { | 198 | if let Some(name) = alias.and_then(|it| it.name()) { |
199 | if compare_path_segment_with_name(&target[0], name) { | 199 | if compare_path_segment_with_name(&target[0], &name) { |
200 | return ImportAction::Nothing; | 200 | return ImportAction::Nothing; |
201 | } | 201 | } |
202 | } | 202 | } |
203 | 203 | ||
204 | collect_path_segments_raw(current_path_segments, path); | 204 | collect_path_segments_raw(current_path_segments, path.clone()); |
205 | 205 | ||
206 | // We compare only the new segments added in the line just above. | 206 | // We compare only the new segments added in the line just above. |
207 | // The first prev_len segments were already compared in 'parent' recursive calls. | 207 | // The first prev_len segments were already compared in 'parent' recursive calls. |
208 | let left = target.split_at(prev_len).1; | 208 | let left = target.split_at(prev_len).1; |
209 | let right = current_path_segments.split_at(prev_len).1; | 209 | let right = current_path_segments.split_at(prev_len).1; |
210 | let common = compare_path_segments(left, right); | 210 | let common = compare_path_segments(left, &right); |
211 | let mut action = match common { | 211 | let mut action = match common { |
212 | 0 => ImportAction::add_new_use( | 212 | 0 => ImportAction::add_new_use( |
213 | // e.g: target is std::fmt and we can have | 213 | // e.g: target is std::fmt and we can have |
214 | // use foo::bar | 214 | // use foo::bar |
215 | // We add a brand new use statement | 215 | // We add a brand new use statement |
216 | current_use_tree.syntax().ancestors().find_map(ast::UseItem::cast).map(AstNode::syntax), | 216 | current_use_tree |
217 | .syntax() | ||
218 | .ancestors() | ||
219 | .find_map(ast::UseItem::cast) | ||
220 | .map(|it| it.syntax().clone()), | ||
217 | true, | 221 | true, |
218 | ), | 222 | ), |
219 | common if common == left.len() && left.len() == right.len() => { | 223 | common if common == left.len() && left.len() == right.len() => { |
@@ -223,9 +227,9 @@ fn walk_use_tree_for_best_action<'a>( | |||
223 | if let Some(list) = tree_list { | 227 | if let Some(list) = tree_list { |
224 | // In case 2 we need to add self to the nested list | 228 | // In case 2 we need to add self to the nested list |
225 | // unless it's already there | 229 | // unless it's already there |
226 | let has_self = list.use_trees().map(ast::UseTree::path).any(|p| { | 230 | let has_self = list.use_trees().map(|it| it.path()).any(|p| { |
227 | p.and_then(ast::Path::segment) | 231 | p.and_then(|it| it.segment()) |
228 | .and_then(ast::PathSegment::kind) | 232 | .and_then(|it| it.kind()) |
229 | .filter(|k| *k == ast::PathSegmentKind::SelfKw) | 233 | .filter(|k| *k == ast::PathSegmentKind::SelfKw) |
230 | .is_some() | 234 | .is_some() |
231 | }); | 235 | }); |
@@ -248,7 +252,7 @@ fn walk_use_tree_for_best_action<'a>( | |||
248 | ImportAction::add_nested_import( | 252 | ImportAction::add_nested_import( |
249 | prev_len + common, | 253 | prev_len + common, |
250 | path, | 254 | path, |
251 | Some(segments_to_split[0]), | 255 | Some(segments_to_split[0].clone()), |
252 | false, | 256 | false, |
253 | ) | 257 | ) |
254 | } | 258 | } |
@@ -263,14 +267,18 @@ fn walk_use_tree_for_best_action<'a>( | |||
263 | .syntax() | 267 | .syntax() |
264 | .ancestors() | 268 | .ancestors() |
265 | .find_map(ast::UseItem::cast) | 269 | .find_map(ast::UseItem::cast) |
266 | .map(AstNode::syntax), | 270 | .map(|it| it.syntax().clone()), |
267 | true, | 271 | true, |
268 | ); | 272 | ); |
269 | if let Some(list) = tree_list { | 273 | if let Some(list) = tree_list { |
270 | // Case 2, check recursively if the path is already imported in the nested list | 274 | // Case 2, check recursively if the path is already imported in the nested list |
271 | for u in list.use_trees() { | 275 | for u in list.use_trees() { |
272 | let child_action = | 276 | let child_action = walk_use_tree_for_best_action( |
273 | walk_use_tree_for_best_action(current_path_segments, Some(list), u, target); | 277 | current_path_segments, |
278 | Some(list.clone()), | ||
279 | u, | ||
280 | target, | ||
281 | ); | ||
274 | if child_action.is_better(&better_action) { | 282 | if child_action.is_better(&better_action) { |
275 | better_action = child_action; | 283 | better_action = child_action; |
276 | if let ImportAction::Nothing = better_action { | 284 | if let ImportAction::Nothing = better_action { |
@@ -291,7 +299,7 @@ fn walk_use_tree_for_best_action<'a>( | |||
291 | ImportAction::add_nested_import( | 299 | ImportAction::add_nested_import( |
292 | prev_len + common, | 300 | prev_len + common, |
293 | path, | 301 | path, |
294 | Some(segments_to_split[0]), | 302 | Some(segments_to_split[0].clone()), |
295 | true, | 303 | true, |
296 | ) | 304 | ) |
297 | } | 305 | } |
@@ -302,7 +310,7 @@ fn walk_use_tree_for_best_action<'a>( | |||
302 | ImportAction::add_nested_import( | 310 | ImportAction::add_nested_import( |
303 | prev_len + common, | 311 | prev_len + common, |
304 | path, | 312 | path, |
305 | Some(segments_to_split[0]), | 313 | Some(segments_to_split[0].clone()), |
306 | false, | 314 | false, |
307 | ) | 315 | ) |
308 | } | 316 | } |
@@ -311,7 +319,7 @@ fn walk_use_tree_for_best_action<'a>( | |||
311 | 319 | ||
312 | // If we are inside a UseTreeList adding a use statement become adding to the existing | 320 | // If we are inside a UseTreeList adding a use statement become adding to the existing |
313 | // tree list. | 321 | // tree list. |
314 | action = match (current_parent_use_tree_list, action) { | 322 | action = match (current_parent_use_tree_list, action.clone()) { |
315 | (Some(use_tree_list), ImportAction::AddNewUse { .. }) => { | 323 | (Some(use_tree_list), ImportAction::AddNewUse { .. }) => { |
316 | ImportAction::add_in_tree_list(prev_len, use_tree_list, false) | 324 | ImportAction::add_in_tree_list(prev_len, use_tree_list, false) |
317 | } | 325 | } |
@@ -323,19 +331,20 @@ fn walk_use_tree_for_best_action<'a>( | |||
323 | action | 331 | action |
324 | } | 332 | } |
325 | 333 | ||
326 | fn best_action_for_target<'b, 'a: 'b>( | 334 | fn best_action_for_target( |
327 | container: &'a SyntaxNode, | 335 | container: SyntaxNode, |
328 | anchor: &'a SyntaxNode, | 336 | anchor: SyntaxNode, |
329 | target: &'b [SmolStr], | 337 | target: &[SmolStr], |
330 | ) -> ImportAction<'a> { | 338 | ) -> ImportAction { |
331 | let mut storage = Vec::with_capacity(16); // this should be the only allocation | 339 | let mut storage = Vec::with_capacity(16); // this should be the only allocation |
332 | let best_action = container | 340 | let best_action = container |
333 | .children() | 341 | .children() |
334 | .filter_map(ast::UseItem::cast) | 342 | .filter_map(ast::UseItem::cast) |
335 | .filter_map(ast::UseItem::use_tree) | 343 | .filter_map(|it| it.use_tree()) |
336 | .map(|u| walk_use_tree_for_best_action(&mut storage, None, u, target)) | 344 | .map(|u| walk_use_tree_for_best_action(&mut storage, None, u, target)) |
337 | .fold(None, |best, a| { | 345 | .fold(None, |best, a| match best { |
338 | best.and_then(|best| Some(*ImportAction::better(&best, &a))).or_else(|| Some(a)) | 346 | Some(best) => Some(ImportAction::better(best, a)), |
347 | None => Some(a), | ||
339 | }); | 348 | }); |
340 | 349 | ||
341 | match best_action { | 350 | match best_action { |
@@ -386,7 +395,7 @@ fn make_assist(action: &ImportAction, target: &[SmolStr], edit: &mut TextEditBui | |||
386 | } | 395 | } |
387 | 396 | ||
388 | fn make_assist_add_new_use( | 397 | fn make_assist_add_new_use( |
389 | anchor: &Option<&SyntaxNode>, | 398 | anchor: &Option<SyntaxNode>, |
390 | after: bool, | 399 | after: bool, |
391 | target: &[SmolStr], | 400 | target: &[SmolStr], |
392 | edit: &mut TextEditBuilder, | 401 | edit: &mut TextEditBuilder, |
@@ -396,7 +405,7 @@ fn make_assist_add_new_use( | |||
396 | let mut buf = String::new(); | 405 | let mut buf = String::new(); |
397 | if after { | 406 | if after { |
398 | buf.push_str("\n"); | 407 | buf.push_str("\n"); |
399 | if let Some(spaces) = indent { | 408 | if let Some(spaces) = &indent { |
400 | buf.push_str(spaces); | 409 | buf.push_str(spaces); |
401 | } | 410 | } |
402 | } | 411 | } |
@@ -405,8 +414,8 @@ fn make_assist_add_new_use( | |||
405 | buf.push_str(";"); | 414 | buf.push_str(";"); |
406 | if !after { | 415 | if !after { |
407 | buf.push_str("\n\n"); | 416 | buf.push_str("\n\n"); |
408 | if let Some(spaces) = indent { | 417 | if let Some(spaces) = &indent { |
409 | buf.push_str(spaces); | 418 | buf.push_str(&spaces); |
410 | } | 419 | } |
411 | } | 420 | } |
412 | let position = if after { anchor.range().end() } else { anchor.range().start() }; | 421 | let position = if after { anchor.range().end() } else { anchor.range().start() }; |
@@ -444,7 +453,7 @@ fn make_assist_add_in_tree_list( | |||
444 | 453 | ||
445 | fn make_assist_add_nested_import( | 454 | fn make_assist_add_nested_import( |
446 | path: &ast::Path, | 455 | path: &ast::Path, |
447 | first_segment_to_split: &Option<&ast::PathSegment>, | 456 | first_segment_to_split: &Option<ast::PathSegment>, |
448 | target: &[SmolStr], | 457 | target: &[SmolStr], |
449 | add_self: bool, | 458 | add_self: bool, |
450 | edit: &mut TextEditBuilder, | 459 | edit: &mut TextEditBuilder, |
@@ -482,7 +491,7 @@ fn apply_auto_import( | |||
482 | target: &[SmolStr], | 491 | target: &[SmolStr], |
483 | edit: &mut TextEditBuilder, | 492 | edit: &mut TextEditBuilder, |
484 | ) { | 493 | ) { |
485 | let action = best_action_for_target(container, path.syntax(), target); | 494 | let action = best_action_for_target(container.clone(), path.syntax().clone(), target); |
486 | make_assist(&action, target, edit); | 495 | make_assist(&action, target, edit); |
487 | if let Some(last) = path.segment() { | 496 | if let Some(last) = path.segment() { |
488 | // Here we are assuming the assist will provide a correct use statement | 497 | // Here we are assuming the assist will provide a correct use statement |
@@ -522,26 +531,26 @@ pub fn auto_import_text_edit( | |||
522 | edit: &mut TextEditBuilder, | 531 | edit: &mut TextEditBuilder, |
523 | ) { | 532 | ) { |
524 | let container = position.ancestors().find_map(|n| { | 533 | let container = position.ancestors().find_map(|n| { |
525 | if let Some(module) = ast::Module::cast(n) { | 534 | if let Some(module) = ast::Module::cast(n.clone()) { |
526 | return module.item_list().map(ast::AstNode::syntax); | 535 | return module.item_list().map(|it| it.syntax().clone()); |
527 | } | 536 | } |
528 | ast::SourceFile::cast(n).map(ast::AstNode::syntax) | 537 | ast::SourceFile::cast(n).map(|it| it.syntax().clone()) |
529 | }); | 538 | }); |
530 | 539 | ||
531 | if let Some(container) = container { | 540 | if let Some(container) = container { |
532 | let action = best_action_for_target(container, anchor, target); | 541 | let action = best_action_for_target(container, anchor.clone(), target); |
533 | make_assist(&action, target, edit); | 542 | make_assist(&action, target, edit); |
534 | } | 543 | } |
535 | } | 544 | } |
536 | 545 | ||
537 | pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 546 | pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
538 | let path: &ast::Path = ctx.node_at_offset()?; | 547 | let path: ast::Path = ctx.node_at_offset()?; |
539 | // We don't want to mess with use statements | 548 | // We don't want to mess with use statements |
540 | if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() { | 549 | if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() { |
541 | return None; | 550 | return None; |
542 | } | 551 | } |
543 | 552 | ||
544 | let hir_path = hir::Path::from_ast(path)?; | 553 | let hir_path = hir::Path::from_ast(path.clone())?; |
545 | let segments = collect_hir_path_segments(&hir_path); | 554 | let segments = collect_hir_path_segments(&hir_path); |
546 | if segments.len() < 2 { | 555 | if segments.len() < 2 { |
547 | return None; | 556 | return None; |
@@ -554,7 +563,7 @@ pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist | |||
554 | format!("import {} in mod {}", fmt_segments(&segments), name.text()), | 563 | format!("import {} in mod {}", fmt_segments(&segments), name.text()), |
555 | |edit| { | 564 | |edit| { |
556 | let mut text_edit = TextEditBuilder::default(); | 565 | let mut text_edit = TextEditBuilder::default(); |
557 | apply_auto_import(item_list.syntax(), path, &segments, &mut text_edit); | 566 | apply_auto_import(item_list.syntax(), &path, &segments, &mut text_edit); |
558 | edit.set_edit_builder(text_edit); | 567 | edit.set_edit_builder(text_edit); |
559 | }, | 568 | }, |
560 | ); | 569 | ); |
@@ -566,7 +575,7 @@ pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist | |||
566 | format!("import {} in the current file", fmt_segments(&segments)), | 575 | format!("import {} in the current file", fmt_segments(&segments)), |
567 | |edit| { | 576 | |edit| { |
568 | let mut text_edit = TextEditBuilder::default(); | 577 | let mut text_edit = TextEditBuilder::default(); |
569 | apply_auto_import(current_file.syntax(), path, &segments, &mut text_edit); | 578 | apply_auto_import(current_file.syntax(), &path, &segments, &mut text_edit); |
570 | edit.set_edit_builder(text_edit); | 579 | edit.set_edit_builder(text_edit); |
571 | }, | 580 | }, |
572 | ); | 581 | ); |
diff --git a/crates/ra_assists/src/change_visibility.rs b/crates/ra_assists/src/change_visibility.rs index 6cabba3e3..ab10d2aa4 100644 --- a/crates/ra_assists/src/change_visibility.rs +++ b/crates/ra_assists/src/change_visibility.rs | |||
@@ -35,7 +35,7 @@ fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | |||
35 | if parent.children().any(|child| child.kind() == VISIBILITY) { | 35 | if parent.children().any(|child| child.kind() == VISIBILITY) { |
36 | return None; | 36 | return None; |
37 | } | 37 | } |
38 | (vis_offset(parent), keyword.range()) | 38 | (vis_offset(&parent), keyword.range()) |
39 | } else { | 39 | } else { |
40 | let ident = ctx.token_at_offset().find(|leaf| leaf.kind() == IDENT)?; | 40 | let ident = ctx.token_at_offset().find(|leaf| leaf.kind() == IDENT)?; |
41 | let field = ident.parent().ancestors().find_map(ast::NamedFieldDef::cast)?; | 41 | let field = ident.parent().ancestors().find_map(ast::NamedFieldDef::cast)?; |
@@ -65,7 +65,7 @@ fn vis_offset(node: &SyntaxNode) -> TextUnit { | |||
65 | .unwrap_or_else(|| node.range().start()) | 65 | .unwrap_or_else(|| node.range().start()) |
66 | } | 66 | } |
67 | 67 | ||
68 | fn change_vis(mut ctx: AssistCtx<impl HirDatabase>, vis: &ast::Visibility) -> Option<Assist> { | 68 | fn change_vis(mut ctx: AssistCtx<impl HirDatabase>, vis: ast::Visibility) -> Option<Assist> { |
69 | if vis.syntax().text() == "pub" { | 69 | if vis.syntax().text() == "pub" { |
70 | ctx.add_action(AssistId("change_visibility"), "change to pub(crate)", |edit| { | 70 | ctx.add_action(AssistId("change_visibility"), "change to pub(crate)", |edit| { |
71 | edit.target(vis.syntax().range()); | 71 | edit.target(vis.syntax().range()); |
diff --git a/crates/ra_assists/src/fill_match_arms.rs b/crates/ra_assists/src/fill_match_arms.rs index deef166b5..b96806ac6 100644 --- a/crates/ra_assists/src/fill_match_arms.rs +++ b/crates/ra_assists/src/fill_match_arms.rs | |||
@@ -27,7 +27,7 @@ pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As | |||
27 | let mut arm_iter = arm_list.arms(); | 27 | let mut arm_iter = arm_list.arms(); |
28 | let first = arm_iter.next(); | 28 | let first = arm_iter.next(); |
29 | 29 | ||
30 | match first { | 30 | match &first { |
31 | // If there arm list is empty or there is only one trivial arm, then proceed. | 31 | // If there arm list is empty or there is only one trivial arm, then proceed. |
32 | Some(arm) if is_trivial_arm(arm) => { | 32 | Some(arm) if is_trivial_arm(arm) => { |
33 | if arm_iter.next() != None { | 33 | if arm_iter.next() != None { |
@@ -44,7 +44,7 @@ pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As | |||
44 | 44 | ||
45 | let expr = match_expr.expr()?; | 45 | let expr = match_expr.expr()?; |
46 | let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, expr.syntax(), None); | 46 | let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, expr.syntax(), None); |
47 | let match_expr_ty = analyzer.type_of(ctx.db, expr)?; | 47 | let match_expr_ty = analyzer.type_of(ctx.db, &expr)?; |
48 | let enum_def = analyzer.autoderef(ctx.db, match_expr_ty).find_map(|ty| match ty.as_adt() { | 48 | let enum_def = analyzer.autoderef(ctx.db, match_expr_ty).find_map(|ty| match ty.as_adt() { |
49 | Some((AdtDef::Enum(e), _)) => Some(e), | 49 | Some((AdtDef::Enum(e), _)) => Some(e), |
50 | _ => None, | 50 | _ => None, |
diff --git a/crates/ra_assists/src/flip_binexpr.rs b/crates/ra_assists/src/flip_binexpr.rs index 5e41f9346..2e591ad3b 100644 --- a/crates/ra_assists/src/flip_binexpr.rs +++ b/crates/ra_assists/src/flip_binexpr.rs | |||
@@ -6,8 +6,8 @@ use crate::{Assist, AssistCtx, AssistId}; | |||
6 | /// Flip binary expression assist. | 6 | /// Flip binary expression assist. |
7 | pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 7 | pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
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().clone(); |
10 | let rhs = expr.rhs()?.syntax(); | 10 | let rhs = expr.rhs()?.syntax().clone(); |
11 | let op_range = expr.op_token()?.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); |
diff --git a/crates/ra_assists/src/flip_comma.rs b/crates/ra_assists/src/flip_comma.rs index d8dba779f..13016ae06 100644 --- a/crates/ra_assists/src/flip_comma.rs +++ b/crates/ra_assists/src/flip_comma.rs | |||
@@ -5,8 +5,8 @@ use crate::{Assist, AssistCtx, AssistId}; | |||
5 | 5 | ||
6 | pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 6 | pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
7 | let comma = ctx.token_at_offset().find(|leaf| leaf.kind() == T![,])?; | 7 | let comma = ctx.token_at_offset().find(|leaf| leaf.kind() == T![,])?; |
8 | let prev = non_trivia_sibling(comma.into(), Direction::Prev)?; | 8 | let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?; |
9 | let next = non_trivia_sibling(comma.into(), Direction::Next)?; | 9 | let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?; |
10 | ctx.add_action(AssistId("flip_comma"), "flip comma", |edit| { | 10 | ctx.add_action(AssistId("flip_comma"), "flip comma", |edit| { |
11 | edit.target(comma.range()); | 11 | edit.target(comma.range()); |
12 | edit.replace(prev.range(), next.to_string()); | 12 | edit.replace(prev.range(), next.to_string()); |
diff --git a/crates/ra_assists/src/inline_local_variable.rs b/crates/ra_assists/src/inline_local_variable.rs index 554de8b46..3c17089de 100644 --- a/crates/ra_assists/src/inline_local_variable.rs +++ b/crates/ra_assists/src/inline_local_variable.rs | |||
@@ -16,18 +16,18 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt | |||
16 | if bind_pat.is_mutable() { | 16 | if bind_pat.is_mutable() { |
17 | return None; | 17 | return None; |
18 | } | 18 | } |
19 | let initializer_expr = let_stmt.initializer(); | 19 | let initializer_expr = let_stmt.initializer()?; |
20 | let delete_range = if let Some(whitespace) = let_stmt | 20 | let delete_range = if let Some(whitespace) = let_stmt |
21 | .syntax() | 21 | .syntax() |
22 | .next_sibling_or_token() | 22 | .next_sibling_or_token() |
23 | .and_then(|it| ast::Whitespace::cast(it.as_token()?)) | 23 | .and_then(|it| ast::Whitespace::cast(it.as_token()?.clone())) |
24 | { | 24 | { |
25 | TextRange::from_to(let_stmt.syntax().range().start(), whitespace.syntax().range().end()) | 25 | TextRange::from_to(let_stmt.syntax().range().start(), whitespace.syntax().range().end()) |
26 | } else { | 26 | } else { |
27 | let_stmt.syntax().range() | 27 | let_stmt.syntax().range() |
28 | }; | 28 | }; |
29 | let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, bind_pat.syntax(), None); | 29 | let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, bind_pat.syntax(), None); |
30 | let refs = analyzer.find_all_refs(bind_pat); | 30 | let refs = analyzer.find_all_refs(&bind_pat); |
31 | 31 | ||
32 | let mut wrap_in_parens = vec![true; refs.len()]; | 32 | let mut wrap_in_parens = vec![true; refs.len()]; |
33 | 33 | ||
@@ -45,7 +45,7 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt | |||
45 | } | 45 | } |
46 | }; | 46 | }; |
47 | 47 | ||
48 | wrap_in_parens[i] = match (initializer_expr?.kind(), usage_parent.kind()) { | 48 | wrap_in_parens[i] = match (initializer_expr.kind(), usage_parent.kind()) { |
49 | (ExprKind::CallExpr(_), _) | 49 | (ExprKind::CallExpr(_), _) |
50 | | (ExprKind::IndexExpr(_), _) | 50 | | (ExprKind::IndexExpr(_), _) |
51 | | (ExprKind::MethodCallExpr(_), _) | 51 | | (ExprKind::MethodCallExpr(_), _) |
@@ -71,7 +71,7 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt | |||
71 | }; | 71 | }; |
72 | } | 72 | } |
73 | 73 | ||
74 | let init_str = initializer_expr?.syntax().text().to_string(); | 74 | let init_str = initializer_expr.syntax().text().to_string(); |
75 | let init_in_paren = format!("({})", &init_str); | 75 | let init_in_paren = format!("({})", &init_str); |
76 | 76 | ||
77 | ctx.add_action( | 77 | ctx.add_action( |
diff --git a/crates/ra_assists/src/introduce_variable.rs b/crates/ra_assists/src/introduce_variable.rs index f7f5ccafa..ce28132c9 100644 --- a/crates/ra_assists/src/introduce_variable.rs +++ b/crates/ra_assists/src/introduce_variable.rs | |||
@@ -20,8 +20,8 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option | |||
20 | return None; | 20 | return None; |
21 | } | 21 | } |
22 | let expr = node.ancestors().find_map(valid_target_expr)?; | 22 | let expr = node.ancestors().find_map(valid_target_expr)?; |
23 | let (anchor_stmt, wrap_in_block) = anchor_stmt(expr)?; | 23 | let (anchor_stmt, wrap_in_block) = anchor_stmt(expr.clone())?; |
24 | let indent = anchor_stmt.prev_sibling_or_token()?.as_token()?; | 24 | let indent = anchor_stmt.prev_sibling_or_token()?.as_token()?.clone(); |
25 | if indent.kind() != WHITESPACE { | 25 | if indent.kind() != WHITESPACE { |
26 | return None; | 26 | return None; |
27 | } | 27 | } |
@@ -37,9 +37,9 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option | |||
37 | }; | 37 | }; |
38 | 38 | ||
39 | expr.syntax().text().push_to(&mut buf); | 39 | expr.syntax().text().push_to(&mut buf); |
40 | let full_stmt = ast::ExprStmt::cast(anchor_stmt); | 40 | let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); |
41 | let is_full_stmt = if let Some(expr_stmt) = full_stmt { | 41 | let is_full_stmt = if let Some(expr_stmt) = &full_stmt { |
42 | Some(expr.syntax()) == expr_stmt.expr().map(|e| e.syntax()) | 42 | Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone()) |
43 | } else { | 43 | } else { |
44 | false | 44 | false |
45 | }; | 45 | }; |
@@ -81,7 +81,7 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option | |||
81 | 81 | ||
82 | /// Check whether the node is a valid expression which can be extracted to a variable. | 82 | /// Check whether the node is a valid expression which can be extracted to a variable. |
83 | /// In general that's true for any expression, but in some cases that would produce invalid code. | 83 | /// In general that's true for any expression, but in some cases that would produce invalid code. |
84 | fn valid_target_expr(node: &SyntaxNode) -> Option<&ast::Expr> { | 84 | fn valid_target_expr(node: SyntaxNode) -> Option<ast::Expr> { |
85 | match node.kind() { | 85 | match node.kind() { |
86 | PATH_EXPR => None, | 86 | PATH_EXPR => None, |
87 | BREAK_EXPR => ast::BreakExpr::cast(node).and_then(|e| e.expr()), | 87 | BREAK_EXPR => ast::BreakExpr::cast(node).and_then(|e| e.expr()), |
@@ -96,14 +96,10 @@ fn valid_target_expr(node: &SyntaxNode) -> Option<&ast::Expr> { | |||
96 | /// to produce correct code. | 96 | /// to produce correct code. |
97 | /// It can be a statement, the last in a block expression or a wanna be block | 97 | /// It can be a statement, the last in a block expression or a wanna be block |
98 | /// expression like a lambda or match arm. | 98 | /// expression like a lambda or match arm. |
99 | fn anchor_stmt(expr: &ast::Expr) -> Option<(&SyntaxNode, bool)> { | 99 | fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> { |
100 | expr.syntax().ancestors().find_map(|node| { | 100 | expr.syntax().ancestors().find_map(|node| { |
101 | if ast::Stmt::cast(node).is_some() { | ||
102 | return Some((node, false)); | ||
103 | } | ||
104 | |||
105 | if let Some(expr) = node.parent().and_then(ast::Block::cast).and_then(|it| it.expr()) { | 101 | if let Some(expr) = node.parent().and_then(ast::Block::cast).and_then(|it| it.expr()) { |
106 | if expr.syntax() == node { | 102 | if expr.syntax() == &node { |
107 | tested_by!(test_introduce_var_last_expr); | 103 | tested_by!(test_introduce_var_last_expr); |
108 | return Some((node, false)); | 104 | return Some((node, false)); |
109 | } | 105 | } |
@@ -115,6 +111,10 @@ fn anchor_stmt(expr: &ast::Expr) -> Option<(&SyntaxNode, bool)> { | |||
115 | } | 111 | } |
116 | } | 112 | } |
117 | 113 | ||
114 | if ast::Stmt::cast(node.clone()).is_some() { | ||
115 | return Some((node, false)); | ||
116 | } | ||
117 | |||
118 | None | 118 | None |
119 | }) | 119 | }) |
120 | } | 120 | } |
diff --git a/crates/ra_assists/src/move_guard.rs b/crates/ra_assists/src/move_guard.rs index e1ce86a33..313c9ad18 100644 --- a/crates/ra_assists/src/move_guard.rs +++ b/crates/ra_assists/src/move_guard.rs | |||
@@ -18,9 +18,9 @@ pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Op | |||
18 | 18 | ||
19 | ctx.add_action(AssistId("move_guard_to_arm_body"), "move guard to arm body", |edit| { | 19 | ctx.add_action(AssistId("move_guard_to_arm_body"), "move guard to arm body", |edit| { |
20 | edit.target(guard.syntax().range()); | 20 | edit.target(guard.syntax().range()); |
21 | let offseting_amount = match space_before_guard { | 21 | let offseting_amount = match &space_before_guard { |
22 | Some(SyntaxElement::Token(tok)) => { | 22 | Some(SyntaxElement::Token(tok)) => { |
23 | if let Some(_) = ast::Whitespace::cast(tok) { | 23 | if let Some(_) = ast::Whitespace::cast(tok.clone()) { |
24 | let ele = space_before_guard.unwrap().range(); | 24 | let ele = space_before_guard.unwrap().range(); |
25 | edit.delete(ele); | 25 | edit.delete(ele); |
26 | ele.len() | 26 | ele.len() |
@@ -39,11 +39,11 @@ pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Op | |||
39 | } | 39 | } |
40 | 40 | ||
41 | pub(crate) fn move_arm_cond_to_match_guard(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 41 | pub(crate) fn move_arm_cond_to_match_guard(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
42 | let match_arm: &MatchArm = ctx.node_at_offset::<MatchArm>()?; | 42 | let match_arm: MatchArm = ctx.node_at_offset::<MatchArm>()?; |
43 | let last_match_pat = match_arm.pats().last()?; | 43 | let last_match_pat = match_arm.pats().last()?; |
44 | 44 | ||
45 | let arm_body = match_arm.expr()?; | 45 | let arm_body = match_arm.expr()?; |
46 | let if_expr: &IfExpr = IfExpr::cast(arm_body.syntax())?; | 46 | let if_expr: IfExpr = IfExpr::cast(arm_body.syntax().clone())?; |
47 | let cond = if_expr.condition()?; | 47 | let cond = if_expr.condition()?; |
48 | let then_block = if_expr.then_branch()?; | 48 | let then_block = if_expr.then_branch()?; |
49 | 49 | ||
@@ -65,7 +65,7 @@ pub(crate) fn move_arm_cond_to_match_guard(mut ctx: AssistCtx<impl HirDatabase>) | |||
65 | edit.target(if_expr.syntax().range()); | 65 | edit.target(if_expr.syntax().range()); |
66 | let then_only_expr = then_block.statements().next().is_none(); | 66 | let then_only_expr = then_block.statements().next().is_none(); |
67 | 67 | ||
68 | match then_block.expr() { | 68 | match &then_block.expr() { |
69 | Some(then_expr) if then_only_expr => { | 69 | Some(then_expr) if then_only_expr => { |
70 | edit.replace(if_expr.syntax().range(), then_expr.syntax().text()) | 70 | edit.replace(if_expr.syntax().range(), then_expr.syntax().text()) |
71 | } | 71 | } |
diff --git a/crates/ra_assists/src/remove_dbg.rs b/crates/ra_assists/src/remove_dbg.rs index 5680f76ca..c330bc827 100644 --- a/crates/ra_assists/src/remove_dbg.rs +++ b/crates/ra_assists/src/remove_dbg.rs | |||
@@ -8,7 +8,7 @@ use ra_syntax::{ | |||
8 | pub(crate) fn remove_dbg(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 8 | pub(crate) fn remove_dbg(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
9 | let macro_call = ctx.node_at_offset::<ast::MacroCall>()?; | 9 | let macro_call = ctx.node_at_offset::<ast::MacroCall>()?; |
10 | 10 | ||
11 | if !is_valid_macrocall(macro_call, "dbg")? { | 11 | if !is_valid_macrocall(¯o_call, "dbg")? { |
12 | return None; | 12 | return None; |
13 | } | 13 | } |
14 | 14 | ||
@@ -35,7 +35,7 @@ pub(crate) fn remove_dbg(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> | |||
35 | }; | 35 | }; |
36 | 36 | ||
37 | let macro_content = { | 37 | let macro_content = { |
38 | let macro_args = macro_call.token_tree()?.syntax(); | 38 | let macro_args = macro_call.token_tree()?.syntax().clone(); |
39 | let range = macro_args.range(); | 39 | let range = macro_args.range(); |
40 | let start = range.start() + TextUnit::of_char('('); | 40 | let start = range.start() + TextUnit::of_char('('); |
41 | let end = range.end() - TextUnit::of_char(')'); | 41 | let end = range.end() - TextUnit::of_char(')'); |
@@ -65,7 +65,7 @@ fn is_valid_macrocall(macro_call: &ast::MacroCall, macro_name: &str) -> Option<b | |||
65 | return None; | 65 | return None; |
66 | } | 66 | } |
67 | 67 | ||
68 | let node = macro_call.token_tree()?.syntax(); | 68 | let node = macro_call.token_tree()?.syntax().clone(); |
69 | let first_child = node.first_child_or_token()?; | 69 | let first_child = node.first_child_or_token()?; |
70 | let last_child = node.last_child_or_token()?; | 70 | let last_child = node.last_child_or_token()?; |
71 | 71 | ||
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 c2c7cf70b..5de6aa266 100644 --- a/crates/ra_assists/src/replace_if_let_with_match.rs +++ b/crates/ra_assists/src/replace_if_let_with_match.rs | |||
@@ -5,7 +5,7 @@ use ra_syntax::{ast, AstNode}; | |||
5 | use crate::{Assist, AssistCtx, AssistId}; | 5 | use crate::{Assist, AssistCtx, AssistId}; |
6 | 6 | ||
7 | pub(crate) fn replace_if_let_with_match(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 7 | pub(crate) fn replace_if_let_with_match(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
8 | let if_expr: &ast::IfExpr = ctx.node_at_offset()?; | 8 | let if_expr: ast::IfExpr = ctx.node_at_offset()?; |
9 | let cond = if_expr.condition()?; | 9 | let cond = if_expr.condition()?; |
10 | let pat = cond.pat()?; | 10 | let pat = cond.pat()?; |
11 | let expr = cond.expr()?; | 11 | let expr = cond.expr()?; |
@@ -25,16 +25,11 @@ pub(crate) fn replace_if_let_with_match(mut ctx: AssistCtx<impl HirDatabase>) -> | |||
25 | ctx.build() | 25 | ctx.build() |
26 | } | 26 | } |
27 | 27 | ||
28 | fn build_match_expr( | 28 | fn build_match_expr(expr: ast::Expr, pat1: ast::Pat, arm1: ast::Block, arm2: ast::Block) -> String { |
29 | expr: &ast::Expr, | ||
30 | pat1: &ast::Pat, | ||
31 | arm1: &ast::Block, | ||
32 | arm2: &ast::Block, | ||
33 | ) -> String { | ||
34 | let mut buf = String::new(); | 29 | let mut buf = String::new(); |
35 | buf.push_str(&format!("match {} {{\n", expr.syntax().text())); | 30 | buf.push_str(&format!("match {} {{\n", expr.syntax().text())); |
36 | buf.push_str(&format!(" {} => {}\n", pat1.syntax().text(), format_arm(arm1))); | 31 | buf.push_str(&format!(" {} => {}\n", pat1.syntax().text(), format_arm(&arm1))); |
37 | buf.push_str(&format!(" _ => {}\n", format_arm(arm2))); | 32 | buf.push_str(&format!(" _ => {}\n", format_arm(&arm2))); |
38 | buf.push_str("}"); | 33 | buf.push_str("}"); |
39 | buf | 34 | buf |
40 | } | 35 | } |
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index fe00e78d1..ceb603c50 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -25,7 +25,7 @@ pub use self::{ | |||
25 | /// conversion itself has zero runtime cost: ast and syntax nodes have exactly | 25 | /// conversion itself has zero runtime cost: ast and syntax nodes have exactly |
26 | /// the same representation: a pointer to the tree root and a pointer to the | 26 | /// the same representation: a pointer to the tree root and a pointer to the |
27 | /// node itself. | 27 | /// node itself. |
28 | pub trait AstNode { | 28 | pub trait AstNode: Clone { |
29 | fn cast(syntax: SyntaxNode) -> Option<Self> | 29 | fn cast(syntax: SyntaxNode) -> Option<Self> |
30 | where | 30 | where |
31 | Self: Sized; | 31 | Self: Sized; |