diff options
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl/module.rs | 19 | ||||
-rw-r--r-- | crates/ra_hir/src/diagnostics.rs | 45 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 65 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 63 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 13 | ||||
-rw-r--r-- | crates/ra_ide_api/src/diagnostics.rs | 66 |
8 files changed, 156 insertions, 135 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index a37d960a1..03b1acef3 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -1,8 +1,7 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use relative_path::RelativePathBuf; | ||
4 | use ra_db::{CrateId, SourceRootId, Edition}; | 3 | use ra_db::{CrateId, SourceRootId, Edition}; |
5 | use ra_syntax::{ast::self, TreeArc, SyntaxNode}; | 4 | use ra_syntax::{ast::self, TreeArc}; |
6 | 5 | ||
7 | use crate::{ | 6 | use crate::{ |
8 | Name, ScopesWithSourceMap, Ty, HirFileId, | 7 | Name, ScopesWithSourceMap, Ty, HirFileId, |
@@ -96,11 +95,6 @@ pub enum ModuleSource { | |||
96 | Module(TreeArc<ast::Module>), | 95 | Module(TreeArc<ast::Module>), |
97 | } | 96 | } |
98 | 97 | ||
99 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] | ||
100 | pub enum Problem { | ||
101 | UnresolvedModule { candidate: RelativePathBuf }, | ||
102 | } | ||
103 | |||
104 | impl Module { | 98 | impl Module { |
105 | /// Name of this module. | 99 | /// Name of this module. |
106 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { | 100 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { |
@@ -172,8 +166,8 @@ impl Module { | |||
172 | db.crate_def_map(self.krate)[self.module_id].scope.clone() | 166 | db.crate_def_map(self.krate)[self.module_id].scope.clone() |
173 | } | 167 | } |
174 | 168 | ||
175 | pub fn problems(&self, db: &impl HirDatabase) -> Vec<(TreeArc<SyntaxNode>, Problem)> { | 169 | pub fn diagnostics(&self, db: &impl HirDatabase, sink: &mut Diagnostics) { |
176 | self.problems_impl(db) | 170 | db.crate_def_map(self.krate).add_diagnostics(db, self.module_id, sink); |
177 | } | 171 | } |
178 | 172 | ||
179 | pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { | 173 | pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { |
@@ -521,10 +515,8 @@ impl Function { | |||
521 | r | 515 | r |
522 | } | 516 | } |
523 | 517 | ||
524 | pub fn diagnostics(&self, db: &impl HirDatabase) -> Diagnostics { | 518 | pub fn diagnostics(&self, db: &impl HirDatabase, sink: &mut Diagnostics) { |
525 | let mut res = Diagnostics::default(); | 519 | self.infer(db).add_diagnostics(db, *self, sink); |
526 | self.infer(db).add_diagnostics(db, *self, &mut res); | ||
527 | res | ||
528 | } | 520 | } |
529 | } | 521 | } |
530 | 522 | ||
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 52a33e981..14237060c 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs | |||
@@ -1,8 +1,8 @@ | |||
1 | use ra_db::FileId; | 1 | use ra_db::FileId; |
2 | use ra_syntax::{ast, SyntaxNode, TreeArc, AstNode}; | 2 | use ra_syntax::{ast, TreeArc, AstNode}; |
3 | 3 | ||
4 | use crate::{ | 4 | use crate::{ |
5 | Module, ModuleSource, Problem, Name, | 5 | Module, ModuleSource, Name, |
6 | nameres::{CrateModuleId, ImportId}, | 6 | nameres::{CrateModuleId, ImportId}, |
7 | HirDatabase, DefDatabase, | 7 | HirDatabase, DefDatabase, |
8 | HirFileId, SourceItemId, | 8 | HirFileId, SourceItemId, |
@@ -108,19 +108,4 @@ impl Module { | |||
108 | let parent_id = def_map[self.module_id].parent?; | 108 | let parent_id = def_map[self.module_id].parent?; |
109 | Some(self.with_module_id(parent_id)) | 109 | Some(self.with_module_id(parent_id)) |
110 | } | 110 | } |
111 | |||
112 | pub(crate) fn problems_impl( | ||
113 | &self, | ||
114 | db: &impl HirDatabase, | ||
115 | ) -> Vec<(TreeArc<SyntaxNode>, Problem)> { | ||
116 | let def_map = db.crate_def_map(self.krate); | ||
117 | let (my_file_id, _) = self.definition_source(db); | ||
118 | // FIXME: not entirely corret filterint by module | ||
119 | def_map | ||
120 | .problems() | ||
121 | .iter() | ||
122 | .filter(|(source_item_id, _problem)| my_file_id == source_item_id.file_id) | ||
123 | .map(|(source_item_id, problem)| (db.file_item(*source_item_id), problem.clone())) | ||
124 | .collect() | ||
125 | } | ||
126 | } | 111 | } |
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs index 46a3fdd47..e8bb1ed92 100644 --- a/crates/ra_hir/src/diagnostics.rs +++ b/crates/ra_hir/src/diagnostics.rs | |||
@@ -3,7 +3,20 @@ use std::{fmt, any::Any}; | |||
3 | use ra_syntax::{SyntaxNodePtr, AstPtr, ast}; | 3 | use ra_syntax::{SyntaxNodePtr, AstPtr, ast}; |
4 | 4 | ||
5 | use crate::HirFileId; | 5 | use crate::HirFileId; |
6 | use relative_path::RelativePathBuf; | ||
6 | 7 | ||
8 | /// Diagnostic defines hir API for errors and warnings. | ||
9 | /// | ||
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 | ||
12 | /// information which can be used by IDE to create fixes. Diagnostics are | ||
13 | /// expressed in terms of macro-expanded syntax tree nodes (so, it's a bad idea | ||
14 | /// to diagnostic in a salsa value). | ||
15 | /// | ||
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 | ||
18 | /// include source locations. Such internal diagnostic are transformed into an | ||
19 | /// instance of `Diagnostic` on demand. | ||
7 | pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { | 20 | pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { |
8 | fn file(&self) -> HirFileId; | 21 | fn file(&self) -> HirFileId; |
9 | fn syntax_node(&self) -> SyntaxNodePtr; | 22 | fn syntax_node(&self) -> SyntaxNodePtr; |
@@ -34,14 +47,8 @@ impl Diagnostics { | |||
34 | 47 | ||
35 | #[derive(Debug)] | 48 | #[derive(Debug)] |
36 | pub struct NoSuchField { | 49 | pub struct NoSuchField { |
37 | pub(crate) file: HirFileId, | 50 | pub file: HirFileId, |
38 | pub(crate) field: AstPtr<ast::NamedField>, | 51 | pub field: AstPtr<ast::NamedField>, |
39 | } | ||
40 | |||
41 | impl NoSuchField { | ||
42 | pub fn field(&self) -> AstPtr<ast::NamedField> { | ||
43 | self.field | ||
44 | } | ||
45 | } | 52 | } |
46 | 53 | ||
47 | impl Diagnostic for NoSuchField { | 54 | impl Diagnostic for NoSuchField { |
@@ -58,3 +65,25 @@ impl Diagnostic for NoSuchField { | |||
58 | self | 65 | self |
59 | } | 66 | } |
60 | } | 67 | } |
68 | |||
69 | #[derive(Debug)] | ||
70 | pub struct UnresolvedModule { | ||
71 | pub file: HirFileId, | ||
72 | pub decl: AstPtr<ast::Module>, | ||
73 | pub candidate: RelativePathBuf, | ||
74 | } | ||
75 | |||
76 | impl Diagnostic for UnresolvedModule { | ||
77 | fn file(&self) -> HirFileId { | ||
78 | self.file | ||
79 | } | ||
80 | fn syntax_node(&self) -> SyntaxNodePtr { | ||
81 | self.decl.into() | ||
82 | } | ||
83 | fn message(&self) -> String { | ||
84 | "unresolved module".to_string() | ||
85 | } | ||
86 | fn as_any(&self) -> &(Any + Send + 'static) { | ||
87 | self | ||
88 | } | ||
89 | } | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 390aef0a9..ce54d7608 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -64,7 +64,7 @@ pub use self::{ | |||
64 | 64 | ||
65 | pub use self::code_model_api::{ | 65 | pub use self::code_model_api::{ |
66 | Crate, CrateDependency, | 66 | Crate, CrateDependency, |
67 | Module, ModuleDef, ModuleSource, Problem, | 67 | Module, ModuleDef, ModuleSource, |
68 | Struct, Enum, EnumVariant, | 68 | Struct, Enum, EnumVariant, |
69 | Function, FnSignature, | 69 | Function, FnSignature, |
70 | StructField, FieldSource, | 70 | StructField, FieldSource, |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index d361cf9e6..416f114b4 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -56,14 +56,17 @@ 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; | ||
59 | use ra_arena::{Arena, RawId, impl_arena_id}; | 60 | use ra_arena::{Arena, RawId, impl_arena_id}; |
60 | use ra_db::{FileId, Edition}; | 61 | use ra_db::{FileId, Edition}; |
62 | use ra_syntax::{AstNode, AstPtr, ast}; | ||
61 | use test_utils::tested_by; | 63 | use test_utils::tested_by; |
62 | 64 | ||
63 | use crate::{ | 65 | use crate::{ |
64 | ModuleDef, Name, Crate, Module, Problem, | 66 | ModuleDef, Name, Crate, Module, |
65 | DefDatabase, Path, PathKind, HirFileId, | 67 | DefDatabase, Path, PathKind, HirFileId, |
66 | ids::{SourceItemId, SourceFileItemId, MacroCallId}, | 68 | ids::{SourceItemId, SourceFileItemId, MacroCallId}, |
69 | diagnostics::{Diagnostics, UnresolvedModule}, | ||
67 | }; | 70 | }; |
68 | 71 | ||
69 | pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap}; | 72 | pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap}; |
@@ -85,7 +88,7 @@ pub struct CrateDefMap { | |||
85 | macros: Arena<CrateMacroId, mbe::MacroRules>, | 88 | macros: Arena<CrateMacroId, mbe::MacroRules>, |
86 | public_macros: FxHashMap<Name, CrateMacroId>, | 89 | public_macros: FxHashMap<Name, CrateMacroId>, |
87 | macro_resolutions: FxHashMap<MacroCallId, (Crate, CrateMacroId)>, | 90 | macro_resolutions: FxHashMap<MacroCallId, (Crate, CrateMacroId)>, |
88 | problems: CrateDefMapProblems, | 91 | diagnostics: Vec<DefDiagnostic>, |
89 | } | 92 | } |
90 | 93 | ||
91 | impl std::ops::Index<CrateModuleId> for CrateDefMap { | 94 | impl std::ops::Index<CrateModuleId> for CrateDefMap { |
@@ -125,21 +128,6 @@ pub(crate) struct ModuleData { | |||
125 | pub(crate) definition: Option<FileId>, | 128 | pub(crate) definition: Option<FileId>, |
126 | } | 129 | } |
127 | 130 | ||
128 | #[derive(Default, Debug, PartialEq, Eq)] | ||
129 | pub(crate) struct CrateDefMapProblems { | ||
130 | problems: Vec<(SourceItemId, Problem)>, | ||
131 | } | ||
132 | |||
133 | impl CrateDefMapProblems { | ||
134 | fn add(&mut self, source_item_id: SourceItemId, problem: Problem) { | ||
135 | self.problems.push((source_item_id, problem)) | ||
136 | } | ||
137 | |||
138 | pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a SourceItemId, &'a Problem)> + 'a { | ||
139 | self.problems.iter().map(|(s, p)| (s, p)) | ||
140 | } | ||
141 | } | ||
142 | |||
143 | #[derive(Debug, Default, PartialEq, Eq, Clone)] | 131 | #[derive(Debug, Default, PartialEq, Eq, Clone)] |
144 | pub struct ModuleScope { | 132 | pub struct ModuleScope { |
145 | items: FxHashMap<Name, Resolution>, | 133 | items: FxHashMap<Name, Resolution>, |
@@ -212,7 +200,7 @@ impl CrateDefMap { | |||
212 | macros: Arena::default(), | 200 | macros: Arena::default(), |
213 | public_macros: FxHashMap::default(), | 201 | public_macros: FxHashMap::default(), |
214 | macro_resolutions: FxHashMap::default(), | 202 | macro_resolutions: FxHashMap::default(), |
215 | problems: CrateDefMapProblems::default(), | 203 | diagnostics: Vec::new(), |
216 | } | 204 | } |
217 | }; | 205 | }; |
218 | let def_map = collector::collect_defs(db, def_map); | 206 | let def_map = collector::collect_defs(db, def_map); |
@@ -224,10 +212,6 @@ impl CrateDefMap { | |||
224 | self.root | 212 | self.root |
225 | } | 213 | } |
226 | 214 | ||
227 | pub(crate) fn problems(&self) -> &CrateDefMapProblems { | ||
228 | &self.problems | ||
229 | } | ||
230 | |||
231 | pub(crate) fn mk_module(&self, module_id: CrateModuleId) -> Module { | 215 | pub(crate) fn mk_module(&self, module_id: CrateModuleId) -> Module { |
232 | Module { krate: self.krate, module_id } | 216 | Module { krate: self.krate, module_id } |
233 | } | 217 | } |
@@ -240,6 +224,15 @@ impl CrateDefMap { | |||
240 | &self.extern_prelude | 224 | &self.extern_prelude |
241 | } | 225 | } |
242 | 226 | ||
227 | pub(crate) fn add_diagnostics( | ||
228 | &self, | ||
229 | db: &impl DefDatabase, | ||
230 | module: CrateModuleId, | ||
231 | sink: &mut Diagnostics, | ||
232 | ) { | ||
233 | self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink)) | ||
234 | } | ||
235 | |||
243 | pub(crate) fn resolve_macro( | 236 | pub(crate) fn resolve_macro( |
244 | &self, | 237 | &self, |
245 | macro_call_id: MacroCallId, | 238 | macro_call_id: MacroCallId, |
@@ -452,3 +445,31 @@ impl CrateDefMap { | |||
452 | } | 445 | } |
453 | } | 446 | } |
454 | } | 447 | } |
448 | |||
449 | #[derive(Debug, PartialEq, Eq)] | ||
450 | enum DefDiagnostic { | ||
451 | UnresolvedModule { | ||
452 | module: CrateModuleId, | ||
453 | declaration: SourceItemId, | ||
454 | candidate: RelativePathBuf, | ||
455 | }, | ||
456 | } | ||
457 | |||
458 | impl DefDiagnostic { | ||
459 | fn add_to(&self, db: &impl DefDatabase, target_module: CrateModuleId, sink: &mut Diagnostics) { | ||
460 | match self { | ||
461 | DefDiagnostic::UnresolvedModule { module, declaration, candidate } => { | ||
462 | if *module != target_module { | ||
463 | return; | ||
464 | } | ||
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 | } | ||
473 | } | ||
474 | } | ||
475 | } | ||
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index c5b73cfbe..bc6bc5e7f 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs | |||
@@ -6,9 +6,9 @@ use ra_db::FileId; | |||
6 | 6 | ||
7 | use crate::{ | 7 | 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, Problem, Crate, | 9 | DefDatabase, HirFileId, Name, Path, Crate, |
10 | KnownName, | 10 | KnownName, |
11 | nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, raw}, | 11 | nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, raw, DefDiagnostic}, |
12 | ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, | 12 | ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, |
13 | }; | 13 | }; |
14 | 14 | ||
@@ -405,25 +405,27 @@ where | |||
405 | raw::ModuleData::Declaration { name, source_item_id } => { | 405 | raw::ModuleData::Declaration { name, source_item_id } => { |
406 | let source_item_id = source_item_id.with_file_id(self.file_id); | 406 | let source_item_id = source_item_id.with_file_id(self.file_id); |
407 | let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); | 407 | let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); |
408 | let (file_ids, problem) = | 408 | match resolve_submodule(self.def_collector.db, self.file_id, name, is_root) { |
409 | resolve_submodule(self.def_collector.db, self.file_id, name, is_root); | 409 | Ok(file_id) => { |
410 | 410 | let module_id = | |
411 | if let Some(problem) = problem { | 411 | self.push_child_module(name.clone(), source_item_id, Some(file_id)); |
412 | self.def_collector.def_map.problems.add(source_item_id, problem) | 412 | let raw_items = self.def_collector.db.raw_items(file_id); |
413 | } | 413 | ModCollector { |
414 | 414 | def_collector: &mut *self.def_collector, | |
415 | if let Some(&file_id) = file_ids.first() { | 415 | module_id, |
416 | let module_id = | 416 | file_id: file_id.into(), |
417 | self.push_child_module(name.clone(), source_item_id, Some(file_id)); | 417 | raw_items: &raw_items, |
418 | let raw_items = self.def_collector.db.raw_items(file_id); | 418 | } |
419 | ModCollector { | 419 | .collect(raw_items.items()) |
420 | def_collector: &mut *self.def_collector, | ||
421 | module_id, | ||
422 | file_id: file_id.into(), | ||
423 | raw_items: &raw_items, | ||
424 | } | 420 | } |
425 | .collect(raw_items.items()) | 421 | Err(candidate) => self.def_collector.def_map.diagnostics.push( |
426 | } | 422 | DefDiagnostic::UnresolvedModule { |
423 | module: self.module_id, | ||
424 | declaration: source_item_id, | ||
425 | candidate, | ||
426 | }, | ||
427 | ), | ||
428 | }; | ||
427 | } | 429 | } |
428 | } | 430 | } |
429 | } | 431 | } |
@@ -524,7 +526,7 @@ fn resolve_submodule( | |||
524 | file_id: HirFileId, | 526 | file_id: HirFileId, |
525 | name: &Name, | 527 | name: &Name, |
526 | is_root: bool, | 528 | is_root: bool, |
527 | ) -> (Vec<FileId>, Option<Problem>) { | 529 | ) -> Result<FileId, RelativePathBuf> { |
528 | // FIXME: handle submodules of inline modules properly | 530 | // FIXME: handle submodules of inline modules properly |
529 | let file_id = file_id.original_file(db); | 531 | let file_id = file_id.original_file(db); |
530 | let source_root_id = db.file_source_root(file_id); | 532 | let source_root_id = db.file_source_root(file_id); |
@@ -545,17 +547,10 @@ fn resolve_submodule( | |||
545 | candidates.push(file_dir_mod.clone()); | 547 | candidates.push(file_dir_mod.clone()); |
546 | }; | 548 | }; |
547 | let sr = db.source_root(source_root_id); | 549 | let sr = db.source_root(source_root_id); |
548 | let points_to = candidates | 550 | let mut points_to = candidates.into_iter().filter_map(|path| sr.files.get(&path)).map(|&it| it); |
549 | .into_iter() | 551 | // FIXME: handle ambiguity |
550 | .filter_map(|path| sr.files.get(&path)) | 552 | match points_to.next() { |
551 | .map(|&it| it) | 553 | Some(file_id) => Ok(file_id), |
552 | .collect::<Vec<_>>(); | 554 | None => Err(if is_dir_owner { file_mod } else { file_dir_mod }), |
553 | let problem = if points_to.is_empty() { | 555 | } |
554 | Some(Problem::UnresolvedModule { | ||
555 | candidate: if is_dir_owner { file_mod } else { file_dir_mod }, | ||
556 | }) | ||
557 | } else { | ||
558 | None | ||
559 | }; | ||
560 | (points_to, problem) | ||
561 | } | 556 | } |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 02708ba0f..6dc3edc7a 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -120,9 +120,9 @@ impl InferenceResult { | |||
120 | &self, | 120 | &self, |
121 | db: &impl HirDatabase, | 121 | db: &impl HirDatabase, |
122 | owner: Function, | 122 | owner: Function, |
123 | diagnostics: &mut Diagnostics, | 123 | sink: &mut Diagnostics, |
124 | ) { | 124 | ) { |
125 | self.diagnostics.iter().for_each(|it| it.add_to(db, owner, diagnostics)) | 125 | self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink)) |
126 | } | 126 | } |
127 | } | 127 | } |
128 | 128 | ||
@@ -1277,12 +1277,17 @@ mod diagnostics { | |||
1277 | } | 1277 | } |
1278 | 1278 | ||
1279 | impl InferenceDiagnostic { | 1279 | impl InferenceDiagnostic { |
1280 | pub(super) fn add_to(&self, db: &impl HirDatabase, owner: Function, acc: &mut Diagnostics) { | 1280 | pub(super) fn add_to( |
1281 | &self, | ||
1282 | db: &impl HirDatabase, | ||
1283 | owner: Function, | ||
1284 | sink: &mut Diagnostics, | ||
1285 | ) { | ||
1281 | match self { | 1286 | match self { |
1282 | InferenceDiagnostic::NoSuchField { expr, field } => { | 1287 | InferenceDiagnostic::NoSuchField { expr, field } => { |
1283 | let (file, _) = owner.source(db); | 1288 | let (file, _) = owner.source(db); |
1284 | let field = owner.body_source_map(db).field_syntax(*expr, *field); | 1289 | let field = owner.body_source_map(db).field_syntax(*expr, *field); |
1285 | acc.push(NoSuchField { file, field }) | 1290 | sink.push(NoSuchField { file, field }) |
1286 | } | 1291 | } |
1287 | } | 1292 | } |
1288 | } | 1293 | } |
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs index 943fd2f53..254342c0a 100644 --- a/crates/ra_ide_api/src/diagnostics.rs +++ b/crates/ra_ide_api/src/diagnostics.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use itertools::Itertools; | 1 | use itertools::Itertools; |
2 | use hir::{Problem, source_binder}; | 2 | use hir::{source_binder, diagnostics::Diagnostic as _}; |
3 | use ra_db::SourceDatabase; | 3 | use ra_db::SourceDatabase; |
4 | use ra_syntax::{ | 4 | use ra_syntax::{ |
5 | Location, SourceFile, SyntaxKind, TextRange, SyntaxNode, | 5 | Location, SourceFile, SyntaxKind, TextRange, SyntaxNode, |
@@ -28,7 +28,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> | |||
28 | } | 28 | } |
29 | 29 | ||
30 | if let Some(m) = source_binder::module_from_file_id(db, file_id) { | 30 | if let Some(m) = source_binder::module_from_file_id(db, file_id) { |
31 | check_module(&mut res, db, file_id, m); | 31 | check_module(&mut res, db, m); |
32 | }; | 32 | }; |
33 | res | 33 | res |
34 | } | 34 | } |
@@ -128,46 +128,40 @@ fn check_struct_shorthand_initialization( | |||
128 | Some(()) | 128 | Some(()) |
129 | } | 129 | } |
130 | 130 | ||
131 | fn check_module( | 131 | fn check_module(acc: &mut Vec<Diagnostic>, db: &RootDatabase, module: hir::Module) { |
132 | acc: &mut Vec<Diagnostic>, | 132 | let mut diagnostics = hir::diagnostics::Diagnostics::default(); |
133 | db: &RootDatabase, | 133 | module.diagnostics(db, &mut diagnostics); |
134 | file_id: FileId, | ||
135 | module: hir::Module, | ||
136 | ) { | ||
137 | for decl in module.declarations(db) { | 134 | for decl in module.declarations(db) { |
138 | match decl { | 135 | match decl { |
139 | hir::ModuleDef::Function(f) => check_function(acc, db, f), | 136 | hir::ModuleDef::Function(f) => f.diagnostics(db, &mut diagnostics), |
140 | _ => (), | 137 | _ => (), |
141 | } | 138 | } |
142 | } | 139 | } |
143 | 140 | ||
144 | let source_root = db.file_source_root(file_id); | 141 | for d in diagnostics.iter() { |
145 | for (name_node, problem) in module.problems(db) { | 142 | if let Some(d) = d.downcast_ref::<hir::diagnostics::UnresolvedModule>() { |
146 | let diag = match problem { | 143 | let source_root = db.file_source_root(d.file().original_file(db)); |
147 | Problem::UnresolvedModule { candidate } => { | 144 | let create_file = FileSystemEdit::CreateFile { source_root, path: d.candidate.clone() }; |
148 | let create_file = | 145 | let fix = SourceChange { |
149 | FileSystemEdit::CreateFile { source_root, path: candidate.clone() }; | 146 | label: "create module".to_string(), |
150 | let fix = SourceChange::file_system_edit("create module", create_file); | 147 | source_file_edits: Vec::new(), |
151 | Diagnostic { | 148 | file_system_edits: vec![create_file], |
152 | range: name_node.range(), | 149 | cursor_position: None, |
153 | message: "unresolved module".to_string(), | 150 | }; |
154 | severity: Severity::Error, | 151 | acc.push(Diagnostic { |
155 | fix: Some(fix), | 152 | range: d.syntax_node().range(), |
156 | } | 153 | message: d.message(), |
157 | } | 154 | severity: Severity::Error, |
158 | }; | 155 | fix: Some(fix), |
159 | acc.push(diag) | 156 | }) |
160 | } | 157 | } else { |
161 | } | 158 | acc.push(Diagnostic { |
162 | 159 | message: d.message(), | |
163 | fn check_function(acc: &mut Vec<Diagnostic>, db: &RootDatabase, function: hir::Function) { | 160 | range: d.syntax_node().range(), |
164 | for d in function.diagnostics(db).iter() { | 161 | severity: Severity::Error, |
165 | acc.push(Diagnostic { | 162 | fix: None, |
166 | message: d.message(), | 163 | }) |
167 | range: d.syntax_node().range(), | 164 | } |
168 | severity: Severity::Error, | ||
169 | fix: None, | ||
170 | }) | ||
171 | } | 165 | } |
172 | } | 166 | } |
173 | 167 | ||