diff options
Diffstat (limited to 'crates/ide_assists/src')
-rw-r--r-- | crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs | 37 |
1 files changed, 14 insertions, 23 deletions
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 f872d20c8..870a8d4ff 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 | |||
@@ -5,7 +5,6 @@ use itertools::Itertools; | |||
5 | use syntax::{ | 5 | use syntax::{ |
6 | ast::{self, make, AstNode, NameOwner}, | 6 | ast::{self, make, AstNode, NameOwner}, |
7 | SyntaxKind::{IDENT, WHITESPACE}, | 7 | SyntaxKind::{IDENT, WHITESPACE}, |
8 | TextSize, | ||
9 | }; | 8 | }; |
10 | 9 | ||
11 | use crate::{ | 10 | use crate::{ |
@@ -43,32 +42,23 @@ pub(crate) fn replace_derive_with_manual_impl( | |||
43 | ctx: &AssistContext, | 42 | ctx: &AssistContext, |
44 | ) -> Option<()> { | 43 | ) -> Option<()> { |
45 | let attr = ctx.find_node_at_offset::<ast::Attr>()?; | 44 | let attr = ctx.find_node_at_offset::<ast::Attr>()?; |
46 | 45 | let (name, args) = attr.as_simple_call()?; | |
47 | let has_derive = attr | 46 | if name != "derive" { |
48 | .syntax() | ||
49 | .descendants_with_tokens() | ||
50 | .filter(|t| t.kind() == IDENT) | ||
51 | .find_map(syntax::NodeOrToken::into_token) | ||
52 | .filter(|t| t.text() == "derive") | ||
53 | .is_some(); | ||
54 | if !has_derive { | ||
55 | return None; | 47 | return None; |
56 | } | 48 | } |
57 | 49 | ||
58 | let trait_token = ctx.token_at_offset().find(|t| t.kind() == IDENT && t.text() != "derive")?; | 50 | let trait_token = args.syntax().token_at_offset(ctx.offset()).find(|t| t.kind() == IDENT)?; |
59 | let trait_path = make::path_unqualified(make::path_segment(make::name_ref(trait_token.text()))); | 51 | let trait_name = trait_token.text(); |
60 | 52 | ||
61 | let adt = attr.syntax().parent().and_then(ast::Adt::cast)?; | 53 | let adt = attr.syntax().parent().and_then(ast::Adt::cast)?; |
62 | let annotated_name = adt.name()?; | ||
63 | let insert_pos = adt.syntax().text_range().end(); | ||
64 | 54 | ||
65 | let current_module = ctx.sema.scope(annotated_name.syntax()).module()?; | 55 | let current_module = ctx.sema.scope(adt.syntax()).module()?; |
66 | let current_crate = current_module.krate(); | 56 | let current_crate = current_module.krate(); |
67 | 57 | ||
68 | let found_traits = items_locator::items_with_name( | 58 | let found_traits = items_locator::items_with_name( |
69 | &ctx.sema, | 59 | &ctx.sema, |
70 | current_crate, | 60 | current_crate, |
71 | NameToImport::Exact(trait_token.text().to_string()), | 61 | NameToImport::Exact(trait_name.to_string()), |
72 | items_locator::AssocItemSearch::Exclude, | 62 | items_locator::AssocItemSearch::Exclude, |
73 | Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT), | 63 | Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT), |
74 | ) | 64 | ) |
@@ -86,10 +76,11 @@ pub(crate) fn replace_derive_with_manual_impl( | |||
86 | 76 | ||
87 | let mut no_traits_found = true; | 77 | let mut no_traits_found = true; |
88 | for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) { | 78 | for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) { |
89 | add_assist(acc, ctx, &attr, &trait_path, Some(trait_), &adt, &annotated_name, insert_pos)?; | 79 | add_assist(acc, ctx, &attr, &args, &trait_path, Some(trait_), &adt)?; |
90 | } | 80 | } |
91 | if no_traits_found { | 81 | if no_traits_found { |
92 | add_assist(acc, ctx, &attr, &trait_path, None, &adt, &annotated_name, insert_pos)?; | 82 | let trait_path = make::path_unqualified(make::path_segment(make::name_ref(trait_name))); |
83 | add_assist(acc, ctx, &attr, &args, &trait_path, None, &adt)?; | ||
93 | } | 84 | } |
94 | Some(()) | 85 | Some(()) |
95 | } | 86 | } |
@@ -98,15 +89,14 @@ fn add_assist( | |||
98 | acc: &mut Assists, | 89 | acc: &mut Assists, |
99 | ctx: &AssistContext, | 90 | ctx: &AssistContext, |
100 | attr: &ast::Attr, | 91 | attr: &ast::Attr, |
92 | input: &ast::TokenTree, | ||
101 | trait_path: &ast::Path, | 93 | trait_path: &ast::Path, |
102 | trait_: Option<hir::Trait>, | 94 | trait_: Option<hir::Trait>, |
103 | adt: &ast::Adt, | 95 | adt: &ast::Adt, |
104 | annotated_name: &ast::Name, | ||
105 | insert_pos: TextSize, | ||
106 | ) -> Option<()> { | 96 | ) -> Option<()> { |
107 | let target = attr.syntax().text_range(); | 97 | let target = attr.syntax().text_range(); |
108 | let input = attr.token_tree()?; | 98 | let annotated_name = adt.name()?; |
109 | let label = format!("Convert to manual `impl {} for {}`", trait_path, annotated_name); | 99 | let label = format!("Convert to manual `impl {} for {}`", trait_path, annotated_name); |
110 | let trait_name = trait_path.segment().and_then(|seg| seg.name_ref())?; | 100 | let trait_name = trait_path.segment().and_then(|seg| seg.name_ref())?; |
111 | 101 | ||
112 | acc.add( | 102 | acc.add( |
@@ -114,8 +104,9 @@ fn add_assist( | |||
114 | label, | 104 | label, |
115 | target, | 105 | target, |
116 | |builder| { | 106 | |builder| { |
107 | let insert_pos = adt.syntax().text_range().end(); | ||
117 | let impl_def_with_items = | 108 | let impl_def_with_items = |
118 | impl_def_from_trait(&ctx.sema, annotated_name, trait_, trait_path); | 109 | impl_def_from_trait(&ctx.sema, &annotated_name, trait_, trait_path); |
119 | update_attribute(builder, &input, &trait_name, &attr); | 110 | update_attribute(builder, &input, &trait_name, &attr); |
120 | let trait_path = format!("{}", trait_path); | 111 | let trait_path = format!("{}", trait_path); |
121 | match (ctx.config.snippet_cap, impl_def_with_items) { | 112 | match (ctx.config.snippet_cap, impl_def_with_items) { |