diff options
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/diagnostics.rs | 28 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 66 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 8 | ||||
-rw-r--r-- | crates/ra_ide_api/src/diagnostics.rs | 4 |
6 files changed, 70 insertions, 51 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 03b1acef3..bc0f74c89 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -16,7 +16,7 @@ use crate::{ | |||
16 | ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, | 16 | ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, |
17 | impl_block::ImplBlock, | 17 | impl_block::ImplBlock, |
18 | resolve::Resolver, | 18 | resolve::Resolver, |
19 | diagnostics::Diagnostics, | 19 | diagnostics::DiagnosticSink, |
20 | }; | 20 | }; |
21 | 21 | ||
22 | /// hir::Crate describes a single crate. It's the main interface with which | 22 | /// hir::Crate describes a single crate. It's the main interface with which |
@@ -166,7 +166,7 @@ impl Module { | |||
166 | db.crate_def_map(self.krate)[self.module_id].scope.clone() | 166 | db.crate_def_map(self.krate)[self.module_id].scope.clone() |
167 | } | 167 | } |
168 | 168 | ||
169 | pub fn diagnostics(&self, db: &impl HirDatabase, sink: &mut Diagnostics) { | 169 | pub fn diagnostics(&self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { |
170 | db.crate_def_map(self.krate).add_diagnostics(db, self.module_id, sink); | 170 | db.crate_def_map(self.krate).add_diagnostics(db, self.module_id, sink); |
171 | } | 171 | } |
172 | 172 | ||
@@ -515,7 +515,7 @@ impl Function { | |||
515 | r | 515 | r |
516 | } | 516 | } |
517 | 517 | ||
518 | pub fn diagnostics(&self, db: &impl HirDatabase, sink: &mut Diagnostics) { | 518 | pub fn diagnostics(&self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { |
519 | self.infer(db).add_diagnostics(db, *self, sink); | 519 | self.infer(db).add_diagnostics(db, *self, sink); |
520 | } | 520 | } |
521 | } | 521 | } |
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs index e8bb1ed92..d6b28159e 100644 --- a/crates/ra_hir/src/diagnostics.rs +++ b/crates/ra_hir/src/diagnostics.rs | |||
@@ -8,19 +8,19 @@ use relative_path::RelativePathBuf; | |||
8 | /// Diagnostic defines hir API for errors and warnings. | 8 | /// Diagnostic defines hir API for errors and warnings. |
9 | /// | 9 | /// |
10 | /// It is used as a `dyn` object, which you can downcast to a concrete | 10 | /// It is used as a `dyn` object, which you can downcast to a concrete |
11 | /// diagnostic. Diagnostics are structured, meaning that they include rich | 11 | /// diagnostic. DiagnosticSink are structured, meaning that they include rich |
12 | /// information which can be used by IDE to create fixes. Diagnostics are | 12 | /// information which can be used by IDE to create fixes. DiagnosticSink are |
13 | /// expressed in terms of macro-expanded syntax tree nodes (so, it's a bad idea | 13 | /// expressed in terms of macro-expanded syntax tree nodes (so, it's a bad idea |
14 | /// to diagnostic in a salsa value). | 14 | /// to diagnostic in a salsa value). |
15 | /// | 15 | /// |
16 | /// Internally, various subsystems of hir produce diagnostics specific to a | 16 | /// Internally, various subsystems of hir produce diagnostics specific to a |
17 | /// subsytem (typically, an `enum`), which are safe to store in salsa but do not | 17 | /// subsystem (typically, an `enum`), which are safe to store in salsa but do not |
18 | /// include source locations. Such internal diagnostic are transformed into an | 18 | /// include source locations. Such internal diagnostic are transformed into an |
19 | /// instance of `Diagnostic` on demand. | 19 | /// instance of `Diagnostic` on demand. |
20 | pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { | 20 | pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { |
21 | fn message(&self) -> String; | ||
21 | fn file(&self) -> HirFileId; | 22 | fn file(&self) -> HirFileId; |
22 | fn syntax_node(&self) -> SyntaxNodePtr; | 23 | fn syntax_node(&self) -> SyntaxNodePtr; |
23 | fn message(&self) -> String; | ||
24 | fn as_any(&self) -> &(Any + Send + 'static); | 24 | fn as_any(&self) -> &(Any + Send + 'static); |
25 | } | 25 | } |
26 | 26 | ||
@@ -31,17 +31,17 @@ impl dyn Diagnostic { | |||
31 | } | 31 | } |
32 | 32 | ||
33 | #[derive(Debug, Default)] | 33 | #[derive(Debug, Default)] |
34 | pub struct Diagnostics { | 34 | pub struct DiagnosticSink { |
35 | data: Vec<Box<dyn Diagnostic>>, | 35 | data: Vec<Box<dyn Diagnostic>>, |
36 | } | 36 | } |
37 | 37 | ||
38 | impl Diagnostics { | 38 | impl DiagnosticSink { |
39 | pub fn push(&mut self, d: impl Diagnostic) { | 39 | pub fn push(&mut self, d: impl Diagnostic) { |
40 | self.data.push(Box::new(d)) | 40 | self.data.push(Box::new(d)) |
41 | } | 41 | } |
42 | 42 | ||
43 | pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a dyn Diagnostic> + 'a { | 43 | pub fn into_diagnostics(self) -> Vec<Box<dyn Diagnostic>> { |
44 | self.data.iter().map(|it| it.as_ref()) | 44 | self.data |
45 | } | 45 | } |
46 | } | 46 | } |
47 | 47 | ||
@@ -52,15 +52,15 @@ pub struct NoSuchField { | |||
52 | } | 52 | } |
53 | 53 | ||
54 | impl Diagnostic for NoSuchField { | 54 | impl Diagnostic for NoSuchField { |
55 | fn message(&self) -> String { | ||
56 | "no such field".to_string() | ||
57 | } | ||
55 | fn file(&self) -> HirFileId { | 58 | fn file(&self) -> HirFileId { |
56 | self.file | 59 | self.file |
57 | } | 60 | } |
58 | fn syntax_node(&self) -> SyntaxNodePtr { | 61 | fn syntax_node(&self) -> SyntaxNodePtr { |
59 | self.field.into() | 62 | self.field.into() |
60 | } | 63 | } |
61 | fn message(&self) -> String { | ||
62 | "no such field".to_string() | ||
63 | } | ||
64 | fn as_any(&self) -> &(Any + Send + 'static) { | 64 | fn as_any(&self) -> &(Any + Send + 'static) { |
65 | self | 65 | self |
66 | } | 66 | } |
@@ -74,15 +74,15 @@ pub struct UnresolvedModule { | |||
74 | } | 74 | } |
75 | 75 | ||
76 | impl Diagnostic for UnresolvedModule { | 76 | impl Diagnostic for UnresolvedModule { |
77 | fn message(&self) -> String { | ||
78 | "unresolved module".to_string() | ||
79 | } | ||
77 | fn file(&self) -> HirFileId { | 80 | fn file(&self) -> HirFileId { |
78 | self.file | 81 | self.file |
79 | } | 82 | } |
80 | fn syntax_node(&self) -> SyntaxNodePtr { | 83 | fn syntax_node(&self) -> SyntaxNodePtr { |
81 | self.decl.into() | 84 | self.decl.into() |
82 | } | 85 | } |
83 | fn message(&self) -> String { | ||
84 | "unresolved module".to_string() | ||
85 | } | ||
86 | fn as_any(&self) -> &(Any + Send + 'static) { | 86 | fn as_any(&self) -> &(Any + Send + 'static) { |
87 | self | 87 | self |
88 | } | 88 | } |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 416f114b4..56ed872d5 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -56,17 +56,16 @@ mod tests; | |||
56 | use std::sync::Arc; | 56 | use std::sync::Arc; |
57 | 57 | ||
58 | use rustc_hash::FxHashMap; | 58 | use rustc_hash::FxHashMap; |
59 | use relative_path::RelativePathBuf; | ||
60 | use ra_arena::{Arena, RawId, impl_arena_id}; | 59 | use ra_arena::{Arena, RawId, impl_arena_id}; |
61 | use ra_db::{FileId, Edition}; | 60 | use ra_db::{FileId, Edition}; |
62 | use ra_syntax::{AstNode, AstPtr, ast}; | ||
63 | use test_utils::tested_by; | 61 | use test_utils::tested_by; |
64 | 62 | ||
65 | use crate::{ | 63 | use crate::{ |
66 | ModuleDef, Name, Crate, Module, | 64 | ModuleDef, Name, Crate, Module, |
67 | DefDatabase, Path, PathKind, HirFileId, | 65 | DefDatabase, Path, PathKind, HirFileId, |
68 | ids::{SourceItemId, SourceFileItemId, MacroCallId}, | 66 | ids::{SourceItemId, SourceFileItemId, MacroCallId}, |
69 | diagnostics::{Diagnostics, UnresolvedModule}, | 67 | diagnostics::DiagnosticSink, |
68 | nameres::diagnostics::DefDiagnostic, | ||
70 | }; | 69 | }; |
71 | 70 | ||
72 | pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap}; | 71 | pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap}; |
@@ -228,7 +227,7 @@ impl CrateDefMap { | |||
228 | &self, | 227 | &self, |
229 | db: &impl DefDatabase, | 228 | db: &impl DefDatabase, |
230 | module: CrateModuleId, | 229 | module: CrateModuleId, |
231 | sink: &mut Diagnostics, | 230 | sink: &mut DiagnosticSink, |
232 | ) { | 231 | ) { |
233 | self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink)) | 232 | self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink)) |
234 | } | 233 | } |
@@ -446,30 +445,47 @@ impl CrateDefMap { | |||
446 | } | 445 | } |
447 | } | 446 | } |
448 | 447 | ||
449 | #[derive(Debug, PartialEq, Eq)] | 448 | mod diagnostics { |
450 | enum DefDiagnostic { | 449 | use relative_path::RelativePathBuf; |
451 | UnresolvedModule { | 450 | use ra_syntax::{AstPtr, AstNode, ast}; |
452 | module: CrateModuleId, | 451 | |
453 | declaration: SourceItemId, | 452 | use crate::{ |
454 | candidate: RelativePathBuf, | 453 | SourceItemId, DefDatabase, |
455 | }, | 454 | nameres::CrateModuleId, |
456 | } | 455 | diagnostics::{DiagnosticSink, UnresolvedModule}, |
456 | }; | ||
457 | 457 | ||
458 | impl DefDiagnostic { | 458 | #[derive(Debug, PartialEq, Eq)] |
459 | fn add_to(&self, db: &impl DefDatabase, target_module: CrateModuleId, sink: &mut Diagnostics) { | 459 | pub(super) enum DefDiagnostic { |
460 | match self { | 460 | UnresolvedModule { |
461 | DefDiagnostic::UnresolvedModule { module, declaration, candidate } => { | 461 | module: CrateModuleId, |
462 | if *module != target_module { | 462 | declaration: SourceItemId, |
463 | return; | 463 | candidate: RelativePathBuf, |
464 | }, | ||
465 | } | ||
466 | |||
467 | impl DefDiagnostic { | ||
468 | pub(super) fn add_to( | ||
469 | &self, | ||
470 | db: &impl DefDatabase, | ||
471 | target_module: CrateModuleId, | ||
472 | sink: &mut DiagnosticSink, | ||
473 | ) { | ||
474 | match self { | ||
475 | DefDiagnostic::UnresolvedModule { module, declaration, candidate } => { | ||
476 | if *module != target_module { | ||
477 | return; | ||
478 | } | ||
479 | let syntax = db.file_item(*declaration); | ||
480 | let decl = ast::Module::cast(&syntax).unwrap(); | ||
481 | sink.push(UnresolvedModule { | ||
482 | file: declaration.file_id, | ||
483 | decl: AstPtr::new(&decl), | ||
484 | candidate: candidate.clone(), | ||
485 | }) | ||
464 | } | 486 | } |
465 | let syntax = db.file_item(*declaration); | ||
466 | let decl = ast::Module::cast(&syntax).unwrap(); | ||
467 | sink.push(UnresolvedModule { | ||
468 | file: declaration.file_id, | ||
469 | decl: AstPtr::new(&decl), | ||
470 | candidate: candidate.clone(), | ||
471 | }) | ||
472 | } | 487 | } |
473 | } | 488 | } |
474 | } | 489 | } |
490 | |||
475 | } | 491 | } |
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index bc6bc5e7f..8830b4624 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs | |||
@@ -8,12 +8,15 @@ use crate::{ | |||
8 | Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, | 8 | Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, |
9 | DefDatabase, HirFileId, Name, Path, Crate, | 9 | DefDatabase, HirFileId, Name, Path, Crate, |
10 | KnownName, | 10 | KnownName, |
11 | nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, raw, DefDiagnostic}, | 11 | nameres::{ |
12 | Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, | ||
13 | CrateDefMap, CrateModuleId, ModuleData, CrateMacroId, | ||
14 | diagnostics::DefDiagnostic, | ||
15 | raw, | ||
16 | }, | ||
12 | ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, | 17 | ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, |
13 | }; | 18 | }; |
14 | 19 | ||
15 | use super::{CrateDefMap, CrateModuleId, ModuleData, CrateMacroId}; | ||
16 | |||
17 | pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { | 20 | pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { |
18 | // populate external prelude | 21 | // populate external prelude |
19 | for dep in def_map.krate.dependencies(db) { | 22 | for dep in def_map.krate.dependencies(db) { |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 6dc3edc7a..5fd602a9e 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -38,7 +38,7 @@ use crate::{ | |||
38 | resolve::{Resolver, Resolution}, | 38 | resolve::{Resolver, Resolution}, |
39 | nameres::Namespace, | 39 | nameres::Namespace, |
40 | ty::infer::diagnostics::InferenceDiagnostic, | 40 | ty::infer::diagnostics::InferenceDiagnostic, |
41 | diagnostics::Diagnostics, | 41 | diagnostics::DiagnosticSink, |
42 | }; | 42 | }; |
43 | use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; | 43 | use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; |
44 | 44 | ||
@@ -120,7 +120,7 @@ impl InferenceResult { | |||
120 | &self, | 120 | &self, |
121 | db: &impl HirDatabase, | 121 | db: &impl HirDatabase, |
122 | owner: Function, | 122 | owner: Function, |
123 | sink: &mut Diagnostics, | 123 | sink: &mut DiagnosticSink, |
124 | ) { | 124 | ) { |
125 | self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink)) | 125 | self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink)) |
126 | } | 126 | } |
@@ -1269,7 +1269,7 @@ impl Expectation { | |||
1269 | } | 1269 | } |
1270 | 1270 | ||
1271 | mod diagnostics { | 1271 | mod diagnostics { |
1272 | use crate::{expr::ExprId, diagnostics::{Diagnostics, NoSuchField}, HirDatabase, Function}; | 1272 | use crate::{expr::ExprId, diagnostics::{DiagnosticSink, NoSuchField}, HirDatabase, Function}; |
1273 | 1273 | ||
1274 | #[derive(Debug, PartialEq, Eq, Clone)] | 1274 | #[derive(Debug, PartialEq, Eq, Clone)] |
1275 | pub(super) enum InferenceDiagnostic { | 1275 | pub(super) enum InferenceDiagnostic { |
@@ -1281,7 +1281,7 @@ mod diagnostics { | |||
1281 | &self, | 1281 | &self, |
1282 | db: &impl HirDatabase, | 1282 | db: &impl HirDatabase, |
1283 | owner: Function, | 1283 | owner: Function, |
1284 | sink: &mut Diagnostics, | 1284 | sink: &mut DiagnosticSink, |
1285 | ) { | 1285 | ) { |
1286 | match self { | 1286 | match self { |
1287 | InferenceDiagnostic::NoSuchField { expr, field } => { | 1287 | InferenceDiagnostic::NoSuchField { expr, field } => { |
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs index 254342c0a..1395cede2 100644 --- a/crates/ra_ide_api/src/diagnostics.rs +++ b/crates/ra_ide_api/src/diagnostics.rs | |||
@@ -129,7 +129,7 @@ fn check_struct_shorthand_initialization( | |||
129 | } | 129 | } |
130 | 130 | ||
131 | fn check_module(acc: &mut Vec<Diagnostic>, db: &RootDatabase, module: hir::Module) { | 131 | fn check_module(acc: &mut Vec<Diagnostic>, db: &RootDatabase, module: hir::Module) { |
132 | let mut diagnostics = hir::diagnostics::Diagnostics::default(); | 132 | let mut diagnostics = hir::diagnostics::DiagnosticSink::default(); |
133 | module.diagnostics(db, &mut diagnostics); | 133 | module.diagnostics(db, &mut diagnostics); |
134 | for decl in module.declarations(db) { | 134 | for decl in module.declarations(db) { |
135 | match decl { | 135 | match decl { |
@@ -138,7 +138,7 @@ fn check_module(acc: &mut Vec<Diagnostic>, db: &RootDatabase, module: hir::Modul | |||
138 | } | 138 | } |
139 | } | 139 | } |
140 | 140 | ||
141 | for d in diagnostics.iter() { | 141 | for d in diagnostics.into_diagnostics().iter() { |
142 | if let Some(d) = d.downcast_ref::<hir::diagnostics::UnresolvedModule>() { | 142 | if let Some(d) = d.downcast_ref::<hir::diagnostics::UnresolvedModule>() { |
143 | let source_root = db.file_source_root(d.file().original_file(db)); | 143 | let source_root = db.file_source_root(d.file().original_file(db)); |
144 | let create_file = FileSystemEdit::CreateFile { source_root, path: d.candidate.clone() }; | 144 | let create_file = FileSystemEdit::CreateFile { source_root, path: d.candidate.clone() }; |