aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/code_model_api.rs6
-rw-r--r--crates/ra_hir/src/diagnostics.rs28
-rw-r--r--crates/ra_hir/src/nameres.rs66
-rw-r--r--crates/ra_hir/src/nameres/collector.rs9
-rw-r--r--crates/ra_hir/src/ty/infer.rs8
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs4
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.
20pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { 20pub 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)]
34pub struct Diagnostics { 34pub struct DiagnosticSink {
35 data: Vec<Box<dyn Diagnostic>>, 35 data: Vec<Box<dyn Diagnostic>>,
36} 36}
37 37
38impl Diagnostics { 38impl 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
54impl Diagnostic for NoSuchField { 54impl 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
76impl Diagnostic for UnresolvedModule { 76impl 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;
56use std::sync::Arc; 56use std::sync::Arc;
57 57
58use rustc_hash::FxHashMap; 58use rustc_hash::FxHashMap;
59use relative_path::RelativePathBuf;
60use ra_arena::{Arena, RawId, impl_arena_id}; 59use ra_arena::{Arena, RawId, impl_arena_id};
61use ra_db::{FileId, Edition}; 60use ra_db::{FileId, Edition};
62use ra_syntax::{AstNode, AstPtr, ast};
63use test_utils::tested_by; 61use test_utils::tested_by;
64 62
65use crate::{ 63use 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
72pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap}; 71pub(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)] 448mod diagnostics {
450enum 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
458impl 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
15use super::{CrateDefMap, CrateModuleId, ModuleData, CrateMacroId};
16
17pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { 20pub(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};
43use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; 43use 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
1271mod diagnostics { 1271mod 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
131fn check_module(acc: &mut Vec<Diagnostic>, db: &RootDatabase, module: hir::Module) { 131fn 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() };