From ea0c124219da33462b9d0be93f7abe0478cc7af2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 5 Mar 2020 19:03:14 +0100 Subject: Rerail split_import API onto AST The code is more verbose and less efficient now, but should be reusable in add_import context as well --- crates/ra_assists/src/handlers/split_import.rs | 52 ++++++++++++++++---------- 1 file changed, 33 insertions(+), 19 deletions(-) (limited to 'crates/ra_assists') diff --git a/crates/ra_assists/src/handlers/split_import.rs b/crates/ra_assists/src/handlers/split_import.rs index 2c3f07a79..292c39f59 100644 --- a/crates/ra_assists/src/handlers/split_import.rs +++ b/crates/ra_assists/src/handlers/split_import.rs @@ -1,6 +1,9 @@ -use std::iter::successors; +use std::iter::{once, successors}; -use ra_syntax::{ast, AstNode, TextUnit, T}; +use ra_syntax::{ + ast::{self, make}, + AstNode, T, +}; use crate::{Assist, AssistCtx, AssistId}; @@ -17,39 +20,50 @@ use crate::{Assist, AssistCtx, AssistId}; // ``` pub(crate) fn split_import(ctx: AssistCtx) -> Option { let colon_colon = ctx.find_token_at_offset(T![::])?; - let path = ast::Path::cast(colon_colon.parent())?; - let top_path = successors(Some(path), |it| it.parent_path()).last()?; + let path = ast::Path::cast(colon_colon.parent())?.qualifier()?; + let top_path = successors(Some(path.clone()), |it| it.parent_path()).last()?; - let use_tree = top_path.syntax().ancestors().find_map(ast::UseTree::cast); - if use_tree.is_none() { - return None; - } + let use_tree = top_path.syntax().ancestors().find_map(ast::UseTree::cast)?; - let l_curly = colon_colon.text_range().end(); - let r_curly = match top_path.syntax().parent().and_then(ast::UseTree::cast) { - Some(tree) => tree.syntax().text_range().end(), - None => top_path.syntax().text_range().end(), - }; + let new_tree = split_use_tree_prefix(&use_tree, &path)?; + let cursor = ctx.frange.range.start(); ctx.add_assist(AssistId("split_import"), "Split import", |edit| { edit.target(colon_colon.text_range()); - edit.insert(l_curly, "{"); - edit.insert(r_curly, "}"); - edit.set_cursor(l_curly + TextUnit::of_str("{")); + edit.replace_ast(use_tree, new_tree); + edit.set_cursor(cursor); }) } +fn split_use_tree_prefix(use_tree: &ast::UseTree, prefix: &ast::Path) -> Option { + let suffix = split_path_prefix(&prefix)?; + let use_tree = make::use_tree(suffix.clone(), use_tree.use_tree_list(), use_tree.alias()); + let nested = make::use_tree_list(once(use_tree)); + let res = make::use_tree(prefix.clone(), Some(nested), None); + Some(res) +} + +fn split_path_prefix(prefix: &ast::Path) -> Option { + let parent = prefix.parent_path()?; + let mut res = make::path_unqualified(parent.segment()?); + for p in successors(parent.parent_path(), |it| it.parent_path()) { + res = make::path_qualified(res, p.segment()?); + } + Some(res) +} + #[cfg(test)] mod tests { - use super::*; use crate::helpers::{check_assist, check_assist_target}; + use super::*; + #[test] fn test_split_import() { check_assist( split_import, "use crate::<|>db::RootDatabase;", - "use crate::{<|>db::RootDatabase};", + "use crate::<|>{db::RootDatabase};", ) } @@ -58,7 +72,7 @@ mod tests { check_assist( split_import, "use crate:<|>:db::{RootDatabase, FileSymbol}", - "use crate::{<|>db::{RootDatabase, FileSymbol}}", + "use crate:<|>:{db::{RootDatabase, FileSymbol}}", ) } -- cgit v1.2.3