diff options
Diffstat (limited to 'crates/ide_assists')
4 files changed, 186 insertions, 15 deletions
diff --git a/crates/ide_assists/src/handlers/auto_import.rs b/crates/ide_assists/src/handlers/auto_import.rs index a454a2af3..506cc292c 100644 --- a/crates/ide_assists/src/handlers/auto_import.rs +++ b/crates/ide_assists/src/handlers/auto_import.rs | |||
@@ -969,4 +969,30 @@ mod bar { | |||
969 | "#, | 969 | "#, |
970 | ); | 970 | ); |
971 | } | 971 | } |
972 | |||
973 | #[test] | ||
974 | fn uses_abs_path_with_extern_crate_clash() { | ||
975 | check_assist( | ||
976 | auto_import, | ||
977 | r#" | ||
978 | //- /main.rs crate:main deps:foo | ||
979 | mod foo {} | ||
980 | |||
981 | const _: () = { | ||
982 | Foo$0 | ||
983 | }; | ||
984 | //- /foo.rs crate:foo | ||
985 | pub struct Foo | ||
986 | "#, | ||
987 | r#" | ||
988 | use ::foo::Foo; | ||
989 | |||
990 | mod foo {} | ||
991 | |||
992 | const _: () = { | ||
993 | Foo | ||
994 | }; | ||
995 | "#, | ||
996 | ); | ||
997 | } | ||
972 | } | 998 | } |
diff --git a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs index 66f274fa7..8e2178391 100644 --- a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs | |||
@@ -151,20 +151,37 @@ fn create_struct_def( | |||
151 | field_list: &Either<ast::RecordFieldList, ast::TupleFieldList>, | 151 | field_list: &Either<ast::RecordFieldList, ast::TupleFieldList>, |
152 | visibility: Option<ast::Visibility>, | 152 | visibility: Option<ast::Visibility>, |
153 | ) -> ast::Struct { | 153 | ) -> ast::Struct { |
154 | let pub_vis = Some(make::visibility_pub()); | 154 | let pub_vis = make::visibility_pub(); |
155 | |||
156 | let insert_pub = |node: &'_ SyntaxNode| { | ||
157 | let pub_vis = pub_vis.clone_for_update(); | ||
158 | ted::insert(ted::Position::before(node), pub_vis.syntax()); | ||
159 | }; | ||
160 | |||
161 | // for fields without any existing visibility, use pub visibility | ||
155 | let field_list = match field_list { | 162 | let field_list = match field_list { |
156 | Either::Left(field_list) => { | 163 | Either::Left(field_list) => { |
157 | make::record_field_list(field_list.fields().flat_map(|field| { | 164 | let field_list = field_list.clone_for_update(); |
158 | Some(make::record_field(pub_vis.clone(), field.name()?, field.ty()?)) | 165 | |
159 | })) | 166 | field_list |
160 | .into() | 167 | .fields() |
168 | .filter(|field| field.visibility().is_none()) | ||
169 | .filter_map(|field| field.name()) | ||
170 | .for_each(|it| insert_pub(it.syntax())); | ||
171 | |||
172 | field_list.into() | ||
161 | } | 173 | } |
162 | Either::Right(field_list) => make::tuple_field_list( | 174 | Either::Right(field_list) => { |
175 | let field_list = field_list.clone_for_update(); | ||
176 | |||
163 | field_list | 177 | field_list |
164 | .fields() | 178 | .fields() |
165 | .flat_map(|field| Some(make::tuple_field(pub_vis.clone(), field.ty()?))), | 179 | .filter(|field| field.visibility().is_none()) |
166 | ) | 180 | .filter_map(|field| field.ty()) |
167 | .into(), | 181 | .for_each(|it| insert_pub(it.syntax())); |
182 | |||
183 | field_list.into() | ||
184 | } | ||
168 | }; | 185 | }; |
169 | 186 | ||
170 | make::struct_(visibility, variant_name, None, field_list).clone_for_update() | 187 | make::struct_(visibility, variant_name, None, field_list).clone_for_update() |
@@ -295,6 +312,106 @@ enum A { One(One) }"#, | |||
295 | } | 312 | } |
296 | 313 | ||
297 | #[test] | 314 | #[test] |
315 | fn test_extract_struct_keep_comments_and_attrs_one_field_named() { | ||
316 | check_assist( | ||
317 | extract_struct_from_enum_variant, | ||
318 | r#" | ||
319 | enum A { | ||
320 | $0One { | ||
321 | // leading comment | ||
322 | /// doc comment | ||
323 | #[an_attr] | ||
324 | foo: u32 | ||
325 | // trailing comment | ||
326 | } | ||
327 | }"#, | ||
328 | r#" | ||
329 | struct One{ | ||
330 | // leading comment | ||
331 | /// doc comment | ||
332 | #[an_attr] | ||
333 | pub foo: u32 | ||
334 | // trailing comment | ||
335 | } | ||
336 | |||
337 | enum A { | ||
338 | One(One) | ||
339 | }"#, | ||
340 | ); | ||
341 | } | ||
342 | |||
343 | #[test] | ||
344 | fn test_extract_struct_keep_comments_and_attrs_several_fields_named() { | ||
345 | check_assist( | ||
346 | extract_struct_from_enum_variant, | ||
347 | r#" | ||
348 | enum A { | ||
349 | $0One { | ||
350 | // comment | ||
351 | /// doc | ||
352 | #[attr] | ||
353 | foo: u32, | ||
354 | // comment | ||
355 | #[attr] | ||
356 | /// doc | ||
357 | bar: u32 | ||
358 | } | ||
359 | }"#, | ||
360 | r#" | ||
361 | struct One{ | ||
362 | // comment | ||
363 | /// doc | ||
364 | #[attr] | ||
365 | pub foo: u32, | ||
366 | // comment | ||
367 | #[attr] | ||
368 | /// doc | ||
369 | pub bar: u32 | ||
370 | } | ||
371 | |||
372 | enum A { | ||
373 | One(One) | ||
374 | }"#, | ||
375 | ); | ||
376 | } | ||
377 | |||
378 | #[test] | ||
379 | fn test_extract_struct_keep_comments_and_attrs_several_fields_tuple() { | ||
380 | check_assist( | ||
381 | extract_struct_from_enum_variant, | ||
382 | "enum A { $0One(/* comment */ #[attr] u32, /* another */ u32 /* tail */) }", | ||
383 | r#" | ||
384 | struct One(/* comment */ #[attr] pub u32, /* another */ pub u32 /* tail */); | ||
385 | |||
386 | enum A { One(One) }"#, | ||
387 | ); | ||
388 | } | ||
389 | |||
390 | #[test] | ||
391 | fn test_extract_struct_keep_existing_visibility_named() { | ||
392 | check_assist( | ||
393 | extract_struct_from_enum_variant, | ||
394 | "enum A { $0One{ pub a: u32, pub(crate) b: u32, pub(super) c: u32, d: u32 } }", | ||
395 | r#" | ||
396 | struct One{ pub a: u32, pub(crate) b: u32, pub(super) c: u32, pub d: u32 } | ||
397 | |||
398 | enum A { One(One) }"#, | ||
399 | ); | ||
400 | } | ||
401 | |||
402 | #[test] | ||
403 | fn test_extract_struct_keep_existing_visibility_tuple() { | ||
404 | check_assist( | ||
405 | extract_struct_from_enum_variant, | ||
406 | "enum A { $0One(pub u32, pub(crate) u32, pub(super) u32, u32) }", | ||
407 | r#" | ||
408 | struct One(pub u32, pub(crate) u32, pub(super) u32, pub u32); | ||
409 | |||
410 | enum A { One(One) }"#, | ||
411 | ); | ||
412 | } | ||
413 | |||
414 | #[test] | ||
298 | fn test_extract_enum_variant_name_value_namespace() { | 415 | fn test_extract_enum_variant_name_value_namespace() { |
299 | check_assist( | 416 | check_assist( |
300 | extract_struct_from_enum_variant, | 417 | extract_struct_from_enum_variant, |
diff --git a/crates/ide_assists/src/handlers/move_module_to_file.rs b/crates/ide_assists/src/handlers/move_module_to_file.rs index 6e685b4b2..93f702c55 100644 --- a/crates/ide_assists/src/handlers/move_module_to_file.rs +++ b/crates/ide_assists/src/handlers/move_module_to_file.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use ast::{edit::IndentLevel, VisibilityOwner}; | 1 | use ast::edit::IndentLevel; |
2 | use ide_db::base_db::AnchoredPathBuf; | 2 | use ide_db::base_db::AnchoredPathBuf; |
3 | use stdx::format_to; | 3 | use stdx::format_to; |
4 | use syntax::{ | 4 | use syntax::{ |
@@ -60,12 +60,18 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Opt | |||
60 | }; | 60 | }; |
61 | 61 | ||
62 | let mut buf = String::new(); | 62 | let mut buf = String::new(); |
63 | if let Some(v) = module_ast.visibility() { | ||
64 | format_to!(buf, "{} ", v); | ||
65 | } | ||
66 | format_to!(buf, "mod {};", module_name); | 63 | format_to!(buf, "mod {};", module_name); |
67 | 64 | ||
68 | builder.replace(module_ast.syntax().text_range(), buf); | 65 | let replacement_start = if let Some(mod_token) = module_ast.mod_token() { |
66 | mod_token.text_range().start() | ||
67 | } else { | ||
68 | module_ast.syntax().text_range().start() | ||
69 | }; | ||
70 | |||
71 | builder.replace( | ||
72 | TextRange::new(replacement_start, module_ast.syntax().text_range().end()), | ||
73 | buf, | ||
74 | ); | ||
69 | 75 | ||
70 | let dst = AnchoredPathBuf { anchor: ctx.frange.file_id, path }; | 76 | let dst = AnchoredPathBuf { anchor: ctx.frange.file_id, path }; |
71 | builder.create_file(dst, contents); | 77 | builder.create_file(dst, contents); |
@@ -184,4 +190,26 @@ pub(crate) mod tests; | |||
184 | cov_mark::check!(available_before_curly); | 190 | cov_mark::check!(available_before_curly); |
185 | check_assist_not_applicable(move_module_to_file, r#"mod m { $0 }"#); | 191 | check_assist_not_applicable(move_module_to_file, r#"mod m { $0 }"#); |
186 | } | 192 | } |
193 | |||
194 | #[test] | ||
195 | fn keep_outer_comments_and_attributes() { | ||
196 | check_assist( | ||
197 | move_module_to_file, | ||
198 | r#" | ||
199 | /// doc comment | ||
200 | #[attribute] | ||
201 | mod $0tests { | ||
202 | #[test] fn t() {} | ||
203 | } | ||
204 | "#, | ||
205 | r#" | ||
206 | //- /main.rs | ||
207 | /// doc comment | ||
208 | #[attribute] | ||
209 | mod tests; | ||
210 | //- /tests.rs | ||
211 | #[test] fn t() {} | ||
212 | "#, | ||
213 | ); | ||
214 | } | ||
187 | } | 215 | } |
diff --git a/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs index 0fec961b4..a3bfa221c 100644 --- a/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs +++ b/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs | |||
@@ -17,7 +17,7 @@ use ide_db::ty_filter::TryEnum; | |||
17 | 17 | ||
18 | // Assist: replace_unwrap_with_match | 18 | // Assist: replace_unwrap_with_match |
19 | // | 19 | // |
20 | // Replaces `unwrap` a `match` expression. Works for Result and Option. | 20 | // Replaces `unwrap` with a `match` expression. Works for Result and Option. |
21 | // | 21 | // |
22 | // ``` | 22 | // ``` |
23 | // enum Result<T, E> { Ok(T), Err(E) } | 23 | // enum Result<T, E> { Ok(T), Err(E) } |