diff options
Diffstat (limited to 'crates/assists/src/handlers/qualify_path.rs')
-rw-r--r-- | crates/assists/src/handlers/qualify_path.rs | 41 |
1 files changed, 17 insertions, 24 deletions
diff --git a/crates/assists/src/handlers/qualify_path.rs b/crates/assists/src/handlers/qualify_path.rs index a7d9fd4dc..af8a11d03 100644 --- a/crates/assists/src/handlers/qualify_path.rs +++ b/crates/assists/src/handlers/qualify_path.rs | |||
@@ -1,10 +1,7 @@ | |||
1 | use std::iter; | 1 | use std::iter; |
2 | 2 | ||
3 | use hir::AsName; | 3 | use hir::AsName; |
4 | use ide_db::helpers::{ | 4 | use ide_db::helpers::{import_assets::ImportCandidate, mod_path_to_ast}; |
5 | import_assets::{ImportAssets, ImportCandidate}, | ||
6 | mod_path_to_ast, | ||
7 | }; | ||
8 | use ide_db::RootDatabase; | 5 | use ide_db::RootDatabase; |
9 | use syntax::{ | 6 | use syntax::{ |
10 | ast, | 7 | ast, |
@@ -18,6 +15,8 @@ use crate::{ | |||
18 | AssistId, AssistKind, GroupLabel, | 15 | AssistId, AssistKind, GroupLabel, |
19 | }; | 16 | }; |
20 | 17 | ||
18 | use super::auto_import::find_importable_node; | ||
19 | |||
21 | // Assist: qualify_path | 20 | // Assist: qualify_path |
22 | // | 21 | // |
23 | // If the name is unresolved, provides all possible qualified paths for it. | 22 | // If the name is unresolved, provides all possible qualified paths for it. |
@@ -36,47 +35,38 @@ use crate::{ | |||
36 | // # pub mod std { pub mod collections { pub struct HashMap { } } } | 35 | // # pub mod std { pub mod collections { pub struct HashMap { } } } |
37 | // ``` | 36 | // ``` |
38 | pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 37 | pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
39 | let import_assets = | 38 | let (import_assets, syntax_under_caret) = find_importable_node(ctx)?; |
40 | if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() { | ||
41 | ImportAssets::for_regular_path(path_under_caret, &ctx.sema) | ||
42 | } else if let Some(method_under_caret) = | ||
43 | ctx.find_node_at_offset_with_descend::<ast::MethodCallExpr>() | ||
44 | { | ||
45 | ImportAssets::for_method_call(method_under_caret, &ctx.sema) | ||
46 | } else { | ||
47 | None | ||
48 | }?; | ||
49 | let proposed_imports = import_assets.search_for_relative_paths(&ctx.sema); | 39 | let proposed_imports = import_assets.search_for_relative_paths(&ctx.sema); |
50 | if proposed_imports.is_empty() { | 40 | if proposed_imports.is_empty() { |
51 | return None; | 41 | return None; |
52 | } | 42 | } |
53 | 43 | ||
54 | let candidate = import_assets.import_candidate(); | 44 | let candidate = import_assets.import_candidate(); |
55 | let range = ctx.sema.original_range(import_assets.syntax_under_caret()).range; | 45 | let range = ctx.sema.original_range(&syntax_under_caret).range; |
56 | 46 | ||
57 | let qualify_candidate = match candidate { | 47 | let qualify_candidate = match candidate { |
58 | ImportCandidate::Path(candidate) => { | 48 | ImportCandidate::Path(candidate) => { |
59 | if candidate.qualifier.is_some() { | 49 | if candidate.qualifier.is_some() { |
60 | mark::hit!(qualify_path_qualifier_start); | 50 | mark::hit!(qualify_path_qualifier_start); |
61 | let path = ast::Path::cast(import_assets.syntax_under_caret().clone())?; | 51 | let path = ast::Path::cast(syntax_under_caret)?; |
62 | let (prev_segment, segment) = (path.qualifier()?.segment()?, path.segment()?); | 52 | let (prev_segment, segment) = (path.qualifier()?.segment()?, path.segment()?); |
63 | QualifyCandidate::QualifierStart(segment, prev_segment.generic_arg_list()) | 53 | QualifyCandidate::QualifierStart(segment, prev_segment.generic_arg_list()) |
64 | } else { | 54 | } else { |
65 | mark::hit!(qualify_path_unqualified_name); | 55 | mark::hit!(qualify_path_unqualified_name); |
66 | let path = ast::Path::cast(import_assets.syntax_under_caret().clone())?; | 56 | let path = ast::Path::cast(syntax_under_caret)?; |
67 | let generics = path.segment()?.generic_arg_list(); | 57 | let generics = path.segment()?.generic_arg_list(); |
68 | QualifyCandidate::UnqualifiedName(generics) | 58 | QualifyCandidate::UnqualifiedName(generics) |
69 | } | 59 | } |
70 | } | 60 | } |
71 | ImportCandidate::TraitAssocItem(_) => { | 61 | ImportCandidate::TraitAssocItem(_) => { |
72 | mark::hit!(qualify_path_trait_assoc_item); | 62 | mark::hit!(qualify_path_trait_assoc_item); |
73 | let path = ast::Path::cast(import_assets.syntax_under_caret().clone())?; | 63 | let path = ast::Path::cast(syntax_under_caret)?; |
74 | let (qualifier, segment) = (path.qualifier()?, path.segment()?); | 64 | let (qualifier, segment) = (path.qualifier()?, path.segment()?); |
75 | QualifyCandidate::TraitAssocItem(qualifier, segment) | 65 | QualifyCandidate::TraitAssocItem(qualifier, segment) |
76 | } | 66 | } |
77 | ImportCandidate::TraitMethod(_) => { | 67 | ImportCandidate::TraitMethod(_) => { |
78 | mark::hit!(qualify_path_trait_method); | 68 | mark::hit!(qualify_path_trait_method); |
79 | let mcall_expr = ast::MethodCallExpr::cast(import_assets.syntax_under_caret().clone())?; | 69 | let mcall_expr = ast::MethodCallExpr::cast(syntax_under_caret)?; |
80 | QualifyCandidate::TraitMethod(ctx.sema.db, mcall_expr) | 70 | QualifyCandidate::TraitMethod(ctx.sema.db, mcall_expr) |
81 | } | 71 | } |
82 | }; | 72 | }; |
@@ -140,7 +130,7 @@ impl QualifyCandidate<'_> { | |||
140 | let generics = | 130 | let generics = |
141 | mcall_expr.generic_arg_list().as_ref().map_or_else(String::new, ToString::to_string); | 131 | mcall_expr.generic_arg_list().as_ref().map_or_else(String::new, ToString::to_string); |
142 | let arg_list = mcall_expr.arg_list().map(|arg_list| arg_list.args()); | 132 | let arg_list = mcall_expr.arg_list().map(|arg_list| arg_list.args()); |
143 | let trait_ = item_as_trait(item)?; | 133 | let trait_ = item_as_trait(db, item)?; |
144 | let method = find_trait_method(db, trait_, &trait_method_name)?; | 134 | let method = find_trait_method(db, trait_, &trait_method_name)?; |
145 | if let Some(self_access) = method.self_param(db).map(|sp| sp.access(db)) { | 135 | if let Some(self_access) = method.self_param(db).map(|sp| sp.access(db)) { |
146 | let receiver = match self_access { | 136 | let receiver = match self_access { |
@@ -179,11 +169,13 @@ fn find_trait_method( | |||
179 | } | 169 | } |
180 | } | 170 | } |
181 | 171 | ||
182 | fn item_as_trait(item: hir::ItemInNs) -> Option<hir::Trait> { | 172 | fn item_as_trait(db: &RootDatabase, item: hir::ItemInNs) -> Option<hir::Trait> { |
183 | if let hir::ModuleDef::Trait(trait_) = hir::ModuleDef::from(item.as_module_def_id()?) { | 173 | let item_module_def = hir::ModuleDef::from(item.as_module_def_id()?); |
174 | |||
175 | if let hir::ModuleDef::Trait(trait_) = item_module_def { | ||
184 | Some(trait_) | 176 | Some(trait_) |
185 | } else { | 177 | } else { |
186 | None | 178 | item_module_def.as_assoc_item(db)?.containing_trait(db) |
187 | } | 179 | } |
188 | } | 180 | } |
189 | 181 | ||
@@ -191,7 +183,8 @@ fn group_label(candidate: &ImportCandidate) -> GroupLabel { | |||
191 | let name = match candidate { | 183 | let name = match candidate { |
192 | ImportCandidate::Path(it) => &it.name, | 184 | ImportCandidate::Path(it) => &it.name, |
193 | ImportCandidate::TraitAssocItem(it) | ImportCandidate::TraitMethod(it) => &it.name, | 185 | ImportCandidate::TraitAssocItem(it) | ImportCandidate::TraitMethod(it) => &it.name, |
194 | }; | 186 | } |
187 | .text(); | ||
195 | GroupLabel(format!("Qualify {}", name)) | 188 | GroupLabel(format!("Qualify {}", name)) |
196 | } | 189 | } |
197 | 190 | ||