From 2a9a66d25485036455eac54747a83ac7c6557d44 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 16 Sep 2020 14:52:39 +0200 Subject: Add diagnostic types for unresolved crates/imports --- crates/hir_def/src/diagnostics.rs | 42 +++++++++++++++ crates/hir_def/src/nameres.rs | 93 ++++++++++++++++++++++++++++----- crates/hir_def/src/nameres/collector.rs | 12 ++--- 3 files changed, 128 insertions(+), 19 deletions(-) (limited to 'crates') diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs index 3e19d9117..2ec0fd3fb 100644 --- a/crates/hir_def/src/diagnostics.rs +++ b/crates/hir_def/src/diagnostics.rs @@ -28,3 +28,45 @@ impl Diagnostic for UnresolvedModule { self } } + +#[derive(Debug)] +pub struct UnresolvedExternCrate { + pub file: HirFileId, + pub item: AstPtr, +} + +impl Diagnostic for UnresolvedExternCrate { + fn code(&self) -> DiagnosticCode { + DiagnosticCode("unresolved-extern-crate") + } + fn message(&self) -> String { + "unresolved extern crate".to_string() + } + fn display_source(&self) -> InFile { + InFile::new(self.file, self.item.clone().into()) + } + fn as_any(&self) -> &(dyn Any + Send + 'static) { + self + } +} + +#[derive(Debug)] +pub struct UnresolvedImport { + pub file: HirFileId, + pub node: AstPtr, +} + +impl Diagnostic for UnresolvedImport { + fn code(&self) -> DiagnosticCode { + DiagnosticCode("unresolved-import") + } + fn message(&self) -> String { + "unresolved import".to_string() + } + fn display_source(&self) -> InFile { + InFile::new(self.file, self.node.clone().into()) + } + fn as_any(&self) -> &(dyn Any + Send + 'static) { + self + } +} diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index bf302172d..5e4d73c1f 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs @@ -288,31 +288,70 @@ pub enum ModuleSource { mod diagnostics { use hir_expand::diagnostics::DiagnosticSink; + use hir_expand::hygiene::Hygiene; + use hir_expand::InFile; use syntax::{ast, AstPtr}; - use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId}; + use crate::path::ModPath; + use crate::{db::DefDatabase, diagnostics::*, nameres::LocalModuleId, AstId}; #[derive(Debug, PartialEq, Eq)] - pub(super) enum DefDiagnostic { - UnresolvedModule { - module: LocalModuleId, - declaration: AstId, - candidate: String, - }, + enum DiagnosticKind { + UnresolvedModule { declaration: AstId, candidate: String }, + + UnresolvedExternCrate { ast: AstId }, + + UnresolvedImport { ast: AstId, index: usize }, + } + + #[derive(Debug, PartialEq, Eq)] + pub(super) struct DefDiagnostic { + in_module: LocalModuleId, + kind: DiagnosticKind, } impl DefDiagnostic { + pub(super) fn unresolved_module( + container: LocalModuleId, + declaration: AstId, + candidate: String, + ) -> Self { + Self { + in_module: container, + kind: DiagnosticKind::UnresolvedModule { declaration, candidate }, + } + } + + pub(super) fn unresolved_extern_crate( + container: LocalModuleId, + declaration: AstId, + ) -> Self { + Self { + in_module: container, + kind: DiagnosticKind::UnresolvedExternCrate { ast: declaration }, + } + } + + pub(super) fn unresolved_import( + container: LocalModuleId, + ast: AstId, + index: usize, + ) -> Self { + Self { in_module: container, kind: DiagnosticKind::UnresolvedImport { ast, index } } + } + pub(super) fn add_to( &self, db: &dyn DefDatabase, target_module: LocalModuleId, sink: &mut DiagnosticSink, ) { - match self { - DefDiagnostic::UnresolvedModule { module, declaration, candidate } => { - if *module != target_module { - return; - } + if self.in_module != target_module { + return; + } + + match &self.kind { + DiagnosticKind::UnresolvedModule { declaration, candidate } => { let decl = declaration.to_node(db.upcast()); sink.push(UnresolvedModule { file: declaration.file_id, @@ -320,6 +359,36 @@ mod diagnostics { candidate: candidate.clone(), }) } + + DiagnosticKind::UnresolvedExternCrate { ast } => { + let item = ast.to_node(db.upcast()); + sink.push(UnresolvedExternCrate { + file: ast.file_id, + item: AstPtr::new(&item), + }); + } + + DiagnosticKind::UnresolvedImport { ast, index } => { + let use_item = ast.to_node(db.upcast()); + let hygiene = Hygiene::new(db.upcast(), ast.file_id); + let mut cur = 0; + let mut tree = None; + ModPath::expand_use_item( + InFile::new(ast.file_id, use_item), + &hygiene, + |_mod_path, use_tree, _is_glob, _alias| { + if cur == *index { + tree = Some(use_tree.clone()); + } + + cur += 1; + }, + ); + + if let Some(tree) = tree { + sink.push(UnresolvedImport { file: ast.file_id, node: AstPtr::new(&tree) }); + } + } } } } diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 3e99c8773..bc286a8a3 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -1051,13 +1051,11 @@ impl ModCollector<'_, '_> { self.import_all_legacy_macros(module_id); } } - Err(candidate) => self.def_collector.def_map.diagnostics.push( - DefDiagnostic::UnresolvedModule { - module: self.module_id, - declaration: ast_id, - candidate, - }, - ), + Err(candidate) => { + self.def_collector.def_map.diagnostics.push( + DefDiagnostic::unresolved_module(self.module_id, ast_id, candidate), + ); + } }; } } -- cgit v1.2.3