From 128eef779f572a8120cb475d86a373ac4c9e5559 Mon Sep 17 00:00:00 2001 From: unexge Date: Thu, 13 Aug 2020 00:51:15 +0300 Subject: Improve AST replacing in expand glob import --- crates/assists/src/handlers/expand_glob_import.rs | 267 +++++++++++++++++++--- 1 file changed, 229 insertions(+), 38 deletions(-) (limited to 'crates/assists/src') 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::{ defs::{classify_name_ref, Definition, NameRefClass}, RootDatabase, }; -use syntax::{algo, ast, match_ast, AstNode, SyntaxNode, SyntaxToken, T}; +use syntax::{ast, AstNode, SyntaxToken, T}; use crate::{ assist_context::{AssistBuilder, AssistContext, Assists}, @@ -38,7 +38,7 @@ use crate::{ // ``` pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { let star = ctx.find_token_at_offset(T![*])?; - let mod_path = find_mod_path(&star)?; + let (parent, mod_path) = find_parent_and_path(&star)?; let module = match ctx.sema.resolve_path(&mod_path)? { PathResolution::Def(ModuleDef::Module(it)) => it, _ => return None, @@ -52,19 +52,23 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti source_file.syntax().descendants().filter_map(ast::NameRef::cast).collect(); let used_names = find_used_names(ctx, defs_in_mod, name_refs_in_source_file); - let parent = star.parent().parent()?; + let target = parent.syntax(); acc.add( AssistId("expand_glob_import", AssistKind::RefactorRewrite), "Expand glob import", - parent.text_range(), + target.text_range(), |builder| { - replace_ast(builder, &parent, mod_path, used_names); + replace_ast(builder, parent, mod_path, used_names); }, ) } -fn find_mod_path(star: &SyntaxToken) -> Option { - star.ancestors().find_map(|n| ast::UseTree::cast(n).and_then(|u| u.path())) +fn find_parent_and_path(star: &SyntaxToken) -> Option<(ast::UseTree, ast::Path)> { + star.ancestors().find_map(|n| { + let use_tree = ast::UseTree::cast(n)?; + let path = use_tree.path()?; + Some((use_tree, path)) + }) } #[derive(PartialEq)] @@ -137,41 +141,28 @@ fn find_used_names( fn replace_ast( builder: &mut AssistBuilder, - node: &SyntaxNode, + parent: ast::UseTree, path: ast::Path, used_names: Vec, ) { - let replacement: Either = match used_names.as_slice() { - [name] => Either::Left(ast::make::use_tree( + let replacement = match used_names.as_slice() { + [name] => ast::make::use_tree( ast::make::path_from_text(&format!("{}::{}", path, name)), None, None, false, - )), - names => Either::Right(ast::make::use_tree_list(names.iter().map(|n| { - ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false) - }))), - }; - - let mut replace_node = |replacement: Either| { - algo::diff(node, &replacement.either(|u| u.syntax().clone(), |ut| ut.syntax().clone())) - .into_text_edit(builder.text_edit_builder()); + ), + names => ast::make::use_tree( + path, + Some(ast::make::use_tree_list(names.iter().map(|n| { + ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false) + }))), + None, + false, + ), }; - match_ast! { - match node { - ast::UseTree(use_tree) => { - replace_node(replacement); - }, - ast::UseTreeList(use_tree_list) => { - replace_node(replacement); - }, - ast::Use(use_item) => { - builder.replace_ast(use_item, ast::make::use_(replacement.left_or_else(|ut| ast::make::use_tree(path, Some(ut), None, false)))); - }, - _ => {}, - } - } + builder.replace_ast(parent, replacement); } #[cfg(test)] @@ -260,7 +251,7 @@ fn qux(bar: Bar, baz: Baz) { expand_glob_import, r" mod foo { - mod bar { + pub mod bar { pub struct Bar; pub struct Baz; pub struct Qux; @@ -268,7 +259,7 @@ mod foo { pub fn f() {} } - mod baz { + pub mod baz { pub fn g() {} } } @@ -282,7 +273,7 @@ fn qux(bar: Bar, baz: Baz) { ", r" mod foo { - mod bar { + pub mod bar { pub struct Bar; pub struct Baz; pub struct Qux; @@ -290,7 +281,7 @@ mod foo { pub fn f() {} } - mod baz { + pub mod baz { pub fn g() {} } } @@ -302,7 +293,207 @@ fn qux(bar: Bar, baz: Baz) { g(); } ", - ) + ); + + check_assist( + expand_glob_import, + r" +mod foo { + pub mod bar { + pub struct Bar; + pub struct Baz; + pub struct Qux; + + pub fn f() {} + } + + pub mod baz { + pub fn g() {} + } +} + +use foo::{bar::{Bar, Baz, f}, baz::*<|>}; + +fn qux(bar: Bar, baz: Baz) { + f(); + g(); +} +", + r" +mod foo { + pub mod bar { + pub struct Bar; + pub struct Baz; + pub struct Qux; + + pub fn f() {} + } + + pub mod baz { + pub fn g() {} + } +} + +use foo::{bar::{Bar, Baz, f}, baz::g}; + +fn qux(bar: Bar, baz: Baz) { + f(); + g(); +} +", + ); + + check_assist( + expand_glob_import, + r" +mod foo { + pub mod bar { + pub struct Bar; + pub struct Baz; + pub struct Qux; + + pub fn f() {} + } + + pub mod baz { + pub fn g() {} + + pub mod qux { + pub fn h() {} + pub fn m() {} + + pub mod q { + pub fn j() {} + } + } + } +} + +use foo::{ + bar::{*, f}, + baz::{g, qux::*<|>} +}; + +fn qux(bar: Bar, baz: Baz) { + f(); + g(); + h(); + q::j(); +} +", + r" +mod foo { + pub mod bar { + pub struct Bar; + pub struct Baz; + pub struct Qux; + + pub fn f() {} + } + + pub mod baz { + pub fn g() {} + + pub mod qux { + pub fn h() {} + pub fn m() {} + + pub mod q { + pub fn j() {} + } + } + } +} + +use foo::{ + bar::{*, f}, + baz::{g, qux::{q, h}} +}; + +fn qux(bar: Bar, baz: Baz) { + f(); + g(); + h(); + q::j(); +} +", + ); + + check_assist( + expand_glob_import, + r" +mod foo { + pub mod bar { + pub struct Bar; + pub struct Baz; + pub struct Qux; + + pub fn f() {} + } + + pub mod baz { + pub fn g() {} + + pub mod qux { + pub fn h() {} + pub fn m() {} + + pub mod q { + pub fn j() {} + } + } + } +} + +use foo::{ + bar::{*, f}, + baz::{g, qux::{h, q::*<|>}} +}; + +fn qux(bar: Bar, baz: Baz) { + f(); + g(); + h(); + j(); +} +", + r" +mod foo { + pub mod bar { + pub struct Bar; + pub struct Baz; + pub struct Qux; + + pub fn f() {} + } + + pub mod baz { + pub fn g() {} + + pub mod qux { + pub fn h() {} + pub fn m() {} + + pub mod q { + pub fn j() {} + } + } + } +} + +use foo::{ + bar::{*, f}, + baz::{g, qux::{h, q::j}} +}; + +fn qux(bar: Bar, baz: Baz) { + f(); + g(); + h(); + j(); +} +", + ); } #[test] -- cgit v1.2.3