@@ -57,27 +57,34 @@ pub(crate) fn unresolved_field(
57
57
}
58
58
59
59
fn 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)
63
69
}
64
- fixes
65
70
}
66
71
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 > {
68
74
// Get the FileRange of the invalid field access
69
75
let root = ctx. sema . db . parse_or_expand ( d. expr . file_id ) ;
70
76
let expr = d. expr . value . to_node ( & root) ;
71
77
72
78
let error_range = ctx. sema . original_range_opt ( expr. syntax ( ) ) ?;
79
+ let field_name = d. name . as_str ( ) ?;
73
80
// Convert the receiver to an ADT
74
- let adt = d. receiver . as_adt ( ) ?;
81
+ let adt = d. receiver . strip_references ( ) . as_adt ( ) ?;
75
82
let target_module = adt. module ( ctx. sema . db ) ;
76
83
77
84
let suggested_type =
78
85
if let Some ( new_field_type) = ctx. sema . type_of_expr ( & expr) . map ( |v| v. adjusted ( ) ) {
79
86
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 ( ) ;
81
88
make:: ty ( display. as_deref ( ) . unwrap_or ( "()" ) )
82
89
} else {
83
90
make:: ty ( "()" )
@@ -87,9 +94,6 @@ fn add_field_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Opti
87
94
return None ;
88
95
}
89
96
90
- // FIXME: Add Snippet Support
91
- let field_name = d. name . as_str ( ) ?;
92
-
93
97
match adt {
94
98
Adt :: Struct ( adt_struct) => {
95
99
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
100
104
_ => None ,
101
105
}
102
106
}
107
+
103
108
fn add_variant_to_union (
104
109
ctx : & DiagnosticsContext < ' _ > ,
105
110
adt_union : Union ,
106
111
field_name : & str ,
107
112
suggested_type : Type ,
108
113
error_range : FileRange ,
109
- ) -> Option < Vec < Assist > > {
114
+ ) -> Option < Assist > {
110
115
let adt_source = adt_union. source ( ctx. sema . db ) ?;
111
116
let adt_syntax = adt_source. syntax ( ) ;
112
117
let Some ( field_list) = adt_source. value . record_field_list ( ) else {
@@ -120,22 +125,23 @@ fn add_variant_to_union(
120
125
121
126
let mut src_change_builder = SourceChangeBuilder :: new ( range. file_id ) ;
122
127
src_change_builder. insert ( offset, record_field) ;
123
- Some ( vec ! [ Assist {
128
+ Some ( Assist {
124
129
id : AssistId ( "add-variant-to-union" , AssistKind :: QuickFix ) ,
125
130
label : Label :: new ( "Add field to union" . to_owned ( ) ) ,
126
131
group : None ,
127
132
target : error_range. range ,
128
133
source_change : Some ( src_change_builder. finish ( ) ) ,
129
134
trigger_signature_help : false ,
130
- } ] )
135
+ } )
131
136
}
137
+
132
138
fn add_field_to_struct_fix (
133
139
ctx : & DiagnosticsContext < ' _ > ,
134
140
adt_struct : Struct ,
135
141
field_name : & str ,
136
142
suggested_type : Type ,
137
143
error_range : FileRange ,
138
- ) -> Option < Vec < Assist > > {
144
+ ) -> Option < Assist > {
139
145
let struct_source = adt_struct. source ( ctx. sema . db ) ?;
140
146
let struct_syntax = struct_source. syntax ( ) ;
141
147
let struct_range = struct_syntax. original_file_range ( ctx. sema . db ) ;
@@ -162,14 +168,14 @@ fn add_field_to_struct_fix(
162
168
163
169
// FIXME: Allow for choosing a visibility modifier see https://github.com/rust-lang/rust-analyzer/issues/11563
164
170
src_change_builder. insert ( offset, record_field) ;
165
- Some ( vec ! [ Assist {
171
+ Some ( Assist {
166
172
id : AssistId ( "add-field-to-record-struct" , AssistKind :: QuickFix ) ,
167
173
label : Label :: new ( "Add field to Record Struct" . to_owned ( ) ) ,
168
174
group : None ,
169
175
target : error_range. range ,
170
176
source_change : Some ( src_change_builder. finish ( ) ) ,
171
177
trigger_signature_help : false ,
172
- } ] )
178
+ } )
173
179
}
174
180
None => {
175
181
// Add a field list to the Unit Struct
@@ -193,21 +199,22 @@ fn add_field_to_struct_fix(
193
199
}
194
200
src_change_builder. replace ( semi_colon. text_range ( ) , record_field_list. to_string ( ) ) ;
195
201
196
- Some ( vec ! [ Assist {
202
+ Some ( Assist {
197
203
id : AssistId ( "convert-unit-struct-to-record-struct" , AssistKind :: QuickFix ) ,
198
204
label : Label :: new ( "Convert Unit Struct to Record Struct and add field" . to_owned ( ) ) ,
199
205
group : None ,
200
206
target : error_range. range ,
201
207
source_change : Some ( src_change_builder. finish ( ) ) ,
202
208
trigger_signature_help : false ,
203
- } ] )
209
+ } )
204
210
}
205
211
Some ( FieldList :: TupleFieldList ( _tuple) ) => {
206
212
// FIXME: Add support for Tuple Structs. Tuple Structs are not sent to this diagnostic
207
213
None
208
214
}
209
215
}
210
216
}
217
+
211
218
/// Used to determine the layout of the record field in the struct.
212
219
fn record_field_layout (
213
220
visibility : Option < Visibility > ,
@@ -242,15 +249,16 @@ fn record_field_layout(
242
249
243
250
Some ( ( offset, format ! ( "{comma}{indent}{record_field}{trailing_new_line}" ) ) )
244
251
}
252
+
245
253
// FIXME: We should fill out the call here, move the cursor and trigger signature help
246
254
fn method_fix (
247
255
ctx : & DiagnosticsContext < ' _ > ,
248
256
expr_ptr : & InFile < AstPtr < ast:: Expr > > ,
249
- ) -> Option < Vec < Assist > > {
257
+ ) -> Option < Assist > {
250
258
let root = ctx. sema . db . parse_or_expand ( expr_ptr. file_id ) ;
251
259
let expr = expr_ptr. value . to_node ( & root) ;
252
260
let FileRange { range, file_id } = ctx. sema . original_range_opt ( expr. syntax ( ) ) ?;
253
- Some ( vec ! [ Assist {
261
+ Some ( Assist {
254
262
id : AssistId ( "expected-field-found-method-call-fix" , AssistKind :: QuickFix ) ,
255
263
label : Label :: new ( "Use parentheses to call the method" . to_owned ( ) ) ,
256
264
group : None ,
@@ -260,7 +268,7 @@ fn method_fix(
260
268
TextEdit :: insert ( range. end ( ) , "()" . to_owned ( ) ) ,
261
269
) ) ,
262
270
trigger_signature_help : false ,
263
- } ] )
271
+ } )
264
272
}
265
273
#[ cfg( test) ]
266
274
mod tests {
0 commit comments