diff options
Diffstat (limited to 'crates/ide_assists/src')
-rw-r--r-- | crates/ide_assists/src/assist_context.rs | 44 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/add_explicit_type.rs | 90 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/add_lifetime_to_type.rs | 70 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/add_missing_impl_members.rs | 6 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/convert_comment_block.rs | 51 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/early_return.rs | 89 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/expand_glob_import.rs | 19 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/merge_imports.rs | 43 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/move_bounds.rs | 8 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/qualify_path.rs | 1 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/reorder_fields.rs | 112 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/reorder_impl.rs | 2 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs | 34 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/unmerge_use.rs | 30 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/unwrap_block.rs | 76 |
15 files changed, 372 insertions, 303 deletions
diff --git a/crates/ide_assists/src/assist_context.rs b/crates/ide_assists/src/assist_context.rs index bba6c08e0..1482d37f8 100644 --- a/crates/ide_assists/src/assist_context.rs +++ b/crates/ide_assists/src/assist_context.rs | |||
@@ -14,8 +14,8 @@ use ide_db::{ | |||
14 | }; | 14 | }; |
15 | use syntax::{ | 15 | use syntax::{ |
16 | algo::{self, find_node_at_offset, SyntaxRewriter}, | 16 | algo::{self, find_node_at_offset, SyntaxRewriter}, |
17 | AstNode, AstToken, SourceFile, SyntaxElement, SyntaxKind, SyntaxToken, TextRange, TextSize, | 17 | AstNode, AstToken, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxNodePtr, |
18 | TokenAtOffset, | 18 | SyntaxToken, TextRange, TextSize, TokenAtOffset, |
19 | }; | 19 | }; |
20 | use text_edit::{TextEdit, TextEditBuilder}; | 20 | use text_edit::{TextEdit, TextEditBuilder}; |
21 | 21 | ||
@@ -180,11 +180,19 @@ pub(crate) struct AssistBuilder { | |||
180 | edit: TextEditBuilder, | 180 | edit: TextEditBuilder, |
181 | file_id: FileId, | 181 | file_id: FileId, |
182 | source_change: SourceChange, | 182 | source_change: SourceChange, |
183 | |||
184 | /// Maps the original, immutable `SyntaxNode` to a `clone_for_update` twin. | ||
185 | mutated_tree: Option<(SyntaxNode, SyntaxNode)>, | ||
183 | } | 186 | } |
184 | 187 | ||
185 | impl AssistBuilder { | 188 | impl AssistBuilder { |
186 | pub(crate) fn new(file_id: FileId) -> AssistBuilder { | 189 | pub(crate) fn new(file_id: FileId) -> AssistBuilder { |
187 | AssistBuilder { edit: TextEdit::builder(), file_id, source_change: SourceChange::default() } | 190 | AssistBuilder { |
191 | edit: TextEdit::builder(), | ||
192 | file_id, | ||
193 | source_change: SourceChange::default(), | ||
194 | mutated_tree: None, | ||
195 | } | ||
188 | } | 196 | } |
189 | 197 | ||
190 | pub(crate) fn edit_file(&mut self, file_id: FileId) { | 198 | pub(crate) fn edit_file(&mut self, file_id: FileId) { |
@@ -193,12 +201,42 @@ impl AssistBuilder { | |||
193 | } | 201 | } |
194 | 202 | ||
195 | fn commit(&mut self) { | 203 | fn commit(&mut self) { |
204 | if let Some((old, new)) = self.mutated_tree.take() { | ||
205 | algo::diff(&old, &new).into_text_edit(&mut self.edit) | ||
206 | } | ||
207 | |||
196 | let edit = mem::take(&mut self.edit).finish(); | 208 | let edit = mem::take(&mut self.edit).finish(); |
197 | if !edit.is_empty() { | 209 | if !edit.is_empty() { |
198 | self.source_change.insert_source_edit(self.file_id, edit); | 210 | self.source_change.insert_source_edit(self.file_id, edit); |
199 | } | 211 | } |
200 | } | 212 | } |
201 | 213 | ||
214 | pub(crate) fn make_ast_mut<N: AstNode>(&mut self, node: N) -> N { | ||
215 | N::cast(self.make_mut(node.syntax().clone())).unwrap() | ||
216 | } | ||
217 | /// Returns a copy of the `node`, suitable for mutation. | ||
218 | /// | ||
219 | /// Syntax trees in rust-analyzer are typically immutable, and mutating | ||
220 | /// operations panic at runtime. However, it is possible to make a copy of | ||
221 | /// the tree and mutate the copy freely. Mutation is based on interior | ||
222 | /// mutability, and different nodes in the same tree see the same mutations. | ||
223 | /// | ||
224 | /// The typical pattern for an assist is to find specific nodes in the read | ||
225 | /// phase, and then get their mutable couterparts using `make_mut` in the | ||
226 | /// mutable state. | ||
227 | pub(crate) fn make_mut(&mut self, node: SyntaxNode) -> SyntaxNode { | ||
228 | let root = &self | ||
229 | .mutated_tree | ||
230 | .get_or_insert_with(|| { | ||
231 | let immutable = node.ancestors().last().unwrap(); | ||
232 | let mutable = immutable.clone_for_update(); | ||
233 | (immutable, mutable) | ||
234 | }) | ||
235 | .1; | ||
236 | let ptr = SyntaxNodePtr::new(&&node); | ||
237 | ptr.to_node(root) | ||
238 | } | ||
239 | |||
202 | /// Remove specified `range` of text. | 240 | /// Remove specified `range` of text. |
203 | pub(crate) fn delete(&mut self, range: TextRange) { | 241 | pub(crate) fn delete(&mut self, range: TextRange) { |
204 | self.edit.delete(range) | 242 | self.edit.delete(range) |
diff --git a/crates/ide_assists/src/handlers/add_explicit_type.rs b/crates/ide_assists/src/handlers/add_explicit_type.rs index cb1548cef..62db31952 100644 --- a/crates/ide_assists/src/handlers/add_explicit_type.rs +++ b/crates/ide_assists/src/handlers/add_explicit_type.rs | |||
@@ -34,26 +34,33 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio | |||
34 | // The binding must have a name | 34 | // The binding must have a name |
35 | let name = pat.name()?; | 35 | let name = pat.name()?; |
36 | let name_range = name.syntax().text_range(); | 36 | let name_range = name.syntax().text_range(); |
37 | let stmt_range = let_stmt.syntax().text_range(); | 37 | |
38 | let eq_range = let_stmt.eq_token()?.text_range(); | ||
39 | // Assist should only be applicable if cursor is between 'let' and '=' | 38 | // Assist should only be applicable if cursor is between 'let' and '=' |
40 | let let_range = TextRange::new(stmt_range.start(), eq_range.start()); | 39 | let cursor_in_range = { |
41 | let cursor_in_range = let_range.contains_range(ctx.frange.range); | 40 | let stmt_range = let_stmt.syntax().text_range(); |
41 | let eq_range = let_stmt.eq_token()?.text_range(); | ||
42 | let let_range = TextRange::new(stmt_range.start(), eq_range.start()); | ||
43 | let_range.contains_range(ctx.frange.range) | ||
44 | }; | ||
42 | if !cursor_in_range { | 45 | if !cursor_in_range { |
46 | cov_mark::hit!(add_explicit_type_not_applicable_if_cursor_after_equals); | ||
43 | return None; | 47 | return None; |
44 | } | 48 | } |
49 | |||
45 | // Assist not applicable if the type has already been specified | 50 | // Assist not applicable if the type has already been specified |
46 | // and it has no placeholders | 51 | // and it has no placeholders |
47 | let ascribed_ty = let_stmt.ty(); | 52 | let ascribed_ty = let_stmt.ty(); |
48 | if let Some(ty) = &ascribed_ty { | 53 | if let Some(ty) = &ascribed_ty { |
49 | if ty.syntax().descendants().find_map(ast::InferType::cast).is_none() { | 54 | if ty.syntax().descendants().find_map(ast::InferType::cast).is_none() { |
55 | cov_mark::hit!(add_explicit_type_not_applicable_if_ty_already_specified); | ||
50 | return None; | 56 | return None; |
51 | } | 57 | } |
52 | } | 58 | } |
59 | |||
53 | // Infer type | 60 | // Infer type |
54 | let ty = ctx.sema.type_of_expr(&expr)?; | 61 | let ty = ctx.sema.type_of_expr(&expr)?; |
55 | |||
56 | if ty.contains_unknown() || ty.is_closure() { | 62 | if ty.contains_unknown() || ty.is_closure() { |
63 | cov_mark::hit!(add_explicit_type_not_applicable_if_ty_not_inferred); | ||
57 | return None; | 64 | return None; |
58 | } | 65 | } |
59 | 66 | ||
@@ -81,17 +88,25 @@ mod tests { | |||
81 | 88 | ||
82 | #[test] | 89 | #[test] |
83 | fn add_explicit_type_target() { | 90 | fn add_explicit_type_target() { |
84 | check_assist_target(add_explicit_type, "fn f() { let a$0 = 1; }", "a"); | 91 | check_assist_target(add_explicit_type, r#"fn f() { let a$0 = 1; }"#, "a"); |
85 | } | 92 | } |
86 | 93 | ||
87 | #[test] | 94 | #[test] |
88 | fn add_explicit_type_works_for_simple_expr() { | 95 | fn add_explicit_type_works_for_simple_expr() { |
89 | check_assist(add_explicit_type, "fn f() { let a$0 = 1; }", "fn f() { let a: i32 = 1; }"); | 96 | check_assist( |
97 | add_explicit_type, | ||
98 | r#"fn f() { let a$0 = 1; }"#, | ||
99 | r#"fn f() { let a: i32 = 1; }"#, | ||
100 | ); | ||
90 | } | 101 | } |
91 | 102 | ||
92 | #[test] | 103 | #[test] |
93 | fn add_explicit_type_works_for_underscore() { | 104 | fn add_explicit_type_works_for_underscore() { |
94 | check_assist(add_explicit_type, "fn f() { let a$0: _ = 1; }", "fn f() { let a: i32 = 1; }"); | 105 | check_assist( |
106 | add_explicit_type, | ||
107 | r#"fn f() { let a$0: _ = 1; }"#, | ||
108 | r#"fn f() { let a: i32 = 1; }"#, | ||
109 | ); | ||
95 | } | 110 | } |
96 | 111 | ||
97 | #[test] | 112 | #[test] |
@@ -99,23 +114,19 @@ mod tests { | |||
99 | check_assist( | 114 | check_assist( |
100 | add_explicit_type, | 115 | add_explicit_type, |
101 | r#" | 116 | r#" |
102 | enum Option<T> { | 117 | enum Option<T> { Some(T), None } |
103 | Some(T), | ||
104 | None | ||
105 | } | ||
106 | 118 | ||
107 | fn f() { | 119 | fn f() { |
108 | let a$0: Option<_> = Option::Some(1); | 120 | let a$0: Option<_> = Option::Some(1); |
109 | }"#, | 121 | } |
122 | "#, | ||
110 | r#" | 123 | r#" |
111 | enum Option<T> { | 124 | enum Option<T> { Some(T), None } |
112 | Some(T), | ||
113 | None | ||
114 | } | ||
115 | 125 | ||
116 | fn f() { | 126 | fn f() { |
117 | let a: Option<i32> = Option::Some(1); | 127 | let a: Option<i32> = Option::Some(1); |
118 | }"#, | 128 | } |
129 | "#, | ||
119 | ); | 130 | ); |
120 | } | 131 | } |
121 | 132 | ||
@@ -139,24 +150,30 @@ mod tests { | |||
139 | 150 | ||
140 | #[test] | 151 | #[test] |
141 | fn add_explicit_type_not_applicable_if_ty_not_inferred() { | 152 | fn add_explicit_type_not_applicable_if_ty_not_inferred() { |
142 | check_assist_not_applicable(add_explicit_type, "fn f() { let a$0 = None; }"); | 153 | cov_mark::check!(add_explicit_type_not_applicable_if_ty_not_inferred); |
154 | check_assist_not_applicable(add_explicit_type, r#"fn f() { let a$0 = None; }"#); | ||
143 | } | 155 | } |
144 | 156 | ||
145 | #[test] | 157 | #[test] |
146 | fn add_explicit_type_not_applicable_if_ty_already_specified() { | 158 | fn add_explicit_type_not_applicable_if_ty_already_specified() { |
147 | check_assist_not_applicable(add_explicit_type, "fn f() { let a$0: i32 = 1; }"); | 159 | cov_mark::check!(add_explicit_type_not_applicable_if_ty_already_specified); |
160 | check_assist_not_applicable(add_explicit_type, r#"fn f() { let a$0: i32 = 1; }"#); | ||
148 | } | 161 | } |
149 | 162 | ||
150 | #[test] | 163 | #[test] |
151 | fn add_explicit_type_not_applicable_if_specified_ty_is_tuple() { | 164 | fn add_explicit_type_not_applicable_if_specified_ty_is_tuple() { |
152 | check_assist_not_applicable(add_explicit_type, "fn f() { let a$0: (i32, i32) = (3, 4); }"); | 165 | check_assist_not_applicable( |
166 | add_explicit_type, | ||
167 | r#"fn f() { let a$0: (i32, i32) = (3, 4); }"#, | ||
168 | ); | ||
153 | } | 169 | } |
154 | 170 | ||
155 | #[test] | 171 | #[test] |
156 | fn add_explicit_type_not_applicable_if_cursor_after_equals() { | 172 | fn add_explicit_type_not_applicable_if_cursor_after_equals() { |
173 | cov_mark::check!(add_explicit_type_not_applicable_if_cursor_after_equals); | ||
157 | check_assist_not_applicable( | 174 | check_assist_not_applicable( |
158 | add_explicit_type, | 175 | add_explicit_type, |
159 | "fn f() {let a =$0 match 1 {2 => 3, 3 => 5};}", | 176 | r#"fn f() {let a =$0 match 1 {2 => 3, 3 => 5};}"#, |
160 | ) | 177 | ) |
161 | } | 178 | } |
162 | 179 | ||
@@ -164,7 +181,7 @@ mod tests { | |||
164 | fn add_explicit_type_not_applicable_if_cursor_before_let() { | 181 | fn add_explicit_type_not_applicable_if_cursor_before_let() { |
165 | check_assist_not_applicable( | 182 | check_assist_not_applicable( |
166 | add_explicit_type, | 183 | add_explicit_type, |
167 | "fn f() $0{let a = match 1 {2 => 3, 3 => 5};}", | 184 | r#"fn f() $0{let a = match 1 {2 => 3, 3 => 5};}"#, |
168 | ) | 185 | ) |
169 | } | 186 | } |
170 | 187 | ||
@@ -176,7 +193,8 @@ mod tests { | |||
176 | fn main() { | 193 | fn main() { |
177 | let multiply_by_two$0 = |i| i * 3; | 194 | let multiply_by_two$0 = |i| i * 3; |
178 | let six = multiply_by_two(2); | 195 | let six = multiply_by_two(2); |
179 | }"#, | 196 | } |
197 | "#, | ||
180 | ) | 198 | ) |
181 | } | 199 | } |
182 | 200 | ||
@@ -185,23 +203,19 @@ fn main() { | |||
185 | check_assist( | 203 | check_assist( |
186 | add_explicit_type, | 204 | add_explicit_type, |
187 | r#" | 205 | r#" |
188 | struct Test<K, T = u8> { | 206 | struct Test<K, T = u8> { k: K, t: T } |
189 | k: K, | ||
190 | t: T, | ||
191 | } | ||
192 | 207 | ||
193 | fn main() { | 208 | fn main() { |
194 | let test$0 = Test { t: 23u8, k: 33 }; | 209 | let test$0 = Test { t: 23u8, k: 33 }; |
195 | }"#, | ||
196 | r#" | ||
197 | struct Test<K, T = u8> { | ||
198 | k: K, | ||
199 | t: T, | ||
200 | } | 210 | } |
211 | "#, | ||
212 | r#" | ||
213 | struct Test<K, T = u8> { k: K, t: T } | ||
201 | 214 | ||
202 | fn main() { | 215 | fn main() { |
203 | let test: Test<i32> = Test { t: 23u8, k: 33 }; | 216 | let test: Test<i32> = Test { t: 23u8, k: 33 }; |
204 | }"#, | 217 | } |
218 | "#, | ||
205 | ); | 219 | ); |
206 | } | 220 | } |
207 | } | 221 | } |
diff --git a/crates/ide_assists/src/handlers/add_lifetime_to_type.rs b/crates/ide_assists/src/handlers/add_lifetime_to_type.rs index 844928754..7030d0f97 100644 --- a/crates/ide_assists/src/handlers/add_lifetime_to_type.rs +++ b/crates/ide_assists/src/handlers/add_lifetime_to_type.rs | |||
@@ -1,5 +1,4 @@ | |||
1 | use ast::FieldList; | 1 | use syntax::ast::{self, AstNode, GenericParamsOwner, NameOwner}; |
2 | use syntax::ast::{self, AstNode, GenericParamsOwner, NameOwner, RefType, Type}; | ||
3 | 2 | ||
4 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 3 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
5 | 4 | ||
@@ -65,8 +64,8 @@ pub(crate) fn add_lifetime_to_type(acc: &mut Assists, ctx: &AssistContext) -> Op | |||
65 | ) | 64 | ) |
66 | } | 65 | } |
67 | 66 | ||
68 | fn fetch_borrowed_types(node: &ast::Adt) -> Option<Vec<RefType>> { | 67 | fn fetch_borrowed_types(node: &ast::Adt) -> Option<Vec<ast::RefType>> { |
69 | let ref_types: Vec<RefType> = match node { | 68 | let ref_types: Vec<ast::RefType> = match node { |
70 | ast::Adt::Enum(enum_) => { | 69 | ast::Adt::Enum(enum_) => { |
71 | let variant_list = enum_.variant_list()?; | 70 | let variant_list = enum_.variant_list()?; |
72 | variant_list | 71 | variant_list |
@@ -88,7 +87,7 @@ fn fetch_borrowed_types(node: &ast::Adt) -> Option<Vec<RefType>> { | |||
88 | record_field_list | 87 | record_field_list |
89 | .fields() | 88 | .fields() |
90 | .filter_map(|r_field| { | 89 | .filter_map(|r_field| { |
91 | if let Type::RefType(ref_type) = r_field.ty()? { | 90 | if let ast::Type::RefType(ref_type) = r_field.ty()? { |
92 | if ref_type.lifetime().is_none() { | 91 | if ref_type.lifetime().is_none() { |
93 | return Some(ref_type); | 92 | return Some(ref_type); |
94 | } | 93 | } |
@@ -107,12 +106,12 @@ fn fetch_borrowed_types(node: &ast::Adt) -> Option<Vec<RefType>> { | |||
107 | } | 106 | } |
108 | } | 107 | } |
109 | 108 | ||
110 | fn find_ref_types_from_field_list(field_list: &FieldList) -> Option<Vec<RefType>> { | 109 | fn find_ref_types_from_field_list(field_list: &ast::FieldList) -> Option<Vec<ast::RefType>> { |
111 | let ref_types: Vec<RefType> = match field_list { | 110 | let ref_types: Vec<ast::RefType> = match field_list { |
112 | ast::FieldList::RecordFieldList(record_list) => record_list | 111 | ast::FieldList::RecordFieldList(record_list) => record_list |
113 | .fields() | 112 | .fields() |
114 | .filter_map(|f| { | 113 | .filter_map(|f| { |
115 | if let Type::RefType(ref_type) = f.ty()? { | 114 | if let ast::Type::RefType(ref_type) = f.ty()? { |
116 | if ref_type.lifetime().is_none() { | 115 | if ref_type.lifetime().is_none() { |
117 | return Some(ref_type); | 116 | return Some(ref_type); |
118 | } | 117 | } |
@@ -124,7 +123,7 @@ fn find_ref_types_from_field_list(field_list: &FieldList) -> Option<Vec<RefType> | |||
124 | ast::FieldList::TupleFieldList(tuple_field_list) => tuple_field_list | 123 | ast::FieldList::TupleFieldList(tuple_field_list) => tuple_field_list |
125 | .fields() | 124 | .fields() |
126 | .filter_map(|f| { | 125 | .filter_map(|f| { |
127 | if let Type::RefType(ref_type) = f.ty()? { | 126 | if let ast::Type::RefType(ref_type) = f.ty()? { |
128 | if ref_type.lifetime().is_none() { | 127 | if ref_type.lifetime().is_none() { |
129 | return Some(ref_type); | 128 | return Some(ref_type); |
130 | } | 129 | } |
@@ -152,76 +151,79 @@ mod tests { | |||
152 | fn add_lifetime_to_struct() { | 151 | fn add_lifetime_to_struct() { |
153 | check_assist( | 152 | check_assist( |
154 | add_lifetime_to_type, | 153 | add_lifetime_to_type, |
155 | "struct Foo { a: &$0i32 }", | 154 | r#"struct Foo { a: &$0i32 }"#, |
156 | "struct Foo<'a> { a: &'a i32 }", | 155 | r#"struct Foo<'a> { a: &'a i32 }"#, |
157 | ); | 156 | ); |
158 | 157 | ||
159 | check_assist( | 158 | check_assist( |
160 | add_lifetime_to_type, | 159 | add_lifetime_to_type, |
161 | "struct Foo { a: &$0i32, b: &usize }", | 160 | r#"struct Foo { a: &$0i32, b: &usize }"#, |
162 | "struct Foo<'a> { a: &'a i32, b: &'a usize }", | 161 | r#"struct Foo<'a> { a: &'a i32, b: &'a usize }"#, |
163 | ); | 162 | ); |
164 | 163 | ||
165 | check_assist( | 164 | check_assist( |
166 | add_lifetime_to_type, | 165 | add_lifetime_to_type, |
167 | "struct Foo { a: &$0i32, b: usize }", | 166 | r#"struct Foo { a: &$0i32, b: usize }"#, |
168 | "struct Foo<'a> { a: &'a i32, b: usize }", | 167 | r#"struct Foo<'a> { a: &'a i32, b: usize }"#, |
169 | ); | 168 | ); |
170 | 169 | ||
171 | check_assist( | 170 | check_assist( |
172 | add_lifetime_to_type, | 171 | add_lifetime_to_type, |
173 | "struct Foo<T> { a: &$0T, b: usize }", | 172 | r#"struct Foo<T> { a: &$0T, b: usize }"#, |
174 | "struct Foo<'a, T> { a: &'a T, b: usize }", | 173 | r#"struct Foo<'a, T> { a: &'a T, b: usize }"#, |
175 | ); | 174 | ); |
176 | 175 | ||
177 | check_assist_not_applicable(add_lifetime_to_type, "struct Foo<'a> { a: &$0'a i32 }"); | 176 | check_assist_not_applicable(add_lifetime_to_type, r#"struct Foo<'a> { a: &$0'a i32 }"#); |
178 | check_assist_not_applicable(add_lifetime_to_type, "struct Foo { a: &'a$0 i32 }"); | 177 | check_assist_not_applicable(add_lifetime_to_type, r#"struct Foo { a: &'a$0 i32 }"#); |
179 | } | 178 | } |
180 | 179 | ||
181 | #[test] | 180 | #[test] |
182 | fn add_lifetime_to_enum() { | 181 | fn add_lifetime_to_enum() { |
183 | check_assist( | 182 | check_assist( |
184 | add_lifetime_to_type, | 183 | add_lifetime_to_type, |
185 | "enum Foo { Bar { a: i32 }, Other, Tuple(u32, &$0u32)}", | 184 | r#"enum Foo { Bar { a: i32 }, Other, Tuple(u32, &$0u32)}"#, |
186 | "enum Foo<'a> { Bar { a: i32 }, Other, Tuple(u32, &'a u32)}", | 185 | r#"enum Foo<'a> { Bar { a: i32 }, Other, Tuple(u32, &'a u32)}"#, |
187 | ); | 186 | ); |
188 | 187 | ||
189 | check_assist( | 188 | check_assist( |
190 | add_lifetime_to_type, | 189 | add_lifetime_to_type, |
191 | "enum Foo { Bar { a: &$0i32 }}", | 190 | r#"enum Foo { Bar { a: &$0i32 }}"#, |
192 | "enum Foo<'a> { Bar { a: &'a i32 }}", | 191 | r#"enum Foo<'a> { Bar { a: &'a i32 }}"#, |
193 | ); | 192 | ); |
194 | 193 | ||
195 | check_assist( | 194 | check_assist( |
196 | add_lifetime_to_type, | 195 | add_lifetime_to_type, |
197 | "enum Foo<T> { Bar { a: &$0i32, b: &T }}", | 196 | r#"enum Foo<T> { Bar { a: &$0i32, b: &T }}"#, |
198 | "enum Foo<'a, T> { Bar { a: &'a i32, b: &'a T }}", | 197 | r#"enum Foo<'a, T> { Bar { a: &'a i32, b: &'a T }}"#, |
199 | ); | 198 | ); |
200 | 199 | ||
201 | check_assist_not_applicable(add_lifetime_to_type, "enum Foo<'a> { Bar { a: &$0'a i32 }}"); | 200 | check_assist_not_applicable( |
202 | check_assist_not_applicable(add_lifetime_to_type, "enum Foo { Bar, $0Misc }"); | 201 | add_lifetime_to_type, |
202 | r#"enum Foo<'a> { Bar { a: &$0'a i32 }}"#, | ||
203 | ); | ||
204 | check_assist_not_applicable(add_lifetime_to_type, r#"enum Foo { Bar, $0Misc }"#); | ||
203 | } | 205 | } |
204 | 206 | ||
205 | #[test] | 207 | #[test] |
206 | fn add_lifetime_to_union() { | 208 | fn add_lifetime_to_union() { |
207 | check_assist( | 209 | check_assist( |
208 | add_lifetime_to_type, | 210 | add_lifetime_to_type, |
209 | "union Foo { a: &$0i32 }", | 211 | r#"union Foo { a: &$0i32 }"#, |
210 | "union Foo<'a> { a: &'a i32 }", | 212 | r#"union Foo<'a> { a: &'a i32 }"#, |
211 | ); | 213 | ); |
212 | 214 | ||
213 | check_assist( | 215 | check_assist( |
214 | add_lifetime_to_type, | 216 | add_lifetime_to_type, |
215 | "union Foo { a: &$0i32, b: &usize }", | 217 | r#"union Foo { a: &$0i32, b: &usize }"#, |
216 | "union Foo<'a> { a: &'a i32, b: &'a usize }", | 218 | r#"union Foo<'a> { a: &'a i32, b: &'a usize }"#, |
217 | ); | 219 | ); |
218 | 220 | ||
219 | check_assist( | 221 | check_assist( |
220 | add_lifetime_to_type, | 222 | add_lifetime_to_type, |
221 | "union Foo<T> { a: &$0T, b: usize }", | 223 | r#"union Foo<T> { a: &$0T, b: usize }"#, |
222 | "union Foo<'a, T> { a: &'a T, b: usize }", | 224 | r#"union Foo<'a, T> { a: &'a T, b: usize }"#, |
223 | ); | 225 | ); |
224 | 226 | ||
225 | check_assist_not_applicable(add_lifetime_to_type, "struct Foo<'a> { a: &'a $0i32 }"); | 227 | check_assist_not_applicable(add_lifetime_to_type, r#"struct Foo<'a> { a: &'a $0i32 }"#); |
226 | } | 228 | } |
227 | } | 229 | } |
diff --git a/crates/ide_assists/src/handlers/add_missing_impl_members.rs b/crates/ide_assists/src/handlers/add_missing_impl_members.rs index 63cea754d..0148635f9 100644 --- a/crates/ide_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide_assists/src/handlers/add_missing_impl_members.rs | |||
@@ -3,9 +3,9 @@ use syntax::ast::{self, AstNode}; | |||
3 | 3 | ||
4 | use crate::{ | 4 | use crate::{ |
5 | assist_context::{AssistContext, Assists}, | 5 | assist_context::{AssistContext, Assists}, |
6 | utils::add_trait_assoc_items_to_impl, | 6 | utils::{ |
7 | utils::DefaultMethods, | 7 | add_trait_assoc_items_to_impl, filter_assoc_items, render_snippet, Cursor, DefaultMethods, |
8 | utils::{filter_assoc_items, render_snippet, Cursor}, | 8 | }, |
9 | AssistId, AssistKind, | 9 | AssistId, AssistKind, |
10 | }; | 10 | }; |
11 | 11 | ||
diff --git a/crates/ide_assists/src/handlers/convert_comment_block.rs b/crates/ide_assists/src/handlers/convert_comment_block.rs index cdc45fc42..d202a85f9 100644 --- a/crates/ide_assists/src/handlers/convert_comment_block.rs +++ b/crates/ide_assists/src/handlers/convert_comment_block.rs | |||
@@ -1,14 +1,6 @@ | |||
1 | use itertools::Itertools; | 1 | use itertools::Itertools; |
2 | use std::convert::identity; | ||
3 | use syntax::{ | 2 | use syntax::{ |
4 | ast::{ | 3 | ast::{self, edit::IndentLevel, Comment, CommentKind, CommentShape, Whitespace}, |
5 | self, | ||
6 | edit::IndentLevel, | ||
7 | Comment, CommentKind, | ||
8 | CommentPlacement::{Inner, Outer}, | ||
9 | CommentShape::{self, Block, Line}, | ||
10 | Whitespace, | ||
11 | }, | ||
12 | AstToken, Direction, SyntaxElement, TextRange, | 4 | AstToken, Direction, SyntaxElement, TextRange, |
13 | }; | 5 | }; |
14 | 6 | ||
@@ -30,21 +22,18 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
30 | /// */ | 22 | /// */ |
31 | /// ``` | 23 | /// ``` |
32 | pub(crate) fn convert_comment_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 24 | pub(crate) fn convert_comment_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
33 | if let Some(comment) = ctx.find_token_at_offset::<ast::Comment>() { | 25 | let comment = ctx.find_token_at_offset::<ast::Comment>()?; |
34 | // Only allow comments which are alone on their line | 26 | // Only allow comments which are alone on their line |
35 | if let Some(prev) = comment.syntax().prev_token() { | 27 | if let Some(prev) = comment.syntax().prev_token() { |
36 | if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() { | 28 | if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() { |
37 | return None; | 29 | return None; |
38 | } | ||
39 | } | 30 | } |
40 | |||
41 | return match comment.kind().shape { | ||
42 | ast::CommentShape::Block => block_to_line(acc, comment), | ||
43 | ast::CommentShape::Line => line_to_block(acc, comment), | ||
44 | }; | ||
45 | } | 31 | } |
46 | 32 | ||
47 | return None; | 33 | match comment.kind().shape { |
34 | ast::CommentShape::Block => block_to_line(acc, comment), | ||
35 | ast::CommentShape::Line => line_to_block(acc, comment), | ||
36 | } | ||
48 | } | 37 | } |
49 | 38 | ||
50 | fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> { | 39 | fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> { |
@@ -56,8 +45,7 @@ fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> { | |||
56 | target, | 45 | target, |
57 | |edit| { | 46 | |edit| { |
58 | let indentation = IndentLevel::from_token(comment.syntax()); | 47 | let indentation = IndentLevel::from_token(comment.syntax()); |
59 | let line_prefix = | 48 | let line_prefix = CommentKind { shape: CommentShape::Line, ..comment.kind() }.prefix(); |
60 | comment_kind_prefix(CommentKind { shape: CommentShape::Line, ..comment.kind() }); | ||
61 | 49 | ||
62 | let text = comment.text(); | 50 | let text = comment.text(); |
63 | let text = &text[comment.prefix().len()..(text.len() - "*/".len())].trim(); | 51 | let text = &text[comment.prefix().len()..(text.len() - "*/".len())].trim(); |
@@ -106,7 +94,7 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { | |||
106 | comments.into_iter().map(|c| line_comment_text(indentation, c)).join("\n"); | 94 | comments.into_iter().map(|c| line_comment_text(indentation, c)).join("\n"); |
107 | 95 | ||
108 | let block_prefix = | 96 | let block_prefix = |
109 | comment_kind_prefix(CommentKind { shape: CommentShape::Block, ..comment.kind() }); | 97 | CommentKind { shape: CommentShape::Block, ..comment.kind() }.prefix(); |
110 | 98 | ||
111 | let output = | 99 | let output = |
112 | format!("{}\n{}\n{}*/", block_prefix, block_comment_body, indentation.to_string()); | 100 | format!("{}\n{}\n{}*/", block_prefix, block_comment_body, indentation.to_string()); |
@@ -140,7 +128,7 @@ fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> { | |||
140 | .filter(|s| !skippable(s)) | 128 | .filter(|s| !skippable(s)) |
141 | .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix)) | 129 | .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix)) |
142 | .take_while(|opt_com| opt_com.is_some()) | 130 | .take_while(|opt_com| opt_com.is_some()) |
143 | .filter_map(identity) | 131 | .flatten() |
144 | .skip(1); // skip the first element so we don't duplicate it in next_comments | 132 | .skip(1); // skip the first element so we don't duplicate it in next_comments |
145 | 133 | ||
146 | let next_comments = comment | 134 | let next_comments = comment |
@@ -149,7 +137,7 @@ fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> { | |||
149 | .filter(|s| !skippable(s)) | 137 | .filter(|s| !skippable(s)) |
150 | .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix)) | 138 | .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix)) |
151 | .take_while(|opt_com| opt_com.is_some()) | 139 | .take_while(|opt_com| opt_com.is_some()) |
152 | .filter_map(identity); | 140 | .flatten(); |
153 | 141 | ||
154 | let mut comments: Vec<_> = prev_comments.collect(); | 142 | let mut comments: Vec<_> = prev_comments.collect(); |
155 | comments.reverse(); | 143 | comments.reverse(); |
@@ -183,17 +171,6 @@ fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> String { | |||
183 | } | 171 | } |
184 | } | 172 | } |
185 | 173 | ||
186 | fn comment_kind_prefix(ck: ast::CommentKind) -> &'static str { | ||
187 | match (ck.shape, ck.doc) { | ||
188 | (Line, Some(Inner)) => "//!", | ||
189 | (Line, Some(Outer)) => "///", | ||
190 | (Line, None) => "//", | ||
191 | (Block, Some(Inner)) => "/*!", | ||
192 | (Block, Some(Outer)) => "/**", | ||
193 | (Block, None) => "/*", | ||
194 | } | ||
195 | } | ||
196 | |||
197 | #[cfg(test)] | 174 | #[cfg(test)] |
198 | mod tests { | 175 | mod tests { |
199 | use crate::tests::{check_assist, check_assist_not_applicable}; | 176 | use crate::tests::{check_assist, check_assist_not_applicable}; |
diff --git a/crates/ide_assists/src/handlers/early_return.rs b/crates/ide_assists/src/handlers/early_return.rs index 9e0918477..c66f8c05d 100644 --- a/crates/ide_assists/src/handlers/early_return.rs +++ b/crates/ide_assists/src/handlers/early_return.rs | |||
@@ -56,7 +56,11 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext) | |||
56 | match path.qualifier() { | 56 | match path.qualifier() { |
57 | None => { | 57 | None => { |
58 | let bound_ident = pat.fields().next().unwrap(); | 58 | let bound_ident = pat.fields().next().unwrap(); |
59 | Some((path, bound_ident)) | 59 | if ast::IdentPat::can_cast(bound_ident.syntax().kind()) { |
60 | Some((path, bound_ident)) | ||
61 | } else { | ||
62 | return None; | ||
63 | } | ||
60 | } | 64 | } |
61 | Some(_) => return None, | 65 | Some(_) => return None, |
62 | } | 66 | } |
@@ -143,10 +147,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext) | |||
143 | make::expr_match(cond_expr, make::match_arm_list(vec![happy_arm, sad_arm])) | 147 | make::expr_match(cond_expr, make::match_arm_list(vec![happy_arm, sad_arm])) |
144 | }; | 148 | }; |
145 | 149 | ||
146 | let let_stmt = make::let_stmt( | 150 | let let_stmt = make::let_stmt(bound_ident, Some(match_expr)); |
147 | make::ident_pat(make::name(&bound_ident.syntax().to_string())).into(), | ||
148 | Some(match_expr), | ||
149 | ); | ||
150 | let let_stmt = let_stmt.indent(if_indent_level); | 151 | let let_stmt = let_stmt.indent(if_indent_level); |
151 | replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr) | 152 | replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr) |
152 | } | 153 | } |
@@ -203,7 +204,7 @@ mod tests { | |||
203 | if$0 true { | 204 | if$0 true { |
204 | foo(); | 205 | foo(); |
205 | 206 | ||
206 | //comment | 207 | // comment |
207 | bar(); | 208 | bar(); |
208 | } | 209 | } |
209 | } | 210 | } |
@@ -216,7 +217,7 @@ mod tests { | |||
216 | } | 217 | } |
217 | foo(); | 218 | foo(); |
218 | 219 | ||
219 | //comment | 220 | // comment |
220 | bar(); | 221 | bar(); |
221 | } | 222 | } |
222 | "#, | 223 | "#, |
@@ -233,7 +234,7 @@ mod tests { | |||
233 | if$0 let Some(n) = n { | 234 | if$0 let Some(n) = n { |
234 | foo(n); | 235 | foo(n); |
235 | 236 | ||
236 | //comment | 237 | // comment |
237 | bar(); | 238 | bar(); |
238 | } | 239 | } |
239 | } | 240 | } |
@@ -247,7 +248,7 @@ mod tests { | |||
247 | }; | 248 | }; |
248 | foo(n); | 249 | foo(n); |
249 | 250 | ||
250 | //comment | 251 | // comment |
251 | bar(); | 252 | bar(); |
252 | } | 253 | } |
253 | "#, | 254 | "#, |
@@ -284,10 +285,10 @@ mod tests { | |||
284 | r#" | 285 | r#" |
285 | fn main(n: Option<String>) { | 286 | fn main(n: Option<String>) { |
286 | bar(); | 287 | bar(); |
287 | if$0 let Ok(n) = n { | 288 | if$0 let Some(n) = n { |
288 | foo(n); | 289 | foo(n); |
289 | 290 | ||
290 | //comment | 291 | // comment |
291 | bar(); | 292 | bar(); |
292 | } | 293 | } |
293 | } | 294 | } |
@@ -296,12 +297,74 @@ mod tests { | |||
296 | fn main(n: Option<String>) { | 297 | fn main(n: Option<String>) { |
297 | bar(); | 298 | bar(); |
298 | let n = match n { | 299 | let n = match n { |
299 | Ok(it) => it, | 300 | Some(it) => it, |
301 | _ => return, | ||
302 | }; | ||
303 | foo(n); | ||
304 | |||
305 | // comment | ||
306 | bar(); | ||
307 | } | ||
308 | "#, | ||
309 | ); | ||
310 | } | ||
311 | |||
312 | #[test] | ||
313 | fn convert_let_mut_ok_inside_fn() { | ||
314 | check_assist( | ||
315 | convert_to_guarded_return, | ||
316 | r#" | ||
317 | fn main(n: Option<String>) { | ||
318 | bar(); | ||
319 | if$0 let Some(mut n) = n { | ||
320 | foo(n); | ||
321 | |||
322 | // comment | ||
323 | bar(); | ||
324 | } | ||
325 | } | ||
326 | "#, | ||
327 | r#" | ||
328 | fn main(n: Option<String>) { | ||
329 | bar(); | ||
330 | let mut n = match n { | ||
331 | Some(it) => it, | ||
332 | _ => return, | ||
333 | }; | ||
334 | foo(n); | ||
335 | |||
336 | // comment | ||
337 | bar(); | ||
338 | } | ||
339 | "#, | ||
340 | ); | ||
341 | } | ||
342 | |||
343 | #[test] | ||
344 | fn convert_let_ref_ok_inside_fn() { | ||
345 | check_assist( | ||
346 | convert_to_guarded_return, | ||
347 | r#" | ||
348 | fn main(n: Option<&str>) { | ||
349 | bar(); | ||
350 | if$0 let Some(ref n) = n { | ||
351 | foo(n); | ||
352 | |||
353 | // comment | ||
354 | bar(); | ||
355 | } | ||
356 | } | ||
357 | "#, | ||
358 | r#" | ||
359 | fn main(n: Option<&str>) { | ||
360 | bar(); | ||
361 | let ref n = match n { | ||
362 | Some(it) => it, | ||
300 | _ => return, | 363 | _ => return, |
301 | }; | 364 | }; |
302 | foo(n); | 365 | foo(n); |
303 | 366 | ||
304 | //comment | 367 | // comment |
305 | bar(); | 368 | bar(); |
306 | } | 369 | } |
307 | "#, | 370 | "#, |
diff --git a/crates/ide_assists/src/handlers/expand_glob_import.rs b/crates/ide_assists/src/handlers/expand_glob_import.rs index 83aa11d52..98389e4f7 100644 --- a/crates/ide_assists/src/handlers/expand_glob_import.rs +++ b/crates/ide_assists/src/handlers/expand_glob_import.rs | |||
@@ -136,18 +136,13 @@ impl Refs { | |||
136 | .into_iter() | 136 | .into_iter() |
137 | .filter(|r| { | 137 | .filter(|r| { |
138 | if let Def::ModuleDef(ModuleDef::Trait(tr)) = r.def { | 138 | if let Def::ModuleDef(ModuleDef::Trait(tr)) = r.def { |
139 | if tr | 139 | if tr.items(ctx.db()).into_iter().any(|ai| { |
140 | .items(ctx.db()) | 140 | if let AssocItem::Function(f) = ai { |
141 | .into_iter() | 141 | Def::ModuleDef(ModuleDef::Function(f)).is_referenced_in(ctx) |
142 | .find(|ai| { | 142 | } else { |
143 | if let AssocItem::Function(f) = *ai { | 143 | false |
144 | Def::ModuleDef(ModuleDef::Function(f)).is_referenced_in(ctx) | 144 | } |
145 | } else { | 145 | }) { |
146 | false | ||
147 | } | ||
148 | }) | ||
149 | .is_some() | ||
150 | { | ||
151 | return true; | 146 | return true; |
152 | } | 147 | } |
153 | } | 148 | } |
diff --git a/crates/ide_assists/src/handlers/merge_imports.rs b/crates/ide_assists/src/handlers/merge_imports.rs index 7bd7e1e36..8e0794218 100644 --- a/crates/ide_assists/src/handlers/merge_imports.rs +++ b/crates/ide_assists/src/handlers/merge_imports.rs | |||
@@ -1,8 +1,5 @@ | |||
1 | use ide_db::helpers::insert_use::{try_merge_imports, try_merge_trees, MergeBehavior}; | 1 | use ide_db::helpers::insert_use::{try_merge_imports, try_merge_trees, MergeBehavior}; |
2 | use syntax::{ | 2 | use syntax::{algo::neighbor, ast, ted, AstNode}; |
3 | algo::{neighbor, SyntaxRewriter}, | ||
4 | ast, AstNode, | ||
5 | }; | ||
6 | 3 | ||
7 | use crate::{ | 4 | use crate::{ |
8 | assist_context::{AssistContext, Assists}, | 5 | assist_context::{AssistContext, Assists}, |
@@ -24,33 +21,23 @@ use crate::{ | |||
24 | // ``` | 21 | // ``` |
25 | pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 22 | pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
26 | let tree: ast::UseTree = ctx.find_node_at_offset()?; | 23 | let tree: ast::UseTree = ctx.find_node_at_offset()?; |
27 | let mut rewriter = SyntaxRewriter::default(); | ||
28 | let mut offset = ctx.offset(); | ||
29 | 24 | ||
25 | let mut imports = None; | ||
26 | let mut uses = None; | ||
30 | if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) { | 27 | if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) { |
31 | let (merged, to_delete) = | 28 | let (merged, to_remove) = |
32 | next_prev().filter_map(|dir| neighbor(&use_item, dir)).find_map(|use_item2| { | 29 | next_prev().filter_map(|dir| neighbor(&use_item, dir)).find_map(|use_item2| { |
33 | try_merge_imports(&use_item, &use_item2, MergeBehavior::Full).zip(Some(use_item2)) | 30 | try_merge_imports(&use_item, &use_item2, MergeBehavior::Full).zip(Some(use_item2)) |
34 | })?; | 31 | })?; |
35 | 32 | ||
36 | rewriter.replace_ast(&use_item, &merged); | 33 | imports = Some((use_item, merged, to_remove)); |
37 | rewriter += to_delete.remove(); | ||
38 | |||
39 | if to_delete.syntax().text_range().end() < offset { | ||
40 | offset -= to_delete.syntax().text_range().len(); | ||
41 | } | ||
42 | } else { | 34 | } else { |
43 | let (merged, to_delete) = | 35 | let (merged, to_remove) = |
44 | next_prev().filter_map(|dir| neighbor(&tree, dir)).find_map(|use_tree| { | 36 | next_prev().filter_map(|dir| neighbor(&tree, dir)).find_map(|use_tree| { |
45 | try_merge_trees(&tree, &use_tree, MergeBehavior::Full).zip(Some(use_tree)) | 37 | try_merge_trees(&tree, &use_tree, MergeBehavior::Full).zip(Some(use_tree)) |
46 | })?; | 38 | })?; |
47 | 39 | ||
48 | rewriter.replace_ast(&tree, &merged); | 40 | uses = Some((tree.clone(), merged, to_remove)) |
49 | rewriter += to_delete.remove(); | ||
50 | |||
51 | if to_delete.syntax().text_range().end() < offset { | ||
52 | offset -= to_delete.syntax().text_range().len(); | ||
53 | } | ||
54 | }; | 41 | }; |
55 | 42 | ||
56 | let target = tree.syntax().text_range(); | 43 | let target = tree.syntax().text_range(); |
@@ -59,7 +46,21 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<() | |||
59 | "Merge imports", | 46 | "Merge imports", |
60 | target, | 47 | target, |
61 | |builder| { | 48 | |builder| { |
62 | builder.rewrite(rewriter); | 49 | if let Some((to_replace, replacement, to_remove)) = imports { |
50 | let to_replace = builder.make_ast_mut(to_replace); | ||
51 | let to_remove = builder.make_ast_mut(to_remove); | ||
52 | |||
53 | ted::replace(to_replace.syntax(), replacement.syntax()); | ||
54 | to_remove.remove(); | ||
55 | } | ||
56 | |||
57 | if let Some((to_replace, replacement, to_remove)) = uses { | ||
58 | let to_replace = builder.make_ast_mut(to_replace); | ||
59 | let to_remove = builder.make_ast_mut(to_remove); | ||
60 | |||
61 | ted::replace(to_replace.syntax(), replacement.syntax()); | ||
62 | to_remove.remove() | ||
63 | } | ||
63 | }, | 64 | }, |
64 | ) | 65 | ) |
65 | } | 66 | } |
diff --git a/crates/ide_assists/src/handlers/move_bounds.rs b/crates/ide_assists/src/handlers/move_bounds.rs index b5dec8014..011a28d44 100644 --- a/crates/ide_assists/src/handlers/move_bounds.rs +++ b/crates/ide_assists/src/handlers/move_bounds.rs | |||
@@ -21,7 +21,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
21 | // } | 21 | // } |
22 | // ``` | 22 | // ``` |
23 | pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 23 | pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
24 | let type_param_list = ctx.find_node_at_offset::<ast::GenericParamList>()?.clone_for_update(); | 24 | let type_param_list = ctx.find_node_at_offset::<ast::GenericParamList>()?; |
25 | 25 | ||
26 | let mut type_params = type_param_list.type_params(); | 26 | let mut type_params = type_param_list.type_params(); |
27 | if type_params.all(|p| p.type_bound_list().is_none()) { | 27 | if type_params.all(|p| p.type_bound_list().is_none()) { |
@@ -29,7 +29,6 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext | |||
29 | } | 29 | } |
30 | 30 | ||
31 | let parent = type_param_list.syntax().parent()?; | 31 | let parent = type_param_list.syntax().parent()?; |
32 | let original_parent_range = parent.text_range(); | ||
33 | 32 | ||
34 | let target = type_param_list.syntax().text_range(); | 33 | let target = type_param_list.syntax().text_range(); |
35 | acc.add( | 34 | acc.add( |
@@ -37,6 +36,9 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext | |||
37 | "Move to where clause", | 36 | "Move to where clause", |
38 | target, | 37 | target, |
39 | |edit| { | 38 | |edit| { |
39 | let type_param_list = edit.make_ast_mut(type_param_list); | ||
40 | let parent = edit.make_mut(parent); | ||
41 | |||
40 | let where_clause: ast::WhereClause = match_ast! { | 42 | let where_clause: ast::WhereClause = match_ast! { |
41 | match parent { | 43 | match parent { |
42 | ast::Fn(it) => it.get_or_create_where_clause(), | 44 | ast::Fn(it) => it.get_or_create_where_clause(), |
@@ -56,8 +58,6 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext | |||
56 | tbl.remove() | 58 | tbl.remove() |
57 | } | 59 | } |
58 | } | 60 | } |
59 | |||
60 | edit.replace(original_parent_range, parent.to_string()) | ||
61 | }, | 61 | }, |
62 | ) | 62 | ) |
63 | } | 63 | } |
diff --git a/crates/ide_assists/src/handlers/qualify_path.rs b/crates/ide_assists/src/handlers/qualify_path.rs index e7444f7db..f91770a76 100644 --- a/crates/ide_assists/src/handlers/qualify_path.rs +++ b/crates/ide_assists/src/handlers/qualify_path.rs | |||
@@ -536,6 +536,7 @@ fn main() { | |||
536 | } | 536 | } |
537 | 537 | ||
538 | #[test] | 538 | #[test] |
539 | #[ignore = "FIXME: non-trait assoc items completion is unsupported yet, see FIXME in the import_assets.rs for more details"] | ||
539 | fn associated_struct_const_unqualified() { | 540 | fn associated_struct_const_unqualified() { |
540 | check_assist( | 541 | check_assist( |
541 | qualify_path, | 542 | qualify_path, |
diff --git a/crates/ide_assists/src/handlers/reorder_fields.rs b/crates/ide_assists/src/handlers/reorder_fields.rs index 794c89323..383ca6c47 100644 --- a/crates/ide_assists/src/handlers/reorder_fields.rs +++ b/crates/ide_assists/src/handlers/reorder_fields.rs | |||
@@ -1,9 +1,6 @@ | |||
1 | use itertools::Itertools; | ||
2 | use rustc_hash::FxHashMap; | 1 | use rustc_hash::FxHashMap; |
3 | 2 | ||
4 | use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; | 3 | use syntax::{algo, ast, match_ast, AstNode, SyntaxKind::*, SyntaxNode}; |
5 | use ide_db::RootDatabase; | ||
6 | use syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode}; | ||
7 | 4 | ||
8 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 5 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
9 | 6 | ||
@@ -23,26 +20,39 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
23 | // ``` | 20 | // ``` |
24 | // | 21 | // |
25 | pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 22 | pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
26 | reorder::<ast::RecordExpr>(acc, ctx).or_else(|| reorder::<ast::RecordPat>(acc, ctx)) | 23 | let record = ctx |
27 | } | 24 | .find_node_at_offset::<ast::RecordExpr>() |
25 | .map(|it| it.syntax().clone()) | ||
26 | .or_else(|| ctx.find_node_at_offset::<ast::RecordPat>().map(|it| it.syntax().clone()))?; | ||
28 | 27 | ||
29 | fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 28 | let path = record.children().find_map(ast::Path::cast)?; |
30 | let record = ctx.find_node_at_offset::<R>()?; | ||
31 | let path = record.syntax().children().find_map(ast::Path::cast)?; | ||
32 | 29 | ||
33 | let ranks = compute_fields_ranks(&path, &ctx)?; | 30 | let ranks = compute_fields_ranks(&path, &ctx)?; |
34 | 31 | ||
35 | let fields = get_fields(&record.syntax()); | 32 | let fields: Vec<SyntaxNode> = { |
36 | let sorted_fields = sorted_by_rank(&fields, |node| { | 33 | let field_kind = match record.kind() { |
37 | *ranks.get(&get_field_name(node)).unwrap_or(&usize::max_value()) | 34 | RECORD_EXPR => RECORD_EXPR_FIELD, |
38 | }); | 35 | RECORD_PAT => RECORD_PAT_FIELD, |
36 | _ => { | ||
37 | stdx::never!(); | ||
38 | return None; | ||
39 | } | ||
40 | }; | ||
41 | record.children().flat_map(|n| n.children()).filter(|n| n.kind() == field_kind).collect() | ||
42 | }; | ||
43 | |||
44 | let sorted_fields = { | ||
45 | let mut fields = fields.clone(); | ||
46 | fields.sort_by_key(|node| *ranks.get(&get_field_name(node)).unwrap_or(&usize::max_value())); | ||
47 | fields | ||
48 | }; | ||
39 | 49 | ||
40 | if sorted_fields == fields { | 50 | if sorted_fields == fields { |
41 | cov_mark::hit!(reorder_sorted_fields); | 51 | cov_mark::hit!(reorder_sorted_fields); |
42 | return None; | 52 | return None; |
43 | } | 53 | } |
44 | 54 | ||
45 | let target = record.syntax().text_range(); | 55 | let target = record.text_range(); |
46 | acc.add( | 56 | acc.add( |
47 | AssistId("reorder_fields", AssistKind::RefactorRewrite), | 57 | AssistId("reorder_fields", AssistKind::RefactorRewrite), |
48 | "Reorder record fields", | 58 | "Reorder record fields", |
@@ -57,14 +67,6 @@ fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
57 | ) | 67 | ) |
58 | } | 68 | } |
59 | 69 | ||
60 | fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> { | ||
61 | match node.kind() { | ||
62 | RECORD_EXPR => vec![RECORD_EXPR_FIELD], | ||
63 | RECORD_PAT => vec![RECORD_PAT_FIELD, IDENT_PAT], | ||
64 | _ => vec![], | ||
65 | } | ||
66 | } | ||
67 | |||
68 | fn get_field_name(node: &SyntaxNode) -> String { | 70 | fn get_field_name(node: &SyntaxNode) -> String { |
69 | let res = match_ast! { | 71 | let res = match_ast! { |
70 | match node { | 72 | match node { |
@@ -76,34 +78,20 @@ fn get_field_name(node: &SyntaxNode) -> String { | |||
76 | res.unwrap_or_default() | 78 | res.unwrap_or_default() |
77 | } | 79 | } |
78 | 80 | ||
79 | fn get_fields(record: &SyntaxNode) -> Vec<SyntaxNode> { | 81 | fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashMap<String, usize>> { |
80 | let kinds = get_fields_kind(record); | 82 | let strukt = match ctx.sema.resolve_path(path) { |
81 | record.children().flat_map(|n| n.children()).filter(|n| kinds.contains(&n.kind())).collect() | 83 | Some(hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Struct(it)))) => it, |
82 | } | 84 | _ => return None, |
83 | 85 | }; | |
84 | fn sorted_by_rank( | ||
85 | fields: &[SyntaxNode], | ||
86 | get_rank: impl Fn(&SyntaxNode) -> usize, | ||
87 | ) -> Vec<SyntaxNode> { | ||
88 | fields.iter().cloned().sorted_by_key(get_rank).collect() | ||
89 | } | ||
90 | 86 | ||
91 | fn struct_definition(path: &ast::Path, sema: &Semantics<RootDatabase>) -> Option<Struct> { | 87 | let res = strukt |
92 | match sema.resolve_path(path) { | 88 | .fields(ctx.db()) |
93 | Some(PathResolution::Def(ModuleDef::Adt(Adt::Struct(s)))) => Some(s), | 89 | .iter() |
94 | _ => None, | 90 | .enumerate() |
95 | } | 91 | .map(|(idx, field)| (field.name(ctx.db()).to_string(), idx)) |
96 | } | 92 | .collect(); |
97 | 93 | ||
98 | fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashMap<String, usize>> { | 94 | Some(res) |
99 | Some( | ||
100 | struct_definition(path, &ctx.sema)? | ||
101 | .fields(ctx.db()) | ||
102 | .iter() | ||
103 | .enumerate() | ||
104 | .map(|(idx, field)| (field.name(ctx.db()).to_string(), idx)) | ||
105 | .collect(), | ||
106 | ) | ||
107 | } | 95 | } |
108 | 96 | ||
109 | #[cfg(test)] | 97 | #[cfg(test)] |
@@ -118,11 +106,7 @@ mod tests { | |||
118 | check_assist_not_applicable( | 106 | check_assist_not_applicable( |
119 | reorder_fields, | 107 | reorder_fields, |
120 | r#" | 108 | r#" |
121 | struct Foo { | 109 | struct Foo { foo: i32, bar: i32 } |
122 | foo: i32, | ||
123 | bar: i32, | ||
124 | } | ||
125 | |||
126 | const test: Foo = $0Foo { foo: 0, bar: 0 }; | 110 | const test: Foo = $0Foo { foo: 0, bar: 0 }; |
127 | "#, | 111 | "#, |
128 | ) | 112 | ) |
@@ -133,8 +117,8 @@ const test: Foo = $0Foo { foo: 0, bar: 0 }; | |||
133 | check_assist_not_applicable( | 117 | check_assist_not_applicable( |
134 | reorder_fields, | 118 | reorder_fields, |
135 | r#" | 119 | r#" |
136 | struct Foo {}; | 120 | struct Foo {} |
137 | const test: Foo = $0Foo {} | 121 | const test: Foo = $0Foo {}; |
138 | "#, | 122 | "#, |
139 | ) | 123 | ) |
140 | } | 124 | } |
@@ -144,12 +128,12 @@ const test: Foo = $0Foo {} | |||
144 | check_assist( | 128 | check_assist( |
145 | reorder_fields, | 129 | reorder_fields, |
146 | r#" | 130 | r#" |
147 | struct Foo {foo: i32, bar: i32}; | 131 | struct Foo { foo: i32, bar: i32 } |
148 | const test: Foo = $0Foo {bar: 0, foo: 1} | 132 | const test: Foo = $0Foo { bar: 0, foo: 1 }; |
149 | "#, | 133 | "#, |
150 | r#" | 134 | r#" |
151 | struct Foo {foo: i32, bar: i32}; | 135 | struct Foo { foo: i32, bar: i32 } |
152 | const test: Foo = Foo {foo: 1, bar: 0} | 136 | const test: Foo = Foo { foo: 1, bar: 0 }; |
153 | "#, | 137 | "#, |
154 | ) | 138 | ) |
155 | } | 139 | } |
@@ -186,10 +170,7 @@ fn f(f: Foo) -> { | |||
186 | check_assist( | 170 | check_assist( |
187 | reorder_fields, | 171 | reorder_fields, |
188 | r#" | 172 | r#" |
189 | struct Foo { | 173 | struct Foo { foo: String, bar: String } |
190 | foo: String, | ||
191 | bar: String, | ||
192 | } | ||
193 | 174 | ||
194 | impl Foo { | 175 | impl Foo { |
195 | fn new() -> Foo { | 176 | fn new() -> Foo { |
@@ -203,10 +184,7 @@ impl Foo { | |||
203 | } | 184 | } |
204 | "#, | 185 | "#, |
205 | r#" | 186 | r#" |
206 | struct Foo { | 187 | struct Foo { foo: String, bar: String } |
207 | foo: String, | ||
208 | bar: String, | ||
209 | } | ||
210 | 188 | ||
211 | impl Foo { | 189 | impl Foo { |
212 | fn new() -> Foo { | 190 | fn new() -> Foo { |
diff --git a/crates/ide_assists/src/handlers/reorder_impl.rs b/crates/ide_assists/src/handlers/reorder_impl.rs index edf4b0bfe..f976e73ad 100644 --- a/crates/ide_assists/src/handlers/reorder_impl.rs +++ b/crates/ide_assists/src/handlers/reorder_impl.rs | |||
@@ -95,7 +95,7 @@ fn compute_method_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashM | |||
95 | _ => None, | 95 | _ => None, |
96 | }) | 96 | }) |
97 | .enumerate() | 97 | .enumerate() |
98 | .map(|(idx, func)| ((func.name(ctx.db()).to_string(), idx))) | 98 | .map(|(idx, func)| (func.name(ctx.db()).to_string(), idx)) |
99 | .collect(), | 99 | .collect(), |
100 | ) | 100 | ) |
101 | } | 101 | } |
diff --git a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs index 88fe2fe90..4f0ef52ca 100644 --- a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use hir::ModuleDef; | 1 | use hir::ModuleDef; |
2 | use ide_db::helpers::mod_path_to_ast; | 2 | use ide_db::helpers::{import_assets::NameToImport, mod_path_to_ast}; |
3 | use ide_db::items_locator; | 3 | use ide_db::items_locator; |
4 | use itertools::Itertools; | 4 | use itertools::Itertools; |
5 | use syntax::{ | 5 | use syntax::{ |
@@ -65,20 +65,24 @@ pub(crate) fn replace_derive_with_manual_impl( | |||
65 | let current_module = ctx.sema.scope(annotated_name.syntax()).module()?; | 65 | let current_module = ctx.sema.scope(annotated_name.syntax()).module()?; |
66 | let current_crate = current_module.krate(); | 66 | let current_crate = current_module.krate(); |
67 | 67 | ||
68 | let found_traits = | 68 | let found_traits = items_locator::items_with_name( |
69 | items_locator::with_exact_name(&ctx.sema, current_crate, trait_token.text().to_string()) | 69 | &ctx.sema, |
70 | .into_iter() | 70 | current_crate, |
71 | .filter_map(|item| match ModuleDef::from(item.as_module_def_id()?) { | 71 | NameToImport::Exact(trait_token.text().to_string()), |
72 | ModuleDef::Trait(trait_) => Some(trait_), | 72 | items_locator::AssocItemSearch::Exclude, |
73 | _ => None, | 73 | Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT), |
74 | }) | 74 | ) |
75 | .flat_map(|trait_| { | 75 | .filter_map(|item| match ModuleDef::from(item.as_module_def_id()?) { |
76 | current_module | 76 | ModuleDef::Trait(trait_) => Some(trait_), |
77 | .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_)) | 77 | _ => None, |
78 | .as_ref() | 78 | }) |
79 | .map(mod_path_to_ast) | 79 | .flat_map(|trait_| { |
80 | .zip(Some(trait_)) | 80 | current_module |
81 | }); | 81 | .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_)) |
82 | .as_ref() | ||
83 | .map(mod_path_to_ast) | ||
84 | .zip(Some(trait_)) | ||
85 | }); | ||
82 | 86 | ||
83 | let mut no_traits_found = true; | 87 | let mut no_traits_found = true; |
84 | for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) { | 88 | for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) { |
diff --git a/crates/ide_assists/src/handlers/unmerge_use.rs b/crates/ide_assists/src/handlers/unmerge_use.rs index 616af7c2e..8d271e056 100644 --- a/crates/ide_assists/src/handlers/unmerge_use.rs +++ b/crates/ide_assists/src/handlers/unmerge_use.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use syntax::{ | 1 | use syntax::{ |
2 | algo::SyntaxRewriter, | 2 | ast::{self, VisibilityOwner}, |
3 | ast::{self, edit::AstNodeEdit, VisibilityOwner}, | 3 | ted::{self, Position}, |
4 | AstNode, SyntaxKind, | 4 | AstNode, SyntaxKind, |
5 | }; | 5 | }; |
6 | 6 | ||
@@ -22,7 +22,7 @@ use crate::{ | |||
22 | // use std::fmt::Display; | 22 | // use std::fmt::Display; |
23 | // ``` | 23 | // ``` |
24 | pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 24 | pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
25 | let tree: ast::UseTree = ctx.find_node_at_offset()?; | 25 | let tree: ast::UseTree = ctx.find_node_at_offset::<ast::UseTree>()?.clone_for_update(); |
26 | 26 | ||
27 | let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?; | 27 | let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?; |
28 | if tree_list.use_trees().count() < 2 { | 28 | if tree_list.use_trees().count() < 2 { |
@@ -33,6 +33,9 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
33 | let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?; | 33 | let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?; |
34 | let path = resolve_full_path(&tree)?; | 34 | let path = resolve_full_path(&tree)?; |
35 | 35 | ||
36 | let old_parent_range = use_.syntax().parent()?.text_range(); | ||
37 | let new_parent = use_.syntax().parent()?; | ||
38 | |||
36 | let target = tree.syntax().text_range(); | 39 | let target = tree.syntax().text_range(); |
37 | acc.add( | 40 | acc.add( |
38 | AssistId("unmerge_use", AssistKind::RefactorRewrite), | 41 | AssistId("unmerge_use", AssistKind::RefactorRewrite), |
@@ -47,20 +50,13 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
47 | tree.rename(), | 50 | tree.rename(), |
48 | tree.star_token().is_some(), | 51 | tree.star_token().is_some(), |
49 | ), | 52 | ), |
50 | ); | 53 | ) |
51 | 54 | .clone_for_update(); | |
52 | let mut rewriter = SyntaxRewriter::default(); | 55 | |
53 | rewriter += tree.remove(); | 56 | tree.remove(); |
54 | rewriter.insert_after(use_.syntax(), &ast::make::tokens::single_newline()); | 57 | ted::insert(Position::after(use_.syntax()), new_use.syntax()); |
55 | if let ident_level @ 1..=usize::MAX = use_.indent_level().0 as usize { | 58 | |
56 | rewriter.insert_after( | 59 | builder.replace(old_parent_range, new_parent.to_string()); |
57 | use_.syntax(), | ||
58 | &ast::make::tokens::whitespace(&" ".repeat(4 * ident_level)), | ||
59 | ); | ||
60 | } | ||
61 | rewriter.insert_after(use_.syntax(), new_use.syntax()); | ||
62 | |||
63 | builder.rewrite(rewriter); | ||
64 | }, | 60 | }, |
65 | ) | 61 | ) |
66 | } | 62 | } |
diff --git a/crates/ide_assists/src/handlers/unwrap_block.rs b/crates/ide_assists/src/handlers/unwrap_block.rs index 440639322..d3c3da018 100644 --- a/crates/ide_assists/src/handlers/unwrap_block.rs +++ b/crates/ide_assists/src/handlers/unwrap_block.rs | |||
@@ -186,7 +186,7 @@ fn main() { | |||
186 | if true {$0 | 186 | if true {$0 |
187 | foo(); | 187 | foo(); |
188 | 188 | ||
189 | //comment | 189 | // comment |
190 | bar(); | 190 | bar(); |
191 | } else { | 191 | } else { |
192 | println!("bar"); | 192 | println!("bar"); |
@@ -198,7 +198,7 @@ fn main() { | |||
198 | bar(); | 198 | bar(); |
199 | foo(); | 199 | foo(); |
200 | 200 | ||
201 | //comment | 201 | // comment |
202 | bar(); | 202 | bar(); |
203 | } | 203 | } |
204 | "#, | 204 | "#, |
@@ -215,7 +215,7 @@ fn main() { | |||
215 | if true { | 215 | if true { |
216 | foo(); | 216 | foo(); |
217 | 217 | ||
218 | //comment | 218 | // comment |
219 | bar(); | 219 | bar(); |
220 | } else {$0 | 220 | } else {$0 |
221 | println!("bar"); | 221 | println!("bar"); |
@@ -228,7 +228,7 @@ fn main() { | |||
228 | if true { | 228 | if true { |
229 | foo(); | 229 | foo(); |
230 | 230 | ||
231 | //comment | 231 | // comment |
232 | bar(); | 232 | bar(); |
233 | } | 233 | } |
234 | println!("bar"); | 234 | println!("bar"); |
@@ -243,12 +243,12 @@ fn main() { | |||
243 | unwrap_block, | 243 | unwrap_block, |
244 | r#" | 244 | r#" |
245 | fn main() { | 245 | fn main() { |
246 | //bar(); | 246 | // bar(); |
247 | if true { | 247 | if true { |
248 | println!("true"); | 248 | println!("true"); |
249 | 249 | ||
250 | //comment | 250 | // comment |
251 | //bar(); | 251 | // bar(); |
252 | } else if false {$0 | 252 | } else if false {$0 |
253 | println!("bar"); | 253 | println!("bar"); |
254 | } else { | 254 | } else { |
@@ -258,12 +258,12 @@ fn main() { | |||
258 | "#, | 258 | "#, |
259 | r#" | 259 | r#" |
260 | fn main() { | 260 | fn main() { |
261 | //bar(); | 261 | // bar(); |
262 | if true { | 262 | if true { |
263 | println!("true"); | 263 | println!("true"); |
264 | 264 | ||
265 | //comment | 265 | // comment |
266 | //bar(); | 266 | // bar(); |
267 | } | 267 | } |
268 | println!("bar"); | 268 | println!("bar"); |
269 | } | 269 | } |
@@ -277,12 +277,12 @@ fn main() { | |||
277 | unwrap_block, | 277 | unwrap_block, |
278 | r#" | 278 | r#" |
279 | fn main() { | 279 | fn main() { |
280 | //bar(); | 280 | // bar(); |
281 | if true { | 281 | if true { |
282 | println!("true"); | 282 | println!("true"); |
283 | 283 | ||
284 | //comment | 284 | // comment |
285 | //bar(); | 285 | // bar(); |
286 | } else if false { | 286 | } else if false { |
287 | println!("bar"); | 287 | println!("bar"); |
288 | } else if true {$0 | 288 | } else if true {$0 |
@@ -292,12 +292,12 @@ fn main() { | |||
292 | "#, | 292 | "#, |
293 | r#" | 293 | r#" |
294 | fn main() { | 294 | fn main() { |
295 | //bar(); | 295 | // bar(); |
296 | if true { | 296 | if true { |
297 | println!("true"); | 297 | println!("true"); |
298 | 298 | ||
299 | //comment | 299 | // comment |
300 | //bar(); | 300 | // bar(); |
301 | } else if false { | 301 | } else if false { |
302 | println!("bar"); | 302 | println!("bar"); |
303 | } | 303 | } |
@@ -313,12 +313,12 @@ fn main() { | |||
313 | unwrap_block, | 313 | unwrap_block, |
314 | r#" | 314 | r#" |
315 | fn main() { | 315 | fn main() { |
316 | //bar(); | 316 | // bar(); |
317 | if true { | 317 | if true { |
318 | println!("true"); | 318 | println!("true"); |
319 | 319 | ||
320 | //comment | 320 | // comment |
321 | //bar(); | 321 | // bar(); |
322 | } else if false { | 322 | } else if false { |
323 | println!("bar"); | 323 | println!("bar"); |
324 | } else if true { | 324 | } else if true { |
@@ -330,12 +330,12 @@ fn main() { | |||
330 | "#, | 330 | "#, |
331 | r#" | 331 | r#" |
332 | fn main() { | 332 | fn main() { |
333 | //bar(); | 333 | // bar(); |
334 | if true { | 334 | if true { |
335 | println!("true"); | 335 | println!("true"); |
336 | 336 | ||
337 | //comment | 337 | // comment |
338 | //bar(); | 338 | // bar(); |
339 | } else if false { | 339 | } else if false { |
340 | println!("bar"); | 340 | println!("bar"); |
341 | } else if true { | 341 | } else if true { |
@@ -353,12 +353,12 @@ fn main() { | |||
353 | unwrap_block, | 353 | unwrap_block, |
354 | r#" | 354 | r#" |
355 | fn main() { | 355 | fn main() { |
356 | //bar(); | 356 | // bar(); |
357 | if true { | 357 | if true { |
358 | println!("true"); | 358 | println!("true"); |
359 | 359 | ||
360 | //comment | 360 | // comment |
361 | //bar(); | 361 | // bar(); |
362 | } else if false { | 362 | } else if false { |
363 | println!("bar"); | 363 | println!("bar"); |
364 | } else if true {$0 | 364 | } else if true {$0 |
@@ -370,12 +370,12 @@ fn main() { | |||
370 | "#, | 370 | "#, |
371 | r#" | 371 | r#" |
372 | fn main() { | 372 | fn main() { |
373 | //bar(); | 373 | // bar(); |
374 | if true { | 374 | if true { |
375 | println!("true"); | 375 | println!("true"); |
376 | 376 | ||
377 | //comment | 377 | // comment |
378 | //bar(); | 378 | // bar(); |
379 | } else if false { | 379 | } else if false { |
380 | println!("bar"); | 380 | println!("bar"); |
381 | } | 381 | } |
@@ -395,7 +395,7 @@ fn main() { | |||
395 | if true { | 395 | if true { |
396 | foo(); | 396 | foo(); |
397 | 397 | ||
398 | //comment | 398 | // comment |
399 | bar(); | 399 | bar(); |
400 | } else { | 400 | } else { |
401 | println!("bar"); | 401 | println!("bar"); |
@@ -415,7 +415,7 @@ fn main() { | |||
415 | if true { | 415 | if true { |
416 | foo(); | 416 | foo(); |
417 | 417 | ||
418 | //comment | 418 | // comment |
419 | bar(); | 419 | bar(); |
420 | } else { | 420 | } else { |
421 | println!("bar"); | 421 | println!("bar"); |
@@ -428,7 +428,7 @@ fn main() { | |||
428 | if true { | 428 | if true { |
429 | foo(); | 429 | foo(); |
430 | 430 | ||
431 | //comment | 431 | // comment |
432 | bar(); | 432 | bar(); |
433 | } else { | 433 | } else { |
434 | println!("bar"); | 434 | println!("bar"); |
@@ -448,7 +448,7 @@ fn main() { | |||
448 | if true {$0 | 448 | if true {$0 |
449 | foo(); | 449 | foo(); |
450 | 450 | ||
451 | //comment | 451 | // comment |
452 | bar(); | 452 | bar(); |
453 | } else { | 453 | } else { |
454 | println!("bar"); | 454 | println!("bar"); |
@@ -461,7 +461,7 @@ fn main() { | |||
461 | for i in 0..5 { | 461 | for i in 0..5 { |
462 | foo(); | 462 | foo(); |
463 | 463 | ||
464 | //comment | 464 | // comment |
465 | bar(); | 465 | bar(); |
466 | } | 466 | } |
467 | } | 467 | } |
@@ -479,7 +479,7 @@ fn main() { | |||
479 | if true { | 479 | if true { |
480 | foo(); | 480 | foo(); |
481 | 481 | ||
482 | //comment | 482 | // comment |
483 | bar(); | 483 | bar(); |
484 | } else { | 484 | } else { |
485 | println!("bar"); | 485 | println!("bar"); |
@@ -492,7 +492,7 @@ fn main() { | |||
492 | if true { | 492 | if true { |
493 | foo(); | 493 | foo(); |
494 | 494 | ||
495 | //comment | 495 | // comment |
496 | bar(); | 496 | bar(); |
497 | } else { | 497 | } else { |
498 | println!("bar"); | 498 | println!("bar"); |
@@ -512,7 +512,7 @@ fn main() { | |||
512 | if true { | 512 | if true { |
513 | foo(); | 513 | foo(); |
514 | 514 | ||
515 | //comment | 515 | // comment |
516 | bar(); | 516 | bar(); |
517 | } else { | 517 | } else { |
518 | println!("bar"); | 518 | println!("bar"); |
@@ -525,7 +525,7 @@ fn main() { | |||
525 | if true { | 525 | if true { |
526 | foo(); | 526 | foo(); |
527 | 527 | ||
528 | //comment | 528 | // comment |
529 | bar(); | 529 | bar(); |
530 | } else { | 530 | } else { |
531 | println!("bar"); | 531 | println!("bar"); |
@@ -569,7 +569,7 @@ fn main() { | |||
569 | if true { | 569 | if true { |
570 | foo();$0 | 570 | foo();$0 |
571 | 571 | ||
572 | //comment | 572 | // comment |
573 | bar(); | 573 | bar(); |
574 | } else { | 574 | } else { |
575 | println!("bar"); | 575 | println!("bar"); |