@@ -35,8 +35,8 @@ use crate::{
35
35
// struct S;
36
36
//
37
37
// impl Debug for S {
38
- // fn fmt(&self, f: &mut Formatter) -> Result<()> {
39
- // ${0:todo!()}
38
+ // $0fn fmt(&self, f: &mut Formatter) -> Result<()> {
39
+ // f.debug_struct(S)
40
40
// }
41
41
// }
42
42
// ```
@@ -114,7 +114,7 @@ fn add_assist(
114
114
|builder| {
115
115
let insert_pos = adt. syntax ( ) . text_range ( ) . end ( ) ;
116
116
let impl_def_with_items =
117
- impl_def_from_trait ( & ctx. sema , & annotated_name, trait_, trait_path) ;
117
+ impl_def_from_trait ( & ctx. sema , adt , & annotated_name, trait_, trait_path) ;
118
118
update_attribute ( builder, input, & trait_name, attr) ;
119
119
let trait_path = format ! ( "{}" , trait_path) ;
120
120
match ( ctx. config . snippet_cap , impl_def_with_items) {
@@ -155,6 +155,7 @@ fn add_assist(
155
155
156
156
fn impl_def_from_trait (
157
157
sema : & hir:: Semantics < ide_db:: RootDatabase > ,
158
+ adt : & ast:: Adt ,
158
159
annotated_name : & ast:: Name ,
159
160
trait_ : Option < hir:: Trait > ,
160
161
trait_path : & ast:: Path ,
@@ -169,25 +170,41 @@ fn impl_def_from_trait(
169
170
make:: impl_trait ( trait_path. clone ( ) , make:: ext:: ident_path ( & annotated_name. text ( ) ) ) ;
170
171
let ( impl_def, first_assoc_item) =
171
172
add_trait_assoc_items_to_impl ( sema, trait_items, trait_, impl_def, target_scope) ;
173
+
172
174
if let ast:: AssocItem :: Fn ( fn_) = & first_assoc_item {
173
175
if trait_path. segment ( ) . unwrap ( ) . name_ref ( ) . unwrap ( ) . text ( ) == "Debug" {
174
- let f_expr = make:: expr_path ( make:: ext:: ident_path ( "f" ) ) ;
175
- let args = make:: arg_list ( Some ( make:: expr_path ( make:: ext:: ident_path (
176
- annotated_name. text ( ) . as_str ( ) ,
177
- ) ) ) ) ;
178
- let body =
179
- make:: block_expr ( None , Some ( make:: expr_method_call ( f_expr, "debug_struct" , args) ) )
180
- . indent ( ast:: edit:: IndentLevel ( 1 ) ) ;
181
-
182
- ted:: replace (
183
- fn_. body ( ) . unwrap ( ) . tail_expr ( ) . unwrap ( ) . syntax ( ) ,
184
- body. clone_for_update ( ) . syntax ( ) ,
185
- ) ;
176
+ gen_debug_impl ( adt, fn_, annotated_name) ;
186
177
}
187
178
}
188
179
Some ( ( impl_def, first_assoc_item) )
189
180
}
190
181
182
+ fn gen_debug_impl ( adt : & ast:: Adt , fn_ : & ast:: Fn , annotated_name : & ast:: Name ) {
183
+ match adt {
184
+ ast:: Adt :: Union ( _) => { } // `Debug` cannot be derived for unions, so no default impl can be provided.
185
+ ast:: Adt :: Enum ( _) => { } // TODO
186
+ ast:: Adt :: Struct ( strukt) => {
187
+ match strukt. field_list ( ) {
188
+ Some ( ast:: FieldList :: RecordFieldList ( field_list) ) => {
189
+ let name = format ! ( "\" {}\" " , annotated_name) ;
190
+ let args = make:: arg_list ( Some ( make:: expr_literal ( & name) . into ( ) ) ) ;
191
+ let target = make:: expr_path ( make:: ext:: ident_path ( "f" ) ) ;
192
+ let mut expr = make:: expr_method_call ( target, "debug_struct" , args) ;
193
+ for field in field_list. fields ( ) {
194
+ let args = make:: arg_list ( Some ( make:: expr_path ( & name) . into ( ) ) ) ;
195
+ expr = make:: expr_method_call ( expr, "field" , args) ;
196
+ }
197
+ let expr = make:: expr_method_call ( expr, "finish" , make:: arg_list ( None ) ) ;
198
+ let body = make:: block_expr ( None , Some ( expr) ) . indent ( ast:: edit:: IndentLevel ( 1 ) ) ;
199
+ ted:: replace ( fn_. body ( ) . unwrap ( ) . syntax ( ) , body. clone_for_update ( ) . syntax ( ) ) ;
200
+ }
201
+ Some ( ast:: FieldList :: TupleFieldList ( field_list) ) => { }
202
+ None => { } // `Debug` cannot be implemented for an incomplete struct.
203
+ }
204
+ }
205
+ }
206
+ }
207
+
191
208
fn update_attribute (
192
209
builder : & mut AssistBuilder ,
193
210
input : & ast:: TokenTree ,
0 commit comments