Move module to SourceBinder

This commit is contained in:
Aleksey Kladov 2020-01-16 16:53:11 +01:00
parent 16cfc8d50c
commit 9a6c26e348
5 changed files with 69 additions and 55 deletions

View file

@ -2,46 +2,22 @@
//! file. //! file.
use hir_def::{nameres::ModuleSource, ModuleId}; use hir_def::{nameres::ModuleSource, ModuleId};
use hir_expand::name::AsName;
use ra_db::FileId; use ra_db::FileId;
use ra_prof::profile; use ra_prof::profile;
use ra_syntax::ast::{self, AstNode, NameOwner};
use crate::{db::DefDatabase, InFile, Module}; use crate::{
db::{DefDatabase, HirDatabase},
InFile, Module,
};
impl Module { impl Module {
pub fn from_declaration(db: &impl DefDatabase, src: InFile<ast::Module>) -> Option<Self> { pub fn from_definition(db: &impl HirDatabase, src: InFile<ModuleSource>) -> Option<Self> {
let _p = profile("Module::from_declaration");
let parent_declaration = src.value.syntax().ancestors().skip(1).find_map(ast::Module::cast);
let parent_module = match parent_declaration {
Some(parent_declaration) => {
let src_parent = InFile { file_id: src.file_id, value: parent_declaration };
Module::from_declaration(db, src_parent)
}
None => {
let source_file = db.parse(src.file_id.original_file(db)).tree();
let src_parent =
InFile { file_id: src.file_id, value: ModuleSource::SourceFile(source_file) };
Module::from_definition(db, src_parent)
}
}?;
let child_name = src.value.name()?.as_name();
let def_map = db.crate_def_map(parent_module.id.krate);
let child_id = def_map[parent_module.id.local_id].children.get(&child_name)?;
Some(parent_module.with_module_id(*child_id))
}
pub fn from_definition(db: &impl DefDatabase, src: InFile<ModuleSource>) -> Option<Self> {
let _p = profile("Module::from_definition"); let _p = profile("Module::from_definition");
let mut sb = crate::SourceBinder::new(db);
match src.value { match src.value {
ModuleSource::Module(ref module) => { ModuleSource::Module(ref module) => {
assert!(!module.has_semi()); assert!(!module.has_semi());
return Module::from_declaration( return sb.to_def(InFile { file_id: src.file_id, value: module.clone() });
db,
InFile { file_id: src.file_id, value: module.clone() },
);
} }
ModuleSource::SourceFile(_) => (), ModuleSource::SourceFile(_) => (),
}; };

View file

@ -11,12 +11,15 @@ use hir_def::{
ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId,
StaticId, StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId, StaticId, StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
}; };
use hir_expand::{AstId, InFile, MacroDefId, MacroDefKind}; use hir_expand::{name::AsName, AstId, InFile, MacroDefId, MacroDefKind};
use ra_prof::profile; use ra_prof::profile;
use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, TextUnit}; use ra_syntax::{
ast::{self, NameOwner},
match_ast, AstNode, SyntaxNode, TextUnit,
};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use crate::{db::HirDatabase, Local, ModuleSource, SourceAnalyzer, TypeParam}; use crate::{db::HirDatabase, Local, Module, ModuleSource, SourceAnalyzer, TypeParam};
pub struct SourceBinder<'a, DB> { pub struct SourceBinder<'a, DB> {
pub db: &'a DB, pub db: &'a DB,
@ -306,3 +309,38 @@ impl ToDef for ast::TypeParam {
Some(TypeParam { id }) Some(TypeParam { id })
} }
} }
impl ToDef for ast::Module {
type Def = Module;
fn to_def<DB: HirDatabase>(
sb: &mut SourceBinder<'_, DB>,
src: InFile<ast::Module>,
) -> Option<Module> {
{
let _p = profile("ast::Module::to_def");
let parent_declaration =
src.value.syntax().ancestors().skip(1).find_map(ast::Module::cast);
let parent_module = match parent_declaration {
Some(parent_declaration) => {
let src_parent = InFile { file_id: src.file_id, value: parent_declaration };
sb.to_def(src_parent)
}
None => {
let source_file = sb.db.parse(src.file_id.original_file(sb.db)).tree();
let src_parent = InFile {
file_id: src.file_id,
value: ModuleSource::SourceFile(source_file),
};
Module::from_definition(sb.db, src_parent)
}
}?;
let child_name = src.value.name()?.as_name();
let def_map = sb.db.crate_def_map(parent_module.id.krate);
let child_id = def_map[parent_module.id.local_id].children.get(&child_name)?;
Some(parent_module.with_module_id(*child_id))
}
}
}

View file

@ -24,13 +24,14 @@ pub(crate) fn goto_definition(
let original_token = pick_best(file.token_at_offset(position.offset))?; let original_token = pick_best(file.token_at_offset(position.offset))?;
let token = descend_into_macros(db, position.file_id, original_token.clone()); let token = descend_into_macros(db, position.file_id, original_token.clone());
let mut sb = SourceBinder::new(db);
let nav_targets = match_ast! { let nav_targets = match_ast! {
match (token.value.parent()) { match (token.value.parent()) {
ast::NameRef(name_ref) => { ast::NameRef(name_ref) => {
reference_definition(db, token.with_value(&name_ref)).to_vec() reference_definition(&mut sb, token.with_value(&name_ref)).to_vec()
}, },
ast::Name(name) => { ast::Name(name) => {
name_definition(db, token.with_value(&name))? name_definition(&mut sb, token.with_value(&name))?
}, },
_ => return None, _ => return None,
} }
@ -67,20 +68,19 @@ impl ReferenceResult {
} }
pub(crate) fn reference_definition( pub(crate) fn reference_definition(
db: &RootDatabase, sb: &mut SourceBinder<RootDatabase>,
name_ref: InFile<&ast::NameRef>, name_ref: InFile<&ast::NameRef>,
) -> ReferenceResult { ) -> ReferenceResult {
use self::ReferenceResult::*; use self::ReferenceResult::*;
let mut sb = SourceBinder::new(db); let name_kind = classify_name_ref(sb, name_ref).map(|d| d.kind);
let name_kind = classify_name_ref(&mut sb, name_ref).map(|d| d.kind);
match name_kind { match name_kind {
Some(Macro(it)) => return Exact(it.to_nav(db)), Some(Macro(it)) => return Exact(it.to_nav(sb.db)),
Some(Field(it)) => return Exact(it.to_nav(db)), Some(Field(it)) => return Exact(it.to_nav(sb.db)),
Some(TypeParam(it)) => return Exact(it.to_nav(db)), Some(TypeParam(it)) => return Exact(it.to_nav(sb.db)),
Some(AssocItem(it)) => return Exact(it.to_nav(db)), Some(AssocItem(it)) => return Exact(it.to_nav(sb.db)),
Some(Local(it)) => return Exact(it.to_nav(db)), Some(Local(it)) => return Exact(it.to_nav(sb.db)),
Some(Def(def)) => match NavigationTarget::from_def(db, def) { Some(Def(def)) => match NavigationTarget::from_def(sb.db, def) {
Some(nav) => return Exact(nav), Some(nav) => return Exact(nav),
None => return Approximate(vec![]), None => return Approximate(vec![]),
}, },
@ -88,21 +88,21 @@ pub(crate) fn reference_definition(
// FIXME: ideally, this should point to the type in the impl, and // FIXME: ideally, this should point to the type in the impl, and
// not at the whole impl. And goto **type** definition should bring // not at the whole impl. And goto **type** definition should bring
// us to the actual type // us to the actual type
return Exact(imp.to_nav(db)); return Exact(imp.to_nav(sb.db));
} }
None => {} None => {}
}; };
// Fallback index based approach: // Fallback index based approach:
let navs = crate::symbol_index::index_resolve(db, name_ref.value) let navs = crate::symbol_index::index_resolve(sb.db, name_ref.value)
.into_iter() .into_iter()
.map(|s| s.to_nav(db)) .map(|s| s.to_nav(sb.db))
.collect(); .collect();
Approximate(navs) Approximate(navs)
} }
pub(crate) fn name_definition( fn name_definition(
db: &RootDatabase, sb: &mut SourceBinder<RootDatabase>,
name: InFile<&ast::Name>, name: InFile<&ast::Name>,
) -> Option<Vec<NavigationTarget>> { ) -> Option<Vec<NavigationTarget>> {
let parent = name.value.syntax().parent()?; let parent = name.value.syntax().parent()?;
@ -110,14 +110,14 @@ pub(crate) fn name_definition(
if let Some(module) = ast::Module::cast(parent.clone()) { if let Some(module) = ast::Module::cast(parent.clone()) {
if module.has_semi() { if module.has_semi() {
let src = name.with_value(module); let src = name.with_value(module);
if let Some(child_module) = hir::Module::from_declaration(db, src) { if let Some(child_module) = sb.to_def(src) {
let nav = child_module.to_nav(db); let nav = child_module.to_nav(sb.db);
return Some(vec![nav]); return Some(vec![nav]);
} }
} }
} }
if let Some(nav) = named_target(db, name.with_value(&parent)) { if let Some(nav) = named_target(sb.db, name.with_value(&parent)) {
return Some(vec![nav]); return Some(vec![nav]);
} }

View file

@ -42,7 +42,7 @@ pub(crate) fn classify_name(
hir::Module::from_definition(sb.db, src) hir::Module::from_definition(sb.db, src)
} else { } else {
let src = name.with_value(it); let src = name.with_value(it);
hir::Module::from_declaration(sb.db, src) sb.to_def(src)
} }
}?; }?;
Some(from_module_def(sb.db, def.into(), None)) Some(from_module_def(sb.db, def.into(), None))

View file

@ -63,7 +63,7 @@ fn rename_mod(
let mut source_file_edits = Vec::new(); let mut source_file_edits = Vec::new();
let mut file_system_edits = Vec::new(); let mut file_system_edits = Vec::new();
let module_src = hir::InFile { file_id: position.file_id.into(), value: ast_module.clone() }; let module_src = hir::InFile { file_id: position.file_id.into(), value: ast_module.clone() };
if let Some(module) = hir::Module::from_declaration(db, module_src) { if let Some(module) = hir::SourceBinder::new(db).to_def(module_src) {
let src = module.definition_source(db); let src = module.definition_source(db);
let file_id = src.file_id.original_file(db); let file_id = src.file_id.original_file(db);
match src.value { match src.value {