Move reference classification to ra_ide_db

Lost some marks along the way :-(
This commit is contained in:
Aleksey Kladov 2020-03-03 18:50:15 +01:00
parent 34d6e22fc1
commit 177229bfde
5 changed files with 77 additions and 104 deletions

View file

@ -206,7 +206,6 @@ mod tests {
#[test]
fn goto_def_for_macros() {
covers!(goto_def_for_macros);
check_goto(
"
//- /lib.rs
@ -223,7 +222,6 @@ mod tests {
#[test]
fn goto_def_for_macros_from_other_crates() {
covers!(goto_def_for_macros);
check_goto(
"
//- /lib.rs
@ -335,7 +333,6 @@ mod tests {
#[test]
fn goto_def_for_methods() {
covers!(goto_def_for_methods);
check_goto(
"
//- /lib.rs
@ -355,7 +352,6 @@ mod tests {
#[test]
fn goto_def_for_fields() {
covers!(goto_def_for_fields);
check_goto(
"
//- /lib.rs
@ -374,7 +370,6 @@ mod tests {
#[test]
fn goto_def_for_record_fields() {
covers!(goto_def_for_record_fields);
check_goto(
"
//- /lib.rs
@ -787,7 +782,6 @@ mod tests {
#[test]
fn goto_def_for_field_init_shorthand() {
covers!(goto_def_for_field_init_shorthand);
check_goto(
"
//- /lib.rs

View file

@ -3,11 +3,6 @@
test_utils::marks!(
inserts_angle_brackets_for_generics
inserts_parens_for_function_calls
goto_def_for_macros
goto_def_for_methods
goto_def_for_fields
goto_def_for_record_fields
goto_def_for_field_init_shorthand
call_info_bad_offset
dont_complete_current_use
test_resolve_parent_module_on_module_decl

View file

@ -9,7 +9,6 @@
//! at the index that the match starts at and its tree parent is
//! resolved to the search element definition, we get a reference.
mod classify;
mod rename;
mod search_scope;
@ -27,11 +26,8 @@ use test_utils::tested_by;
use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo};
pub(crate) use self::{
classify::{classify_name_ref, NameRefClass},
rename::rename,
};
pub(crate) use ra_ide_db::defs::{classify_name, Definition};
pub(crate) use self::rename::rename;
pub(crate) use ra_ide_db::defs::{classify_name, classify_name_ref, Definition, NameRefClass};
pub use self::search_scope::SearchScope;

View file

@ -1,84 +0,0 @@
//! Functions that are used to classify an element from its definition or reference.
use hir::{Local, PathResolution, Semantics};
use ra_ide_db::defs::Definition;
use ra_ide_db::RootDatabase;
use ra_prof::profile;
use ra_syntax::{ast, AstNode};
use test_utils::tested_by;
pub enum NameRefClass {
Definition(Definition),
FieldShorthand { local: Local, field: Definition },
}
impl NameRefClass {
pub fn definition(self) -> Definition {
match self {
NameRefClass::Definition(def) => def,
NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local),
}
}
}
pub(crate) fn classify_name_ref(
sema: &Semantics<RootDatabase>,
name_ref: &ast::NameRef,
) -> Option<NameRefClass> {
let _p = profile("classify_name_ref");
let parent = name_ref.syntax().parent()?;
if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
tested_by!(goto_def_for_methods);
if let Some(func) = sema.resolve_method_call(&method_call) {
return Some(NameRefClass::Definition(Definition::ModuleDef(func.into())));
}
}
if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
tested_by!(goto_def_for_fields);
if let Some(field) = sema.resolve_field(&field_expr) {
return Some(NameRefClass::Definition(Definition::StructField(field)));
}
}
if let Some(record_field) = ast::RecordField::cast(parent.clone()) {
tested_by!(goto_def_for_record_fields);
tested_by!(goto_def_for_field_init_shorthand);
if let Some((field, local)) = sema.resolve_record_field(&record_field) {
let field = Definition::StructField(field);
let res = match local {
None => NameRefClass::Definition(field),
Some(local) => NameRefClass::FieldShorthand { field, local },
};
return Some(res);
}
}
if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
tested_by!(goto_def_for_macros);
if let Some(macro_def) = sema.resolve_macro_call(&macro_call) {
return Some(NameRefClass::Definition(Definition::Macro(macro_def)));
}
}
let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
let resolved = sema.resolve_path(&path)?;
let res = match resolved {
PathResolution::Def(def) => Definition::ModuleDef(def),
PathResolution::AssocItem(item) => {
let def = match item {
hir::AssocItem::Function(it) => it.into(),
hir::AssocItem::Const(it) => it.into(),
hir::AssocItem::TypeAlias(it) => it.into(),
};
Definition::ModuleDef(def)
}
PathResolution::Local(local) => Definition::Local(local),
PathResolution::TypeParam(par) => Definition::TypeParam(par),
PathResolution::Macro(def) => Definition::Macro(def),
PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def),
};
Some(NameRefClass::Definition(res))
}

View file

@ -6,8 +6,8 @@
// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
use hir::{
Adt, FieldSource, HasSource, ImplDef, Local, MacroDef, Module, ModuleDef, Name, Semantics,
StructField, TypeParam,
Adt, FieldSource, HasSource, ImplDef, Local, MacroDef, Module, ModuleDef, Name, PathResolution,
Semantics, StructField, TypeParam,
};
use ra_prof::profile;
use ra_syntax::{
@ -117,6 +117,8 @@ impl NameClass {
}
pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> {
let _p = profile("classify_name");
if let Some(bind_pat) = name.syntax().parent().and_then(ast::BindPat::cast) {
if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) {
return Some(NameClass::ConstReference(Definition::ModuleDef(def)));
@ -127,7 +129,6 @@ pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option
}
fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<Definition> {
let _p = profile("classify_name");
let parent = name.syntax().parent()?;
match_ast! {
@ -192,3 +193,74 @@ fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Opti
}
}
}
pub enum NameRefClass {
Definition(Definition),
FieldShorthand { local: Local, field: Definition },
}
impl NameRefClass {
pub fn definition(self) -> Definition {
match self {
NameRefClass::Definition(def) => def,
NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local),
}
}
}
pub fn classify_name_ref(
sema: &Semantics<RootDatabase>,
name_ref: &ast::NameRef,
) -> Option<NameRefClass> {
let _p = profile("classify_name_ref");
let parent = name_ref.syntax().parent()?;
if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
if let Some(func) = sema.resolve_method_call(&method_call) {
return Some(NameRefClass::Definition(Definition::ModuleDef(func.into())));
}
}
if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
if let Some(field) = sema.resolve_field(&field_expr) {
return Some(NameRefClass::Definition(Definition::StructField(field)));
}
}
if let Some(record_field) = ast::RecordField::cast(parent.clone()) {
if let Some((field, local)) = sema.resolve_record_field(&record_field) {
let field = Definition::StructField(field);
let res = match local {
None => NameRefClass::Definition(field),
Some(local) => NameRefClass::FieldShorthand { field, local },
};
return Some(res);
}
}
if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
if let Some(macro_def) = sema.resolve_macro_call(&macro_call) {
return Some(NameRefClass::Definition(Definition::Macro(macro_def)));
}
}
let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
let resolved = sema.resolve_path(&path)?;
let res = match resolved {
PathResolution::Def(def) => Definition::ModuleDef(def),
PathResolution::AssocItem(item) => {
let def = match item {
hir::AssocItem::Function(it) => it.into(),
hir::AssocItem::Const(it) => it.into(),
hir::AssocItem::TypeAlias(it) => it.into(),
};
Definition::ModuleDef(def)
}
PathResolution::Local(local) => Definition::Local(local),
PathResolution::TypeParam(par) => Definition::TypeParam(par),
PathResolution::Macro(def) => Definition::Macro(def),
PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def),
};
Some(NameRefClass::Definition(res))
}