mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-19 00:31:19 +00:00
Inline name classification reference calls
This commit is contained in:
parent
c65bb7f8b9
commit
c41f1279a3
9 changed files with 117 additions and 80 deletions
|
@ -112,8 +112,16 @@ pub(crate) fn external_docs(
|
||||||
let node = token.parent()?;
|
let node = token.parent()?;
|
||||||
let definition = match_ast! {
|
let definition = match_ast! {
|
||||||
match node {
|
match node {
|
||||||
ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced_field())?,
|
ast::NameRef(name_ref) => match NameRefClass::classify(&sema, &name_ref)? {
|
||||||
ast::Name(name) => NameClass::classify(&sema, &name).map(|d| d.defined_or_referenced_field())?,
|
NameRefClass::Definition(def) => def,
|
||||||
|
NameRefClass::FieldShorthand { local_ref: _, field_ref } => {
|
||||||
|
Definition::Field(field_ref)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ast::Name(name) => match NameClass::classify(&sema, &name)? {
|
||||||
|
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
||||||
|
NameClass::PatFieldShorthand { local_def: _, field_ref } => Definition::Field(field_ref),
|
||||||
|
},
|
||||||
_ => return None,
|
_ => return None,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,12 +23,15 @@ pub(crate) fn goto_declaration(
|
||||||
let parent = token.parent()?;
|
let parent = token.parent()?;
|
||||||
let def = match_ast! {
|
let def = match_ast! {
|
||||||
match parent {
|
match parent {
|
||||||
ast::NameRef(name_ref) => {
|
ast::NameRef(name_ref) => match NameRefClass::classify(&sema, &name_ref)? {
|
||||||
let name_kind = NameRefClass::classify(&sema, &name_ref)?;
|
NameRefClass::Definition(def) => def,
|
||||||
name_kind.referenced_local()
|
NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
|
||||||
|
Definition::Local(local_ref)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ast::Name(name) => {
|
ast::Name(name) => match NameClass::classify(&sema, &name)? {
|
||||||
NameClass::classify(&sema, &name)?.defined_or_referenced_local()
|
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
||||||
|
NameClass::PatFieldShorthand { local_def, field_ref: _ } => Definition::Local(local_def),
|
||||||
},
|
},
|
||||||
_ => return None,
|
_ => return None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,11 +60,17 @@ pub(crate) fn goto_definition(
|
||||||
reference_definition(&sema, Either::Right(&name_ref))
|
reference_definition(&sema, Either::Right(&name_ref))
|
||||||
},
|
},
|
||||||
ast::Name(name) => {
|
ast::Name(name) => {
|
||||||
let def = NameClass::classify(&sema, &name)?.defined_or_referenced_local();
|
let def = match NameClass::classify(&sema, &name)? {
|
||||||
|
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
||||||
|
NameClass::PatFieldShorthand { local_def, field_ref: _ } => Definition::Local(local_def),
|
||||||
|
};
|
||||||
try_find_trait_item_definition(sema.db, &def).or_else(|| def.try_to_nav(sema.db))
|
try_find_trait_item_definition(sema.db, &def).or_else(|| def.try_to_nav(sema.db))
|
||||||
},
|
},
|
||||||
ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, <) {
|
ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, <) {
|
||||||
let def = name_class.defined_or_referenced_local();
|
let def = match name_class {
|
||||||
|
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
||||||
|
NameClass::PatFieldShorthand { local_def, field_ref: _ } => Definition::Local(local_def),
|
||||||
|
};
|
||||||
def.try_to_nav(sema.db)
|
def.try_to_nav(sema.db)
|
||||||
} else {
|
} else {
|
||||||
reference_definition(&sema, Either::Left(<))
|
reference_definition(&sema, Either::Left(<))
|
||||||
|
@ -139,7 +145,10 @@ pub(crate) fn reference_definition(
|
||||||
|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),
|
||||||
)?;
|
)?;
|
||||||
let def = name_kind.referenced_local();
|
let def = match name_kind {
|
||||||
|
NameRefClass::Definition(def) => def,
|
||||||
|
NameRefClass::FieldShorthand { local_ref, field_ref: _ } => Definition::Local(local_ref),
|
||||||
|
};
|
||||||
def.try_to_nav(sema.db)
|
def.try_to_nav(sema.db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,19 @@ pub(crate) fn goto_implementation(
|
||||||
|
|
||||||
let node = sema.find_node_at_offset_with_descend(&syntax, position.offset)?;
|
let node = sema.find_node_at_offset_with_descend(&syntax, position.offset)?;
|
||||||
let def = match &node {
|
let def = match &node {
|
||||||
ast::NameLike::Name(name) => {
|
ast::NameLike::Name(name) => NameClass::classify(&sema, name).map(|class| match class {
|
||||||
NameClass::classify(&sema, name).map(|class| class.defined_or_referenced_local())
|
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
||||||
|
NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
|
||||||
|
Definition::Local(local_def)
|
||||||
}
|
}
|
||||||
|
}),
|
||||||
ast::NameLike::NameRef(name_ref) => {
|
ast::NameLike::NameRef(name_ref) => {
|
||||||
NameRefClass::classify(&sema, name_ref).map(|class| class.referenced_local())
|
NameRefClass::classify(&sema, name_ref).map(|class| match class {
|
||||||
|
NameRefClass::Definition(def) => def,
|
||||||
|
NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
|
||||||
|
Definition::Local(local_ref)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
ast::NameLike::Lifetime(_) => None,
|
ast::NameLike::Lifetime(_) => None,
|
||||||
}?;
|
}?;
|
||||||
|
|
|
@ -96,12 +96,21 @@ pub(crate) fn hover(
|
||||||
match node {
|
match node {
|
||||||
// we don't use NameClass::referenced_or_defined here as we do not want to resolve
|
// we don't use NameClass::referenced_or_defined here as we do not want to resolve
|
||||||
// field pattern shorthands to their definition
|
// field pattern shorthands to their definition
|
||||||
ast::Name(name) => NameClass::classify(&sema, &name).map(|class| class.defined_or_referenced_local()),
|
ast::Name(name) => NameClass::classify(&sema, &name).map(|class| match class {
|
||||||
ast::NameRef(name_ref) => {
|
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
||||||
NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced_field())
|
NameClass::PatFieldShorthand { local_def, field_ref: _ } => Definition::Local(local_def),
|
||||||
},
|
}),
|
||||||
|
ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|class| match class {
|
||||||
|
NameRefClass::Definition(def) => def,
|
||||||
|
NameRefClass::FieldShorthand { local_ref: _, field_ref } => {
|
||||||
|
Definition::Field(field_ref)
|
||||||
|
}
|
||||||
|
}),
|
||||||
ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime).map_or_else(
|
ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime).map_or_else(
|
||||||
|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced_local()),
|
|| NameRefClass::classify_lifetime(&sema, &lifetime).and_then(|class| match class {
|
||||||
|
NameRefClass::Definition(it) => Some(it),
|
||||||
|
_ => None,
|
||||||
|
}),
|
||||||
|d| d.defined(),
|
|d| d.defined(),
|
||||||
),
|
),
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -58,7 +58,15 @@ pub(crate) fn find_all_refs(
|
||||||
|
|
||||||
let (def, is_literal_search) =
|
let (def, is_literal_search) =
|
||||||
if let Some(name) = get_name_of_item_declaration(&syntax, position) {
|
if let Some(name) = get_name_of_item_declaration(&syntax, position) {
|
||||||
(NameClass::classify(sema, &name)?.defined_or_referenced_field(), true)
|
(
|
||||||
|
match NameClass::classify(sema, &name)? {
|
||||||
|
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
||||||
|
NameClass::PatFieldShorthand { local_def: _, field_ref } => {
|
||||||
|
Definition::Field(field_ref)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
(find_def(sema, &syntax, position.offset)?, false)
|
(find_def(sema, &syntax, position.offset)?, false)
|
||||||
};
|
};
|
||||||
|
@ -116,17 +124,28 @@ pub(crate) fn find_def(
|
||||||
offset: TextSize,
|
offset: TextSize,
|
||||||
) -> Option<Definition> {
|
) -> Option<Definition> {
|
||||||
let def = match sema.find_node_at_offset_with_descend(syntax, offset)? {
|
let def = match sema.find_node_at_offset_with_descend(syntax, offset)? {
|
||||||
ast::NameLike::NameRef(name_ref) => {
|
ast::NameLike::NameRef(name_ref) => match NameRefClass::classify(sema, &name_ref)? {
|
||||||
NameRefClass::classify(sema, &name_ref)?.referenced_local()
|
NameRefClass::Definition(def) => def,
|
||||||
|
NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
|
||||||
|
Definition::Local(local_ref)
|
||||||
}
|
}
|
||||||
ast::NameLike::Name(name) => {
|
},
|
||||||
NameClass::classify(sema, &name)?.defined_or_referenced_local()
|
ast::NameLike::Name(name) => match NameClass::classify(sema, &name)? {
|
||||||
|
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
||||||
|
NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
|
||||||
|
Definition::Local(local_def)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
|
ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
|
||||||
.map(|class| class.referenced_local())
|
.and_then(|class| match class {
|
||||||
|
NameRefClass::Definition(it) => Some(it),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
NameClass::classify_lifetime(sema, &lifetime)
|
NameClass::classify_lifetime(sema, &lifetime).and_then(|class| match class {
|
||||||
.map(|class| class.defined_or_referenced_local())
|
NameClass::Definition(it) => Some(it),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
})?,
|
})?,
|
||||||
};
|
};
|
||||||
Some(def)
|
Some(def)
|
||||||
|
|
|
@ -107,13 +107,19 @@ fn find_definition(
|
||||||
{
|
{
|
||||||
bail!("Renaming aliases is currently unsupported")
|
bail!("Renaming aliases is currently unsupported")
|
||||||
}
|
}
|
||||||
ast::NameLike::Name(name) => {
|
ast::NameLike::Name(name) => NameClass::classify(sema, &name).map(|class| match class {
|
||||||
NameClass::classify(sema, &name).map(|class| class.defined_or_referenced_local())
|
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
||||||
|
NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
|
||||||
|
Definition::Local(local_def)
|
||||||
}
|
}
|
||||||
|
}),
|
||||||
ast::NameLike::NameRef(name_ref) => {
|
ast::NameLike::NameRef(name_ref) => {
|
||||||
if let Some(def) =
|
if let Some(def) = NameRefClass::classify(sema, &name_ref).map(|class| match class {
|
||||||
NameRefClass::classify(sema, &name_ref).map(|class| class.referenced_local())
|
NameRefClass::Definition(def) => def,
|
||||||
{
|
NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
|
||||||
|
Definition::Local(local_ref)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
// if the name differs from the definitions name it has to be an alias
|
// if the name differs from the definitions name it has to be an alias
|
||||||
if def.name(sema.db).map_or(false, |it| it.to_string() != name_ref.text()) {
|
if def.name(sema.db).map_or(false, |it| it.to_string() != name_ref.text()) {
|
||||||
bail!("Renaming aliases is currently unsupported");
|
bail!("Renaming aliases is currently unsupported");
|
||||||
|
@ -124,10 +130,15 @@ fn find_definition(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
|
ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
|
||||||
.map(|class| class.referenced_local())
|
.and_then(|class| match class {
|
||||||
|
NameRefClass::Definition(def) => Some(def),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
NameClass::classify_lifetime(sema, &lifetime)
|
NameClass::classify_lifetime(sema, &lifetime).and_then(|it| match it {
|
||||||
.map(|it| it.defined_or_referenced_field())
|
NameClass::Definition(it) => Some(it),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
.ok_or_else(|| format_err!("No references found at position"))?;
|
.ok_or_else(|| format_err!("No references found at position"))?;
|
||||||
|
|
|
@ -638,7 +638,12 @@ fn vars_used_in_body(ctx: &AssistContext, body: &FunctionBody) -> Vec<Local> {
|
||||||
body.descendants()
|
body.descendants()
|
||||||
.filter_map(ast::NameRef::cast)
|
.filter_map(ast::NameRef::cast)
|
||||||
.filter_map(|name_ref| NameRefClass::classify(&ctx.sema, &name_ref))
|
.filter_map(|name_ref| NameRefClass::classify(&ctx.sema, &name_ref))
|
||||||
.map(|name_kind| name_kind.referenced_local())
|
.map(|name_kind| match name_kind {
|
||||||
|
NameRefClass::Definition(def) => def,
|
||||||
|
NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
|
||||||
|
Definition::Local(local_ref)
|
||||||
|
}
|
||||||
|
})
|
||||||
.filter_map(|definition| match definition {
|
.filter_map(|definition| match definition {
|
||||||
Definition::Local(local) => Some(local),
|
Definition::Local(local) => Some(local),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
@ -133,26 +133,6 @@ impl NameClass {
|
||||||
Some(res)
|
Some(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Definition` referenced or defined by this name, in case of a shorthand this will yield the field reference.
|
|
||||||
pub fn defined_or_referenced_field(self) -> Definition {
|
|
||||||
match self {
|
|
||||||
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
|
||||||
NameClass::PatFieldShorthand { local_def: _, field_ref } => {
|
|
||||||
Definition::Field(field_ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `Definition` referenced or defined by this name, in case of a shorthand this will yield the local definition.
|
|
||||||
pub fn defined_or_referenced_local(self) -> Definition {
|
|
||||||
match self {
|
|
||||||
NameClass::Definition(it) | NameClass::ConstReference(it) => it,
|
|
||||||
NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
|
|
||||||
Definition::Local(local_def)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn classify(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> {
|
pub fn classify(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> {
|
||||||
let _p = profile::span("classify_name");
|
let _p = profile::span("classify_name");
|
||||||
|
|
||||||
|
@ -194,7 +174,12 @@ impl NameClass {
|
||||||
})
|
})
|
||||||
.and_then(|name_ref| NameRefClass::classify(sema, &name_ref))?;
|
.and_then(|name_ref| NameRefClass::classify(sema, &name_ref))?;
|
||||||
|
|
||||||
Some(NameClass::Definition(name_ref_class.referenced_field()))
|
Some(NameClass::Definition(match name_ref_class {
|
||||||
|
NameRefClass::Definition(def) => def,
|
||||||
|
NameRefClass::FieldShorthand { local_ref: _, field_ref } => {
|
||||||
|
Definition::Field(field_ref)
|
||||||
|
}
|
||||||
|
}))
|
||||||
} else {
|
} else {
|
||||||
let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?;
|
let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?;
|
||||||
let krate = sema.resolve_extern_crate(&extern_crate)?;
|
let krate = sema.resolve_extern_crate(&extern_crate)?;
|
||||||
|
@ -316,26 +301,6 @@ pub enum NameRefClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NameRefClass {
|
impl NameRefClass {
|
||||||
/// `Definition`, which this name refers to with a preference for the field reference in case of a field shorthand.
|
|
||||||
pub fn referenced_field(self) -> Definition {
|
|
||||||
match self {
|
|
||||||
NameRefClass::Definition(def) => def,
|
|
||||||
NameRefClass::FieldShorthand { local_ref: _, field_ref } => {
|
|
||||||
Definition::Field(field_ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `Definition`, which this name refers to with a preference for the local reference in case of a field shorthand.
|
|
||||||
pub fn referenced_local(self) -> Definition {
|
|
||||||
match self {
|
|
||||||
NameRefClass::Definition(def) => def,
|
|
||||||
NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
|
|
||||||
Definition::Local(local_ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: we don't have unit-tests for this rather important function.
|
// Note: we don't have unit-tests for this rather important function.
|
||||||
// It is primarily exercised via goto definition tests in `ide`.
|
// It is primarily exercised via goto definition tests in `ide`.
|
||||||
pub fn classify(
|
pub fn classify(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue