Remove index based fallback for goto def

We are so precise that the fallback creates more confusion, when you can
goto def on an unresolved reference.
This commit is contained in:
Aleksey Kladov 2021-01-22 15:11:29 +03:00
parent 6403b530bb
commit 2c786f1b98

View file

@ -2,16 +2,14 @@ use either::Either;
use hir::{HasAttrs, ModuleDef, Semantics}; use hir::{HasAttrs, ModuleDef, Semantics};
use ide_db::{ use ide_db::{
defs::{Definition, NameClass, NameRefClass}, defs::{Definition, NameClass, NameRefClass},
symbol_index, RootDatabase, RootDatabase,
}; };
use syntax::{ use syntax::{
ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextSize, TokenAtOffset, T, ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextSize, TokenAtOffset, T,
}; };
use crate::{ use crate::{
display::{ToNav, TryToNav}, display::TryToNav, doc_links::extract_definitions_from_markdown, runnables::doc_owner_to_def,
doc_links::extract_definitions_from_markdown,
runnables::doc_owner_to_def,
FilePosition, NavigationTarget, RangeInfo, FilePosition, NavigationTarget, RangeInfo,
}; };
@ -38,28 +36,26 @@ pub(crate) fn goto_definition(
return Some(RangeInfo::new(original_token.text_range(), vec![nav])); return Some(RangeInfo::new(original_token.text_range(), vec![nav]));
} }
let nav_targets = match_ast! { let nav = match_ast! {
match parent { match parent {
ast::NameRef(name_ref) => { ast::NameRef(name_ref) => {
reference_definition(&sema, Either::Right(&name_ref)).to_vec() reference_definition(&sema, Either::Right(&name_ref))
}, },
ast::Name(name) => { ast::Name(name) => {
let def = NameClass::classify(&sema, &name)?.referenced_or_defined(sema.db); let def = NameClass::classify(&sema, &name)?.referenced_or_defined(sema.db);
let nav = def.try_to_nav(sema.db)?; def.try_to_nav(sema.db)
vec![nav]
}, },
ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) { ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) {
let def = name_class.referenced_or_defined(sema.db); let def = name_class.referenced_or_defined(sema.db);
let nav = def.try_to_nav(sema.db)?; def.try_to_nav(sema.db)
vec![nav]
} else { } else {
reference_definition(&sema, Either::Left(&lt)).to_vec() reference_definition(&sema, Either::Left(&lt))
}, },
_ => return None, _ => return None,
} }
}; };
Some(RangeInfo::new(original_token.text_range(), nav_targets)) Some(RangeInfo::new(original_token.text_range(), nav.into_iter().collect()))
} }
fn def_for_doc_comment( fn def_for_doc_comment(
@ -120,42 +116,16 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
} }
} }
#[derive(Debug)]
pub(crate) enum ReferenceResult {
Exact(NavigationTarget),
Approximate(Vec<NavigationTarget>),
}
impl ReferenceResult {
fn to_vec(self) -> Vec<NavigationTarget> {
match self {
ReferenceResult::Exact(target) => vec![target],
ReferenceResult::Approximate(vec) => vec,
}
}
}
pub(crate) fn reference_definition( pub(crate) fn reference_definition(
sema: &Semantics<RootDatabase>, sema: &Semantics<RootDatabase>,
name_ref: Either<&ast::Lifetime, &ast::NameRef>, name_ref: Either<&ast::Lifetime, &ast::NameRef>,
) -> ReferenceResult { ) -> Option<NavigationTarget> {
let name_kind = name_ref.either( let name_kind = name_ref.either(
|lifetime| NameRefClass::classify_lifetime(sema, lifetime), |lifetime| NameRefClass::classify_lifetime(sema, lifetime),
|name_ref| NameRefClass::classify(sema, name_ref), |name_ref| NameRefClass::classify(sema, name_ref),
); )?;
if let Some(def) = name_kind { let def = name_kind.referenced(sema.db);
let def = def.referenced(sema.db); def.try_to_nav(sema.db)
return match def.try_to_nav(sema.db) {
Some(nav) => ReferenceResult::Exact(nav),
None => ReferenceResult::Approximate(Vec::new()),
};
}
// Fallback index based approach:
let name = name_ref.either(ast::Lifetime::text, ast::NameRef::text);
let navs =
symbol_index::index_resolve(sema.db, name).into_iter().map(|s| s.to_nav(sema.db)).collect();
ReferenceResult::Approximate(navs)
} }
#[cfg(test)] #[cfg(test)]
@ -297,13 +267,13 @@ fn bar() {
fn goto_def_for_macros_from_other_crates() { fn goto_def_for_macros_from_other_crates() {
check( check(
r#" r#"
//- /lib.rs //- /lib.rs crate:main deps:foo
use foo::foo; use foo::foo;
fn bar() { fn bar() {
$0foo!(); $0foo!();
} }
//- /foo/lib.rs //- /foo/lib.rs crate:foo
#[macro_export] #[macro_export]
macro_rules! foo { () => { () } } macro_rules! foo { () => { () } }
//^^^ //^^^
@ -315,10 +285,10 @@ macro_rules! foo { () => { () } }
fn goto_def_for_macros_in_use_tree() { fn goto_def_for_macros_in_use_tree() {
check( check(
r#" r#"
//- /lib.rs //- /lib.rs crate:main deps:foo
use foo::foo$0; use foo::foo$0;
//- /foo/lib.rs //- /foo/lib.rs crate:foo
#[macro_export] #[macro_export]
macro_rules! foo { () => { () } } macro_rules! foo { () => { () } }
//^^^ //^^^
@ -976,10 +946,10 @@ type Alias<T> = T$0;
fn goto_def_for_macro_container() { fn goto_def_for_macro_container() {
check( check(
r#" r#"
//- /lib.rs //- /lib.rs crate:main deps:foo
foo::module$0::mac!(); foo::module$0::mac!();
//- /foo/lib.rs //- /foo/lib.rs crate:foo
pub mod module { pub mod module {
//^^^^^^ //^^^^^^
#[macro_export] #[macro_export]