Only use HIR when searching for enum constructors, otherwise fall back to AST

This commit is contained in:
Lukas Wirth 2021-02-13 17:57:14 +01:00
parent c395dd1032
commit 8ac6041bcf

View File

@ -70,14 +70,11 @@ pub(crate) fn find_all_refs(
}); });
usages.references.retain(|_, it| !it.is_empty()); usages.references.retain(|_, it| !it.is_empty());
} }
Definition::ModuleDef(def @ hir::ModuleDef::Adt(_)) Definition::ModuleDef(hir::ModuleDef::Adt(_))
| Definition::ModuleDef(def @ hir::ModuleDef::Variant(_)) => { | Definition::ModuleDef(hir::ModuleDef::Variant(_)) => {
refs.for_each(|it| { refs.for_each(|it| {
it.retain(|reference| { it.retain(|reference| {
reference reference.name.as_name_ref().map_or(false, is_lit_name_ref)
.name
.as_name_ref()
.map_or(false, |name_ref| is_lit_name_ref(sema, def, name_ref))
}) })
}); });
usages.references.retain(|_, it| !it.is_empty()); usages.references.retain(|_, it| !it.is_empty());
@ -189,55 +186,44 @@ fn is_enum_lit_name_ref(
enum_: hir::Enum, enum_: hir::Enum,
name_ref: &ast::NameRef, name_ref: &ast::NameRef,
) -> bool { ) -> bool {
for ancestor in name_ref.syntax().ancestors() { let path_is_variant_of_enum = |path: ast::Path| {
match_ast! { matches!(
match ancestor { sema.resolve_path(&path),
ast::PathExpr(path_expr) => { Some(PathResolution::Def(hir::ModuleDef::Variant(variant)))
return matches!( if variant.parent_enum(sema.db) == enum_
path_expr.path().and_then(|p| sema.resolve_path(&p)), )
Some(PathResolution::Def(hir::ModuleDef::Variant(variant))) };
if variant.parent_enum(sema.db) == enum_ name_ref
) .syntax()
}, .ancestors()
ast::RecordExpr(record_expr) => { .find_map(|ancestor| {
return matches!( match_ast! {
record_expr.path().and_then(|p| sema.resolve_path(&p)), match ancestor {
Some(PathResolution::Def(hir::ModuleDef::Variant(variant))) ast::PathExpr(path_expr) => path_expr.path().map(path_is_variant_of_enum),
if variant.parent_enum(sema.db) == enum_ ast::RecordExpr(record_expr) => record_expr.path().map(path_is_variant_of_enum),
) _ => None,
}, }
_ => (),
} }
} })
} .unwrap_or(false)
false
} }
fn is_lit_name_ref( fn path_ends_with(path: Option<ast::Path>, name_ref: &ast::NameRef) -> bool {
sema: &Semantics<RootDatabase>, path.and_then(|path| path.segment())
def: hir::ModuleDef, .and_then(|segment| segment.name_ref())
name_ref: &ast::NameRef, .map_or(false, |segment| segment == *name_ref)
) -> bool { }
for ancestor in name_ref.syntax().ancestors() {
fn is_lit_name_ref(name_ref: &ast::NameRef) -> bool {
name_ref.syntax().ancestors().find_map(|ancestor| {
match_ast! { match_ast! {
match ancestor { match ancestor {
ast::PathExpr(path_expr) => { ast::PathExpr(path_expr) => Some(path_ends_with(path_expr.path(), name_ref)),
return matches!( ast::RecordExpr(record_expr) => Some(path_ends_with(record_expr.path(), name_ref)),
path_expr.path().and_then(|p| sema.resolve_path(&p)), _ => None,
Some(PathResolution::Def(def2)) if def == def2
)
},
ast::RecordExpr(record_expr) => {
return matches!(
record_expr.path().and_then(|p| sema.resolve_path(&p)),
Some(PathResolution::Def(def2)) if def == def2
)
},
_ => (),
} }
} }
} }).unwrap_or(false)
false
} }
#[cfg(test)] #[cfg(test)]