aboutsummaryrefslogtreecommitdiff
path: root/crates/assists/src/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'crates/assists/src/handlers')
-rw-r--r--crates/assists/src/handlers/expand_glob_import.rs267
1 files changed, 229 insertions, 38 deletions
diff --git a/crates/assists/src/handlers/expand_glob_import.rs b/crates/assists/src/handlers/expand_glob_import.rs
index 81d0af2f3..0288d1c77 100644
--- a/crates/assists/src/handlers/expand_glob_import.rs
+++ b/crates/assists/src/handlers/expand_glob_import.rs
@@ -4,7 +4,7 @@ use ide_db::{
4 defs::{classify_name_ref, Definition, NameRefClass}, 4 defs::{classify_name_ref, Definition, NameRefClass},
5 RootDatabase, 5 RootDatabase,
6}; 6};
7use syntax::{algo, ast, match_ast, AstNode, SyntaxNode, SyntaxToken, T}; 7use syntax::{ast, AstNode, SyntaxToken, T};
8 8
9use crate::{ 9use crate::{
10 assist_context::{AssistBuilder, AssistContext, Assists}, 10 assist_context::{AssistBuilder, AssistContext, Assists},
@@ -38,7 +38,7 @@ use crate::{
38// ``` 38// ```
39pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 39pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
40 let star = ctx.find_token_at_offset(T![*])?; 40 let star = ctx.find_token_at_offset(T![*])?;
41 let mod_path = find_mod_path(&star)?; 41 let (parent, mod_path) = find_parent_and_path(&star)?;
42 let module = match ctx.sema.resolve_path(&mod_path)? { 42 let module = match ctx.sema.resolve_path(&mod_path)? {
43 PathResolution::Def(ModuleDef::Module(it)) => it, 43 PathResolution::Def(ModuleDef::Module(it)) => it,
44 _ => return None, 44 _ => return None,
@@ -52,19 +52,23 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti
52 source_file.syntax().descendants().filter_map(ast::NameRef::cast).collect(); 52 source_file.syntax().descendants().filter_map(ast::NameRef::cast).collect();
53 let used_names = find_used_names(ctx, defs_in_mod, name_refs_in_source_file); 53 let used_names = find_used_names(ctx, defs_in_mod, name_refs_in_source_file);
54 54
55 let parent = star.parent().parent()?; 55 let target = parent.syntax();
56 acc.add( 56 acc.add(
57 AssistId("expand_glob_import", AssistKind::RefactorRewrite), 57 AssistId("expand_glob_import", AssistKind::RefactorRewrite),
58 "Expand glob import", 58 "Expand glob import",
59 parent.text_range(), 59 target.text_range(),
60 |builder| { 60 |builder| {
61 replace_ast(builder, &parent, mod_path, used_names); 61 replace_ast(builder, parent, mod_path, used_names);
62 }, 62 },
63 ) 63 )
64} 64}
65 65
66fn find_mod_path(star: &SyntaxToken) -> Option<ast::Path> { 66fn find_parent_and_path(star: &SyntaxToken) -> Option<(ast::UseTree, ast::Path)> {
67 star.ancestors().find_map(|n| ast::UseTree::cast(n).and_then(|u| u.path())) 67 star.ancestors().find_map(|n| {
68 let use_tree = ast::UseTree::cast(n)?;
69 let path = use_tree.path()?;
70 Some((use_tree, path))
71 })
68} 72}
69 73
70#[derive(PartialEq)] 74#[derive(PartialEq)]
@@ -137,41 +141,28 @@ fn find_used_names(
137 141
138fn replace_ast( 142fn replace_ast(
139 builder: &mut AssistBuilder, 143 builder: &mut AssistBuilder,
140 node: &SyntaxNode, 144 parent: ast::UseTree,
141 path: ast::Path, 145 path: ast::Path,
142 used_names: Vec<Name>, 146 used_names: Vec<Name>,
143) { 147) {
144 let replacement: Either<ast::UseTree, ast::UseTreeList> = match used_names.as_slice() { 148 let replacement = match used_names.as_slice() {
145 [name] => Either::Left(ast::make::use_tree( 149 [name] => ast::make::use_tree(
146 ast::make::path_from_text(&format!("{}::{}", path, name)), 150 ast::make::path_from_text(&format!("{}::{}", path, name)),
147 None, 151 None,
148 None, 152 None,
149 false, 153 false,
150 )), 154 ),
151 names => Either::Right(ast::make::use_tree_list(names.iter().map(|n| { 155 names => ast::make::use_tree(
152 ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false) 156 path,
153 }))), 157 Some(ast::make::use_tree_list(names.iter().map(|n| {
154 }; 158 ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false)
155 159 }))),
156 let mut replace_node = |replacement: Either<ast::UseTree, ast::UseTreeList>| { 160 None,
157 algo::diff(node, &replacement.either(|u| u.syntax().clone(), |ut| ut.syntax().clone())) 161 false,
158 .into_text_edit(builder.text_edit_builder()); 162 ),
159 }; 163 };
160 164
161 match_ast! { 165 builder.replace_ast(parent, replacement);
162 match node {
163 ast::UseTree(use_tree) => {
164 replace_node(replacement);
165 },
166 ast::UseTreeList(use_tree_list) => {
167 replace_node(replacement);
168 },
169 ast::Use(use_item) => {
170 builder.replace_ast(use_item, ast::make::use_(replacement.left_or_else(|ut| ast::make::use_tree(path, Some(ut), None, false))));
171 },
172 _ => {},
173 }
174 }
175} 166}
176 167
177#[cfg(test)] 168#[cfg(test)]
@@ -260,7 +251,7 @@ fn qux(bar: Bar, baz: Baz) {
260 expand_glob_import, 251 expand_glob_import,
261 r" 252 r"
262mod foo { 253mod foo {
263 mod bar { 254 pub mod bar {
264 pub struct Bar; 255 pub struct Bar;
265 pub struct Baz; 256 pub struct Baz;
266 pub struct Qux; 257 pub struct Qux;
@@ -268,7 +259,7 @@ mod foo {
268 pub fn f() {} 259 pub fn f() {}
269 } 260 }
270 261
271 mod baz { 262 pub mod baz {
272 pub fn g() {} 263 pub fn g() {}
273 } 264 }
274} 265}
@@ -282,7 +273,7 @@ fn qux(bar: Bar, baz: Baz) {
282", 273",
283 r" 274 r"
284mod foo { 275mod foo {
285 mod bar { 276 pub mod bar {
286 pub struct Bar; 277 pub struct Bar;
287 pub struct Baz; 278 pub struct Baz;
288 pub struct Qux; 279 pub struct Qux;
@@ -290,7 +281,7 @@ mod foo {
290 pub fn f() {} 281 pub fn f() {}
291 } 282 }
292 283
293 mod baz { 284 pub mod baz {
294 pub fn g() {} 285 pub fn g() {}
295 } 286 }
296} 287}
@@ -302,7 +293,207 @@ fn qux(bar: Bar, baz: Baz) {
302 g(); 293 g();
303} 294}
304", 295",
305 ) 296 );
297
298 check_assist(
299 expand_glob_import,
300 r"
301mod foo {
302 pub mod bar {
303 pub struct Bar;
304 pub struct Baz;
305 pub struct Qux;
306
307 pub fn f() {}
308 }
309
310 pub mod baz {
311 pub fn g() {}
312 }
313}
314
315use foo::{bar::{Bar, Baz, f}, baz::*<|>};
316
317fn qux(bar: Bar, baz: Baz) {
318 f();
319 g();
320}
321",
322 r"
323mod foo {
324 pub mod bar {
325 pub struct Bar;
326 pub struct Baz;
327 pub struct Qux;
328
329 pub fn f() {}
330 }
331
332 pub mod baz {
333 pub fn g() {}
334 }
335}
336
337use foo::{bar::{Bar, Baz, f}, baz::g};
338
339fn qux(bar: Bar, baz: Baz) {
340 f();
341 g();
342}
343",
344 );
345
346 check_assist(
347 expand_glob_import,
348 r"
349mod foo {
350 pub mod bar {
351 pub struct Bar;
352 pub struct Baz;
353 pub struct Qux;
354
355 pub fn f() {}
356 }
357
358 pub mod baz {
359 pub fn g() {}
360
361 pub mod qux {
362 pub fn h() {}
363 pub fn m() {}
364
365 pub mod q {
366 pub fn j() {}
367 }
368 }
369 }
370}
371
372use foo::{
373 bar::{*, f},
374 baz::{g, qux::*<|>}
375};
376
377fn qux(bar: Bar, baz: Baz) {
378 f();
379 g();
380 h();
381 q::j();
382}
383",
384 r"
385mod foo {
386 pub mod bar {
387 pub struct Bar;
388 pub struct Baz;
389 pub struct Qux;
390
391 pub fn f() {}
392 }
393
394 pub mod baz {
395 pub fn g() {}
396
397 pub mod qux {
398 pub fn h() {}
399 pub fn m() {}
400
401 pub mod q {
402 pub fn j() {}
403 }
404 }
405 }
406}
407
408use foo::{
409 bar::{*, f},
410 baz::{g, qux::{q, h}}
411};
412
413fn qux(bar: Bar, baz: Baz) {
414 f();
415 g();
416 h();
417 q::j();
418}
419",
420 );
421
422 check_assist(
423 expand_glob_import,
424 r"
425mod foo {
426 pub mod bar {
427 pub struct Bar;
428 pub struct Baz;
429 pub struct Qux;
430
431 pub fn f() {}
432 }
433
434 pub mod baz {
435 pub fn g() {}
436
437 pub mod qux {
438 pub fn h() {}
439 pub fn m() {}
440
441 pub mod q {
442 pub fn j() {}
443 }
444 }
445 }
446}
447
448use foo::{
449 bar::{*, f},
450 baz::{g, qux::{h, q::*<|>}}
451};
452
453fn qux(bar: Bar, baz: Baz) {
454 f();
455 g();
456 h();
457 j();
458}
459",
460 r"
461mod foo {
462 pub mod bar {
463 pub struct Bar;
464 pub struct Baz;
465 pub struct Qux;
466
467 pub fn f() {}
468 }
469
470 pub mod baz {
471 pub fn g() {}
472
473 pub mod qux {
474 pub fn h() {}
475 pub fn m() {}
476
477 pub mod q {
478 pub fn j() {}
479 }
480 }
481 }
482}
483
484use foo::{
485 bar::{*, f},
486 baz::{g, qux::{h, q::j}}
487};
488
489fn qux(bar: Bar, baz: Baz) {
490 f();
491 g();
492 h();
493 j();
494}
495",
496 );
306 } 497 }
307 498
308 #[test] 499 #[test]