mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
Track import sources and emit diagnostics
This commit is contained in:
parent
4ac9a2e5d3
commit
4785162b08
2 changed files with 60 additions and 21 deletions
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
use base_db::{CrateId, FileId, ProcMacroId};
|
use base_db::{CrateId, FileId, ProcMacroId};
|
||||||
use cfg::CfgOptions;
|
use cfg::CfgOptions;
|
||||||
|
use hir_expand::InFile;
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
ast_id_map::FileAstId,
|
ast_id_map::FileAstId,
|
||||||
builtin_derive::find_builtin_derive,
|
builtin_derive::find_builtin_derive,
|
||||||
|
@ -21,9 +22,7 @@ use crate::{
|
||||||
attr::Attrs,
|
attr::Attrs,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
item_scope::{ImportType, PerNsGlobImports},
|
item_scope::{ImportType, PerNsGlobImports},
|
||||||
item_tree::{
|
item_tree::{self, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind},
|
||||||
self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind,
|
|
||||||
},
|
|
||||||
nameres::{
|
nameres::{
|
||||||
diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
|
diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
|
||||||
BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
|
BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
|
||||||
|
@ -111,6 +110,12 @@ impl PartialResolvedImport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
enum ImportSource {
|
||||||
|
Import(ItemTreeId<item_tree::Import>),
|
||||||
|
ExternCrate(ItemTreeId<item_tree::ExternCrate>),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
struct Import {
|
struct Import {
|
||||||
pub path: ModPath,
|
pub path: ModPath,
|
||||||
|
@ -120,11 +125,12 @@ struct Import {
|
||||||
pub is_prelude: bool,
|
pub is_prelude: bool,
|
||||||
pub is_extern_crate: bool,
|
pub is_extern_crate: bool,
|
||||||
pub is_macro_use: bool,
|
pub is_macro_use: bool,
|
||||||
|
source: ImportSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Import {
|
impl Import {
|
||||||
fn from_use(tree: &ItemTree, id: FileItemTreeId<item_tree::Import>) -> Self {
|
fn from_use(tree: &ItemTree, id: ItemTreeId<item_tree::Import>) -> Self {
|
||||||
let it = &tree[id];
|
let it = &tree[id.value];
|
||||||
let visibility = &tree[it.visibility];
|
let visibility = &tree[it.visibility];
|
||||||
Self {
|
Self {
|
||||||
path: it.path.clone(),
|
path: it.path.clone(),
|
||||||
|
@ -134,11 +140,12 @@ impl Import {
|
||||||
is_prelude: it.is_prelude,
|
is_prelude: it.is_prelude,
|
||||||
is_extern_crate: false,
|
is_extern_crate: false,
|
||||||
is_macro_use: false,
|
is_macro_use: false,
|
||||||
|
source: ImportSource::Import(id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_extern_crate(tree: &ItemTree, id: FileItemTreeId<item_tree::ExternCrate>) -> Self {
|
fn from_extern_crate(tree: &ItemTree, id: ItemTreeId<item_tree::ExternCrate>) -> Self {
|
||||||
let it = &tree[id];
|
let it = &tree[id.value];
|
||||||
let visibility = &tree[it.visibility];
|
let visibility = &tree[it.visibility];
|
||||||
Self {
|
Self {
|
||||||
path: it.path.clone(),
|
path: it.path.clone(),
|
||||||
|
@ -148,6 +155,7 @@ impl Import {
|
||||||
is_prelude: false,
|
is_prelude: false,
|
||||||
is_extern_crate: true,
|
is_extern_crate: true,
|
||||||
is_macro_use: it.is_macro_use,
|
is_macro_use: it.is_macro_use,
|
||||||
|
source: ImportSource::ExternCrate(id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,9 +253,10 @@ impl DefCollector<'_> {
|
||||||
|
|
||||||
let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
|
let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
|
||||||
// show unresolved imports in completion, etc
|
// show unresolved imports in completion, etc
|
||||||
for directive in unresolved_imports {
|
for directive in &unresolved_imports {
|
||||||
self.record_resolved_import(&directive)
|
self.record_resolved_import(directive)
|
||||||
}
|
}
|
||||||
|
self.unresolved_imports = unresolved_imports;
|
||||||
|
|
||||||
// Record proc-macros
|
// Record proc-macros
|
||||||
self.collect_proc_macro();
|
self.collect_proc_macro();
|
||||||
|
@ -778,7 +787,29 @@ impl DefCollector<'_> {
|
||||||
.collect(item_tree.top_level_items());
|
.collect(item_tree.top_level_items());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(self) -> CrateDefMap {
|
fn finish(mut self) -> CrateDefMap {
|
||||||
|
for directive in &self.unresolved_imports {
|
||||||
|
match directive.import.source {
|
||||||
|
ImportSource::Import(import) => {
|
||||||
|
let item_tree = self.db.item_tree(import.file_id);
|
||||||
|
let import_data = &item_tree[import.value];
|
||||||
|
self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
|
||||||
|
directive.module_id,
|
||||||
|
InFile::new(import.file_id, import_data.ast_id),
|
||||||
|
import_data.index,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
ImportSource::ExternCrate(krate) => {
|
||||||
|
let item_tree = self.db.item_tree(krate.file_id);
|
||||||
|
let extern_crate = &item_tree[krate.value];
|
||||||
|
self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
|
||||||
|
directive.module_id,
|
||||||
|
InFile::new(krate.file_id, extern_crate.ast_id),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.def_map
|
self.def_map
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -834,14 +865,20 @@ impl ModCollector<'_, '_> {
|
||||||
ModItem::Import(import_id) => {
|
ModItem::Import(import_id) => {
|
||||||
self.def_collector.unresolved_imports.push(ImportDirective {
|
self.def_collector.unresolved_imports.push(ImportDirective {
|
||||||
module_id: self.module_id,
|
module_id: self.module_id,
|
||||||
import: Import::from_use(&self.item_tree, import_id),
|
import: Import::from_use(
|
||||||
|
&self.item_tree,
|
||||||
|
InFile::new(self.file_id, import_id),
|
||||||
|
),
|
||||||
status: PartialResolvedImport::Unresolved,
|
status: PartialResolvedImport::Unresolved,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ModItem::ExternCrate(import_id) => {
|
ModItem::ExternCrate(import_id) => {
|
||||||
self.def_collector.unresolved_imports.push(ImportDirective {
|
self.def_collector.unresolved_imports.push(ImportDirective {
|
||||||
module_id: self.module_id,
|
module_id: self.module_id,
|
||||||
import: Import::from_extern_crate(&self.item_tree, import_id),
|
import: Import::from_extern_crate(
|
||||||
|
&self.item_tree,
|
||||||
|
InFile::new(self.file_id, import_id),
|
||||||
|
),
|
||||||
status: PartialResolvedImport::Unresolved,
|
status: PartialResolvedImport::Unresolved,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -688,8 +688,9 @@ fn unresolved_module_diagnostics() {
|
||||||
|
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
[
|
[
|
||||||
UnresolvedModule {
|
DefDiagnostic {
|
||||||
module: Idx::<ModuleData>(0),
|
in_module: Idx::<ModuleData>(0),
|
||||||
|
kind: UnresolvedModule {
|
||||||
declaration: InFile {
|
declaration: InFile {
|
||||||
file_id: HirFileId(
|
file_id: HirFileId(
|
||||||
FileId(
|
FileId(
|
||||||
|
@ -702,6 +703,7 @@ fn unresolved_module_diagnostics() {
|
||||||
},
|
},
|
||||||
candidate: "bar.rs",
|
candidate: "bar.rs",
|
||||||
},
|
},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
"#]]
|
"#]]
|
||||||
.assert_debug_eq(&crate_def_map.diagnostics);
|
.assert_debug_eq(&crate_def_map.diagnostics);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue