let node = token.parent()?;
let definition = match_ast! {
match node {
- ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced())?,
- ast::Name(name) => NameClass::classify(&sema, &name).map(|d| d.referenced_or_defined())?,
+ ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced_field())?,
+ ast::Name(name) => NameClass::classify(&sema, &name).map(|d| d.defined_or_referenced_field())?,
_ => return None,
}
};
match parent {
ast::NameRef(name_ref) => {
let name_kind = NameRefClass::classify(&sema, &name_ref)?;
- name_kind.referenced()
+ name_kind.referenced_local()
},
ast::Name(name) => {
- NameClass::classify(&sema, &name)?.referenced_or_defined()
+ NameClass::classify(&sema, &name)?.defined_or_referenced_local()
},
_ => return None,
}
reference_definition(&sema, Either::Right(&name_ref))
},
ast::Name(name) => {
- let def = NameClass::classify(&sema, &name)?.referenced_or_defined();
- try_find_trait_item_definition(sema.db, &def)
- .or_else(|| def.try_to_nav(sema.db))
+ let def = NameClass::classify(&sema, &name)?.defined_or_referenced_local();
+ 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, <) {
- let def = name_class.referenced_or_defined();
+ let def = name_class.defined_or_referenced_local();
def.try_to_nav(sema.db)
} else {
reference_definition(&sema, Either::Left(<))
|lifetime| NameRefClass::classify_lifetime(sema, lifetime),
|name_ref| NameRefClass::classify(sema, name_ref),
)?;
- let def = name_kind.referenced();
+ let def = name_kind.referenced_local();
def.try_to_nav(sema.db)
}
r#"
enum Foo {
Bar { x: i32 }
-} //^
+}
fn baz(foo: Foo) {
match foo {
Foo::Bar { x$0 } => x
+ //^
};
}
"#,
let node = sema.find_node_at_offset_with_descend(&syntax, position.offset)?;
let def = match &node {
ast::NameLike::Name(name) => {
- NameClass::classify(&sema, name).map(|class| class.referenced_or_defined())
+ NameClass::classify(&sema, name).map(|class| class.defined_or_referenced_local())
}
ast::NameLike::NameRef(name_ref) => {
- NameRefClass::classify(&sema, name_ref).map(|class| class.referenced())
+ NameRefClass::classify(&sema, name_ref).map(|class| class.referenced_local())
}
ast::NameLike::Lifetime(_) => None,
}?;
match node {
// we don't use NameClass::referenced_or_defined here as we do not want to resolve
// field pattern shorthands to their definition
- ast::Name(name) => NameClass::classify(&sema, &name).and_then(|class| match class {
- NameClass::ConstReference(def) => Some(def),
- def => def.defined(),
- }),
+ ast::Name(name) => NameClass::classify(&sema, &name).map(|class| class.defined_or_referenced_local()),
ast::NameRef(name_ref) => {
- NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced())
+ NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced_field())
},
ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime).map_or_else(
- || NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced()),
+ || NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced_local()),
|d| d.defined(),
),
-
_ => {
if ast::Comment::cast(token.clone()).is_some() {
cov_mark::hit!(no_highlight_on_comment_hover);
let (def, is_literal_search) =
if let Some(name) = get_name_of_item_declaration(&syntax, position) {
- (NameClass::classify(sema, &name)?.referenced_or_defined(), true)
+ (NameClass::classify(sema, &name)?.defined_or_referenced_field(), true)
} else {
(find_def(sema, &syntax, position.offset)?, false)
};
offset: TextSize,
) -> Option<Definition> {
let def = match sema.find_node_at_offset_with_descend(syntax, offset)? {
- ast::NameLike::NameRef(name_ref) => NameRefClass::classify(sema, &name_ref)?.referenced(),
- ast::NameLike::Name(name) => NameClass::classify(sema, &name)?.referenced_or_defined(),
+ ast::NameLike::NameRef(name_ref) => {
+ NameRefClass::classify(sema, &name_ref)?.referenced_local()
+ }
+ ast::NameLike::Name(name) => {
+ NameClass::classify(sema, &name)?.defined_or_referenced_local()
+ }
ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
- .map(|class| class.referenced())
+ .map(|class| class.referenced_local())
.or_else(|| {
NameClass::classify_lifetime(sema, &lifetime)
- .map(|class| class.referenced_or_defined())
+ .map(|class| class.defined_or_referenced_local())
})?,
};
Some(def)
bail!("Renaming aliases is currently unsupported")
}
ast::NameLike::Name(name) => {
- NameClass::classify(sema, &name).map(|class| class.referenced_or_defined())
+ NameClass::classify(sema, &name).map(|class| class.defined_or_referenced_local())
}
ast::NameLike::NameRef(name_ref) => {
if let Some(def) =
- NameRefClass::classify(sema, &name_ref).map(|class| class.referenced())
+ NameRefClass::classify(sema, &name_ref).map(|class| class.referenced_local())
{
// 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()) {
}
}
ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
- .map(|class| class.referenced())
+ .map(|class| class.referenced_local())
.or_else(|| {
- NameClass::classify_lifetime(sema, &lifetime).map(|it| it.referenced_or_defined())
+ NameClass::classify_lifetime(sema, &lifetime)
+ .map(|it| it.defined_or_referenced_field())
}),
}
.ok_or_else(|| format_err!("No references found at position"))?;
Some(NameClass::ConstReference(def)) => highlight_def(db, krate, def),
Some(NameClass::PatFieldShorthand { field_ref, .. }) => {
let mut h = HlTag::Symbol(SymbolKind::Field).into();
- if let Definition::Field(field) = field_ref {
- if let hir::VariantDef::Union(_) = field.parent_def(db) {
- h |= HlMod::Unsafe;
- }
+ if let hir::VariantDef::Union(_) = field_ref.parent_def(db) {
+ h |= HlMod::Unsafe;
}
h
}
body.descendants()
.filter_map(ast::NameRef::cast)
.filter_map(|name_ref| NameRefClass::classify(&ctx.sema, &name_ref))
- .map(|name_kind| name_kind.referenced())
+ .map(|name_kind| name_kind.referenced_local())
.filter_map(|definition| match definition {
Definition::Local(local) => Some(local),
_ => None,
/// `None` in `if let None = Some(82) {}`.
/// Syntactically, it is a name, but semantically it is a reference.
ConstReference(Definition),
- /// `field` in `if let Foo { field } = foo`. Here, `ast::Name` both Here the
- /// name both introduces a definition into a local scope, and refers to an
- /// existing definition.
+ /// `field` in `if let Foo { field } = foo`. Here, `ast::Name` both introduces
+ /// a definition into a local scope, and refers to an existing definition.
PatFieldShorthand {
local_def: Local,
- field_ref: Definition,
+ field_ref: Field,
},
}
Some(res)
}
- /// `Definition` referenced or defined by this name.
- pub fn referenced_or_defined(self) -> Definition {
+ /// `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 } => field_ref,
+ 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)
+ }
}
}
})
.and_then(|name_ref| NameRefClass::classify(sema, &name_ref))?;
- Some(NameClass::Definition(name_ref_class.referenced()))
+ Some(NameClass::Definition(name_ref_class.referenced_field()))
} else {
let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?;
let krate = sema.resolve_extern_crate(&extern_crate)?;
if let Some(record_pat_field) = it.syntax().parent().and_then(ast::RecordPatField::cast) {
if record_pat_field.name_ref().is_none() {
if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) {
- let field = Definition::Field(field);
return Some(NameClass::PatFieldShorthand { local_def: local, field_ref: field });
}
}
#[derive(Debug)]
pub enum NameRefClass {
Definition(Definition),
- FieldShorthand { local_ref: Local, field_ref: Definition },
+ FieldShorthand { local_ref: Local, field_ref: Field },
}
impl NameRefClass {
- /// `Definition`, which this name refers to.
- pub fn referenced(self) -> Definition {
+ /// `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: _ } => {
- // FIXME: this is inherently ambiguous -- this name refers to
- // two different defs....
Definition::Local(local_ref)
}
}
if let Some(record_field) = ast::RecordExprField::for_field_name(name_ref) {
if let Some((field, local, _)) = sema.resolve_record_field(&record_field) {
- let field = Definition::Field(field);
let res = match local {
- None => NameRefClass::Definition(field),
+ None => NameRefClass::Definition(Definition::Field(field)),
Some(local) => {
NameRefClass::FieldShorthand { field_ref: field, local_ref: local }
}
}
}
Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => {
+ let field = Definition::Field(field);
let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
let access = match self.def {
Definition::Field(_) if field == self.def => reference_access(&field, name_ref),
match NameClass::classify(self.sema, name) {
Some(NameClass::PatFieldShorthand { local_def: _, field_ref })
if matches!(
- self.def, Definition::Field(_) if field_ref == self.def
+ self.def, Definition::Field(_) if Definition::Field(field_ref) == self.def
) =>
{
let FileRange { file_id, range } = self.sema.original_range(name.syntax());