diff options
Diffstat (limited to 'crates/ide_assists')
-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 | 46 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/merge_imports.rs | 24 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/move_bounds.rs | 8 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/reorder_fields.rs | 112 |
8 files changed, 201 insertions, 199 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 9dc3ee28f..d202a85f9 100644 --- a/crates/ide_assists/src/handlers/convert_comment_block.rs +++ b/crates/ide_assists/src/handlers/convert_comment_block.rs | |||
@@ -1,13 +1,6 @@ | |||
1 | use itertools::Itertools; | 1 | use itertools::Itertools; |
2 | use syntax::{ | 2 | use syntax::{ |
3 | ast::{ | 3 | ast::{self, edit::IndentLevel, Comment, CommentKind, CommentShape, Whitespace}, |
4 | self, | ||
5 | edit::IndentLevel, | ||
6 | Comment, CommentKind, | ||
7 | CommentPlacement::{Inner, Outer}, | ||
8 | CommentShape::{self, Block, Line}, | ||
9 | Whitespace, | ||
10 | }, | ||
11 | AstToken, Direction, SyntaxElement, TextRange, | 4 | AstToken, Direction, SyntaxElement, TextRange, |
12 | }; | 5 | }; |
13 | 6 | ||
@@ -29,21 +22,18 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
29 | /// */ | 22 | /// */ |
30 | /// ``` | 23 | /// ``` |
31 | 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<()> { |
32 | if let Some(comment) = ctx.find_token_at_offset::<ast::Comment>() { | 25 | let comment = ctx.find_token_at_offset::<ast::Comment>()?; |
33 | // Only allow comments which are alone on their line | 26 | // Only allow comments which are alone on their line |
34 | if let Some(prev) = comment.syntax().prev_token() { | 27 | if let Some(prev) = comment.syntax().prev_token() { |
35 | 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() { |
36 | return None; | 29 | return None; |
37 | } | ||
38 | } | 30 | } |
39 | |||
40 | return match comment.kind().shape { | ||
41 | ast::CommentShape::Block => block_to_line(acc, comment), | ||
42 | ast::CommentShape::Line => line_to_block(acc, comment), | ||
43 | }; | ||
44 | } | 31 | } |
45 | 32 | ||
46 | 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 | } | ||
47 | } | 37 | } |
48 | 38 | ||
49 | fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> { | 39 | fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> { |
@@ -55,8 +45,7 @@ fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> { | |||
55 | target, | 45 | target, |
56 | |edit| { | 46 | |edit| { |
57 | let indentation = IndentLevel::from_token(comment.syntax()); | 47 | let indentation = IndentLevel::from_token(comment.syntax()); |
58 | let line_prefix = | 48 | let line_prefix = CommentKind { shape: CommentShape::Line, ..comment.kind() }.prefix(); |
59 | comment_kind_prefix(CommentKind { shape: CommentShape::Line, ..comment.kind() }); | ||
60 | 49 | ||
61 | let text = comment.text(); | 50 | let text = comment.text(); |
62 | let text = &text[comment.prefix().len()..(text.len() - "*/".len())].trim(); | 51 | let text = &text[comment.prefix().len()..(text.len() - "*/".len())].trim(); |
@@ -105,7 +94,7 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { | |||
105 | 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"); |
106 | 95 | ||
107 | let block_prefix = | 96 | let block_prefix = |
108 | comment_kind_prefix(CommentKind { shape: CommentShape::Block, ..comment.kind() }); | 97 | CommentKind { shape: CommentShape::Block, ..comment.kind() }.prefix(); |
109 | 98 | ||
110 | let output = | 99 | let output = |
111 | format!("{}\n{}\n{}*/", block_prefix, block_comment_body, indentation.to_string()); | 100 | format!("{}\n{}\n{}*/", block_prefix, block_comment_body, indentation.to_string()); |
@@ -182,17 +171,6 @@ fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> String { | |||
182 | } | 171 | } |
183 | } | 172 | } |
184 | 173 | ||
185 | fn comment_kind_prefix(ck: ast::CommentKind) -> &'static str { | ||
186 | match (ck.shape, ck.doc) { | ||
187 | (Line, Some(Inner)) => "//!", | ||
188 | (Line, Some(Outer)) => "///", | ||
189 | (Line, None) => "//", | ||
190 | (Block, Some(Inner)) => "/*!", | ||
191 | (Block, Some(Outer)) => "/**", | ||
192 | (Block, None) => "/*", | ||
193 | } | ||
194 | } | ||
195 | |||
196 | #[cfg(test)] | 174 | #[cfg(test)] |
197 | mod tests { | 175 | mod tests { |
198 | 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/merge_imports.rs b/crates/ide_assists/src/handlers/merge_imports.rs index cfc472a32..8e0794218 100644 --- a/crates/ide_assists/src/handlers/merge_imports.rs +++ b/crates/ide_assists/src/handlers/merge_imports.rs | |||
@@ -21,12 +21,6 @@ use crate::{ | |||
21 | // ``` | 21 | // ``` |
22 | pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 22 | pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
23 | let tree: ast::UseTree = ctx.find_node_at_offset()?; | 23 | let tree: ast::UseTree = ctx.find_node_at_offset()?; |
24 | let original_parent = tree.syntax().ancestors().last()?; | ||
25 | |||
26 | let tree = tree.clone_for_update(); | ||
27 | let new_parent = tree.syntax().ancestors().last()?; | ||
28 | |||
29 | let mut offset = ctx.offset(); | ||
30 | 24 | ||
31 | let mut imports = None; | 25 | let mut imports = None; |
32 | let mut uses = None; | 26 | let mut uses = None; |
@@ -53,22 +47,20 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<() | |||
53 | target, | 47 | target, |
54 | |builder| { | 48 | |builder| { |
55 | if let Some((to_replace, replacement, to_remove)) = imports { | 49 | if let Some((to_replace, replacement, to_remove)) = imports { |
56 | if to_remove.syntax().text_range().end() < offset { | 50 | let to_replace = builder.make_ast_mut(to_replace); |
57 | offset -= to_remove.syntax().text_range().len(); | 51 | let to_remove = builder.make_ast_mut(to_remove); |
58 | } | 52 | |
59 | ted::replace(to_replace.syntax().clone(), replacement.syntax().clone()); | 53 | ted::replace(to_replace.syntax(), replacement.syntax()); |
60 | to_remove.remove(); | 54 | to_remove.remove(); |
61 | } | 55 | } |
62 | 56 | ||
63 | if let Some((to_replace, replacement, to_remove)) = uses { | 57 | if let Some((to_replace, replacement, to_remove)) = uses { |
64 | if to_remove.syntax().text_range().end() < offset { | 58 | let to_replace = builder.make_ast_mut(to_replace); |
65 | offset -= to_remove.syntax().text_range().len(); | 59 | let to_remove = builder.make_ast_mut(to_remove); |
66 | } | 60 | |
67 | ted::replace(to_replace.syntax().clone(), replacement.syntax().clone()); | 61 | ted::replace(to_replace.syntax(), replacement.syntax()); |
68 | to_remove.remove() | 62 | to_remove.remove() |
69 | } | 63 | } |
70 | |||
71 | builder.replace(original_parent.text_range(), new_parent.to_string()) | ||
72 | }, | 64 | }, |
73 | ) | 65 | ) |
74 | } | 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/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 { |