aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/code_model_api.rs18
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs19
-rw-r--r--crates/ra_hir/src/diagnostics.rs45
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/nameres.rs65
-rw-r--r--crates/ra_hir/src/nameres/collector.rs63
-rw-r--r--crates/ra_hir/src/ty/infer.rs13
7 files changed, 126 insertions, 99 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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use relative_path::RelativePathBuf;
4use ra_db::{CrateId, SourceRootId, Edition}; 3use ra_db::{CrateId, SourceRootId, Edition};
5use ra_syntax::{ast::self, TreeArc, SyntaxNode}; 4use ra_syntax::{ast::self, TreeArc};
6 5
7use crate::{ 6use 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)]
100pub enum Problem {
101 UnresolvedModule { candidate: RelativePathBuf },
102}
103
104impl Module { 98impl 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 @@
1use ra_db::FileId; 1use ra_db::FileId;
2use ra_syntax::{ast, SyntaxNode, TreeArc, AstNode}; 2use ra_syntax::{ast, TreeArc, AstNode};
3 3
4use crate::{ 4use 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};
3use ra_syntax::{SyntaxNodePtr, AstPtr, ast}; 3use ra_syntax::{SyntaxNodePtr, AstPtr, ast};
4 4
5use crate::HirFileId; 5use crate::HirFileId;
6use 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.
7pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { 20pub 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)]
36pub struct NoSuchField { 49pub 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
41impl NoSuchField {
42 pub fn field(&self) -> AstPtr<ast::NamedField> {
43 self.field
44 }
45} 52}
46 53
47impl Diagnostic for NoSuchField { 54impl Diagnostic for NoSuchField {
@@ -58,3 +65,25 @@ impl Diagnostic for NoSuchField {
58 self 65 self
59 } 66 }
60} 67}
68
69#[derive(Debug)]
70pub struct UnresolvedModule {
71 pub file: HirFileId,
72 pub decl: AstPtr<ast::Module>,
73 pub candidate: RelativePathBuf,
74}
75
76impl 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
65pub use self::code_model_api::{ 65pub 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;
56use std::sync::Arc; 56use std::sync::Arc;
57 57
58use rustc_hash::FxHashMap; 58use rustc_hash::FxHashMap;
59use relative_path::RelativePathBuf;
59use ra_arena::{Arena, RawId, impl_arena_id}; 60use ra_arena::{Arena, RawId, impl_arena_id};
60use ra_db::{FileId, Edition}; 61use ra_db::{FileId, Edition};
62use ra_syntax::{AstNode, AstPtr, ast};
61use test_utils::tested_by; 63use test_utils::tested_by;
62 64
63use crate::{ 65use 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
69pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap}; 72pub(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
91impl std::ops::Index<CrateModuleId> for CrateDefMap { 94impl 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)]
129pub(crate) struct CrateDefMapProblems {
130 problems: Vec<(SourceItemId, Problem)>,
131}
132
133impl 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)]
144pub struct ModuleScope { 132pub 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)]
450enum DefDiagnostic {
451 UnresolvedModule {
452 module: CrateModuleId,
453 declaration: SourceItemId,
454 candidate: RelativePathBuf,
455 },
456}
457
458impl 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
7use crate::{ 7use 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 }