Classify name takes const patterns into account

This commit is contained in:
Aleksey Kladov 2020-02-28 15:27:52 +01:00
parent 9ef6359950
commit 209eb32796
6 changed files with 44 additions and 23 deletions

View file

@ -30,7 +30,9 @@ pub(crate) fn goto_definition(
reference_definition(&sema, &name_ref).to_vec()
},
ast::Name(name) => {
name_definition(&sema, &name)?
let def = classify_name(&sema, &name)?.definition();
let nav = def.try_to_nav(sema.db)?;
vec![nav]
},
_ => return None,
}
@ -88,15 +90,6 @@ pub(crate) fn reference_definition(
Approximate(navs)
}
fn name_definition(
sema: &Semantics<RootDatabase>,
name: &ast::Name,
) -> Option<Vec<NavigationTarget>> {
let def = classify_name(sema, name)?;
let nav = def.try_to_nav(sema.db)?;
Some(vec![nav])
}
#[cfg(test)]
mod tests {
use test_utils::{assert_eq_text, covers};

View file

@ -156,7 +156,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
classify_name_ref(&sema, &name_ref).map(|d| (name_ref.syntax().clone(), d))
},
ast::Name(name) => {
classify_name(&sema, &name).map(|d| (name.syntax().clone(), d))
classify_name(&sema, &name).map(|d| (name.syntax().clone(), d.definition()))
},
_ => None,
}
@ -761,13 +761,13 @@ fn func(foo: i32) { if true { <|>foo; }; }
fn test_hover_through_literal_string_in_builtin_macro() {
check_hover_no_result(
r#"
//- /lib.rs
//- /lib.rs
#[rustc_builtin_macro]
macro_rules! assert {
($cond:expr) => {{ /* compiler built-in */ }};
($cond:expr,) => {{ /* compiler built-in */ }};
($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};
}
}
fn foo() {
assert!("hel<|>lo");

View file

@ -155,7 +155,7 @@ fn find_name(
opt_name: Option<ast::Name>,
) -> Option<RangeInfo<(String, NameDefinition)>> {
if let Some(name) = opt_name {
let def = classify_name(sema, &name)?;
let def = classify_name(sema, &name)?.definition();
let range = name.syntax().text_range();
return Some(RangeInfo::new(range, (name.text().to_string(), def)));
}

View file

@ -7,7 +7,7 @@ mod tests;
use hir::{Name, Semantics};
use ra_ide_db::{
defs::{classify_name, NameDefinition},
defs::{classify_name, NameClass, NameDefinition},
RootDatabase,
};
use ra_prof::profile;
@ -169,7 +169,7 @@ fn highlight_element(
let name = element.into_node().and_then(ast::Name::cast).unwrap();
let name_kind = classify_name(sema, &name);
if let Some(NameDefinition::Local(local)) = &name_kind {
if let Some(NameClass::NameDefinition(NameDefinition::Local(local))) = &name_kind {
if let Some(name) = local.name(db) {
let shadow_count = bindings_shadow_count.entry(name.clone()).or_default();
*shadow_count += 1;
@ -177,11 +177,13 @@ fn highlight_element(
}
};
let h = match name_kind {
Some(name_kind) => highlight_name(db, name_kind),
None => highlight_name_by_syntax(name),
};
h | HighlightModifier::Definition
match name_kind {
Some(NameClass::NameDefinition(def)) => {
highlight_name(db, def) | HighlightModifier::Definition
}
Some(NameClass::ConstReference(def)) => highlight_name(db, def),
None => highlight_name_by_syntax(name) | HighlightModifier::Definition,
}
}
// Highlight references like the definitions they resolve to

View file

@ -68,7 +68,32 @@ impl NameDefinition {
}
}
pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameDefinition> {
pub enum NameClass {
NameDefinition(NameDefinition),
/// `None` in `if let None = Some(82) {}`
ConstReference(NameDefinition),
}
impl NameClass {
pub fn into_definition(self) -> Option<NameDefinition> {
match self {
NameClass::NameDefinition(it) => Some(it),
NameClass::ConstReference(_) => None,
}
}
pub fn definition(self) -> NameDefinition {
match self {
NameClass::NameDefinition(it) | NameClass::ConstReference(it) => it,
}
}
}
pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> {
classify_name_inner(sema, name).map(NameClass::NameDefinition)
}
fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameDefinition> {
let _p = profile("classify_name");
let parent = name.syntax().parent()?;

View file

@ -59,6 +59,7 @@ impl<'a> ImportsLocator<'a> {
} else {
candidate_node
};
classify_name(&self.sema, &ast::Name::cast(candidate_name_node)?)
let name = ast::Name::cast(candidate_name_node)?;
classify_name(&self.sema, &name)?.into_definition()
}
}