Skip to content

Commit 6e541ae

Browse files
committed
Add a fix that inserts a missing method
1 parent 9fc1b90 commit 6e541ae

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed

crates/hir/src/has_source.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use syntax::ast;
1212
use tt::TextRange;
1313

1414
use crate::{
15-
Adt, Callee, Const, Enum, ExternCrateDecl, Field, FieldSource, Function, Impl,
15+
Adt, AssocItem, Callee, Const, Enum, ExternCrateDecl, Field, FieldSource, Function, Impl,
1616
InlineAsmOperand, Label, LifetimeParam, LocalSource, Macro, Module, Param, SelfParam, Static,
1717
Struct, Trait, TraitAlias, TypeAlias, TypeOrConstParam, Union, Variant, VariantDef,
1818
db::HirDatabase,
@@ -100,6 +100,17 @@ impl HasSource for Field {
100100
Some(field_source)
101101
}
102102
}
103+
impl HasSource for AssocItem {
104+
type Ast = ast::AssocItem;
105+
106+
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
107+
match self {
108+
AssocItem::Const(c) => Some(c.source(db)?.map(ast::AssocItem::Const)),
109+
AssocItem::Function(f) => Some(f.source(db)?.map(ast::AssocItem::Fn)),
110+
AssocItem::TypeAlias(t) => Some(t.source(db)?.map(ast::AssocItem::TypeAlias)),
111+
}
112+
}
113+
}
103114
impl HasSource for Adt {
104115
type Ast = ast::Adt;
105116
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {

crates/ide-diagnostics/src/handlers/unresolved_method.rs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use hir::HasSource;
12
use hir::{FileRange, HirDisplay, InFile, db::ExpandDatabase};
23
use ide_db::text_edit::TextEdit;
34
use ide_db::{
@@ -11,7 +12,7 @@ use syntax::{
1112
format_smolstr,
1213
};
1314

14-
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, adjusted_display_range};
15+
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, adjusted_display_range, fix};
1516

1617
// Diagnostic: unresolved-method
1718
//
@@ -67,9 +68,44 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -> Option<
6768
fixes.push(assoc_func_fix);
6869
}
6970

71+
if let Some(method_fix) = add_method_fix(ctx, d) {
72+
fixes.push(method_fix);
73+
}
74+
7075
if fixes.is_empty() { None } else { Some(fixes) }
7176
}
7277

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+
73109
fn field_fix(
74110
ctx: &DiagnosticsContext<'_>,
75111
d: &hir::UnresolvedMethodCall,
@@ -286,6 +322,35 @@ fn main() {
286322
);
287323
}
288324

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+
289354
#[test]
290355
fn smoke_test_in_macro_def_site() {
291356
check_diagnostics(

0 commit comments

Comments
 (0)