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.
use hir_def::{nameres::ModuleSource, ModuleId};
use hir_expand::name::AsName;
use ra_db::FileId;
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 {
pub fn from_declaration(db: &impl DefDatabase, src: InFile<ast::Module>) -> 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> {
pub fn from_definition(db: &impl HirDatabase, src: InFile<ModuleSource>) -> Option<Self> {
let _p = profile("Module::from_definition");
let mut sb = crate::SourceBinder::new(db);
match src.value {
ModuleSource::Module(ref module) => {
assert!(!module.has_semi());
return Module::from_declaration(
db,
InFile { file_id: src.file_id, value: module.clone() },
);
return sb.to_def(InFile { file_id: src.file_id, value: module.clone() });
}
ModuleSource::SourceFile(_) => (),
};

View file

@ -11,12 +11,15 @@ use hir_def::{
ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId,
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_syntax::{ast, match_ast, AstNode, SyntaxNode, TextUnit};
use ra_syntax::{
ast::{self, NameOwner},
match_ast, AstNode, SyntaxNode, TextUnit,
};
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 db: &'a DB,
@ -306,3 +309,38 @@ impl ToDef for ast::TypeParam {
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 token = descend_into_macros(db, position.file_id, original_token.clone());
let mut sb = SourceBinder::new(db);
let nav_targets = match_ast! {
match (token.value.parent()) {
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) => {
name_definition(db, token.with_value(&name))?
name_definition(&mut sb, token.with_value(&name))?
},
_ => return None,
}
@ -67,20 +68,19 @@ impl ReferenceResult {
}
pub(crate) fn reference_definition(
db: &RootDatabase,
sb: &mut SourceBinder<RootDatabase>,
name_ref: InFile<&ast::NameRef>,
) -> ReferenceResult {
use self::ReferenceResult::*;
let mut sb = SourceBinder::new(db);
let name_kind = classify_name_ref(&mut sb, name_ref).map(|d| d.kind);
let name_kind = classify_name_ref(sb, name_ref).map(|d| d.kind);
match name_kind {
Some(Macro(it)) => return Exact(it.to_nav(db)),
Some(Field(it)) => return Exact(it.to_nav(db)),
Some(TypeParam(it)) => return Exact(it.to_nav(db)),
Some(AssocItem(it)) => return Exact(it.to_nav(db)),
Some(Local(it)) => return Exact(it.to_nav(db)),
Some(Def(def)) => match NavigationTarget::from_def(db, def) {
Some(Macro(it)) => return Exact(it.to_nav(sb.db)),
Some(Field(it)) => return Exact(it.to_nav(sb.db)),
Some(TypeParam(it)) => return Exact(it.to_nav(sb.db)),
Some(AssocItem(it)) => return Exact(it.to_nav(sb.db)),
Some(Local(it)) => return Exact(it.to_nav(sb.db)),
Some(Def(def)) => match NavigationTarget::from_def(sb.db, def) {
Some(nav) => return Exact(nav),
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
// not at the whole impl. And goto **type** definition should bring
// us to the actual type
return Exact(imp.to_nav(db));
return Exact(imp.to_nav(sb.db));
}
None => {}
};
// 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()
.map(|s| s.to_nav(db))
.map(|s| s.to_nav(sb.db))
.collect();
Approximate(navs)
}
pub(crate) fn name_definition(
db: &RootDatabase,
fn name_definition(
sb: &mut SourceBinder<RootDatabase>,
name: InFile<&ast::Name>,
) -> Option<Vec<NavigationTarget>> {
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 module.has_semi() {
let src = name.with_value(module);
if let Some(child_module) = hir::Module::from_declaration(db, src) {
let nav = child_module.to_nav(db);
if let Some(child_module) = sb.to_def(src) {
let nav = child_module.to_nav(sb.db);
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]);
}

View file

@ -42,7 +42,7 @@ pub(crate) fn classify_name(
hir::Module::from_definition(sb.db, src)
} else {
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))

View file

@ -63,7 +63,7 @@ fn rename_mod(
let mut source_file_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() };
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 file_id = src.file_id.original_file(db);
match src.value {