mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 22:54:58 +00:00
Refactor the diagnostics
This commit is contained in:
parent
cfbbd91a88
commit
9963f43d51
6 changed files with 106 additions and 136 deletions
|
@ -7,7 +7,7 @@
|
|||
use std::cell::RefCell;
|
||||
|
||||
use hir::{
|
||||
diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSinkBuilder},
|
||||
diagnostics::{Diagnostic as _, DiagnosticSinkBuilder},
|
||||
HasSource, HirDisplay, Semantics, VariantDef,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
|
@ -63,10 +63,10 @@ pub(crate) fn diagnostics(
|
|||
.into(),
|
||||
);
|
||||
res.borrow_mut().push(Diagnostic {
|
||||
range: sema.diagnostics_range(d).range,
|
||||
range: sema.diagnostics_presentation_range(d).range,
|
||||
message: d.message(),
|
||||
severity: Severity::Error,
|
||||
fix: Some((fix, sema.diagnostics_fix_range(d).range)),
|
||||
fix: Some((fix, sema.diagnostic_fix_source(d).syntax().text_range())),
|
||||
})
|
||||
})
|
||||
.on::<hir::diagnostics::MissingFields, _>(|d| {
|
||||
|
@ -78,56 +78,58 @@ pub(crate) fn diagnostics(
|
|||
let fix = if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
|
||||
None
|
||||
} else {
|
||||
let mut field_list = d.ast(db);
|
||||
for f in d.missed_fields.iter() {
|
||||
let field = make::record_expr_field(
|
||||
make::name_ref(&f.to_string()),
|
||||
Some(make::expr_unit()),
|
||||
);
|
||||
field_list = field_list.append_field(&field);
|
||||
}
|
||||
let record_expr = sema.diagnostic_fix_source(d);
|
||||
if let Some(old_field_list) = record_expr.record_expr_field_list() {
|
||||
let mut new_field_list = old_field_list.clone();
|
||||
for f in d.missed_fields.iter() {
|
||||
let field = make::record_expr_field(
|
||||
make::name_ref(&f.to_string()),
|
||||
Some(make::expr_unit()),
|
||||
);
|
||||
new_field_list = new_field_list.append_field(&field);
|
||||
}
|
||||
|
||||
let edit = {
|
||||
let mut builder = TextEditBuilder::default();
|
||||
algo::diff(&d.ast(db).syntax(), &field_list.syntax())
|
||||
.into_text_edit(&mut builder);
|
||||
builder.finish()
|
||||
};
|
||||
Some((
|
||||
Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into()),
|
||||
sema.diagnostics_fix_range(d).range,
|
||||
))
|
||||
let edit = {
|
||||
let mut builder = TextEditBuilder::default();
|
||||
algo::diff(&old_field_list.syntax(), &new_field_list.syntax())
|
||||
.into_text_edit(&mut builder);
|
||||
builder.finish()
|
||||
};
|
||||
Some((
|
||||
Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into()),
|
||||
sema.original_range(&old_field_list.syntax()).range,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
res.borrow_mut().push(Diagnostic {
|
||||
range: sema.diagnostics_range(d).range,
|
||||
range: sema.diagnostics_presentation_range(d).range,
|
||||
message: d.message(),
|
||||
severity: Severity::Error,
|
||||
fix,
|
||||
})
|
||||
})
|
||||
.on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| {
|
||||
let node = d.ast(db);
|
||||
let replacement = format!("Ok({})", node.syntax());
|
||||
let edit = TextEdit::replace(node.syntax().text_range(), replacement);
|
||||
let tail_expr = sema.diagnostic_fix_source(d);
|
||||
let tail_expr_range = tail_expr.syntax().text_range();
|
||||
let edit = TextEdit::replace(tail_expr_range, format!("Ok({})", tail_expr.syntax()));
|
||||
let source_change = SourceFileEdit { file_id, edit }.into();
|
||||
res.borrow_mut().push(Diagnostic {
|
||||
range: sema.diagnostics_range(d).range,
|
||||
range: sema.diagnostics_presentation_range(d).range,
|
||||
message: d.message(),
|
||||
severity: Severity::Error,
|
||||
fix: Some((
|
||||
Fix::new("Wrap with ok", source_change),
|
||||
sema.diagnostics_fix_range(d).range,
|
||||
)),
|
||||
fix: Some((Fix::new("Wrap with ok", source_change), tail_expr_range)),
|
||||
})
|
||||
})
|
||||
.on::<hir::diagnostics::NoSuchField, _>(|d| {
|
||||
res.borrow_mut().push(Diagnostic {
|
||||
range: sema.diagnostics_range(d).range,
|
||||
range: sema.diagnostics_presentation_range(d).range,
|
||||
message: d.message(),
|
||||
severity: Severity::Error,
|
||||
fix: missing_struct_field_fix(&sema, file_id, d)
|
||||
.map(|fix| (fix, sema.diagnostics_fix_range(d).range)),
|
||||
.map(|fix| (fix, sema.diagnostic_fix_source(d).syntax().text_range())),
|
||||
})
|
||||
})
|
||||
// Only collect experimental diagnostics when they're enabled.
|
||||
|
@ -136,7 +138,7 @@ pub(crate) fn diagnostics(
|
|||
.build(|d| {
|
||||
res.borrow_mut().push(Diagnostic {
|
||||
message: d.message(),
|
||||
range: sema.diagnostics_range(d).range,
|
||||
range: sema.diagnostics_presentation_range(d).range,
|
||||
severity: Severity::Error,
|
||||
fix: None,
|
||||
})
|
||||
|
@ -154,9 +156,9 @@ fn missing_struct_field_fix(
|
|||
usage_file_id: FileId,
|
||||
d: &hir::diagnostics::NoSuchField,
|
||||
) -> Option<Fix> {
|
||||
let record_expr = sema.ast(d);
|
||||
let record_expr_field = sema.diagnostic_fix_source(d);
|
||||
|
||||
let record_lit = ast::RecordExpr::cast(record_expr.syntax().parent()?.parent()?)?;
|
||||
let record_lit = ast::RecordExpr::cast(record_expr_field.syntax().parent()?.parent()?)?;
|
||||
let def_id = sema.resolve_variant(record_lit)?;
|
||||
let module;
|
||||
let def_file_id;
|
||||
|
@ -184,12 +186,12 @@ fn missing_struct_field_fix(
|
|||
};
|
||||
let def_file_id = def_file_id.original_file(sema.db);
|
||||
|
||||
let new_field_type = sema.type_of_expr(&record_expr.expr()?)?;
|
||||
let new_field_type = sema.type_of_expr(&record_expr_field.expr()?)?;
|
||||
if new_field_type.is_unknown() {
|
||||
return None;
|
||||
}
|
||||
let new_field = make::record_field(
|
||||
record_expr.field_name()?,
|
||||
record_expr_field.field_name()?,
|
||||
make::ty(&new_field_type.display_source_code(sema.db, module.into()).ok()?),
|
||||
);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue