1
1
use hir:: { self , HasCrate , HasSource , HirDisplay } ;
2
- use syntax:: ast:: { self , make, AstNode , HasName , HasVisibility } ;
2
+ use syntax:: ast:: { self , make, AstNode , HasGenericParams , HasName , HasVisibility } ;
3
3
4
4
use crate :: {
5
5
utils:: { find_struct_impl, render_snippet, Cursor } ,
6
6
AssistContext , AssistId , AssistKind , Assists , GroupLabel ,
7
7
} ;
8
8
use syntax:: ast:: edit:: AstNodeEdit ;
9
9
10
- // Assist: generate_setter
10
+ // Assist: generate_delegate
11
11
//
12
- // Generate a setter method.
12
+ // Generate a delegate method.
13
13
//
14
14
// ```
15
+ // struct Age(u8);
16
+ // impl Age {
17
+ // fn age(&self) -> u8 {
18
+ // self.0
19
+ // }
20
+ // }
21
+ //
15
22
// struct Person {
16
- // nam $0e: String ,
23
+ // ag $0e: Age ,
17
24
// }
18
25
// ```
19
26
// ->
20
27
// ```
28
+ // struct Age(u8);
29
+ // impl Age {
30
+ // fn age(&self) -> u8 {
31
+ // self.0
32
+ // }
33
+ // }
34
+ //
21
35
// struct Person {
22
- // name: String ,
36
+ // age: Age ,
23
37
// }
24
38
//
25
39
// impl Person {
26
- // /// Set the person's name.
27
- // fn set_name(&mut self, name: String) {
28
- // self.name = name;
40
+ // $0fn age(&self) -> u8 {
41
+ // self.age.age()
29
42
// }
30
43
// }
31
44
// ```
32
45
pub ( crate ) fn generate_delegate ( acc : & mut Assists , ctx : & AssistContext ) -> Option < ( ) > {
46
+ let cap = ctx. config . snippet_cap ?;
47
+
33
48
let strukt = ctx. find_node_at_offset :: < ast:: Struct > ( ) ?;
34
49
let strukt_name = strukt. name ( ) ?;
35
50
@@ -62,37 +77,39 @@ pub(crate) fn generate_delegate(acc: &mut Assists, ctx: &AssistContext) -> Optio
62
77
format ! ( "Generate a delegate method for '{}'" , method. name( ctx. db( ) ) ) ,
63
78
target,
64
79
|builder| {
65
- // make function
80
+ // Create the function
66
81
let method_source = match method. source ( ctx. db ( ) ) {
67
82
Some ( source) => source. value ,
68
83
None => return ,
69
84
} ;
70
85
let method_name = method. name ( ctx. db ( ) ) ;
71
86
let vis = method_source. visibility ( ) ;
72
87
let name = make:: name ( & method. name ( ctx. db ( ) ) . to_string ( ) ) ;
73
- let type_params = None ;
74
- let self_ty = method
75
- . self_param ( ctx. db ( ) )
76
- . map ( |s| s. source ( ctx. db ( ) ) . map ( |s| s. value ) )
77
- . flatten ( ) ;
78
- let params = make:: param_list ( self_ty, [ ] ) ;
88
+ let params =
89
+ method_source. param_list ( ) . unwrap_or_else ( || make:: param_list ( None , [ ] ) ) ;
79
90
let tail_expr = make:: expr_method_call (
80
- field_from_idents ( [ "self" , & field_name. to_string ( ) ] ) . unwrap ( ) ,
91
+ make :: ext :: field_from_idents ( [ "self" , & field_name. to_string ( ) ] ) . unwrap ( ) , // This unwrap is ok because we have at least 1 arg in the list
81
92
make:: name_ref ( & method_name. to_string ( ) ) ,
82
93
make:: arg_list ( [ ] ) ,
83
94
) ;
95
+ let type_params = method_source. generic_param_list ( ) ;
84
96
let body = make:: block_expr ( [ ] , Some ( tail_expr) ) ;
85
- let ret_type = & method. ret_type ( ctx. db ( ) ) . display ( ctx. db ( ) ) . to_string ( ) ;
86
- let ret_type = Some ( make:: ret_type ( make:: ty ( ret_type) ) ) ;
87
- let is_async = false ;
97
+ let ret_type = method. ret_type ( ctx. db ( ) ) ;
98
+ let ret_type = if ret_type. is_unknown ( ) {
99
+ Some ( make:: ret_type ( make:: ty_placeholder ( ) ) )
100
+ } else {
101
+ let ret_type = & ret_type. display ( ctx. db ( ) ) . to_string ( ) ;
102
+ Some ( make:: ret_type ( make:: ty ( ret_type) ) )
103
+ } ;
104
+ let is_async = method_source. async_token ( ) . is_some ( ) ;
88
105
let f = make:: fn_ ( vis, name, type_params, params, body, ret_type, is_async)
89
106
. indent ( ast:: edit:: IndentLevel ( 1 ) )
90
107
. clone_for_update ( ) ;
91
108
92
109
let cursor = Cursor :: Before ( f. syntax ( ) ) ;
93
- let cap = ctx. config . snippet_cap . unwrap ( ) ; // FIXME.
94
110
95
- // Create or update an impl block, and attach the function to it.
111
+ // Create or update an impl block, attach the function to it,
112
+ // then insert into our code.
96
113
match impl_def {
97
114
Some ( impl_def) => {
98
115
// Remember where in our source our `impl` block lives.
@@ -110,7 +127,10 @@ pub(crate) fn generate_delegate(acc: &mut Assists, ctx: &AssistContext) -> Optio
110
127
None => {
111
128
// Attach the function to the impl block
112
129
let name = & strukt_name. to_string ( ) ;
113
- let impl_def = make:: impl_ ( make:: ext:: ident_path ( name) ) . clone_for_update ( ) ;
130
+ let params = strukt. generic_param_list ( ) ;
131
+ let ty_params = params. clone ( ) ;
132
+ let impl_def = make:: impl_ ( make:: ext:: ident_path ( name) , params, ty_params)
133
+ . clone_for_update ( ) ;
114
134
let assoc_items = impl_def. get_or_create_assoc_item_list ( ) ;
115
135
assoc_items. add_item ( f. clone ( ) . into ( ) ) ;
116
136
@@ -127,15 +147,6 @@ pub(crate) fn generate_delegate(acc: &mut Assists, ctx: &AssistContext) -> Optio
127
147
Some ( ( ) )
128
148
}
129
149
130
- pub fn field_from_idents < ' a > (
131
- parts : impl std:: iter:: IntoIterator < Item = & ' a str > ,
132
- ) -> Option < ast:: Expr > {
133
- let mut iter = parts. into_iter ( ) ;
134
- let base = make:: expr_path ( make:: ext:: ident_path ( iter. next ( ) ?) ) ;
135
- let expr = iter. fold ( base, |base, s| make:: expr_field ( base, s) ) ;
136
- Some ( expr)
137
- }
138
-
139
150
#[ cfg( test) ]
140
151
mod tests {
141
152
use crate :: tests:: check_assist;
@@ -213,6 +224,36 @@ impl Person {
213
224
}"# ,
214
225
) ;
215
226
}
227
+
228
+ #[ test]
229
+ fn test_generate_delegate_enable_all_attributes ( ) {
230
+ check_assist (
231
+ generate_delegate,
232
+ r#"
233
+ struct Age<T>(T);
234
+ impl<T> Age<T> {
235
+ pub(crate) async fn age<J, 'a>(&'a mut self, ty: T, arg: J) -> T {
236
+ self.0
237
+ }
238
+ }
239
+
240
+ struct Person<T> {
241
+ ag$0e: Age<T>,
242
+ }"# ,
243
+ r#"
244
+ struct Age<T>(T);
245
+ impl<T> Age<T> {
246
+ pub(crate) async fn age<J, 'a>(&'a mut self, ty: T, arg: J) -> T {
247
+ self.0
248
+ }
249
+ }
250
+
251
+ struct Person<T> {
252
+ age: Age<T>,
253
+ }
254
+
255
+ impl<T> Person<T> {
256
+ $0pub(crate) async fn age<J, 'a>(&'a mut self, ty: T, arg: J) -> _ {
216
257
self.age.age()
217
258
}
218
259
}"# ,
0 commit comments