Skip to content

Commit 4785162

Browse files
author
Jonas Schievink
committed
Track import sources and emit diagnostics
1 parent 4ac9a2e commit 4785162

File tree

2 files changed

+60
-21
lines changed

2 files changed

+60
-21
lines changed

crates/hir_def/src/nameres/collector.rs

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
66
use base_db::{CrateId, FileId, ProcMacroId};
77
use cfg::CfgOptions;
8+
use hir_expand::InFile;
89
use hir_expand::{
910
ast_id_map::FileAstId,
1011
builtin_derive::find_builtin_derive,
@@ -21,9 +22,7 @@ use crate::{
2122
attr::Attrs,
2223
db::DefDatabase,
2324
item_scope::{ImportType, PerNsGlobImports},
24-
item_tree::{
25-
self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind,
26-
},
25+
item_tree::{self, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind},
2726
nameres::{
2827
diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
2928
BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
@@ -111,6 +110,12 @@ impl PartialResolvedImport {
111110
}
112111
}
113112

113+
#[derive(Clone, Debug, Eq, PartialEq)]
114+
enum ImportSource {
115+
Import(ItemTreeId<item_tree::Import>),
116+
ExternCrate(ItemTreeId<item_tree::ExternCrate>),
117+
}
118+
114119
#[derive(Clone, Debug, Eq, PartialEq)]
115120
struct Import {
116121
pub path: ModPath,
@@ -120,11 +125,12 @@ struct Import {
120125
pub is_prelude: bool,
121126
pub is_extern_crate: bool,
122127
pub is_macro_use: bool,
128+
source: ImportSource,
123129
}
124130

125131
impl Import {
126-
fn from_use(tree: &ItemTree, id: FileItemTreeId<item_tree::Import>) -> Self {
127-
let it = &tree[id];
132+
fn from_use(tree: &ItemTree, id: ItemTreeId<item_tree::Import>) -> Self {
133+
let it = &tree[id.value];
128134
let visibility = &tree[it.visibility];
129135
Self {
130136
path: it.path.clone(),
@@ -134,11 +140,12 @@ impl Import {
134140
is_prelude: it.is_prelude,
135141
is_extern_crate: false,
136142
is_macro_use: false,
143+
source: ImportSource::Import(id),
137144
}
138145
}
139146

140-
fn from_extern_crate(tree: &ItemTree, id: FileItemTreeId<item_tree::ExternCrate>) -> Self {
141-
let it = &tree[id];
147+
fn from_extern_crate(tree: &ItemTree, id: ItemTreeId<item_tree::ExternCrate>) -> Self {
148+
let it = &tree[id.value];
142149
let visibility = &tree[it.visibility];
143150
Self {
144151
path: it.path.clone(),
@@ -148,6 +155,7 @@ impl Import {
148155
is_prelude: false,
149156
is_extern_crate: true,
150157
is_macro_use: it.is_macro_use,
158+
source: ImportSource::ExternCrate(id),
151159
}
152160
}
153161
}
@@ -245,9 +253,10 @@ impl DefCollector<'_> {
245253

246254
let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
247255
// show unresolved imports in completion, etc
248-
for directive in unresolved_imports {
249-
self.record_resolved_import(&directive)
256+
for directive in &unresolved_imports {
257+
self.record_resolved_import(directive)
250258
}
259+
self.unresolved_imports = unresolved_imports;
251260

252261
// Record proc-macros
253262
self.collect_proc_macro();
@@ -778,7 +787,29 @@ impl DefCollector<'_> {
778787
.collect(item_tree.top_level_items());
779788
}
780789

781-
fn finish(self) -> CrateDefMap {
790+
fn finish(mut self) -> CrateDefMap {
791+
for directive in &self.unresolved_imports {
792+
match directive.import.source {
793+
ImportSource::Import(import) => {
794+
let item_tree = self.db.item_tree(import.file_id);
795+
let import_data = &item_tree[import.value];
796+
self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
797+
directive.module_id,
798+
InFile::new(import.file_id, import_data.ast_id),
799+
import_data.index,
800+
));
801+
}
802+
ImportSource::ExternCrate(krate) => {
803+
let item_tree = self.db.item_tree(krate.file_id);
804+
let extern_crate = &item_tree[krate.value];
805+
self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
806+
directive.module_id,
807+
InFile::new(krate.file_id, extern_crate.ast_id),
808+
));
809+
}
810+
}
811+
}
812+
782813
self.def_map
783814
}
784815
}
@@ -834,14 +865,20 @@ impl ModCollector<'_, '_> {
834865
ModItem::Import(import_id) => {
835866
self.def_collector.unresolved_imports.push(ImportDirective {
836867
module_id: self.module_id,
837-
import: Import::from_use(&self.item_tree, import_id),
868+
import: Import::from_use(
869+
&self.item_tree,
870+
InFile::new(self.file_id, import_id),
871+
),
838872
status: PartialResolvedImport::Unresolved,
839873
})
840874
}
841875
ModItem::ExternCrate(import_id) => {
842876
self.def_collector.unresolved_imports.push(ImportDirective {
843877
module_id: self.module_id,
844-
import: Import::from_extern_crate(&self.item_tree, import_id),
878+
import: Import::from_extern_crate(
879+
&self.item_tree,
880+
InFile::new(self.file_id, import_id),
881+
),
845882
status: PartialResolvedImport::Unresolved,
846883
})
847884
}

crates/hir_def/src/nameres/tests/mod_resolution.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -688,19 +688,21 @@ fn unresolved_module_diagnostics() {
688688

689689
expect![[r#"
690690
[
691-
UnresolvedModule {
692-
module: Idx::<ModuleData>(0),
693-
declaration: InFile {
694-
file_id: HirFileId(
695-
FileId(
691+
DefDiagnostic {
692+
in_module: Idx::<ModuleData>(0),
693+
kind: UnresolvedModule {
694+
declaration: InFile {
695+
file_id: HirFileId(
696696
FileId(
697-
0,
697+
FileId(
698+
0,
699+
),
698700
),
699701
),
700-
),
701-
value: FileAstId::<syntax::ast::generated::nodes::Module>(1),
702+
value: FileAstId::<syntax::ast::generated::nodes::Module>(1),
703+
},
704+
candidate: "bar.rs",
702705
},
703-
candidate: "bar.rs",
704706
},
705707
]
706708
"#]]

0 commit comments

Comments
 (0)