@@ -129,9 +129,6 @@ fn add_assist(
129
129
let mut cursor = Cursor :: Before ( first_assoc_item. syntax ( ) ) ;
130
130
let placeholder;
131
131
if let ast:: AssocItem :: Fn ( ref func) = first_assoc_item {
132
- // need to know what kind of derive this is: if it's Derive Debug, special case it.
133
- // the name of the struct
134
- // list of fields of the struct
135
132
if let Some ( m) = func. syntax ( ) . descendants ( ) . find_map ( ast:: MacroCall :: cast)
136
133
{
137
134
if m. syntax ( ) . text ( ) == "todo!()" {
@@ -170,10 +167,12 @@ fn impl_def_from_trait(
170
167
let ( impl_def, first_assoc_item) =
171
168
add_trait_assoc_items_to_impl ( sema, trait_items, trait_, impl_def, target_scope) ;
172
169
170
+ // Generate a default `impl` function body for the derived trait.
173
171
if let ast:: AssocItem :: Fn ( func) = & first_assoc_item {
174
- if trait_path. segment ( ) . unwrap ( ) . name_ref ( ) . unwrap ( ) . text ( ) == "Debug" {
175
- gen_debug_impl ( adt, func, annotated_name) ;
176
- }
172
+ match trait_path. segment ( ) . unwrap ( ) . name_ref ( ) . unwrap ( ) . text ( ) . as_str ( ) {
173
+ "Debug" => gen_debug_impl ( adt, func, annotated_name) ,
174
+ _ => { } // => If we don't know about the trait, the function body is left as `todo!`.
175
+ } ;
177
176
}
178
177
Some ( ( impl_def, first_assoc_item) )
179
178
}
@@ -183,31 +182,31 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn, annotated_name: &ast::Name) {
183
182
match adt {
184
183
ast:: Adt :: Union ( _) => { } // `Debug` cannot be derived for unions, so no default impl can be provided.
185
184
ast:: Adt :: Enum ( enum_) => {
185
+ // => match self { Self::Variant => write!(f, "Variant") }
186
186
if let Some ( list) = enum_. variant_list ( ) {
187
187
let mut arms = vec ! [ ] ;
188
188
for variant in list. variants ( ) {
189
- // => Self::<Variant>
190
189
let name = variant. name ( ) . unwrap ( ) ;
191
- let first = make:: ext:: ident_path ( "Self" ) ;
192
- let second = make:: ext:: ident_path ( & format ! ( "{}" , name) ) ;
193
- let pat = make:: path_pat ( make:: path_concat ( first, second) ) ;
194
190
195
- // => write!(f, "<Variant>")
191
+ let left = make:: ext:: ident_path ( "Self" ) ;
192
+ let right = make:: ext:: ident_path ( & format ! ( "{}" , name) ) ;
193
+ let variant_name = make:: path_pat ( make:: path_concat ( left, right) ) ;
194
+
196
195
let target = make:: expr_path ( make:: ext:: ident_path ( "f" ) . into ( ) ) ;
197
196
let fmt_string = make:: expr_literal ( & ( format ! ( "\" {}\" " , name) ) ) . into ( ) ;
198
197
let args = make:: arg_list ( vec ! [ target, fmt_string] ) ;
199
- let target = make:: expr_path ( make:: ext:: ident_path ( "write" ) ) ;
200
- let expr = make:: expr_macro_call ( target , args) ;
198
+ let macro_name = make:: expr_path ( make:: ext:: ident_path ( "write" ) ) ;
199
+ let macro_call = make:: expr_macro_call ( macro_name , args) ;
201
200
202
- arms. push ( make:: match_arm ( Some ( pat . into ( ) ) , None , expr . into ( ) ) ) ;
201
+ arms. push ( make:: match_arm ( Some ( variant_name . into ( ) ) , None , macro_call . into ( ) ) ) ;
203
202
}
204
203
205
- // => match self { ... }
206
- let f_path = make:: expr_path ( make:: ext:: ident_path ( "self" ) ) ;
204
+ let match_target = make:: expr_path ( make:: ext:: ident_path ( "self" ) ) ;
207
205
let list = make:: match_arm_list ( arms) . indent ( ast:: edit:: IndentLevel ( 1 ) ) ;
208
- let expr = make:: expr_match ( f_path , list) ;
206
+ let match_expr = make:: expr_match ( match_target , list) ;
209
207
210
- let body = make:: block_expr ( None , Some ( expr) ) . indent ( ast:: edit:: IndentLevel ( 1 ) ) ;
208
+ let body = make:: block_expr ( None , Some ( match_expr) ) ;
209
+ let body = body. indent ( ast:: edit:: IndentLevel ( 1 ) ) ;
211
210
ted:: replace ( func. body ( ) . unwrap ( ) . syntax ( ) , body. clone_for_update ( ) . syntax ( ) ) ;
212
211
}
213
212
}
@@ -217,8 +216,12 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn, annotated_name: &ast::Name) {
217
216
let target = make:: expr_path ( make:: ext:: ident_path ( "f" ) ) ;
218
217
219
218
let expr = match strukt. field_list ( ) {
220
- None => make:: expr_method_call ( target, "debug_struct" , args) ,
219
+ None => {
220
+ // => f.debug_struct("Name").finish()
221
+ make:: expr_method_call ( target, "debug_struct" , args)
222
+ }
221
223
Some ( ast:: FieldList :: RecordFieldList ( field_list) ) => {
224
+ // => f.debug_struct("Name").field("foo", &self.foo).finish()
222
225
let mut expr = make:: expr_method_call ( target, "debug_struct" , args) ;
223
226
for field in field_list. fields ( ) {
224
227
if let Some ( name) = field. name ( ) {
@@ -233,6 +236,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn, annotated_name: &ast::Name) {
233
236
expr
234
237
}
235
238
Some ( ast:: FieldList :: TupleFieldList ( field_list) ) => {
239
+ // => f.debug_tuple("Name").field(self.0).finish()
236
240
let mut expr = make:: expr_method_call ( target, "debug_tuple" , args) ;
237
241
for ( idx, _) in field_list. fields ( ) . enumerate ( ) {
238
242
let f_path = make:: expr_path ( make:: ext:: ident_path ( "self" ) ) ;
0 commit comments