diff options
Diffstat (limited to 'crates/hir/src')
-rw-r--r-- | crates/hir/src/diagnostics.rs | 54 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 22 |
2 files changed, 72 insertions, 4 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 2cdbd172a..2edb53765 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs | |||
@@ -14,8 +14,7 @@ use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange}; | |||
14 | pub use hir_ty::{ | 14 | pub use hir_ty::{ |
15 | diagnostics::{ | 15 | diagnostics::{ |
16 | IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms, | 16 | IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms, |
17 | MissingOkOrSomeInTailExpr, NoSuchField, RemoveThisSemicolon, | 17 | MissingOkOrSomeInTailExpr, RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap, |
18 | ReplaceFilterMapNextWithFindMap, | ||
19 | }, | 18 | }, |
20 | diagnostics_sink::{Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder}, | 19 | diagnostics_sink::{Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder}, |
21 | }; | 20 | }; |
@@ -251,3 +250,54 @@ impl Diagnostic for UnimplementedBuiltinMacro { | |||
251 | self | 250 | self |
252 | } | 251 | } |
253 | } | 252 | } |
253 | |||
254 | // Diagnostic: no-such-field | ||
255 | // | ||
256 | // This diagnostic is triggered if created structure does not have field provided in record. | ||
257 | #[derive(Debug)] | ||
258 | pub struct NoSuchField { | ||
259 | pub file: HirFileId, | ||
260 | pub field: AstPtr<ast::RecordExprField>, | ||
261 | } | ||
262 | |||
263 | impl Diagnostic for NoSuchField { | ||
264 | fn code(&self) -> DiagnosticCode { | ||
265 | DiagnosticCode("no-such-field") | ||
266 | } | ||
267 | |||
268 | fn message(&self) -> String { | ||
269 | "no such field".to_string() | ||
270 | } | ||
271 | |||
272 | fn display_source(&self) -> InFile<SyntaxNodePtr> { | ||
273 | InFile::new(self.file, self.field.clone().into()) | ||
274 | } | ||
275 | |||
276 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | ||
277 | self | ||
278 | } | ||
279 | } | ||
280 | |||
281 | // Diagnostic: break-outside-of-loop | ||
282 | // | ||
283 | // This diagnostic is triggered if the `break` keyword is used outside of a loop. | ||
284 | #[derive(Debug)] | ||
285 | pub struct BreakOutsideOfLoop { | ||
286 | pub file: HirFileId, | ||
287 | pub expr: AstPtr<ast::Expr>, | ||
288 | } | ||
289 | |||
290 | impl Diagnostic for BreakOutsideOfLoop { | ||
291 | fn code(&self) -> DiagnosticCode { | ||
292 | DiagnosticCode("break-outside-of-loop") | ||
293 | } | ||
294 | fn message(&self) -> String { | ||
295 | "break outside of loop".to_string() | ||
296 | } | ||
297 | fn display_source(&self) -> InFile<SyntaxNodePtr> { | ||
298 | InFile { file_id: self.file, value: self.expr.clone().into() } | ||
299 | } | ||
300 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | ||
301 | self | ||
302 | } | ||
303 | } | ||
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 0bb3767c1..bce626b03 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -36,8 +36,9 @@ use std::{iter, sync::Arc}; | |||
36 | use arrayvec::ArrayVec; | 36 | use arrayvec::ArrayVec; |
37 | use base_db::{CrateDisplayName, CrateId, Edition, FileId}; | 37 | use base_db::{CrateDisplayName, CrateId, Edition, FileId}; |
38 | use diagnostics::{ | 38 | use diagnostics::{ |
39 | InactiveCode, MacroError, UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, | 39 | BreakOutsideOfLoop, InactiveCode, MacroError, NoSuchField, UnimplementedBuiltinMacro, |
40 | UnresolvedMacroCall, UnresolvedModule, UnresolvedProcMacro, | 40 | UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, UnresolvedModule, |
41 | UnresolvedProcMacro, | ||
41 | }; | 42 | }; |
42 | use either::Either; | 43 | use either::Either; |
43 | use hir_def::{ | 44 | use hir_def::{ |
@@ -1042,6 +1043,23 @@ impl Function { | |||
1042 | } | 1043 | } |
1043 | } | 1044 | } |
1044 | 1045 | ||
1046 | let infer = db.infer(self.id.into()); | ||
1047 | let (_, source_map) = db.body_with_source_map(self.id.into()); | ||
1048 | for d in &infer.diagnostics { | ||
1049 | match d { | ||
1050 | hir_ty::InferenceDiagnostic::NoSuchField { expr } => { | ||
1051 | let field = source_map.field_syntax(*expr); | ||
1052 | sink.push(NoSuchField { file: field.file_id, field: field.value }) | ||
1053 | } | ||
1054 | hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { expr } => { | ||
1055 | let ptr = source_map | ||
1056 | .expr_syntax(*expr) | ||
1057 | .expect("break outside of loop in synthetic syntax"); | ||
1058 | sink.push(BreakOutsideOfLoop { file: ptr.file_id, expr: ptr.value }) | ||
1059 | } | ||
1060 | } | ||
1061 | } | ||
1062 | |||
1045 | hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); | 1063 | hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); |
1046 | hir_ty::diagnostics::validate_body(db, self.id.into(), sink); | 1064 | hir_ty::diagnostics::validate_body(db, self.id.into(), sink); |
1047 | } | 1065 | } |