rust-analyzer/crates/ra_hir/src/code_model_impl/module.rs
Aleksey Kladov 5270bca5f7 store macro def inside macro id
This solves the problem of "macro expansion can't call into name
resolution, because name resolution calls back into macro expansion"

Because we store macro def as a part of call id, macro expansion just
knows the def!
2019-03-26 13:20:54 +03:00

111 lines
3.8 KiB
Rust

use ra_db::FileId;
use ra_syntax::{ast, TreeArc, AstNode};
use crate::{
Module, ModuleSource, Name,
nameres::{CrateModuleId, ImportId},
HirDatabase, DefDatabase,
HirFileId, SourceItemId,
};
impl ModuleSource {
pub(crate) fn new(
db: &impl DefDatabase,
file_id: Option<FileId>,
decl_id: Option<SourceItemId>,
) -> ModuleSource {
match (file_id, decl_id) {
(Some(file_id), _) => {
let source_file = db.parse(file_id);
ModuleSource::SourceFile(source_file)
}
(None, Some(item_id)) => {
let module = db.file_item(item_id);
let module = ast::Module::cast(&*module).unwrap();
assert!(module.item_list().is_some(), "expected inline module");
ModuleSource::Module(module.to_owned())
}
(None, None) => panic!(),
}
}
}
impl Module {
fn with_module_id(&self, module_id: CrateModuleId) -> Module {
Module { module_id, krate: self.krate }
}
pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Option<Name> {
let def_map = db.crate_def_map(self.krate);
let parent = def_map[self.module_id].parent?;
def_map[parent].children.iter().find_map(|(name, module_id)| {
if *module_id == self.module_id {
Some(name.clone())
} else {
None
}
})
}
pub(crate) fn definition_source_impl(
&self,
db: &impl DefDatabase,
) -> (HirFileId, ModuleSource) {
let def_map = db.crate_def_map(self.krate);
let decl_id = def_map[self.module_id].declaration;
let file_id = def_map[self.module_id].definition;
let module_source = ModuleSource::new(db, file_id, decl_id);
let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id);
(file_id, module_source)
}
pub(crate) fn declaration_source_impl(
&self,
db: &impl HirDatabase,
) -> Option<(HirFileId, TreeArc<ast::Module>)> {
let def_map = db.crate_def_map(self.krate);
let decl = def_map[self.module_id].declaration?;
let syntax_node = db.file_item(decl);
let ast = ast::Module::cast(&syntax_node).unwrap().to_owned();
Some((decl.file_id, ast))
}
pub(crate) fn import_source_impl(
&self,
db: &impl HirDatabase,
import: ImportId,
) -> TreeArc<ast::PathSegment> {
let (file_id, source) = self.definition_source(db);
let (_, source_map) = db.raw_items_with_source_map(file_id);
source_map.get(&source, import)
}
pub(crate) fn crate_root_impl(&self, db: &impl DefDatabase) -> Module {
let def_map = db.crate_def_map(self.krate);
self.with_module_id(def_map.root())
}
/// Finds a child module with the specified name.
pub(crate) fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> {
let def_map = db.crate_def_map(self.krate);
let child_id = def_map[self.module_id].children.get(name)?;
Some(self.with_module_id(*child_id))
}
/// Iterates over all child modules.
pub(crate) fn children_impl(&self, db: &impl DefDatabase) -> impl Iterator<Item = Module> {
let def_map = db.crate_def_map(self.krate);
let children = def_map[self.module_id]
.children
.iter()
.map(|(_, module_id)| self.with_module_id(*module_id))
.collect::<Vec<_>>();
children.into_iter()
}
pub(crate) fn parent_impl(&self, db: &impl DefDatabase) -> Option<Module> {
let def_map = db.crate_def_map(self.krate);
let parent_id = def_map[self.module_id].parent?;
Some(self.with_module_id(parent_id))
}
}