@@ -57,27 +57,34 @@ pub(crate) fn unresolved_field(
5757}
5858
5959fn fixes ( ctx : & DiagnosticsContext < ' _ > , d : & hir:: UnresolvedField ) -> Option < Vec < Assist > > {
60- let mut fixes = if d. method_with_same_name_exists { method_fix ( ctx, & d. expr ) } else { None } ;
61- if let Some ( fix) = add_field_fix ( ctx, d) {
62- fixes. get_or_insert_with ( Vec :: new) . extend ( fix) ;
60+ let mut fixes = Vec :: new ( ) ;
61+ if d. method_with_same_name_exists {
62+ fixes. extend ( method_fix ( ctx, & d. expr ) ) ;
63+ }
64+ fixes. extend ( field_fix ( ctx, d) ) ;
65+ if fixes. is_empty ( ) {
66+ None
67+ } else {
68+ Some ( fixes)
6369 }
64- fixes
6570}
6671
67- fn add_field_fix ( ctx : & DiagnosticsContext < ' _ > , d : & hir:: UnresolvedField ) -> Option < Vec < Assist > > {
72+ // FIXME: Add Snippet Support
73+ fn field_fix ( ctx : & DiagnosticsContext < ' _ > , d : & hir:: UnresolvedField ) -> Option < Assist > {
6874 // Get the FileRange of the invalid field access
6975 let root = ctx. sema . db . parse_or_expand ( d. expr . file_id ) ;
7076 let expr = d. expr . value . to_node ( & root) ;
7177
7278 let error_range = ctx. sema . original_range_opt ( expr. syntax ( ) ) ?;
79+ let field_name = d. name . as_str ( ) ?;
7380 // Convert the receiver to an ADT
74- let adt = d. receiver . as_adt ( ) ?;
81+ let adt = d. receiver . strip_references ( ) . as_adt ( ) ?;
7582 let target_module = adt. module ( ctx. sema . db ) ;
7683
7784 let suggested_type =
7885 if let Some ( new_field_type) = ctx. sema . type_of_expr ( & expr) . map ( |v| v. adjusted ( ) ) {
7986 let display =
80- new_field_type. display_source_code ( ctx. sema . db , target_module. into ( ) , true ) . ok ( ) ;
87+ new_field_type. display_source_code ( ctx. sema . db , target_module. into ( ) , false ) . ok ( ) ;
8188 make:: ty ( display. as_deref ( ) . unwrap_or ( "()" ) )
8289 } else {
8390 make:: ty ( "()" )
@@ -87,9 +94,6 @@ fn add_field_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Opti
8794 return None ;
8895 }
8996
90- // FIXME: Add Snippet Support
91- let field_name = d. name . as_str ( ) ?;
92-
9397 match adt {
9498 Adt :: Struct ( adt_struct) => {
9599 add_field_to_struct_fix ( ctx, adt_struct, field_name, suggested_type, error_range)
@@ -100,13 +104,14 @@ fn add_field_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Opti
100104 _ => None ,
101105 }
102106}
107+
103108fn add_variant_to_union (
104109 ctx : & DiagnosticsContext < ' _ > ,
105110 adt_union : Union ,
106111 field_name : & str ,
107112 suggested_type : Type ,
108113 error_range : FileRange ,
109- ) -> Option < Vec < Assist > > {
114+ ) -> Option < Assist > {
110115 let adt_source = adt_union. source ( ctx. sema . db ) ?;
111116 let adt_syntax = adt_source. syntax ( ) ;
112117 let Some ( field_list) = adt_source. value . record_field_list ( ) else {
@@ -120,22 +125,23 @@ fn add_variant_to_union(
120125
121126 let mut src_change_builder = SourceChangeBuilder :: new ( range. file_id ) ;
122127 src_change_builder. insert ( offset, record_field) ;
123- Some ( vec ! [ Assist {
128+ Some ( Assist {
124129 id : AssistId ( "add-variant-to-union" , AssistKind :: QuickFix ) ,
125130 label : Label :: new ( "Add field to union" . to_owned ( ) ) ,
126131 group : None ,
127132 target : error_range. range ,
128133 source_change : Some ( src_change_builder. finish ( ) ) ,
129134 trigger_signature_help : false ,
130- } ] )
135+ } )
131136}
137+
132138fn add_field_to_struct_fix (
133139 ctx : & DiagnosticsContext < ' _ > ,
134140 adt_struct : Struct ,
135141 field_name : & str ,
136142 suggested_type : Type ,
137143 error_range : FileRange ,
138- ) -> Option < Vec < Assist > > {
144+ ) -> Option < Assist > {
139145 let struct_source = adt_struct. source ( ctx. sema . db ) ?;
140146 let struct_syntax = struct_source. syntax ( ) ;
141147 let struct_range = struct_syntax. original_file_range ( ctx. sema . db ) ;
@@ -162,14 +168,14 @@ fn add_field_to_struct_fix(
162168
163169 // FIXME: Allow for choosing a visibility modifier see https://github.com/rust-lang/rust-analyzer/issues/11563
164170 src_change_builder. insert ( offset, record_field) ;
165- Some ( vec ! [ Assist {
171+ Some ( Assist {
166172 id : AssistId ( "add-field-to-record-struct" , AssistKind :: QuickFix ) ,
167173 label : Label :: new ( "Add field to Record Struct" . to_owned ( ) ) ,
168174 group : None ,
169175 target : error_range. range ,
170176 source_change : Some ( src_change_builder. finish ( ) ) ,
171177 trigger_signature_help : false ,
172- } ] )
178+ } )
173179 }
174180 None => {
175181 // Add a field list to the Unit Struct
@@ -193,21 +199,22 @@ fn add_field_to_struct_fix(
193199 }
194200 src_change_builder. replace ( semi_colon. text_range ( ) , record_field_list. to_string ( ) ) ;
195201
196- Some ( vec ! [ Assist {
202+ Some ( Assist {
197203 id : AssistId ( "convert-unit-struct-to-record-struct" , AssistKind :: QuickFix ) ,
198204 label : Label :: new ( "Convert Unit Struct to Record Struct and add field" . to_owned ( ) ) ,
199205 group : None ,
200206 target : error_range. range ,
201207 source_change : Some ( src_change_builder. finish ( ) ) ,
202208 trigger_signature_help : false ,
203- } ] )
209+ } )
204210 }
205211 Some ( FieldList :: TupleFieldList ( _tuple) ) => {
206212 // FIXME: Add support for Tuple Structs. Tuple Structs are not sent to this diagnostic
207213 None
208214 }
209215 }
210216}
217+
211218/// Used to determine the layout of the record field in the struct.
212219fn record_field_layout (
213220 visibility : Option < Visibility > ,
@@ -242,15 +249,16 @@ fn record_field_layout(
242249
243250 Some ( ( offset, format ! ( "{comma}{indent}{record_field}{trailing_new_line}" ) ) )
244251}
252+
245253// FIXME: We should fill out the call here, move the cursor and trigger signature help
246254fn method_fix (
247255 ctx : & DiagnosticsContext < ' _ > ,
248256 expr_ptr : & InFile < AstPtr < ast:: Expr > > ,
249- ) -> Option < Vec < Assist > > {
257+ ) -> Option < Assist > {
250258 let root = ctx. sema . db . parse_or_expand ( expr_ptr. file_id ) ;
251259 let expr = expr_ptr. value . to_node ( & root) ;
252260 let FileRange { range, file_id } = ctx. sema . original_range_opt ( expr. syntax ( ) ) ?;
253- Some ( vec ! [ Assist {
261+ Some ( Assist {
254262 id : AssistId ( "expected-field-found-method-call-fix" , AssistKind :: QuickFix ) ,
255263 label : Label :: new ( "Use parentheses to call the method" . to_owned ( ) ) ,
256264 group : None ,
@@ -260,7 +268,7 @@ fn method_fix(
260268 TextEdit :: insert ( range. end ( ) , "()" . to_owned ( ) ) ,
261269 ) ) ,
262270 trigger_signature_help : false ,
263- } ] )
271+ } )
264272}
265273#[ cfg( test) ]
266274mod tests {
0 commit comments