Skip to content

Commit 2a9a66d

Browse files
author
Jonas Schievink
committed
Add diagnostic types for unresolved crates/imports
1 parent 44f4510 commit 2a9a66d

File tree

3 files changed

+128
-19
lines changed

3 files changed

+128
-19
lines changed

crates/hir_def/src/diagnostics.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,45 @@ impl Diagnostic for UnresolvedModule {
2828
self
2929
}
3030
}
31+
32+
#[derive(Debug)]
33+
pub struct UnresolvedExternCrate {
34+
pub file: HirFileId,
35+
pub item: AstPtr<ast::ExternCrate>,
36+
}
37+
38+
impl Diagnostic for UnresolvedExternCrate {
39+
fn code(&self) -> DiagnosticCode {
40+
DiagnosticCode("unresolved-extern-crate")
41+
}
42+
fn message(&self) -> String {
43+
"unresolved extern crate".to_string()
44+
}
45+
fn display_source(&self) -> InFile<SyntaxNodePtr> {
46+
InFile::new(self.file, self.item.clone().into())
47+
}
48+
fn as_any(&self) -> &(dyn Any + Send + 'static) {
49+
self
50+
}
51+
}
52+
53+
#[derive(Debug)]
54+
pub struct UnresolvedImport {
55+
pub file: HirFileId,
56+
pub node: AstPtr<ast::UseTree>,
57+
}
58+
59+
impl Diagnostic for UnresolvedImport {
60+
fn code(&self) -> DiagnosticCode {
61+
DiagnosticCode("unresolved-import")
62+
}
63+
fn message(&self) -> String {
64+
"unresolved import".to_string()
65+
}
66+
fn display_source(&self) -> InFile<SyntaxNodePtr> {
67+
InFile::new(self.file, self.node.clone().into())
68+
}
69+
fn as_any(&self) -> &(dyn Any + Send + 'static) {
70+
self
71+
}
72+
}

crates/hir_def/src/nameres.rs

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -288,38 +288,107 @@ pub enum ModuleSource {
288288

289289
mod diagnostics {
290290
use hir_expand::diagnostics::DiagnosticSink;
291+
use hir_expand::hygiene::Hygiene;
292+
use hir_expand::InFile;
291293
use syntax::{ast, AstPtr};
292294

293-
use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId};
295+
use crate::path::ModPath;
296+
use crate::{db::DefDatabase, diagnostics::*, nameres::LocalModuleId, AstId};
294297

295298
#[derive(Debug, PartialEq, Eq)]
296-
pub(super) enum DefDiagnostic {
297-
UnresolvedModule {
298-
module: LocalModuleId,
299-
declaration: AstId<ast::Module>,
300-
candidate: String,
301-
},
299+
enum DiagnosticKind {
300+
UnresolvedModule { declaration: AstId<ast::Module>, candidate: String },
301+
302+
UnresolvedExternCrate { ast: AstId<ast::ExternCrate> },
303+
304+
UnresolvedImport { ast: AstId<ast::Use>, index: usize },
305+
}
306+
307+
#[derive(Debug, PartialEq, Eq)]
308+
pub(super) struct DefDiagnostic {
309+
in_module: LocalModuleId,
310+
kind: DiagnosticKind,
302311
}
303312

304313
impl DefDiagnostic {
314+
pub(super) fn unresolved_module(
315+
container: LocalModuleId,
316+
declaration: AstId<ast::Module>,
317+
candidate: String,
318+
) -> Self {
319+
Self {
320+
in_module: container,
321+
kind: DiagnosticKind::UnresolvedModule { declaration, candidate },
322+
}
323+
}
324+
325+
pub(super) fn unresolved_extern_crate(
326+
container: LocalModuleId,
327+
declaration: AstId<ast::ExternCrate>,
328+
) -> Self {
329+
Self {
330+
in_module: container,
331+
kind: DiagnosticKind::UnresolvedExternCrate { ast: declaration },
332+
}
333+
}
334+
335+
pub(super) fn unresolved_import(
336+
container: LocalModuleId,
337+
ast: AstId<ast::Use>,
338+
index: usize,
339+
) -> Self {
340+
Self { in_module: container, kind: DiagnosticKind::UnresolvedImport { ast, index } }
341+
}
342+
305343
pub(super) fn add_to(
306344
&self,
307345
db: &dyn DefDatabase,
308346
target_module: LocalModuleId,
309347
sink: &mut DiagnosticSink,
310348
) {
311-
match self {
312-
DefDiagnostic::UnresolvedModule { module, declaration, candidate } => {
313-
if *module != target_module {
314-
return;
315-
}
349+
if self.in_module != target_module {
350+
return;
351+
}
352+
353+
match &self.kind {
354+
DiagnosticKind::UnresolvedModule { declaration, candidate } => {
316355
let decl = declaration.to_node(db.upcast());
317356
sink.push(UnresolvedModule {
318357
file: declaration.file_id,
319358
decl: AstPtr::new(&decl),
320359
candidate: candidate.clone(),
321360
})
322361
}
362+
363+
DiagnosticKind::UnresolvedExternCrate { ast } => {
364+
let item = ast.to_node(db.upcast());
365+
sink.push(UnresolvedExternCrate {
366+
file: ast.file_id,
367+
item: AstPtr::new(&item),
368+
});
369+
}
370+
371+
DiagnosticKind::UnresolvedImport { ast, index } => {
372+
let use_item = ast.to_node(db.upcast());
373+
let hygiene = Hygiene::new(db.upcast(), ast.file_id);
374+
let mut cur = 0;
375+
let mut tree = None;
376+
ModPath::expand_use_item(
377+
InFile::new(ast.file_id, use_item),
378+
&hygiene,
379+
|_mod_path, use_tree, _is_glob, _alias| {
380+
if cur == *index {
381+
tree = Some(use_tree.clone());
382+
}
383+
384+
cur += 1;
385+
},
386+
);
387+
388+
if let Some(tree) = tree {
389+
sink.push(UnresolvedImport { file: ast.file_id, node: AstPtr::new(&tree) });
390+
}
391+
}
323392
}
324393
}
325394
}

crates/hir_def/src/nameres/collector.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,13 +1051,11 @@ impl ModCollector<'_, '_> {
10511051
self.import_all_legacy_macros(module_id);
10521052
}
10531053
}
1054-
Err(candidate) => self.def_collector.def_map.diagnostics.push(
1055-
DefDiagnostic::UnresolvedModule {
1056-
module: self.module_id,
1057-
declaration: ast_id,
1058-
candidate,
1059-
},
1060-
),
1054+
Err(candidate) => {
1055+
self.def_collector.def_map.diagnostics.push(
1056+
DefDiagnostic::unresolved_module(self.module_id, ast_id, candidate),
1057+
);
1058+
}
10611059
};
10621060
}
10631061
}

0 commit comments

Comments
 (0)