rust/crates/ra_hir/src/query_definitions.rs

194 lines
6.4 KiB
Rust
Raw Normal View History

2018-11-28 01:42:26 +01:00
use std::{
sync::Arc,
time::Instant,
};
use rustc_hash::FxHashMap;
use ra_syntax::{
2019-01-01 18:59:00 +01:00
AstNode, SyntaxNode, SourceFileNode,
2018-12-27 21:51:44 +01:00
ast::{self, NameOwner, ModuleItemOwner}
2018-11-28 01:42:26 +01:00
};
use ra_db::{SourceRootId, FileId, Cancelable,};
use crate::{
2019-01-01 18:59:00 +01:00
SourceFileItems, SourceItemId, DefKind, Function, DefId, Name, AsName, MFileId,
2019-01-01 19:52:07 +01:00
macros::MacroCallLoc,
2018-12-04 21:44:00 +01:00
db::HirDatabase,
2018-12-27 21:51:44 +01:00
function::FnScopes,
2018-12-04 21:44:00 +01:00
module::{
ModuleSource, ModuleSourceNode, ModuleId,
imp::Submodule,
nameres::{InputModuleItems, ItemMap, Resolver},
},
adt::{StructData, EnumData},
2018-11-28 01:42:26 +01:00
};
2018-12-27 21:51:44 +01:00
pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Arc<FnScopes> {
let function = Function::new(def_id);
let syntax = function.syntax(db);
2018-11-28 01:42:26 +01:00
let res = FnScopes::new(syntax.borrowed());
Arc::new(res)
}
pub(super) fn struct_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<StructData>> {
let def_loc = def_id.loc(db);
assert!(def_loc.kind == DefKind::Struct);
let syntax = db.file_item(def_loc.source_item_id);
let struct_def =
ast::StructDef::cast(syntax.borrowed()).expect("struct def should point to StructDef node");
Ok(Arc::new(StructData::new(struct_def.borrowed())))
}
pub(super) fn enum_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<EnumData>> {
let def_loc = def_id.loc(db);
assert!(def_loc.kind == DefKind::Enum);
let syntax = db.file_item(def_loc.source_item_id);
let enum_def =
ast::EnumDef::cast(syntax.borrowed()).expect("enum def should point to EnumDef node");
Ok(Arc::new(EnumData::new(enum_def.borrowed())))
}
2019-01-01 18:59:00 +01:00
pub(super) fn m_source_file(db: &impl HirDatabase, mfile_id: MFileId) -> SourceFileNode {
match mfile_id {
MFileId::File(file_id) => db.source_file(file_id),
MFileId::Macro(m) => {
if let Some(exp) = db.expand_macro_invocation(m) {
return exp.file();
}
SourceFileNode::parse("")
}
}
}
pub(super) fn file_items(db: &impl HirDatabase, mfile_id: MFileId) -> Arc<SourceFileItems> {
let source_file = db.m_source_file(mfile_id);
2018-11-28 01:42:26 +01:00
let source_file = source_file.borrowed();
2019-01-01 18:59:00 +01:00
let res = SourceFileItems::new(mfile_id, source_file);
2018-11-28 01:42:26 +01:00
Arc::new(res)
}
pub(super) fn file_item(db: &impl HirDatabase, source_item_id: SourceItemId) -> SyntaxNode {
match source_item_id.item_id {
2019-01-01 18:59:00 +01:00
Some(id) => db.file_items(source_item_id.mfile_id)[id].clone(),
None => db.m_source_file(source_item_id.mfile_id).syntax().owned(),
}
2018-11-28 01:42:26 +01:00
}
pub(crate) fn submodules(
db: &impl HirDatabase,
source: ModuleSource,
) -> Cancelable<Arc<Vec<Submodule>>> {
db.check_canceled()?;
let file_id = source.file_id();
let submodules = match source.resolve(db) {
ModuleSourceNode::SourceFile(it) => collect_submodules(db, file_id, it.borrowed()),
ModuleSourceNode::Module(it) => it
.borrowed()
.item_list()
.map(|it| collect_submodules(db, file_id, it))
.unwrap_or_else(Vec::new),
};
return Ok(Arc::new(submodules));
fn collect_submodules<'a>(
db: &impl HirDatabase,
file_id: FileId,
root: impl ast::ModuleItemOwner<'a>,
) -> Vec<Submodule> {
modules(root)
.map(|(name, m)| {
if m.has_semi() {
Submodule::Declaration(name)
} else {
let src = ModuleSource::new_inline(db, file_id, m);
Submodule::Definition(name, src)
}
})
.collect()
}
}
pub(crate) fn modules<'a>(
root: impl ast::ModuleItemOwner<'a>,
2018-12-27 18:07:21 +01:00
) -> impl Iterator<Item = (Name, ast::Module<'a>)> {
2018-11-28 01:42:26 +01:00
root.items()
.filter_map(|item| match item {
ast::ModuleItem::Module(m) => Some(m),
_ => None,
})
.filter_map(|module| {
2018-12-27 18:07:21 +01:00
let name = module.name()?.as_name();
2018-11-28 01:42:26 +01:00
Some((name, module))
})
}
pub(super) fn input_module_items(
db: &impl HirDatabase,
2019-01-01 19:52:07 +01:00
source_root_id: SourceRootId,
2018-11-28 01:42:26 +01:00
module_id: ModuleId,
) -> Cancelable<Arc<InputModuleItems>> {
2019-01-01 19:52:07 +01:00
let module_tree = db.module_tree(source_root_id)?;
2018-11-28 01:42:26 +01:00
let source = module_id.source(&module_tree);
2019-01-01 19:17:52 +01:00
let mfile_id = source.file_id().into();
let file_items = db.file_items(mfile_id);
2019-01-01 19:52:07 +01:00
let fill = |acc: &mut InputModuleItems, items: &mut Iterator<Item = ast::ItemOrMacro>| {
for item in items {
match item {
ast::ItemOrMacro::Item(it) => {
acc.add_item(mfile_id, &file_items, it);
}
ast::ItemOrMacro::Macro(macro_call) => {
let item_id = file_items.id_of_unchecked(macro_call.syntax());
let loc = MacroCallLoc {
source_root_id,
module_id,
source_item_id: SourceItemId {
mfile_id,
item_id: Some(item_id),
},
};
let id = loc.id(db);
let mfile_id = MFileId::Macro(id);
let file_items = db.file_items(mfile_id);
//FIXME: expand recursively
for item in db.m_source_file(mfile_id).borrowed().items() {
acc.add_item(mfile_id, &file_items, item);
}
}
}
2018-11-28 01:42:26 +01:00
}
2019-01-01 19:52:07 +01:00
};
let mut res = InputModuleItems::default();
match source.resolve(db) {
ModuleSourceNode::SourceFile(it) => fill(&mut res, &mut it.borrowed().items_with_macros()),
2018-11-28 01:42:26 +01:00
ModuleSourceNode::Module(it) => {
2019-01-01 19:52:07 +01:00
if let Some(item_list) = it.borrowed().item_list() {
fill(&mut res, &mut item_list.items_with_macros())
}
2018-11-28 01:42:26 +01:00
}
};
Ok(Arc::new(res))
}
pub(super) fn item_map(
db: &impl HirDatabase,
source_root: SourceRootId,
) -> Cancelable<Arc<ItemMap>> {
let start = Instant::now();
let module_tree = db.module_tree(source_root)?;
let input = module_tree
.modules()
.map(|id| {
let items = db.input_module_items(source_root, id)?;
Ok((id, items))
})
.collect::<Cancelable<FxHashMap<_, _>>>()?;
2018-12-09 10:24:52 +01:00
let resolver = Resolver::new(db, &input, source_root, module_tree);
2018-11-28 01:42:26 +01:00
let res = resolver.resolve()?;
let elapsed = start.elapsed();
log::info!("item_map: {:?}", elapsed);
Ok(Arc::new(res))
}