Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-diagnostics/src/handlers/missing_fields.rs')
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_fields.rs59
1 files changed, 39 insertions, 20 deletions
diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs
index 85368cc09f..607f0cbd23 100644
--- a/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -18,6 +18,7 @@ use stdx::format_to;
use syntax::{
AstNode, Edition, SyntaxNode, SyntaxNodePtr, ToSmolStr,
ast::{self, make},
+ syntax_editor::SyntaxEditor,
};
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, fix};
@@ -33,7 +34,10 @@ use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, fix};
//
// let a = A { a: 10 };
// ```
-pub(crate) fn missing_fields(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Diagnostic {
+pub(crate) fn missing_fields(
+ ctx: &DiagnosticsContext<'_, '_>,
+ d: &hir::MissingFields,
+) -> Diagnostic {
let mut message = String::from("missing structure fields:\n");
for (field, _) in &d.missed_fields {
format_to!(message, "- {}\n", field.display(ctx.sema.db, ctx.edition));
@@ -51,7 +55,7 @@ pub(crate) fn missing_fields(ctx: &DiagnosticsContext<'_>, d: &hir::MissingField
.with_fixes(fixes(ctx, d))
}
-fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Assist>> {
+fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::MissingFields) -> Option<Vec<Assist>> {
// Note that although we could add a diagnostics to
// fill the missing tuple field, e.g :
// `struct A(usize);`
@@ -112,16 +116,20 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
}
});
+ let old_field_list = field_list_parent.record_expr_field_list()?;
+ let root = old_field_list.syntax().ancestors().last()?;
+ let (editor, _) = SyntaxEditor::new(root);
+ let make = editor.make();
+
let generate_fill_expr = |ty: &Type<'_>| match ctx.config.expr_fill_default {
- ExprFillDefaultMode::Todo => make::ext::expr_todo(),
- ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
+ ExprFillDefaultMode::Todo => make.expr_todo(),
+ ExprFillDefaultMode::Underscore => make.expr_underscore().into(),
ExprFillDefaultMode::Default => {
- get_default_constructor(ctx, d, ty).unwrap_or_else(make::ext::expr_todo)
+ get_default_constructor(ctx, d, ty).unwrap_or_else(|| make.expr_todo())
}
};
- let old_field_list = field_list_parent.record_expr_field_list()?;
- let new_field_list = old_field_list.clone_for_update();
+ let mut new_fields = Vec::new();
for (f, ty) in missing_fields.iter() {
let field_expr = if let Some(local_candidate) = locals.get(&f.name(ctx.sema.db)) {
cov_mark::hit!(field_shorthand);
@@ -156,31 +164,39 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
if expr.is_some() { expr } else { Some(generate_fill_expr(ty)) }
};
- let field = make::record_expr_field(
- make::name_ref(&f.name(ctx.sema.db).display_no_db(ctx.edition).to_smolstr()),
+ let field = make.record_expr_field(
+ make.name_ref(&f.name(ctx.sema.db).display_no_db(ctx.edition).to_smolstr()),
field_expr,
);
- new_field_list.add_field(field.clone_for_update());
+ new_fields.push(field);
}
- build_text_edit(new_field_list.syntax(), old_field_list.syntax())
+ old_field_list.add_fields(&editor, new_fields);
+ let new_field_list = editor.finish().find_element(old_field_list.syntax())?;
+ build_text_edit(&new_field_list, old_field_list.syntax())
}
Either::Right(field_list_parent) => {
let missing_fields = ctx.sema.record_pattern_missing_fields(field_list_parent);
let old_field_list = field_list_parent.record_pat_field_list()?;
- let new_field_list = old_field_list.clone_for_update();
+ let root = old_field_list.syntax().ancestors().last()?;
+ let (editor, _) = SyntaxEditor::new(root);
+ let make = editor.make();
+
+ let mut new_fields = Vec::new();
for (f, _) in missing_fields.iter() {
- let field = make::record_pat_field_shorthand(
- make::ident_pat(
+ let field = make.record_pat_field_shorthand(
+ make.ident_pat(
false,
false,
- make::name(&f.name(ctx.sema.db).display_no_db(ctx.edition).to_smolstr()),
+ make.name(&f.name(ctx.sema.db).display_no_db(ctx.edition).to_smolstr()),
)
.into(),
);
- new_field_list.add_field(field.clone_for_update());
+ new_fields.push(field);
}
- build_text_edit(new_field_list.syntax(), old_field_list.syntax())
+ old_field_list.add_fields(&editor, new_fields);
+ let new_field_list = editor.finish().find_element(old_field_list.syntax())?;
+ build_text_edit(&new_field_list, old_field_list.syntax())
}
}
}
@@ -202,7 +218,7 @@ fn make_ty(
}
fn get_default_constructor(
- ctx: &DiagnosticsContext<'_>,
+ ctx: &DiagnosticsContext<'_, '_>,
d: &hir::MissingFields,
ty: &Type<'_>,
) -> Option<ast::Expr> {
@@ -293,12 +309,15 @@ fn baz(s: S) -> i32 {
#[test]
fn missing_record_pat_field_box() {
check_diagnostics(
- r"
+ r#"
+#![feature(lang_items)]
+#[lang = "owned_box"]
+struct Box<T>(T);
struct S { s: Box<u32> }
fn x(a: S) {
let S { box s } = a;
}
-",
+"#,
)
}