Move the DiagnosticsWithFix trait on the ide level

This commit is contained in:
Kirill Bulatov 2020-08-11 00:37:23 +03:00
parent 9368619939
commit 29fbc8e021
7 changed files with 75 additions and 63 deletions

View file

@ -1,8 +1,6 @@
//! FIXME: write short doc here
pub use hir_def::diagnostics::UnresolvedModule;
pub use hir_expand::diagnostics::{
Diagnostic, DiagnosticSink, DiagnosticSinkBuilder, DiagnosticWithFix,
};
pub use hir_expand::diagnostics::{Diagnostic, DiagnosticSink, DiagnosticSinkBuilder};
pub use hir_ty::diagnostics::{
MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField,
};

View file

@ -8,7 +8,7 @@ use hir_def::{
resolver::{self, HasResolver, Resolver},
AsMacroCall, FunctionId, TraitId, VariantId,
};
use hir_expand::{diagnostics::DiagnosticWithFix, hygiene::Hygiene, name::AsName, ExpansionInfo};
use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo};
use hir_ty::associated_type_shorthand_candidates;
use itertools::Itertools;
use ra_db::{FileId, FileRange};
@ -109,14 +109,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
self.imp.parse(file_id)
}
pub fn diagnostic_fix_source<T: DiagnosticWithFix + Diagnostic>(
&self,
d: &T,
) -> Option<<T as DiagnosticWithFix>::AST> {
let file_id = d.presentation().file_id;
let root = self.db.parse_or_expand(file_id)?;
self.imp.cache(root, file_id);
d.fix_source(self.db.upcast())
pub fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
self.imp.cache(root_node, file_id)
}
pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {

View file

@ -2,7 +2,7 @@
use std::any::Any;
use hir_expand::diagnostics::{Diagnostic, DiagnosticWithFix};
use hir_expand::diagnostics::Diagnostic;
use ra_syntax::{ast, AstPtr, SyntaxNodePtr};
use hir_expand::{HirFileId, InFile};
@ -25,11 +25,3 @@ impl Diagnostic for UnresolvedModule {
self
}
}
impl DiagnosticWithFix for UnresolvedModule {
type AST = ast::Module;
fn fix_source(&self, db: &dyn hir_expand::db::AstDatabase) -> Option<Self::AST> {
let root = db.parse_or_expand(self.file)?;
Some(self.decl.to_node(&root))
}
}

View file

@ -18,7 +18,7 @@ use std::{any::Any, fmt};
use ra_syntax::SyntaxNodePtr;
use crate::{db::AstDatabase, InFile};
use crate::InFile;
pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static {
fn message(&self) -> String;
@ -29,11 +29,6 @@ pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static {
}
}
pub trait DiagnosticWithFix {
type AST;
fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST>;
}
pub struct DiagnosticSink<'a> {
callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>,
filters: Vec<Box<dyn FnMut(&dyn Diagnostic) -> bool + 'a>>,

View file

@ -6,8 +6,8 @@ mod unsafe_check;
use std::any::Any;
use hir_def::DefWithBodyId;
use hir_expand::diagnostics::{Diagnostic, DiagnosticSink, DiagnosticWithFix};
use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile};
use hir_expand::diagnostics::{Diagnostic, DiagnosticSink};
use hir_expand::{name::Name, HirFileId, InFile};
use ra_prof::profile;
use ra_syntax::{ast, AstPtr, SyntaxNodePtr};
use stdx::format_to;
@ -46,15 +46,6 @@ impl Diagnostic for NoSuchField {
}
}
impl DiagnosticWithFix for NoSuchField {
type AST = ast::RecordExprField;
fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
let root = db.parse_or_expand(self.file)?;
Some(self.field.to_node(&root))
}
}
#[derive(Debug)]
pub struct MissingFields {
pub file: HirFileId,
@ -88,15 +79,6 @@ impl Diagnostic for MissingFields {
}
}
impl DiagnosticWithFix for MissingFields {
type AST = ast::RecordExpr;
fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
let root = db.parse_or_expand(self.file)?;
Some(self.field_list_parent.to_node(&root))
}
}
#[derive(Debug)]
pub struct MissingPatFields {
pub file: HirFileId,
@ -163,15 +145,6 @@ impl Diagnostic for MissingOkInTailExpr {
}
}
impl DiagnosticWithFix for MissingOkInTailExpr {
type AST = ast::Expr;
fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
let root = db.parse_or_expand(self.file)?;
Some(self.expr.to_node(&root))
}
}
#[derive(Debug)]
pub struct BreakOutsideOfLoop {
pub file: HirFileId,

View file

@ -7,11 +7,12 @@
use std::cell::RefCell;
use hir::{
db::AstDatabase,
diagnostics::{Diagnostic as _, DiagnosticSinkBuilder},
HasSource, HirDisplay, Semantics, VariantDef,
};
use itertools::Itertools;
use ra_db::SourceDatabase;
use ra_db::{SourceDatabase, Upcast};
use ra_ide_db::RootDatabase;
use ra_prof::profile;
use ra_syntax::{
@ -23,6 +24,9 @@ use ra_text_edit::{TextEdit, TextEditBuilder};
use crate::{Diagnostic, FileId, FileSystemEdit, Fix, SourceFileEdit};
mod diagnostics_with_fix;
use diagnostics_with_fix::DiagnosticWithFix;
#[derive(Debug, Copy, Clone)]
pub enum Severity {
Error,
@ -62,8 +66,7 @@ pub(crate) fn diagnostics(
}
.into(),
);
let fix = sema
.diagnostic_fix_source(d)
let fix = diagnostic_fix_source(&sema, d)
.map(|unresolved_module| unresolved_module.syntax().text_range())
.map(|fix_range| (fix, fix_range));
@ -84,7 +87,7 @@ pub(crate) fn diagnostics(
let fix = if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
None
} else {
sema.diagnostic_fix_source(d)
diagnostic_fix_source(&sema, d)
.and_then(|record_expr| record_expr.record_expr_field_list())
.map(|old_field_list| {
let mut new_field_list = old_field_list.clone();
@ -105,6 +108,7 @@ pub(crate) fn diagnostics(
(
Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into()),
sema.original_range(&old_field_list.syntax()).range,
// old_field_list.syntax().text_range(),
)
})
};
@ -118,7 +122,7 @@ pub(crate) fn diagnostics(
Some(())
})
.on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| {
let fix = sema.diagnostic_fix_source(d).map(|tail_expr| {
let fix = diagnostic_fix_source(&sema, d).map(|tail_expr| {
let tail_expr_range = tail_expr.syntax().text_range();
let edit =
TextEdit::replace(tail_expr_range, format!("Ok({})", tail_expr.syntax()));
@ -140,7 +144,7 @@ pub(crate) fn diagnostics(
message: d.message(),
severity: Severity::Error,
fix: missing_struct_field_fix(&sema, file_id, d).and_then(|fix| {
Some((fix, sema.diagnostic_fix_source(d)?.syntax().text_range()))
Some((fix, diagnostic_fix_source(&sema, d)?.syntax().text_range()))
}),
});
Some(())
@ -164,12 +168,22 @@ pub(crate) fn diagnostics(
res.into_inner()
}
fn diagnostic_fix_source<T: DiagnosticWithFix + hir::diagnostics::Diagnostic>(
sema: &Semantics<RootDatabase>,
d: &T,
) -> Option<<T as DiagnosticWithFix>::AST> {
let file_id = d.presentation().file_id;
let root = sema.db.parse_or_expand(file_id)?;
sema.cache(root, file_id);
d.fix_source(sema.db.upcast())
}
fn missing_struct_field_fix(
sema: &Semantics<RootDatabase>,
usage_file_id: FileId,
d: &hir::diagnostics::NoSuchField,
) -> Option<Fix> {
let record_expr_field = sema.diagnostic_fix_source(d)?;
let record_expr_field = diagnostic_fix_source(&sema, d)?;
let record_lit = ast::RecordExpr::cast(record_expr_field.syntax().parent()?.parent()?)?;
let def_id = sema.resolve_variant(record_lit)?;

View file

@ -0,0 +1,46 @@
use hir::{
db::AstDatabase,
diagnostics::{MissingFields, MissingOkInTailExpr, NoSuchField, UnresolvedModule},
};
use ra_syntax::ast;
// TODO kb
pub trait DiagnosticWithFix {
type AST;
fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST>;
}
impl DiagnosticWithFix for UnresolvedModule {
type AST = ast::Module;
fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
let root = db.parse_or_expand(self.file)?;
Some(self.decl.to_node(&root))
}
}
impl DiagnosticWithFix for NoSuchField {
type AST = ast::RecordExprField;
fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
let root = db.parse_or_expand(self.file)?;
Some(self.field.to_node(&root))
}
}
impl DiagnosticWithFix for MissingFields {
type AST = ast::RecordExpr;
fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
let root = db.parse_or_expand(self.file)?;
Some(self.field_list_parent.to_node(&root))
}
}
impl DiagnosticWithFix for MissingOkInTailExpr {
type AST = ast::Expr;
fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
let root = db.parse_or_expand(self.file)?;
Some(self.expr.to_node(&root))
}
}