Move convert_to_def_in_trait into ide-db

This commit is contained in:
Lukas Wirth 2022-07-18 18:23:50 +02:00
parent dcb4837b2d
commit 38c11bea21
4 changed files with 30 additions and 47 deletions

View File

@ -401,7 +401,7 @@ fn import_for_item(
})
}
fn item_for_path_search(db: &RootDatabase, item: ItemInNs) -> Option<ItemInNs> {
pub fn item_for_path_search(db: &RootDatabase, item: ItemInNs) -> Option<ItemInNs> {
Some(match item {
ItemInNs::Types(_) | ItemInNs::Values(_) => match item_as_assoc(db, item) {
Some(assoc_item) => match assoc_item.container(db) {

View File

@ -24,7 +24,7 @@
use base_db::{AnchoredPathBuf, FileId, FileRange};
use either::Either;
use hir::{AsAssocItem, FieldSource, HasSource, InFile, ModuleSource, Semantics};
use hir::{FieldSource, HasSource, InFile, ModuleSource, Semantics};
use stdx::never;
use syntax::{
ast::{self, HasName},
@ -37,6 +37,7 @@
search::FileReference,
source_change::{FileSystemEdit, SourceChange},
syntax_helpers::node_ext::expr_as_name_ref,
traits::convert_to_def_in_trait,
RootDatabase,
};
@ -271,7 +272,7 @@ fn rename_reference(
}
}
let def = convert_to_def_in_trait(def, sema);
let def = convert_to_def_in_trait(sema.db, def);
let usages = def.usages(sema).all();
if !usages.is_empty() && ident_kind == IdentifierKind::Underscore {
@ -298,47 +299,6 @@ fn rename_reference(
Ok(source_change)
}
pub(crate) fn convert_to_def_in_trait(
def: Definition,
sema: &Semantics<RootDatabase>,
) -> Definition {
// HACK: resolve trait impl items to the item def of the trait definition
// so that we properly resolve all trait item references
let assoc_item = match def {
Definition::Function(it) => it.as_assoc_item(sema.db),
Definition::TypeAlias(it) => it.as_assoc_item(sema.db),
Definition::Const(it) => it.as_assoc_item(sema.db),
_ => None,
};
match assoc_item {
Some(assoc) => assoc
.containing_trait_impl(sema.db)
.and_then(|trait_| {
trait_.items(sema.db).into_iter().find_map(|it| match (it, assoc) {
(hir::AssocItem::Function(trait_func), hir::AssocItem::Function(func))
if trait_func.name(sema.db) == func.name(sema.db) =>
{
Some(Definition::Function(trait_func))
}
(hir::AssocItem::Const(trait_konst), hir::AssocItem::Const(konst))
if trait_konst.name(sema.db) == konst.name(sema.db) =>
{
Some(Definition::Const(trait_konst))
}
(
hir::AssocItem::TypeAlias(trait_type_alias),
hir::AssocItem::TypeAlias(type_alias),
) if trait_type_alias.name(sema.db) == type_alias.name(sema.db) => {
Some(Definition::TypeAlias(trait_type_alias))
}
_ => None,
})
})
.unwrap_or(def),
None => def,
}
}
pub fn source_edit_from_references(
references: &[FileReference],
def: Definition,

View File

@ -16,6 +16,7 @@
use crate::{
defs::{Definition, NameClass, NameRefClass},
traits::convert_to_def_in_trait,
RootDatabase,
};
@ -620,7 +621,7 @@ fn found_name_ref(
sink(file_id, reference)
}
Some(NameRefClass::Definition(def))
if crate::rename::convert_to_def_in_trait(def, self.sema) == self.def =>
if convert_to_def_in_trait(self.sema.db, def) == self.def =>
{
let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
let reference = FileReference {

View File

@ -1,7 +1,7 @@
//! Functionality for obtaining data related to traits from the DB.
use crate::RootDatabase;
use hir::Semantics;
use crate::{defs::Definition, RootDatabase};
use hir::{db::HirDatabase, AsAssocItem, Semantics};
use rustc_hash::FxHashSet;
use syntax::{ast, AstNode};
@ -69,6 +69,28 @@ pub fn get_missing_assoc_items(
})
}
/// Converts associated trait impl items to their trait definition counterpart
pub(crate) fn convert_to_def_in_trait(db: &dyn HirDatabase, def: Definition) -> Definition {
use hir::AssocItem::*;
(|| {
let assoc = def.as_assoc_item(db)?;
let trait_ = assoc.containing_trait_impl(db)?;
let name = match assoc {
Function(it) => it.name(db),
Const(it) => it.name(db)?,
TypeAlias(it) => it.name(db),
};
let item = trait_.items(db).into_iter().find(|it| match (it, assoc) {
(Function(trait_func), Function(_)) => trait_func.name(db) == name,
(Const(trait_konst), Const(_)) => trait_konst.name(db).map_or(false, |it| it == name),
(TypeAlias(trait_type_alias), TypeAlias(_)) => trait_type_alias.name(db) == name,
_ => false,
})?;
Some(Definition::from(item))
})()
.unwrap_or(def)
}
#[cfg(test)]
mod tests {
use base_db::{fixture::ChangeFixture, FilePosition};