From 9963f43d51071ea02f8f6d490b9c49882034b42c Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 9 Aug 2020 01:59:26 +0300 Subject: Refactor the diagnostics --- crates/ra_ide/src/diagnostics.rs | 76 +++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 37 deletions(-) (limited to 'crates/ra_ide') diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index 0d2ff17e1..55593a8cb 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs @@ -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::(|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(&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 } - - 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, - )) }; 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::(|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::(|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 { - 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()?), ); -- cgit v1.2.3