aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists/src')
-rw-r--r--crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs37
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;
5use syntax::{ 5use 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
11use crate::{ 10use 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) {