diff options
-rw-r--r-- | crates/assists/src/handlers/auto_import.rs | 8 | ||||
-rw-r--r-- | crates/assists/src/handlers/expand_glob_import.rs | 8 | ||||
-rw-r--r-- | crates/assists/src/handlers/extract_struct_from_enum_variant.rs | 7 | ||||
-rw-r--r-- | crates/assists/src/handlers/replace_qualified_name_with_use.rs | 26 | ||||
-rw-r--r-- | crates/hir_def/src/path.rs | 26 | ||||
-rw-r--r-- | crates/syntax/src/ast/make.rs | 33 |
6 files changed, 61 insertions, 47 deletions
diff --git a/crates/assists/src/handlers/auto_import.rs b/crates/assists/src/handlers/auto_import.rs index b5eb2c722..5a1b5a4ac 100644 --- a/crates/assists/src/handlers/auto_import.rs +++ b/crates/assists/src/handlers/auto_import.rs | |||
@@ -1,6 +1,5 @@ | |||
1 | use std::collections::BTreeSet; | 1 | use std::collections::BTreeSet; |
2 | 2 | ||
3 | use ast::make; | ||
4 | use either::Either; | 3 | use either::Either; |
5 | use hir::{ | 4 | use hir::{ |
6 | AsAssocItem, AssocItemContainer, ModPath, Module, ModuleDef, PathResolution, Semantics, Trait, | 5 | AsAssocItem, AssocItemContainer, ModPath, Module, ModuleDef, PathResolution, Semantics, Trait, |
@@ -54,11 +53,8 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
54 | format!("Import `{}`", &import), | 53 | format!("Import `{}`", &import), |
55 | range, | 54 | range, |
56 | |builder| { | 55 | |builder| { |
57 | let new_syntax = insert_use( | 56 | let new_syntax = |
58 | &scope, | 57 | insert_use(&scope, import.to_ast_path(), ctx.config.insert_use.merge); |
59 | make::path_from_text(&import.to_string()), | ||
60 | ctx.config.insert_use.merge, | ||
61 | ); | ||
62 | builder.replace(syntax.text_range(), new_syntax.to_string()) | 58 | builder.replace(syntax.text_range(), new_syntax.to_string()) |
63 | }, | 59 | }, |
64 | ); | 60 | ); |
diff --git a/crates/assists/src/handlers/expand_glob_import.rs b/crates/assists/src/handlers/expand_glob_import.rs index e14ac7f65..d1adff972 100644 --- a/crates/assists/src/handlers/expand_glob_import.rs +++ b/crates/assists/src/handlers/expand_glob_import.rs | |||
@@ -264,12 +264,8 @@ fn replace_ast( | |||
264 | match use_trees.as_slice() { | 264 | match use_trees.as_slice() { |
265 | [name] => { | 265 | [name] => { |
266 | if let Some(end_path) = name.path() { | 266 | if let Some(end_path) = name.path() { |
267 | let replacement = make::use_tree( | 267 | let replacement = |
268 | make::path_from_text(&format!("{}::{}", path, end_path)), | 268 | make::use_tree(make::path_concat(path, end_path), None, None, false); |
269 | None, | ||
270 | None, | ||
271 | false, | ||
272 | ); | ||
273 | 269 | ||
274 | algo::diff( | 270 | algo::diff( |
275 | &parent.either(|n| n.syntax().clone(), |n| n.syntax().clone()), | 271 | &parent.either(|n| n.syntax().clone(), |n| n.syntax().clone()), |
diff --git a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs index 3ea50f375..d1eadaa99 100644 --- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs | |||
@@ -12,7 +12,6 @@ use syntax::{ | |||
12 | use crate::{ | 12 | use crate::{ |
13 | assist_context::AssistBuilder, utils::insert_use, AssistContext, AssistId, AssistKind, Assists, | 13 | assist_context::AssistBuilder, utils::insert_use, AssistContext, AssistId, AssistKind, Assists, |
14 | }; | 14 | }; |
15 | use ast::make; | ||
16 | use insert_use::ImportScope; | 15 | use insert_use::ImportScope; |
17 | 16 | ||
18 | // Assist: extract_struct_from_enum_variant | 17 | // Assist: extract_struct_from_enum_variant |
@@ -112,11 +111,7 @@ fn insert_import( | |||
112 | let scope = ImportScope::find_insert_use_container(path.syntax(), ctx)?; | 111 | let scope = ImportScope::find_insert_use_container(path.syntax(), ctx)?; |
113 | let syntax = scope.as_syntax_node(); | 112 | let syntax = scope.as_syntax_node(); |
114 | 113 | ||
115 | let new_syntax = insert_use( | 114 | let new_syntax = insert_use(&scope, mod_path.to_ast_path(), ctx.config.insert_use.merge); |
116 | &scope, | ||
117 | make::path_from_text(&mod_path.to_string()), | ||
118 | ctx.config.insert_use.merge, | ||
119 | ); | ||
120 | // FIXME: this will currently panic as multiple imports will have overlapping text ranges | 115 | // FIXME: this will currently panic as multiple imports will have overlapping text ranges |
121 | builder.replace(syntax.text_range(), new_syntax.to_string()) | 116 | builder.replace(syntax.text_range(), new_syntax.to_string()) |
122 | } | 117 | } |
diff --git a/crates/assists/src/handlers/replace_qualified_name_with_use.rs b/crates/assists/src/handlers/replace_qualified_name_with_use.rs index e48407fcc..27b49455c 100644 --- a/crates/assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/assists/src/handlers/replace_qualified_name_with_use.rs | |||
@@ -1,11 +1,10 @@ | |||
1 | use syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SyntaxNode, TextRange}; | 1 | use syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SyntaxNode}; |
2 | use test_utils::mark; | 2 | use test_utils::mark; |
3 | 3 | ||
4 | use crate::{ | 4 | use crate::{ |
5 | utils::{insert_use, ImportScope}, | 5 | utils::{insert_use, ImportScope}, |
6 | AssistContext, AssistId, AssistKind, Assists, | 6 | AssistContext, AssistId, AssistKind, Assists, |
7 | }; | 7 | }; |
8 | use ast::make; | ||
9 | 8 | ||
10 | // Assist: replace_qualified_name_with_use | 9 | // Assist: replace_qualified_name_with_use |
11 | // | 10 | // |
@@ -33,15 +32,6 @@ pub(crate) fn replace_qualified_name_with_use( | |||
33 | mark::hit!(dont_import_trivial_paths); | 32 | mark::hit!(dont_import_trivial_paths); |
34 | return None; | 33 | return None; |
35 | } | 34 | } |
36 | let path_to_import = path.to_string(); | ||
37 | let path_to_import = match path.segment()?.generic_arg_list() { | ||
38 | Some(generic_args) => { | ||
39 | let generic_args_start = | ||
40 | generic_args.syntax().text_range().start() - path.syntax().text_range().start(); | ||
41 | &path_to_import[TextRange::up_to(generic_args_start)] | ||
42 | } | ||
43 | None => path_to_import.as_str(), | ||
44 | }; | ||
45 | 35 | ||
46 | let target = path.syntax().text_range(); | 36 | let target = path.syntax().text_range(); |
47 | let scope = ImportScope::find_insert_use_container(path.syntax(), ctx)?; | 37 | let scope = ImportScope::find_insert_use_container(path.syntax(), ctx)?; |
@@ -54,14 +44,10 @@ pub(crate) fn replace_qualified_name_with_use( | |||
54 | // Now that we've brought the name into scope, re-qualify all paths that could be | 44 | // Now that we've brought the name into scope, re-qualify all paths that could be |
55 | // affected (that is, all paths inside the node we added the `use` to). | 45 | // affected (that is, all paths inside the node we added the `use` to). |
56 | let mut rewriter = SyntaxRewriter::default(); | 46 | let mut rewriter = SyntaxRewriter::default(); |
57 | shorten_paths(&mut rewriter, syntax.clone(), path); | 47 | shorten_paths(&mut rewriter, syntax.clone(), &path); |
58 | let rewritten_syntax = rewriter.rewrite(&syntax); | 48 | let rewritten_syntax = rewriter.rewrite(&syntax); |
59 | if let Some(ref import_scope) = ImportScope::from(rewritten_syntax) { | 49 | if let Some(ref import_scope) = ImportScope::from(rewritten_syntax) { |
60 | let new_syntax = insert_use( | 50 | let new_syntax = insert_use(import_scope, path, ctx.config.insert_use.merge); |
61 | import_scope, | ||
62 | make::path_from_text(path_to_import), | ||
63 | ctx.config.insert_use.merge, | ||
64 | ); | ||
65 | builder.replace(syntax.text_range(), new_syntax.to_string()) | 51 | builder.replace(syntax.text_range(), new_syntax.to_string()) |
66 | } | 52 | } |
67 | }, | 53 | }, |
@@ -69,7 +55,7 @@ pub(crate) fn replace_qualified_name_with_use( | |||
69 | } | 55 | } |
70 | 56 | ||
71 | /// Adds replacements to `re` that shorten `path` in all descendants of `node`. | 57 | /// Adds replacements to `re` that shorten `path` in all descendants of `node`. |
72 | fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: ast::Path) { | 58 | fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: &ast::Path) { |
73 | for child in node.children() { | 59 | for child in node.children() { |
74 | match_ast! { | 60 | match_ast! { |
75 | match child { | 61 | match child { |
@@ -82,10 +68,10 @@ fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: | |||
82 | ast::Path(p) => { | 68 | ast::Path(p) => { |
83 | match maybe_replace_path(rewriter, p.clone(), path.clone()) { | 69 | match maybe_replace_path(rewriter, p.clone(), path.clone()) { |
84 | Some(()) => {}, | 70 | Some(()) => {}, |
85 | None => shorten_paths(rewriter, p.syntax().clone(), path.clone()), | 71 | None => shorten_paths(rewriter, p.syntax().clone(), path), |
86 | } | 72 | } |
87 | }, | 73 | }, |
88 | _ => shorten_paths(rewriter, child, path.clone()), | 74 | _ => shorten_paths(rewriter, child, path), |
89 | } | 75 | } |
90 | } | 76 | } |
91 | } | 77 | } |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index 99395667d..40ec38f56 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -13,7 +13,7 @@ use hir_expand::{ | |||
13 | hygiene::Hygiene, | 13 | hygiene::Hygiene, |
14 | name::{AsName, Name}, | 14 | name::{AsName, Name}, |
15 | }; | 15 | }; |
16 | use syntax::ast; | 16 | use syntax::ast::{self, make}; |
17 | 17 | ||
18 | use crate::{ | 18 | use crate::{ |
19 | type_ref::{TypeBound, TypeRef}, | 19 | type_ref::{TypeBound, TypeRef}, |
@@ -104,6 +104,26 @@ impl ModPath { | |||
104 | } | 104 | } |
105 | self.segments.first() | 105 | self.segments.first() |
106 | } | 106 | } |
107 | |||
108 | pub fn to_ast_path(&self) -> ast::Path { | ||
109 | let mut segments = Vec::new(); | ||
110 | let mut is_abs = false; | ||
111 | match self.kind { | ||
112 | PathKind::Plain => {} | ||
113 | PathKind::Super(0) => segments.push(make::path_segment_self()), | ||
114 | PathKind::Super(n) => segments.extend((0..n).map(|_| make::path_segment_super())), | ||
115 | PathKind::Crate => segments.push(make::path_segment_crate()), | ||
116 | PathKind::Abs => is_abs = true, | ||
117 | PathKind::DollarCrate(_) => (), | ||
118 | } | ||
119 | |||
120 | segments.extend( | ||
121 | self.segments | ||
122 | .iter() | ||
123 | .map(|segment| make::path_segment(make::name_ref(&segment.to_string()))), | ||
124 | ); | ||
125 | make::path_from_segments(segments, is_abs) | ||
126 | } | ||
107 | } | 127 | } |
108 | 128 | ||
109 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 129 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -290,10 +310,8 @@ impl Display for ModPath { | |||
290 | }; | 310 | }; |
291 | match self.kind { | 311 | match self.kind { |
292 | PathKind::Plain => {} | 312 | PathKind::Plain => {} |
313 | PathKind::Super(0) => add_segment("self")?, | ||
293 | PathKind::Super(n) => { | 314 | PathKind::Super(n) => { |
294 | if n == 0 { | ||
295 | add_segment("self")?; | ||
296 | } | ||
297 | for _ in 0..n { | 315 | for _ in 0..n { |
298 | add_segment("super")?; | 316 | add_segment("super")?; |
299 | } | 317 | } |
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 25e8a359d..580eb3690 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs | |||
@@ -24,18 +24,41 @@ pub fn ty(text: &str) -> ast::Type { | |||
24 | pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment { | 24 | pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment { |
25 | ast_from_text(&format!("use {};", name_ref)) | 25 | ast_from_text(&format!("use {};", name_ref)) |
26 | } | 26 | } |
27 | |||
27 | pub fn path_segment_self() -> ast::PathSegment { | 28 | pub fn path_segment_self() -> ast::PathSegment { |
28 | ast_from_text("use self;") | 29 | ast_from_text("use self;") |
29 | } | 30 | } |
31 | |||
32 | pub fn path_segment_super() -> ast::PathSegment { | ||
33 | ast_from_text("use super;") | ||
34 | } | ||
35 | |||
36 | pub fn path_segment_crate() -> ast::PathSegment { | ||
37 | ast_from_text("use crate;") | ||
38 | } | ||
39 | |||
30 | pub fn path_unqualified(segment: ast::PathSegment) -> ast::Path { | 40 | pub fn path_unqualified(segment: ast::PathSegment) -> ast::Path { |
31 | path_from_text(&format!("use {}", segment)) | 41 | ast_from_text(&format!("use {}", segment)) |
32 | } | 42 | } |
43 | |||
33 | pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path { | 44 | pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path { |
34 | path_from_text(&format!("{}::{}", qual, segment)) | 45 | ast_from_text(&format!("{}::{}", qual, segment)) |
35 | } | 46 | } |
36 | // FIXME: make this private | 47 | |
37 | pub fn path_from_text(text: &str) -> ast::Path { | 48 | pub fn path_concat(first: ast::Path, second: ast::Path) -> ast::Path { |
38 | ast_from_text(text) | 49 | ast_from_text(&format!("{}::{}", first, second)) |
50 | } | ||
51 | |||
52 | pub fn path_from_segments( | ||
53 | segments: impl IntoIterator<Item = ast::PathSegment>, | ||
54 | is_abs: bool, | ||
55 | ) -> ast::Path { | ||
56 | let segments = segments.into_iter().map(|it| it.syntax().clone()).join("::"); | ||
57 | ast_from_text(&if is_abs { | ||
58 | format!("use ::{};", segments) | ||
59 | } else { | ||
60 | format!("use {};", segments) | ||
61 | }) | ||
39 | } | 62 | } |
40 | 63 | ||
41 | pub fn use_tree( | 64 | pub fn use_tree( |