mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 13:25:09 +00:00
Move module to SourceBinder
This commit is contained in:
parent
16cfc8d50c
commit
9a6c26e348
5 changed files with 69 additions and 55 deletions
|
@ -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(_) => (),
|
||||
};
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue