diff options
author | Aleksey Kladov <[email protected]> | 2020-03-05 18:03:14 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-03-06 13:08:43 +0000 |
commit | ea0c124219da33462b9d0be93f7abe0478cc7af2 (patch) | |
tree | 18d0c7a15da29214a6387f0880135fdf7f738df1 /crates/ra_assists | |
parent | d75577fcee79aac06bdddb01fde431f26432c36c (diff) |
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
Diffstat (limited to 'crates/ra_assists')
-rw-r--r-- | crates/ra_assists/src/handlers/split_import.rs | 52 |
1 files changed, 33 insertions, 19 deletions
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 @@ | |||
1 | use std::iter::successors; | 1 | use std::iter::{once, successors}; |
2 | 2 | ||
3 | use ra_syntax::{ast, AstNode, TextUnit, T}; | 3 | use ra_syntax::{ |
4 | ast::{self, make}, | ||
5 | AstNode, T, | ||
6 | }; | ||
4 | 7 | ||
5 | use crate::{Assist, AssistCtx, AssistId}; | 8 | use crate::{Assist, AssistCtx, AssistId}; |
6 | 9 | ||
@@ -17,39 +20,50 @@ use crate::{Assist, AssistCtx, AssistId}; | |||
17 | // ``` | 20 | // ``` |
18 | pub(crate) fn split_import(ctx: AssistCtx) -> Option<Assist> { | 21 | pub(crate) fn split_import(ctx: AssistCtx) -> Option<Assist> { |
19 | let colon_colon = ctx.find_token_at_offset(T![::])?; | 22 | let colon_colon = ctx.find_token_at_offset(T![::])?; |
20 | let path = ast::Path::cast(colon_colon.parent())?; | 23 | let path = ast::Path::cast(colon_colon.parent())?.qualifier()?; |
21 | let top_path = successors(Some(path), |it| it.parent_path()).last()?; | 24 | let top_path = successors(Some(path.clone()), |it| it.parent_path()).last()?; |
22 | 25 | ||
23 | let use_tree = top_path.syntax().ancestors().find_map(ast::UseTree::cast); | 26 | let use_tree = top_path.syntax().ancestors().find_map(ast::UseTree::cast)?; |
24 | if use_tree.is_none() { | ||
25 | return None; | ||
26 | } | ||
27 | 27 | ||
28 | let l_curly = colon_colon.text_range().end(); | 28 | let new_tree = split_use_tree_prefix(&use_tree, &path)?; |
29 | let r_curly = match top_path.syntax().parent().and_then(ast::UseTree::cast) { | 29 | let cursor = ctx.frange.range.start(); |
30 | Some(tree) => tree.syntax().text_range().end(), | ||
31 | None => top_path.syntax().text_range().end(), | ||
32 | }; | ||
33 | 30 | ||
34 | ctx.add_assist(AssistId("split_import"), "Split import", |edit| { | 31 | ctx.add_assist(AssistId("split_import"), "Split import", |edit| { |
35 | edit.target(colon_colon.text_range()); | 32 | edit.target(colon_colon.text_range()); |
36 | edit.insert(l_curly, "{"); | 33 | edit.replace_ast(use_tree, new_tree); |
37 | edit.insert(r_curly, "}"); | 34 | edit.set_cursor(cursor); |
38 | edit.set_cursor(l_curly + TextUnit::of_str("{")); | ||
39 | }) | 35 | }) |
40 | } | 36 | } |
41 | 37 | ||
38 | fn split_use_tree_prefix(use_tree: &ast::UseTree, prefix: &ast::Path) -> Option<ast::UseTree> { | ||
39 | let suffix = split_path_prefix(&prefix)?; | ||
40 | let use_tree = make::use_tree(suffix.clone(), use_tree.use_tree_list(), use_tree.alias()); | ||
41 | let nested = make::use_tree_list(once(use_tree)); | ||
42 | let res = make::use_tree(prefix.clone(), Some(nested), None); | ||
43 | Some(res) | ||
44 | } | ||
45 | |||
46 | fn split_path_prefix(prefix: &ast::Path) -> Option<ast::Path> { | ||
47 | let parent = prefix.parent_path()?; | ||
48 | let mut res = make::path_unqualified(parent.segment()?); | ||
49 | for p in successors(parent.parent_path(), |it| it.parent_path()) { | ||
50 | res = make::path_qualified(res, p.segment()?); | ||
51 | } | ||
52 | Some(res) | ||
53 | } | ||
54 | |||
42 | #[cfg(test)] | 55 | #[cfg(test)] |
43 | mod tests { | 56 | mod tests { |
44 | use super::*; | ||
45 | use crate::helpers::{check_assist, check_assist_target}; | 57 | use crate::helpers::{check_assist, check_assist_target}; |
46 | 58 | ||
59 | use super::*; | ||
60 | |||
47 | #[test] | 61 | #[test] |
48 | fn test_split_import() { | 62 | fn test_split_import() { |
49 | check_assist( | 63 | check_assist( |
50 | split_import, | 64 | split_import, |
51 | "use crate::<|>db::RootDatabase;", | 65 | "use crate::<|>db::RootDatabase;", |
52 | "use crate::{<|>db::RootDatabase};", | 66 | "use crate::<|>{db::RootDatabase};", |
53 | ) | 67 | ) |
54 | } | 68 | } |
55 | 69 | ||
@@ -58,7 +72,7 @@ mod tests { | |||
58 | check_assist( | 72 | check_assist( |
59 | split_import, | 73 | split_import, |
60 | "use crate:<|>:db::{RootDatabase, FileSymbol}", | 74 | "use crate:<|>:db::{RootDatabase, FileSymbol}", |
61 | "use crate::{<|>db::{RootDatabase, FileSymbol}}", | 75 | "use crate:<|>:{db::{RootDatabase, FileSymbol}}", |
62 | ) | 76 | ) |
63 | } | 77 | } |
64 | 78 | ||