@@ -5,7 +5,6 @@ use itertools::Itertools;
55use syntax:: {
66 ast:: { self , make, AstNode , NameOwner } ,
77 SyntaxKind :: { IDENT , WHITESPACE } ,
8- TextSize ,
98} ;
109
1110use crate :: {
@@ -43,32 +42,23 @@ pub(crate) fn replace_derive_with_manual_impl(
4342 ctx : & AssistContext ,
4443) -> Option < ( ) > {
4544 let attr = ctx. find_node_at_offset :: < ast:: Attr > ( ) ?;
46-
47- let has_derive = attr
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 {
45+ let ( name, args) = attr. as_simple_call ( ) ?;
46+ if name != "derive" {
5547 return None ;
5648 }
5749
58- let trait_token = ctx . token_at_offset ( ) . find ( |t| t. kind ( ) == IDENT && t . text ( ) != "derive" ) ?;
59- let trait_path = make :: path_unqualified ( make :: path_segment ( make :: name_ref ( trait_token. text ( ) ) ) ) ;
50+ let trait_token = args . syntax ( ) . token_at_offset ( ctx . offset ( ) ) . find ( |t| t. kind ( ) == IDENT ) ?;
51+ let trait_name = trait_token. text ( ) ;
6052
6153 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 ( ) ;
6454
65- let current_module = ctx. sema . scope ( annotated_name . syntax ( ) ) . module ( ) ?;
55+ let current_module = ctx. sema . scope ( adt . syntax ( ) ) . module ( ) ?;
6656 let current_crate = current_module. krate ( ) ;
6757
6858 let found_traits = items_locator:: items_with_name (
6959 & ctx. sema ,
7060 current_crate,
71- NameToImport :: Exact ( trait_token . text ( ) . to_string ( ) ) ,
61+ NameToImport :: Exact ( trait_name . to_string ( ) ) ,
7262 items_locator:: AssocItemSearch :: Exclude ,
7363 Some ( items_locator:: DEFAULT_QUERY_SEARCH_LIMIT ) ,
7464 )
@@ -86,10 +76,11 @@ pub(crate) fn replace_derive_with_manual_impl(
8676
8777 let mut no_traits_found = true ;
8878 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) ?;
9080 }
9181 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) ?;
9384 }
9485 Some ( ( ) )
9586}
@@ -98,24 +89,24 @@ fn add_assist(
9889 acc : & mut Assists ,
9990 ctx : & AssistContext ,
10091 attr : & ast:: Attr ,
92+ input : & ast:: TokenTree ,
10193 trait_path : & ast:: Path ,
10294 trait_ : Option < hir:: Trait > ,
10395 adt : & ast:: Adt ,
104- annotated_name : & ast:: Name ,
105- insert_pos : TextSize ,
10696) -> Option < ( ) > {
10797 let target = attr. syntax ( ) . text_range ( ) ;
108- let input = attr . token_tree ( ) ?;
109- let label = format ! ( "Convert to manual `impl {} for {}`" , trait_path, annotated_name) ;
98+ let annotated_name = adt . name ( ) ?;
99+ let label = format ! ( "Convert to manual `impl {} for {}`" , trait_path, annotated_name) ;
110100 let trait_name = trait_path. segment ( ) . and_then ( |seg| seg. name_ref ( ) ) ?;
111101
112102 acc. add (
113103 AssistId ( "replace_derive_with_manual_impl" , AssistKind :: Refactor ) ,
114104 label,
115105 target,
116106 |builder| {
107+ let insert_pos = adt. syntax ( ) . text_range ( ) . end ( ) ;
117108 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) ;
119110 update_attribute ( builder, & input, & trait_name, & attr) ;
120111 let trait_path = format ! ( "{}" , trait_path) ;
121112 match ( ctx. config . snippet_cap , impl_def_with_items) {
0 commit comments