mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 20:43:21 +00:00
Add functions to DefId
This commit is contained in:
parent
947e3350e0
commit
d8b0379e10
10 changed files with 90 additions and 83 deletions
|
@ -163,7 +163,7 @@ fn complete_path(
|
|||
};
|
||||
let target_module = match def_id.resolve(db)? {
|
||||
Def::Module(it) => it,
|
||||
Def::Item => return Ok(()),
|
||||
_ => return Ok(()),
|
||||
};
|
||||
let module_scope = target_module.scope(db)?;
|
||||
let completions = module_scope.entries().map(|(name, _res)| CompletionItem {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
use salsa::{self, Database};
|
||||
use ra_db::{LocationIntener, BaseDatabase};
|
||||
use hir::{self, DefId, DefLoc, FnId, SourceItemId};
|
||||
use hir::{self, DefId, DefLoc};
|
||||
|
||||
use crate::{
|
||||
symbol_index,
|
||||
|
@ -15,7 +15,6 @@ pub(crate) struct RootDatabase {
|
|||
|
||||
#[derive(Debug, Default)]
|
||||
struct IdMaps {
|
||||
fns: LocationIntener<SourceItemId, FnId>,
|
||||
defs: LocationIntener<DefLoc, DefId>,
|
||||
}
|
||||
|
||||
|
@ -58,12 +57,6 @@ impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsRef<LocationIntener<hir::SourceItemId, FnId>> for RootDatabase {
|
||||
fn as_ref(&self) -> &LocationIntener<hir::SourceItemId, FnId> {
|
||||
&self.id_maps.fns
|
||||
}
|
||||
}
|
||||
|
||||
salsa::database_storage! {
|
||||
pub(crate) struct RootDatabaseStorage for RootDatabase {
|
||||
impl ra_db::FilesDatabase {
|
||||
|
|
|
@ -210,7 +210,7 @@ impl AnalysisImpl {
|
|||
let syntax = file.syntax();
|
||||
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
|
||||
if let Some(fn_descr) =
|
||||
hir::Function::guess_for_name_ref(&*self.db, position.file_id, name_ref)
|
||||
hir::Function::guess_for_name_ref(&*self.db, position.file_id, name_ref)?
|
||||
{
|
||||
let scope = fn_descr.scope(&*self.db);
|
||||
// First try to resolve the symbol locally
|
||||
|
@ -257,11 +257,11 @@ impl AnalysisImpl {
|
|||
Ok(vec![])
|
||||
}
|
||||
|
||||
pub fn find_all_refs(&self, position: FilePosition) -> Vec<(FileId, TextRange)> {
|
||||
pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
|
||||
let file = self.db.source_file(position.file_id);
|
||||
// Find the binding associated with the offset
|
||||
let (binding, descr) = match find_binding(&self.db, &file, position) {
|
||||
None => return Vec::new(),
|
||||
let (binding, descr) = match find_binding(&self.db, &file, position)? {
|
||||
None => return Ok(Vec::new()),
|
||||
Some(it) => it,
|
||||
};
|
||||
|
||||
|
@ -274,25 +274,36 @@ impl AnalysisImpl {
|
|||
.map(|ref_desc| (position.file_id, ref_desc.range)),
|
||||
);
|
||||
|
||||
return ret;
|
||||
return Ok(ret);
|
||||
|
||||
fn find_binding<'a>(
|
||||
db: &db::RootDatabase,
|
||||
source_file: &'a SourceFileNode,
|
||||
position: FilePosition,
|
||||
) -> Option<(ast::BindPat<'a>, hir::Function)> {
|
||||
) -> Cancelable<Option<(ast::BindPat<'a>, hir::Function)>> {
|
||||
let syntax = source_file.syntax();
|
||||
if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) {
|
||||
let descr = hir::Function::guess_for_bind_pat(db, position.file_id, binding)?;
|
||||
return Some((binding, descr));
|
||||
let descr = ctry!(hir::Function::guess_for_bind_pat(
|
||||
db,
|
||||
position.file_id,
|
||||
binding
|
||||
)?);
|
||||
return Ok(Some((binding, descr)));
|
||||
};
|
||||
let name_ref = find_node_at_offset::<ast::NameRef>(syntax, position.offset)?;
|
||||
let descr = hir::Function::guess_for_name_ref(db, position.file_id, name_ref)?;
|
||||
let name_ref = ctry!(find_node_at_offset::<ast::NameRef>(syntax, position.offset));
|
||||
let descr = ctry!(hir::Function::guess_for_name_ref(
|
||||
db,
|
||||
position.file_id,
|
||||
name_ref
|
||||
)?);
|
||||
let scope = descr.scope(db);
|
||||
let resolved = scope.resolve_local_name(name_ref)?;
|
||||
let resolved = ctry!(scope.resolve_local_name(name_ref));
|
||||
let resolved = resolved.ptr().resolve(source_file);
|
||||
let binding = find_node_at_offset::<ast::BindPat>(syntax, resolved.range().end())?;
|
||||
Some((binding, descr))
|
||||
let binding = ctry!(find_node_at_offset::<ast::BindPat>(
|
||||
syntax,
|
||||
resolved.range().end()
|
||||
));
|
||||
Ok(Some((binding, descr)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,7 +419,9 @@ impl AnalysisImpl {
|
|||
if fs.kind == FN_DEF {
|
||||
let fn_file = self.db.source_file(fn_file_id);
|
||||
if let Some(fn_def) = find_node_at_offset(fn_file.syntax(), fs.node_range.start()) {
|
||||
let descr = hir::Function::guess_from_source(&*self.db, fn_file_id, fn_def);
|
||||
let descr = ctry!(hir::Function::guess_from_source(
|
||||
&*self.db, fn_file_id, fn_def
|
||||
)?);
|
||||
if let Some(descriptor) = descr.signature_info(&*self.db) {
|
||||
// If we have a calling expression let's find which argument we are on
|
||||
let mut current_parameter = None;
|
||||
|
|
|
@ -248,7 +248,7 @@ impl Analysis {
|
|||
self.imp.approximately_resolve_symbol(position)
|
||||
}
|
||||
pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
|
||||
Ok(self.imp.find_all_refs(position))
|
||||
self.imp.find_all_refs(position)
|
||||
}
|
||||
pub fn doc_comment_for(
|
||||
&self,
|
||||
|
|
|
@ -7,10 +7,11 @@ use ra_syntax::{
|
|||
use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, FileId, Cancelable};
|
||||
|
||||
use crate::{
|
||||
DefLoc, DefId, FnId,
|
||||
DefLoc, DefId,
|
||||
SourceFileItems, SourceItemId,
|
||||
query_definitions,
|
||||
FnScopes,
|
||||
function::FnId,
|
||||
module::{ModuleId, ModuleTree, ModuleSource,
|
||||
nameres::{ItemMap, InputModuleItems}},
|
||||
};
|
||||
|
@ -19,7 +20,6 @@ salsa::query_group! {
|
|||
|
||||
pub trait HirDatabase: SyntaxDatabase
|
||||
+ AsRef<LocationIntener<DefLoc, DefId>>
|
||||
+ AsRef<LocationIntener<SourceItemId, FnId>>
|
||||
{
|
||||
fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> {
|
||||
type FnScopesQuery;
|
||||
|
|
|
@ -12,19 +12,15 @@ use ra_syntax::{
|
|||
use ra_db::FileId;
|
||||
|
||||
use crate::{
|
||||
FnId, HirDatabase, SourceItemId,
|
||||
Cancelable,
|
||||
DefLoc, DefKind, DefId, HirDatabase, SourceItemId,
|
||||
Module,
|
||||
};
|
||||
|
||||
pub use self::scope::FnScopes;
|
||||
|
||||
impl FnId {
|
||||
pub fn get(db: &impl HirDatabase, file_id: FileId, fn_def: ast::FnDef) -> FnId {
|
||||
let file_items = db.file_items(file_id);
|
||||
let item_id = file_items.id_of(fn_def.syntax());
|
||||
let item_id = SourceItemId { file_id, item_id };
|
||||
FnId::from_loc(db, &item_id)
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct FnId(pub(crate) DefId);
|
||||
|
||||
pub struct Function {
|
||||
fn_id: FnId,
|
||||
|
@ -35,16 +31,26 @@ impl Function {
|
|||
db: &impl HirDatabase,
|
||||
file_id: FileId,
|
||||
fn_def: ast::FnDef,
|
||||
) -> Function {
|
||||
let fn_id = FnId::get(db, file_id, fn_def);
|
||||
Function { fn_id }
|
||||
) -> Cancelable<Option<Function>> {
|
||||
let module = ctry!(Module::guess_from_child_node(db, file_id, fn_def.syntax())?);
|
||||
let file_items = db.file_items(file_id);
|
||||
let item_id = file_items.id_of(fn_def.syntax());
|
||||
let source_item_id = SourceItemId { file_id, item_id };
|
||||
let def_loc = DefLoc {
|
||||
kind: DefKind::Function,
|
||||
source_root_id: module.source_root_id,
|
||||
module_id: module.module_id,
|
||||
source_item_id,
|
||||
};
|
||||
let fn_id = FnId(def_loc.id(db));
|
||||
Ok(Some(Function { fn_id }))
|
||||
}
|
||||
|
||||
pub fn guess_for_name_ref(
|
||||
db: &impl HirDatabase,
|
||||
file_id: FileId,
|
||||
name_ref: ast::NameRef,
|
||||
) -> Option<Function> {
|
||||
) -> Cancelable<Option<Function>> {
|
||||
Function::guess_for_node(db, file_id, name_ref.syntax())
|
||||
}
|
||||
|
||||
|
@ -52,7 +58,7 @@ impl Function {
|
|||
db: &impl HirDatabase,
|
||||
file_id: FileId,
|
||||
bind_pat: ast::BindPat,
|
||||
) -> Option<Function> {
|
||||
) -> Cancelable<Option<Function>> {
|
||||
Function::guess_for_node(db, file_id, bind_pat.syntax())
|
||||
}
|
||||
|
||||
|
@ -60,10 +66,9 @@ impl Function {
|
|||
db: &impl HirDatabase,
|
||||
file_id: FileId,
|
||||
node: SyntaxNodeRef,
|
||||
) -> Option<Function> {
|
||||
let fn_def = node.ancestors().find_map(ast::FnDef::cast)?;
|
||||
let res = Function::guess_from_source(db, file_id, fn_def);
|
||||
Some(res)
|
||||
) -> Cancelable<Option<Function>> {
|
||||
let fn_def = ctry!(node.ancestors().find_map(ast::FnDef::cast));
|
||||
Function::guess_from_source(db, file_id, fn_def)
|
||||
}
|
||||
|
||||
pub fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> {
|
||||
|
|
|
@ -41,22 +41,6 @@ pub use self::{
|
|||
|
||||
pub use self::function::FnSignatureInfo;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct FnId(u32);
|
||||
ra_db::impl_numeric_id!(FnId);
|
||||
|
||||
impl FnId {
|
||||
pub fn from_loc(
|
||||
db: &impl AsRef<LocationIntener<SourceItemId, FnId>>,
|
||||
loc: &SourceItemId,
|
||||
) -> FnId {
|
||||
db.as_ref().loc2id(loc)
|
||||
}
|
||||
pub fn loc(self, db: &impl AsRef<LocationIntener<SourceItemId, FnId>>) -> SourceItemId {
|
||||
db.as_ref().id2loc(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct DefId(u32);
|
||||
ra_db::impl_numeric_id!(DefId);
|
||||
|
@ -64,6 +48,7 @@ ra_db::impl_numeric_id!(DefId);
|
|||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub(crate) enum DefKind {
|
||||
Module,
|
||||
Function,
|
||||
Item,
|
||||
}
|
||||
|
||||
|
@ -89,6 +74,7 @@ impl DefLoc {
|
|||
|
||||
pub enum Def {
|
||||
Module(Module),
|
||||
Function(Function),
|
||||
Item,
|
||||
}
|
||||
|
||||
|
@ -100,7 +86,7 @@ impl DefId {
|
|||
let descr = Module::new(db, loc.source_root_id, loc.module_id)?;
|
||||
Def::Module(descr)
|
||||
}
|
||||
DefKind::Item => Def::Item,
|
||||
DefKind::Item | DefKind::Function => Def::Item,
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use ra_db::{LocationIntener, BaseDatabase, FilePosition, mock::FileMap, FileId,
|
|||
use relative_path::RelativePathBuf;
|
||||
use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset};
|
||||
|
||||
use crate::{db, DefId, DefLoc, FnId, SourceItemId};
|
||||
use crate::{db, DefId, DefLoc};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct MockDatabase {
|
||||
|
@ -65,7 +65,6 @@ impl MockDatabase {
|
|||
|
||||
#[derive(Debug, Default)]
|
||||
struct IdMaps {
|
||||
fns: LocationIntener<SourceItemId, FnId>,
|
||||
defs: LocationIntener<DefLoc, DefId>,
|
||||
}
|
||||
|
||||
|
@ -117,12 +116,6 @@ impl AsRef<LocationIntener<DefLoc, DefId>> for MockDatabase {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsRef<LocationIntener<SourceItemId, FnId>> for MockDatabase {
|
||||
fn as_ref(&self) -> &LocationIntener<SourceItemId, FnId> {
|
||||
&self.id_maps.fns
|
||||
}
|
||||
}
|
||||
|
||||
impl MockDatabase {
|
||||
pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> {
|
||||
*self.events.lock() = Some(Vec::new());
|
||||
|
|
|
@ -8,7 +8,7 @@ use ra_editor::find_node_at_offset;
|
|||
use ra_syntax::{
|
||||
algo::generate,
|
||||
ast::{self, AstNode, NameOwner},
|
||||
SmolStr, SyntaxNode,
|
||||
SmolStr, SyntaxNode, SyntaxNodeRef,
|
||||
};
|
||||
use ra_db::{SourceRootId, FileId, FilePosition, Cancelable};
|
||||
use relative_path::RelativePathBuf;
|
||||
|
@ -25,8 +25,8 @@ pub use self::nameres::ModuleScope;
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Module {
|
||||
tree: Arc<ModuleTree>,
|
||||
source_root_id: SourceRootId,
|
||||
module_id: ModuleId,
|
||||
pub(crate) source_root_id: SourceRootId,
|
||||
pub(crate) module_id: ModuleId,
|
||||
}
|
||||
|
||||
impl Module {
|
||||
|
@ -57,6 +57,23 @@ impl Module {
|
|||
Module::guess_from_source(db, module_source)
|
||||
}
|
||||
|
||||
pub fn guess_from_child_node(
|
||||
db: &impl HirDatabase,
|
||||
file_id: FileId,
|
||||
node: SyntaxNodeRef,
|
||||
) -> Cancelable<Option<Module>> {
|
||||
let module_source = if let Some(m) = node
|
||||
.ancestors()
|
||||
.filter_map(ast::Module::cast)
|
||||
.find(|it| !it.has_semi())
|
||||
{
|
||||
ModuleSource::new_inline(db, file_id, m)
|
||||
} else {
|
||||
ModuleSource::new_file(db, file_id)
|
||||
};
|
||||
Module::guess_from_source(db, module_source)
|
||||
}
|
||||
|
||||
fn guess_from_source(
|
||||
db: &impl HirDatabase,
|
||||
module_source: ModuleSource,
|
||||
|
|
|
@ -11,21 +11,21 @@ use ra_syntax::{
|
|||
use ra_db::{SourceRootId, FileId, Cancelable,};
|
||||
|
||||
use crate::{
|
||||
FnId,
|
||||
SourceFileItems, SourceItemId,
|
||||
db::HirDatabase,
|
||||
function::FnScopes,
|
||||
module::{
|
||||
ModuleSource, ModuleSourceNode, ModuleId,
|
||||
imp::Submodule,
|
||||
nameres::{InputModuleItems, ItemMap, Resolver},
|
||||
},
|
||||
SourceFileItems, SourceItemId, DefKind,
|
||||
db::HirDatabase,
|
||||
function::{FnScopes, FnId},
|
||||
module::{
|
||||
ModuleSource, ModuleSourceNode, ModuleId,
|
||||
imp::Submodule,
|
||||
nameres::{InputModuleItems, ItemMap, Resolver},
|
||||
},
|
||||
};
|
||||
|
||||
/// Resolve `FnId` to the corresponding `SyntaxNode`
|
||||
pub(super) fn fn_syntax(db: &impl HirDatabase, fn_id: FnId) -> FnDefNode {
|
||||
let item_id = fn_id.loc(db);
|
||||
let syntax = db.file_item(item_id);
|
||||
let def_loc = fn_id.0.loc(db);
|
||||
assert!(def_loc.kind == DefKind::Function);
|
||||
let syntax = db.file_item(def_loc.source_item_id);
|
||||
FnDef::cast(syntax.borrowed()).unwrap().owned()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue