diff options
Diffstat (limited to 'crates/ide_assists/src/handlers')
8 files changed, 84 insertions, 63 deletions
diff --git a/crates/ide_assists/src/handlers/add_lifetime_to_type.rs b/crates/ide_assists/src/handlers/add_lifetime_to_type.rs index 2edf7b204..844928754 100644 --- a/crates/ide_assists/src/handlers/add_lifetime_to_type.rs +++ b/crates/ide_assists/src/handlers/add_lifetime_to_type.rs | |||
@@ -29,8 +29,7 @@ pub(crate) fn add_lifetime_to_type(acc: &mut Assists, ctx: &AssistContext) -> Op | |||
29 | let node = ctx.find_node_at_offset::<ast::Adt>()?; | 29 | let node = ctx.find_node_at_offset::<ast::Adt>()?; |
30 | let has_lifetime = node | 30 | let has_lifetime = node |
31 | .generic_param_list() | 31 | .generic_param_list() |
32 | .map(|gen_list| gen_list.lifetime_params().count() > 0) | 32 | .map_or(false, |gen_list| gen_list.lifetime_params().next().is_some()); |
33 | .unwrap_or_default(); | ||
34 | 33 | ||
35 | if has_lifetime { | 34 | if has_lifetime { |
36 | return None; | 35 | return None; |
@@ -41,7 +40,7 @@ pub(crate) fn add_lifetime_to_type(acc: &mut Assists, ctx: &AssistContext) -> Op | |||
41 | 40 | ||
42 | acc.add( | 41 | acc.add( |
43 | AssistId("add_lifetime_to_type", AssistKind::Generate), | 42 | AssistId("add_lifetime_to_type", AssistKind::Generate), |
44 | "Add lifetime`", | 43 | "Add lifetime", |
45 | target, | 44 | target, |
46 | |builder| { | 45 | |builder| { |
47 | match node.generic_param_list() { | 46 | match node.generic_param_list() { |
diff --git a/crates/ide_assists/src/handlers/add_turbo_fish.rs b/crates/ide_assists/src/handlers/add_turbo_fish.rs index 436767895..e4bb61c4e 100644 --- a/crates/ide_assists/src/handlers/add_turbo_fish.rs +++ b/crates/ide_assists/src/handlers/add_turbo_fish.rs | |||
@@ -26,7 +26,7 @@ use crate::{ | |||
26 | pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 26 | pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
27 | let ident = ctx.find_token_syntax_at_offset(SyntaxKind::IDENT).or_else(|| { | 27 | let ident = ctx.find_token_syntax_at_offset(SyntaxKind::IDENT).or_else(|| { |
28 | let arg_list = ctx.find_node_at_offset::<ast::ArgList>()?; | 28 | let arg_list = ctx.find_node_at_offset::<ast::ArgList>()?; |
29 | if arg_list.args().count() > 0 { | 29 | if arg_list.args().next().is_some() { |
30 | return None; | 30 | return None; |
31 | } | 31 | } |
32 | cov_mark::hit!(add_turbo_fish_after_call); | 32 | cov_mark::hit!(add_turbo_fish_after_call); |
diff --git a/crates/ide_assists/src/handlers/convert_comment_block.rs b/crates/ide_assists/src/handlers/convert_comment_block.rs index cdc45fc42..9dc3ee28f 100644 --- a/crates/ide_assists/src/handlers/convert_comment_block.rs +++ b/crates/ide_assists/src/handlers/convert_comment_block.rs | |||
@@ -1,5 +1,4 @@ | |||
1 | use itertools::Itertools; | 1 | use itertools::Itertools; |
2 | use std::convert::identity; | ||
3 | use syntax::{ | 2 | use syntax::{ |
4 | ast::{ | 3 | ast::{ |
5 | self, | 4 | self, |
@@ -140,7 +139,7 @@ fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> { | |||
140 | .filter(|s| !skippable(s)) | 139 | .filter(|s| !skippable(s)) |
141 | .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix)) | 140 | .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix)) |
142 | .take_while(|opt_com| opt_com.is_some()) | 141 | .take_while(|opt_com| opt_com.is_some()) |
143 | .filter_map(identity) | 142 | .flatten() |
144 | .skip(1); // skip the first element so we don't duplicate it in next_comments | 143 | .skip(1); // skip the first element so we don't duplicate it in next_comments |
145 | 144 | ||
146 | let next_comments = comment | 145 | let next_comments = comment |
@@ -149,7 +148,7 @@ fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> { | |||
149 | .filter(|s| !skippable(s)) | 148 | .filter(|s| !skippable(s)) |
150 | .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix)) | 149 | .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix)) |
151 | .take_while(|opt_com| opt_com.is_some()) | 150 | .take_while(|opt_com| opt_com.is_some()) |
152 | .filter_map(identity); | 151 | .flatten(); |
153 | 152 | ||
154 | let mut comments: Vec<_> = prev_comments.collect(); | 153 | let mut comments: Vec<_> = prev_comments.collect(); |
155 | comments.reverse(); | 154 | comments.reverse(); |
diff --git a/crates/ide_assists/src/handlers/expand_glob_import.rs b/crates/ide_assists/src/handlers/expand_glob_import.rs index 83aa11d52..98389e4f7 100644 --- a/crates/ide_assists/src/handlers/expand_glob_import.rs +++ b/crates/ide_assists/src/handlers/expand_glob_import.rs | |||
@@ -136,18 +136,13 @@ impl Refs { | |||
136 | .into_iter() | 136 | .into_iter() |
137 | .filter(|r| { | 137 | .filter(|r| { |
138 | if let Def::ModuleDef(ModuleDef::Trait(tr)) = r.def { | 138 | if let Def::ModuleDef(ModuleDef::Trait(tr)) = r.def { |
139 | if tr | 139 | if tr.items(ctx.db()).into_iter().any(|ai| { |
140 | .items(ctx.db()) | 140 | if let AssocItem::Function(f) = ai { |
141 | .into_iter() | 141 | Def::ModuleDef(ModuleDef::Function(f)).is_referenced_in(ctx) |
142 | .find(|ai| { | 142 | } else { |
143 | if let AssocItem::Function(f) = *ai { | 143 | false |
144 | Def::ModuleDef(ModuleDef::Function(f)).is_referenced_in(ctx) | 144 | } |
145 | } else { | 145 | }) { |
146 | false | ||
147 | } | ||
148 | }) | ||
149 | .is_some() | ||
150 | { | ||
151 | return true; | 146 | return true; |
152 | } | 147 | } |
153 | } | 148 | } |
diff --git a/crates/ide_assists/src/handlers/move_bounds.rs b/crates/ide_assists/src/handlers/move_bounds.rs index 9ad0c9816..b5dec8014 100644 --- a/crates/ide_assists/src/handlers/move_bounds.rs +++ b/crates/ide_assists/src/handlers/move_bounds.rs | |||
@@ -50,8 +50,8 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext | |||
50 | 50 | ||
51 | for type_param in type_param_list.type_params() { | 51 | for type_param in type_param_list.type_params() { |
52 | if let Some(tbl) = type_param.type_bound_list() { | 52 | if let Some(tbl) = type_param.type_bound_list() { |
53 | if let Some(predicate) = build_predicate(type_param.clone()) { | 53 | if let Some(predicate) = build_predicate(type_param) { |
54 | where_clause.add_predicate(predicate.clone_for_update()) | 54 | where_clause.add_predicate(predicate) |
55 | } | 55 | } |
56 | tbl.remove() | 56 | tbl.remove() |
57 | } | 57 | } |
@@ -69,7 +69,7 @@ fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> { | |||
69 | make::path_unqualified(segment) | 69 | make::path_unqualified(segment) |
70 | }; | 70 | }; |
71 | let predicate = make::where_pred(path, param.type_bound_list()?.bounds()); | 71 | let predicate = make::where_pred(path, param.type_bound_list()?.bounds()); |
72 | Some(predicate) | 72 | Some(predicate.clone_for_update()) |
73 | } | 73 | } |
74 | 74 | ||
75 | #[cfg(test)] | 75 | #[cfg(test)] |
diff --git a/crates/ide_assists/src/handlers/qualify_path.rs b/crates/ide_assists/src/handlers/qualify_path.rs index 30b23da6c..f91770a76 100644 --- a/crates/ide_assists/src/handlers/qualify_path.rs +++ b/crates/ide_assists/src/handlers/qualify_path.rs | |||
@@ -14,11 +14,10 @@ use syntax::{ | |||
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | assist_context::{AssistContext, Assists}, | 16 | assist_context::{AssistContext, Assists}, |
17 | handlers::auto_import::find_importable_node, | ||
17 | AssistId, AssistKind, GroupLabel, | 18 | AssistId, AssistKind, GroupLabel, |
18 | }; | 19 | }; |
19 | 20 | ||
20 | use super::auto_import::find_importable_node; | ||
21 | |||
22 | // Assist: qualify_path | 21 | // Assist: qualify_path |
23 | // | 22 | // |
24 | // If the name is unresolved, provides all possible qualified paths for it. | 23 | // If the name is unresolved, provides all possible qualified paths for it. |
@@ -43,22 +42,20 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
43 | return None; | 42 | return None; |
44 | } | 43 | } |
45 | 44 | ||
46 | let candidate = import_assets.import_candidate(); | ||
47 | let range = ctx.sema.original_range(&syntax_under_caret).range; | 45 | let range = ctx.sema.original_range(&syntax_under_caret).range; |
48 | 46 | let candidate = import_assets.import_candidate(); | |
49 | let qualify_candidate = match candidate { | 47 | let qualify_candidate = match candidate { |
50 | ImportCandidate::Path(candidate) => { | 48 | ImportCandidate::Path(candidate) if candidate.qualifier.is_some() => { |
51 | if candidate.qualifier.is_some() { | 49 | cov_mark::hit!(qualify_path_qualifier_start); |
52 | cov_mark::hit!(qualify_path_qualifier_start); | 50 | let path = ast::Path::cast(syntax_under_caret)?; |
53 | let path = ast::Path::cast(syntax_under_caret)?; | 51 | let (prev_segment, segment) = (path.qualifier()?.segment()?, path.segment()?); |
54 | let (prev_segment, segment) = (path.qualifier()?.segment()?, path.segment()?); | 52 | QualifyCandidate::QualifierStart(segment, prev_segment.generic_arg_list()) |
55 | QualifyCandidate::QualifierStart(segment, prev_segment.generic_arg_list()) | 53 | } |
56 | } else { | 54 | ImportCandidate::Path(_) => { |
57 | cov_mark::hit!(qualify_path_unqualified_name); | 55 | cov_mark::hit!(qualify_path_unqualified_name); |
58 | let path = ast::Path::cast(syntax_under_caret)?; | 56 | let path = ast::Path::cast(syntax_under_caret)?; |
59 | let generics = path.segment()?.generic_arg_list(); | 57 | let generics = path.segment()?.generic_arg_list(); |
60 | QualifyCandidate::UnqualifiedName(generics) | 58 | QualifyCandidate::UnqualifiedName(generics) |
61 | } | ||
62 | } | 59 | } |
63 | ImportCandidate::TraitAssocItem(_) => { | 60 | ImportCandidate::TraitAssocItem(_) => { |
64 | cov_mark::hit!(qualify_path_trait_assoc_item); | 61 | cov_mark::hit!(qualify_path_trait_assoc_item); |
@@ -119,7 +116,7 @@ impl QualifyCandidate<'_> { | |||
119 | QualifyCandidate::TraitAssocItem(qualifier, segment) => { | 116 | QualifyCandidate::TraitAssocItem(qualifier, segment) => { |
120 | replacer(format!("<{} as {}>::{}", qualifier, import, segment)); | 117 | replacer(format!("<{} as {}>::{}", qualifier, import, segment)); |
121 | } | 118 | } |
122 | &QualifyCandidate::TraitMethod(db, ref mcall_expr) => { | 119 | QualifyCandidate::TraitMethod(db, mcall_expr) => { |
123 | Self::qualify_trait_method(db, mcall_expr, replacer, import, item); | 120 | Self::qualify_trait_method(db, mcall_expr, replacer, import, item); |
124 | } | 121 | } |
125 | } | 122 | } |
@@ -201,15 +198,10 @@ fn group_label(candidate: &ImportCandidate) -> GroupLabel { | |||
201 | 198 | ||
202 | fn label(candidate: &ImportCandidate, import: &LocatedImport) -> String { | 199 | fn label(candidate: &ImportCandidate, import: &LocatedImport) -> String { |
203 | match candidate { | 200 | match candidate { |
204 | ImportCandidate::Path(candidate) => { | 201 | ImportCandidate::Path(candidate) if candidate.qualifier.is_none() => { |
205 | if candidate.qualifier.is_some() { | 202 | format!("Qualify as `{}`", import.import_path) |
206 | format!("Qualify with `{}`", import.import_path) | ||
207 | } else { | ||
208 | format!("Qualify as `{}`", import.import_path) | ||
209 | } | ||
210 | } | 203 | } |
211 | ImportCandidate::TraitAssocItem(_) => format!("Qualify `{}`", import.import_path), | 204 | _ => format!("Qualify with `{}`", import.import_path), |
212 | ImportCandidate::TraitMethod(_) => format!("Qualify with cast as `{}`", import.import_path), | ||
213 | } | 205 | } |
214 | } | 206 | } |
215 | 207 | ||
@@ -544,6 +536,38 @@ fn main() { | |||
544 | } | 536 | } |
545 | 537 | ||
546 | #[test] | 538 | #[test] |
539 | #[ignore = "FIXME: non-trait assoc items completion is unsupported yet, see FIXME in the import_assets.rs for more details"] | ||
540 | fn associated_struct_const_unqualified() { | ||
541 | check_assist( | ||
542 | qualify_path, | ||
543 | r" | ||
544 | mod test_mod { | ||
545 | pub struct TestStruct {} | ||
546 | impl TestStruct { | ||
547 | const TEST_CONST: u8 = 42; | ||
548 | } | ||
549 | } | ||
550 | |||
551 | fn main() { | ||
552 | TEST_CONST$0 | ||
553 | } | ||
554 | ", | ||
555 | r" | ||
556 | mod test_mod { | ||
557 | pub struct TestStruct {} | ||
558 | impl TestStruct { | ||
559 | const TEST_CONST: u8 = 42; | ||
560 | } | ||
561 | } | ||
562 | |||
563 | fn main() { | ||
564 | test_mod::TestStruct::TEST_CONST | ||
565 | } | ||
566 | ", | ||
567 | ); | ||
568 | } | ||
569 | |||
570 | #[test] | ||
547 | fn associated_trait_function() { | 571 | fn associated_trait_function() { |
548 | check_assist( | 572 | check_assist( |
549 | qualify_path, | 573 | qualify_path, |
diff --git a/crates/ide_assists/src/handlers/reorder_impl.rs b/crates/ide_assists/src/handlers/reorder_impl.rs index edf4b0bfe..f976e73ad 100644 --- a/crates/ide_assists/src/handlers/reorder_impl.rs +++ b/crates/ide_assists/src/handlers/reorder_impl.rs | |||
@@ -95,7 +95,7 @@ fn compute_method_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashM | |||
95 | _ => None, | 95 | _ => None, |
96 | }) | 96 | }) |
97 | .enumerate() | 97 | .enumerate() |
98 | .map(|(idx, func)| ((func.name(ctx.db()).to_string(), idx))) | 98 | .map(|(idx, func)| (func.name(ctx.db()).to_string(), idx)) |
99 | .collect(), | 99 | .collect(), |
100 | ) | 100 | ) |
101 | } | 101 | } |
diff --git a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs index 88fe2fe90..4f0ef52ca 100644 --- a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use hir::ModuleDef; | 1 | use hir::ModuleDef; |
2 | use ide_db::helpers::mod_path_to_ast; | 2 | use ide_db::helpers::{import_assets::NameToImport, mod_path_to_ast}; |
3 | use ide_db::items_locator; | 3 | use ide_db::items_locator; |
4 | use itertools::Itertools; | 4 | use itertools::Itertools; |
5 | use syntax::{ | 5 | use syntax::{ |
@@ -65,20 +65,24 @@ pub(crate) fn replace_derive_with_manual_impl( | |||
65 | let current_module = ctx.sema.scope(annotated_name.syntax()).module()?; | 65 | let current_module = ctx.sema.scope(annotated_name.syntax()).module()?; |
66 | let current_crate = current_module.krate(); | 66 | let current_crate = current_module.krate(); |
67 | 67 | ||
68 | let found_traits = | 68 | let found_traits = items_locator::items_with_name( |
69 | items_locator::with_exact_name(&ctx.sema, current_crate, trait_token.text().to_string()) | 69 | &ctx.sema, |
70 | .into_iter() | 70 | current_crate, |
71 | .filter_map(|item| match ModuleDef::from(item.as_module_def_id()?) { | 71 | NameToImport::Exact(trait_token.text().to_string()), |
72 | ModuleDef::Trait(trait_) => Some(trait_), | 72 | items_locator::AssocItemSearch::Exclude, |
73 | _ => None, | 73 | Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT), |
74 | }) | 74 | ) |
75 | .flat_map(|trait_| { | 75 | .filter_map(|item| match ModuleDef::from(item.as_module_def_id()?) { |
76 | current_module | 76 | ModuleDef::Trait(trait_) => Some(trait_), |
77 | .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_)) | 77 | _ => None, |
78 | .as_ref() | 78 | }) |
79 | .map(mod_path_to_ast) | 79 | .flat_map(|trait_| { |
80 | .zip(Some(trait_)) | 80 | current_module |
81 | }); | 81 | .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_)) |
82 | .as_ref() | ||
83 | .map(mod_path_to_ast) | ||
84 | .zip(Some(trait_)) | ||
85 | }); | ||
82 | 86 | ||
83 | let mut no_traits_found = true; | 87 | let mut no_traits_found = true; |
84 | for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) { | 88 | for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) { |