internal: move inference diagnostics to hir

This commit is contained in:
Aleksey Kladov 2021-06-12 17:17:23 +03:00
parent 409f5fb563
commit f8009666be
6 changed files with 222 additions and 244 deletions

View file

@ -14,8 +14,7 @@ use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange};
pub use hir_ty::{
diagnostics::{
IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms,
MissingOkOrSomeInTailExpr, NoSuchField, RemoveThisSemicolon,
ReplaceFilterMapNextWithFindMap,
MissingOkOrSomeInTailExpr, RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap,
},
diagnostics_sink::{Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder},
};
@ -251,3 +250,54 @@ impl Diagnostic for UnimplementedBuiltinMacro {
self
}
}
// Diagnostic: no-such-field
//
// This diagnostic is triggered if created structure does not have field provided in record.
#[derive(Debug)]
pub struct NoSuchField {
pub file: HirFileId,
pub field: AstPtr<ast::RecordExprField>,
}
impl Diagnostic for NoSuchField {
fn code(&self) -> DiagnosticCode {
DiagnosticCode("no-such-field")
}
fn message(&self) -> String {
"no such field".to_string()
}
fn display_source(&self) -> InFile<SyntaxNodePtr> {
InFile::new(self.file, self.field.clone().into())
}
fn as_any(&self) -> &(dyn Any + Send + 'static) {
self
}
}
// Diagnostic: break-outside-of-loop
//
// This diagnostic is triggered if the `break` keyword is used outside of a loop.
#[derive(Debug)]
pub struct BreakOutsideOfLoop {
pub file: HirFileId,
pub expr: AstPtr<ast::Expr>,
}
impl Diagnostic for BreakOutsideOfLoop {
fn code(&self) -> DiagnosticCode {
DiagnosticCode("break-outside-of-loop")
}
fn message(&self) -> String {
"break outside of loop".to_string()
}
fn display_source(&self) -> InFile<SyntaxNodePtr> {
InFile { file_id: self.file, value: self.expr.clone().into() }
}
fn as_any(&self) -> &(dyn Any + Send + 'static) {
self
}
}

View file

@ -36,8 +36,9 @@ use std::{iter, sync::Arc};
use arrayvec::ArrayVec;
use base_db::{CrateDisplayName, CrateId, Edition, FileId};
use diagnostics::{
InactiveCode, MacroError, UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport,
UnresolvedMacroCall, UnresolvedModule, UnresolvedProcMacro,
BreakOutsideOfLoop, InactiveCode, MacroError, NoSuchField, UnimplementedBuiltinMacro,
UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, UnresolvedModule,
UnresolvedProcMacro,
};
use either::Either;
use hir_def::{
@ -1042,6 +1043,23 @@ impl Function {
}
}
let infer = db.infer(self.id.into());
let (_, source_map) = db.body_with_source_map(self.id.into());
for d in &infer.diagnostics {
match d {
hir_ty::InferenceDiagnostic::NoSuchField { expr } => {
let field = source_map.field_syntax(*expr);
sink.push(NoSuchField { file: field.file_id, field: field.value })
}
hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { expr } => {
let ptr = source_map
.expr_syntax(*expr)
.expect("break outside of loop in synthetic syntax");
sink.push(BreakOutsideOfLoop { file: ptr.file_id, expr: ptr.value })
}
}
}
hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink);
hir_ty::diagnostics::validate_body(db, self.id.into(), sink);
}