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<'_>) -> Opt
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 < ' _ > ,
@@ -289,6 +325,35 @@ fn main() {
289
325
) ;
290
326
}
291
327
328
+ #[ test]
329
+ fn test_add_method_fix ( ) {
330
+ check_fix (
331
+ r#"
332
+ struct Tiger;
333
+
334
+ impl Tiger {
335
+ fn sleep(&self) {}
336
+ }
337
+
338
+ fn main() {
339
+ let t = Tiger;
340
+ t.roar$0();
341
+ }"# ,
342
+ r#"
343
+ struct Tiger;
344
+
345
+ impl Tiger {
346
+ fn sleep(&self) {}
347
+ fn roar(&self) {}
348
+ }
349
+
350
+ fn main() {
351
+ let t = Tiger;
352
+ t.roar();
353
+ }"# ,
354
+ ) ;
355
+ }
356
+
292
357
#[ test]
293
358
fn smoke_test_in_macro_def_site ( ) {
294
359
check_diagnostics (
0 commit comments