aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-03-25 11:38:46 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-03-25 11:38:46 +0000
commitc4ead49361e4b8c0586b810399c8e96a468b891c (patch)
tree0b1ba767e34e3baef938f6b7672f95ce4572ec07 /crates/ra_hir/src/nameres.rs
parent8aedf9603df1bc68eafcd8dcf3c14e5a6a2c8638 (diff)
parent309716cffe93d065bcad0344b0f332425576c1e5 (diff)
Merge #1034
1034: HIR diagnostics API r=matklad a=matklad This PR introduces diagnostics API for HIR, so we can now start issuing errors and warnings! Here are requirements that this solution aims to fulfill: * structured diagnostics: rather than immediately rendering error to string, we provide a well-typed blob of data with error-description. These data is used by IDE to provide fixes * open set diagnostics: there's no single enum with all possible diagnostics, which hopefully should result in better modularity The `Diagnostic` trait describes "a diagnostic", which can be downcast to a specific diagnostic kind. Diagnostics are expressed in terms of macro-expanded syntax tree: they store pointers to syntax nodes. Diagnostics are self-contained: you don't need any context, besides `db`, to fully understand the meaning of a diagnostic. Because diagnostics are tied to the source, we can't store them in salsa. So subsystems like type-checking produce subsystem-local diagnostic (which is a closed `enum`), which is expressed in therms of subsystem IR. A separate step converts these proto-diagnostics into `Diagnostic`, by merging them with source-maps. Note that this PR stresses type-system quite a bit: we now type-check every function in open files to compute errors! Discussion on Zulip: https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0/topic/Diagnostics.20API Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/nameres.rs')
-rw-r--r--crates/ra_hir/src/nameres.rs81
1 files changed, 59 insertions, 22 deletions
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index d361cf9e6..56ed872d5 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -61,9 +61,11 @@ use ra_db::{FileId, Edition};
61use test_utils::tested_by; 61use test_utils::tested_by;
62 62
63use crate::{ 63use crate::{
64 ModuleDef, Name, Crate, Module, Problem, 64 ModuleDef, Name, Crate, Module,
65 DefDatabase, Path, PathKind, HirFileId, 65 DefDatabase, Path, PathKind, HirFileId,
66 ids::{SourceItemId, SourceFileItemId, MacroCallId}, 66 ids::{SourceItemId, SourceFileItemId, MacroCallId},
67 diagnostics::DiagnosticSink,
68 nameres::diagnostics::DefDiagnostic,
67}; 69};
68 70
69pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap}; 71pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap};
@@ -85,7 +87,7 @@ pub struct CrateDefMap {
85 macros: Arena<CrateMacroId, mbe::MacroRules>, 87 macros: Arena<CrateMacroId, mbe::MacroRules>,
86 public_macros: FxHashMap<Name, CrateMacroId>, 88 public_macros: FxHashMap<Name, CrateMacroId>,
87 macro_resolutions: FxHashMap<MacroCallId, (Crate, CrateMacroId)>, 89 macro_resolutions: FxHashMap<MacroCallId, (Crate, CrateMacroId)>,
88 problems: CrateDefMapProblems, 90 diagnostics: Vec<DefDiagnostic>,
89} 91}
90 92
91impl std::ops::Index<CrateModuleId> for CrateDefMap { 93impl std::ops::Index<CrateModuleId> for CrateDefMap {
@@ -125,21 +127,6 @@ pub(crate) struct ModuleData {
125 pub(crate) definition: Option<FileId>, 127 pub(crate) definition: Option<FileId>,
126} 128}
127 129
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)] 130#[derive(Debug, Default, PartialEq, Eq, Clone)]
144pub struct ModuleScope { 131pub struct ModuleScope {
145 items: FxHashMap<Name, Resolution>, 132 items: FxHashMap<Name, Resolution>,
@@ -212,7 +199,7 @@ impl CrateDefMap {
212 macros: Arena::default(), 199 macros: Arena::default(),
213 public_macros: FxHashMap::default(), 200 public_macros: FxHashMap::default(),
214 macro_resolutions: FxHashMap::default(), 201 macro_resolutions: FxHashMap::default(),
215 problems: CrateDefMapProblems::default(), 202 diagnostics: Vec::new(),
216 } 203 }
217 }; 204 };
218 let def_map = collector::collect_defs(db, def_map); 205 let def_map = collector::collect_defs(db, def_map);
@@ -224,10 +211,6 @@ impl CrateDefMap {
224 self.root 211 self.root
225 } 212 }
226 213
227 pub(crate) fn problems(&self) -> &CrateDefMapProblems {
228 &self.problems
229 }
230
231 pub(crate) fn mk_module(&self, module_id: CrateModuleId) -> Module { 214 pub(crate) fn mk_module(&self, module_id: CrateModuleId) -> Module {
232 Module { krate: self.krate, module_id } 215 Module { krate: self.krate, module_id }
233 } 216 }
@@ -240,6 +223,15 @@ impl CrateDefMap {
240 &self.extern_prelude 223 &self.extern_prelude
241 } 224 }
242 225
226 pub(crate) fn add_diagnostics(
227 &self,
228 db: &impl DefDatabase,
229 module: CrateModuleId,
230 sink: &mut DiagnosticSink,
231 ) {
232 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
233 }
234
243 pub(crate) fn resolve_macro( 235 pub(crate) fn resolve_macro(
244 &self, 236 &self,
245 macro_call_id: MacroCallId, 237 macro_call_id: MacroCallId,
@@ -452,3 +444,48 @@ impl CrateDefMap {
452 } 444 }
453 } 445 }
454} 446}
447
448mod diagnostics {
449 use relative_path::RelativePathBuf;
450 use ra_syntax::{AstPtr, AstNode, ast};
451
452 use crate::{
453 SourceItemId, DefDatabase,
454 nameres::CrateModuleId,
455 diagnostics::{DiagnosticSink, UnresolvedModule},
456};
457
458 #[derive(Debug, PartialEq, Eq)]
459 pub(super) enum DefDiagnostic {
460 UnresolvedModule {
461 module: CrateModuleId,
462 declaration: SourceItemId,
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 })
486 }
487 }
488 }
489 }
490
491}