mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
populate resolve from unresolved imports
This commit is contained in:
parent
aab71bff8e
commit
9bb11aee44
2 changed files with 98 additions and 17 deletions
|
@ -103,9 +103,11 @@ impl ModuleDescriptor {
|
||||||
|
|
||||||
/// The root of the tree this module is part of
|
/// The root of the tree this module is part of
|
||||||
pub fn crate_root(&self) -> ModuleDescriptor {
|
pub fn crate_root(&self) -> ModuleDescriptor {
|
||||||
generate(Some(self.clone()), |it| it.parent())
|
let root_id = self.module_id.crate_root(&self.tree);
|
||||||
.last()
|
ModuleDescriptor {
|
||||||
.unwrap()
|
module_id: root_id,
|
||||||
|
..self.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `name` is `None` for the crate's root module
|
/// `name` is `None` for the crate's root module
|
||||||
|
@ -205,6 +207,11 @@ impl ModuleId {
|
||||||
let link = self.parent_link(tree)?;
|
let link = self.parent_link(tree)?;
|
||||||
Some(tree.link(link).owner)
|
Some(tree.link(link).owner)
|
||||||
}
|
}
|
||||||
|
fn crate_root(self, tree: &ModuleTree) -> ModuleId {
|
||||||
|
generate(Some(self), move |it| it.parent(tree))
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> {
|
fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> {
|
||||||
let link = tree
|
let link = tree
|
||||||
.module(self)
|
.module(self)
|
||||||
|
|
|
@ -52,10 +52,18 @@ struct ItemMap {
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
struct ModuleItems {
|
struct ModuleItems {
|
||||||
items: FxHashMap<SmolStr, DefId>,
|
items: FxHashMap<SmolStr, Resolution>,
|
||||||
import_resolutions: FxHashMap<LocalSyntaxPtr, DefId>,
|
import_resolutions: FxHashMap<LocalSyntaxPtr, DefId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolution is basically `DefId` atm, but it should account for stuff like
|
||||||
|
/// multiple namespaces, ambiguity and errors.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Resolution {
|
||||||
|
/// None for unresolved
|
||||||
|
def_id: Option<DefId>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
enum Namespace {
|
enum Namespace {
|
||||||
Types,
|
Types,
|
||||||
|
@ -221,22 +229,27 @@ where
|
||||||
{
|
{
|
||||||
fn resolve(&mut self) {
|
fn resolve(&mut self) {
|
||||||
for (&module_id, items) in self.input.iter() {
|
for (&module_id, items) in self.input.iter() {
|
||||||
self.populate_module(
|
self.populate_module(module_id, items)
|
||||||
module_id,
|
}
|
||||||
items,
|
|
||||||
)
|
for &module_id in self.input.keys() {
|
||||||
|
self.resolve_imports(module_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn populate_module(
|
fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) {
|
||||||
&mut self,
|
|
||||||
module_id: ModuleId,
|
|
||||||
input: &InputModuleItems,
|
|
||||||
) {
|
|
||||||
let file_id = module_id.source(&self.module_tree).file_id();
|
let file_id = module_id.source(&self.module_tree).file_id();
|
||||||
|
|
||||||
let mut module_items = ModuleItems::default();
|
let mut module_items = ModuleItems::default();
|
||||||
|
|
||||||
|
for import in input.imports.iter() {
|
||||||
|
if let Some((_, name)) = import.segments.last() {
|
||||||
|
module_items
|
||||||
|
.items
|
||||||
|
.insert(name.clone(), Resolution { def_id: None });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for item in input.items.iter() {
|
for item in input.items.iter() {
|
||||||
if item.kind == MODULE {
|
if item.kind == MODULE {
|
||||||
// handle submodules separatelly
|
// handle submodules separatelly
|
||||||
|
@ -245,7 +258,10 @@ where
|
||||||
let ptr = item.ptr.into_global(file_id);
|
let ptr = item.ptr.into_global(file_id);
|
||||||
let def_loc = DefLoc::Item { ptr };
|
let def_loc = DefLoc::Item { ptr };
|
||||||
let def_id = self.db.id_maps().def_id(def_loc);
|
let def_id = self.db.id_maps().def_id(def_loc);
|
||||||
module_items.items.insert(item.name.clone(), def_id);
|
let resolution = Resolution {
|
||||||
|
def_id: Some(def_id),
|
||||||
|
};
|
||||||
|
module_items.items.insert(item.name.clone(), resolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, mod_id) in module_id.children(&self.module_tree) {
|
for (name, mod_id) in module_id.children(&self.module_tree) {
|
||||||
|
@ -254,11 +270,69 @@ where
|
||||||
source_root: self.source_root,
|
source_root: self.source_root,
|
||||||
};
|
};
|
||||||
let def_id = self.db.id_maps().def_id(def_loc);
|
let def_id = self.db.id_maps().def_id(def_loc);
|
||||||
module_items.items.insert(name, def_id);
|
let resolution = Resolution {
|
||||||
|
def_id: Some(def_id),
|
||||||
|
};
|
||||||
|
module_items.items.insert(name, resolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.result.per_module.insert(module_id, module_items);
|
self.result.per_module.insert(module_id, module_items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_imports(&mut self, module_id: ModuleId) {
|
||||||
|
for import in self.input[&module_id].imports.iter() {
|
||||||
|
self.resolve_import(module_id, import);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_import(&mut self, module_id: ModuleId, import: &Path) {
|
||||||
|
let mut curr = match import.kind {
|
||||||
|
// TODO: handle extern crates
|
||||||
|
PathKind::Abs => return,
|
||||||
|
PathKind::Self_ => module_id,
|
||||||
|
PathKind::Super => {
|
||||||
|
match module_id.parent(&self.module_tree) {
|
||||||
|
Some(it) => it,
|
||||||
|
// TODO: error
|
||||||
|
None => return,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PathKind::Crate => module_id.crate_root(&self.module_tree),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i, (ptr, name)) in import.segments.iter().enumerate() {
|
||||||
|
let is_last = i == import.segments.len() - 1;
|
||||||
|
|
||||||
|
let def_id = match self.result.per_module[&curr].items.get(name) {
|
||||||
|
None => return,
|
||||||
|
Some(res) => match res.def_id {
|
||||||
|
Some(it) => it,
|
||||||
|
None => return,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
self.update(module_id, |items| {
|
||||||
|
items.import_resolutions.insert(*ptr, def_id);
|
||||||
|
});
|
||||||
|
|
||||||
|
if !is_last {
|
||||||
|
curr = match self.db.id_maps().def_loc(def_id) {
|
||||||
|
DefLoc::Module { id, .. } => id,
|
||||||
|
_ => return,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.update(module_id, |items| {
|
||||||
|
let res = Resolution {
|
||||||
|
def_id: Some(def_id),
|
||||||
|
};
|
||||||
|
items.items.insert(name.clone(), res);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleItems)) {
|
||||||
|
let module_items = self.result.per_module.get_mut(&module_id).unwrap();
|
||||||
|
f(module_items)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue