1
+ use hir:: HasSource ;
1
2
use hir:: { FileRange , HirDisplay , InFile , db:: ExpandDatabase } ;
2
3
use ide_db:: text_edit:: TextEdit ;
3
4
use ide_db:: {
@@ -11,7 +12,7 @@ use syntax::{
11
12
format_smolstr,
12
13
} ;
13
14
14
- use crate :: { Diagnostic , DiagnosticCode , DiagnosticsContext , adjusted_display_range} ;
15
+ use crate :: { Diagnostic , DiagnosticCode , DiagnosticsContext , adjusted_display_range, fix } ;
15
16
16
17
// Diagnostic: unresolved-method
17
18
//
@@ -67,9 +68,44 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -> Option<
67
68
fixes. push ( assoc_func_fix) ;
68
69
}
69
70
71
+ if let Some ( method_fix) = add_method_fix ( ctx, d) {
72
+ fixes. push ( method_fix) ;
73
+ }
74
+
70
75
if fixes. is_empty ( ) { None } else { Some ( fixes) }
71
76
}
72
77
78
+ /// Fix to add the missing method.
79
+ fn add_method_fix ( ctx : & DiagnosticsContext < ' _ > , d : & hir:: UnresolvedMethodCall ) -> Option < Assist > {
80
+ let root = ctx. sema . db . parse_or_expand ( d. expr . file_id ) ;
81
+ let expr = d. expr . value . to_node ( & root) . left ( ) ?;
82
+
83
+ let db = ctx. sema . db ;
84
+ let ty = d. receiver . clone ( ) ;
85
+
86
+ let impl_block =
87
+ hir:: Impl :: all_for_type ( db, ty) . into_iter ( ) . find ( |block| block. trait_ ( db) . is_none ( ) ) ?;
88
+ let items = impl_block. items ( db) ;
89
+ let last_item = items. last ( ) ?;
90
+ let source = last_item. source ( db) ?;
91
+ let file_id = match source. file_id {
92
+ hir:: HirFileId :: FileId ( file_id) => file_id,
93
+ hir:: HirFileId :: MacroFile ( _) => return None ,
94
+ } ;
95
+ let end_of_last_item = source. node_file_range ( ) . file_range ( ) ?. range . end ( ) ;
96
+
97
+ let text_to_insert = format ! ( "\n fn {}(&self) {{}}" , d. name. as_str( ) ) ;
98
+ Some ( fix (
99
+ "add-missing-method" ,
100
+ "Add missing method" ,
101
+ SourceChange :: from_text_edit (
102
+ file_id. file_id ( db) ,
103
+ TextEdit :: insert ( end_of_last_item, text_to_insert) ,
104
+ ) ,
105
+ ctx. sema . original_range ( expr. syntax ( ) ) . range ,
106
+ ) )
107
+ }
108
+
73
109
fn field_fix (
74
110
ctx : & DiagnosticsContext < ' _ > ,
75
111
d : & hir:: UnresolvedMethodCall ,
@@ -286,6 +322,35 @@ fn main() {
286
322
) ;
287
323
}
288
324
325
+ #[ test]
326
+ fn test_add_method_fix ( ) {
327
+ check_fix (
328
+ r#"
329
+ struct Tiger;
330
+
331
+ impl Tiger {
332
+ fn sleep(&self) {}
333
+ }
334
+
335
+ fn main() {
336
+ let t = Tiger;
337
+ t.roar$0();
338
+ }"# ,
339
+ r#"
340
+ struct Tiger;
341
+
342
+ impl Tiger {
343
+ fn sleep(&self) {}
344
+ fn roar(&self) {}
345
+ }
346
+
347
+ fn main() {
348
+ let t = Tiger;
349
+ t.roar();
350
+ }"# ,
351
+ ) ;
352
+ }
353
+
289
354
#[ test]
290
355
fn smoke_test_in_macro_def_site ( ) {
291
356
check_diagnostics (
0 commit comments