2018-11-28 00:42:26 +00:00
|
|
|
use std::{
|
|
|
|
sync::Arc,
|
|
|
|
time::Instant,
|
|
|
|
};
|
|
|
|
|
|
|
|
use rustc_hash::FxHashMap;
|
|
|
|
use ra_syntax::{
|
2019-01-01 17:59:00 +00:00
|
|
|
AstNode, SyntaxNode, SourceFileNode,
|
2018-12-27 20:51:44 +00:00
|
|
|
ast::{self, NameOwner, ModuleItemOwner}
|
2018-11-28 00:42:26 +00:00
|
|
|
};
|
|
|
|
use ra_db::{SourceRootId, FileId, Cancelable,};
|
|
|
|
|
|
|
|
use crate::{
|
2019-01-01 17:59:00 +00:00
|
|
|
SourceFileItems, SourceItemId, DefKind, Function, DefId, Name, AsName, MFileId,
|
2018-12-04 20:44:00 +00:00
|
|
|
db::HirDatabase,
|
2018-12-27 20:51:44 +00:00
|
|
|
function::FnScopes,
|
2018-12-04 20:44:00 +00:00
|
|
|
module::{
|
|
|
|
ModuleSource, ModuleSourceNode, ModuleId,
|
|
|
|
imp::Submodule,
|
|
|
|
nameres::{InputModuleItems, ItemMap, Resolver},
|
|
|
|
},
|
2018-12-24 18:07:48 +00:00
|
|
|
adt::{StructData, EnumData},
|
2018-11-28 00:42:26 +00:00
|
|
|
};
|
|
|
|
|
2018-12-27 20:51:44 +00: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 00:42:26 +00:00
|
|
|
let res = FnScopes::new(syntax.borrowed());
|
|
|
|
Arc::new(res)
|
|
|
|
}
|
|
|
|
|
2018-12-24 18:07:48 +00:00
|
|
|
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");
|
2018-12-25 20:40:33 +00:00
|
|
|
Ok(Arc::new(StructData::new(struct_def.borrowed())))
|
2018-12-24 18:07:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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");
|
2018-12-25 20:40:33 +00:00
|
|
|
Ok(Arc::new(EnumData::new(enum_def.borrowed())))
|
2018-12-24 18:07:48 +00:00
|
|
|
}
|
|
|
|
|
2019-01-01 17:59:00 +00: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 00:42:26 +00:00
|
|
|
let source_file = source_file.borrowed();
|
2019-01-01 17:59:00 +00:00
|
|
|
let res = SourceFileItems::new(mfile_id, source_file);
|
2018-11-28 00:42:26 +00:00
|
|
|
Arc::new(res)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn file_item(db: &impl HirDatabase, source_item_id: SourceItemId) -> SyntaxNode {
|
2018-12-18 22:48:46 +00:00
|
|
|
match source_item_id.item_id {
|
2019-01-01 17:59:00 +00: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-12-18 22:48:46 +00:00
|
|
|
}
|
2018-11-28 00:42:26 +00: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 17:07:21 +00:00
|
|
|
) -> impl Iterator<Item = (Name, ast::Module<'a>)> {
|
2018-11-28 00:42:26 +00:00
|
|
|
root.items()
|
|
|
|
.filter_map(|item| match item {
|
|
|
|
ast::ModuleItem::Module(m) => Some(m),
|
|
|
|
_ => None,
|
|
|
|
})
|
|
|
|
.filter_map(|module| {
|
2018-12-27 17:07:21 +00:00
|
|
|
let name = module.name()?.as_name();
|
2018-11-28 00:42:26 +00:00
|
|
|
Some((name, module))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn input_module_items(
|
|
|
|
db: &impl HirDatabase,
|
|
|
|
source_root: SourceRootId,
|
|
|
|
module_id: ModuleId,
|
|
|
|
) -> Cancelable<Arc<InputModuleItems>> {
|
|
|
|
let module_tree = db.module_tree(source_root)?;
|
|
|
|
let source = module_id.source(&module_tree);
|
2019-01-01 18:17:52 +00:00
|
|
|
let mfile_id = source.file_id().into();
|
|
|
|
let file_items = db.file_items(mfile_id);
|
2018-11-28 00:42:26 +00:00
|
|
|
let res = match source.resolve(db) {
|
|
|
|
ModuleSourceNode::SourceFile(it) => {
|
|
|
|
let items = it.borrowed().items();
|
2019-01-01 18:17:52 +00:00
|
|
|
InputModuleItems::new(mfile_id, &file_items, items)
|
2018-11-28 00:42:26 +00:00
|
|
|
}
|
|
|
|
ModuleSourceNode::Module(it) => {
|
|
|
|
let items = it
|
|
|
|
.borrowed()
|
|
|
|
.item_list()
|
|
|
|
.into_iter()
|
|
|
|
.flat_map(|it| it.items());
|
2019-01-01 18:17:52 +00:00
|
|
|
InputModuleItems::new(mfile_id, &file_items, items)
|
2018-11-28 00:42:26 +00: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 09:24:52 +00:00
|
|
|
|
|
|
|
let resolver = Resolver::new(db, &input, source_root, module_tree);
|
2018-11-28 00:42:26 +00:00
|
|
|
let res = resolver.resolve()?;
|
|
|
|
let elapsed = start.elapsed();
|
|
|
|
log::info!("item_map: {:?}", elapsed);
|
|
|
|
Ok(Arc::new(res))
|
|
|
|
}
|