diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 00b6f7a5c3..480adb8419 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -112,8 +112,16 @@ pub(crate) fn external_docs( let node = token.parent()?; let definition = match_ast! { match node { - 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())?, + ast::NameRef(name_ref) => match NameRefClass::classify(&sema, &name_ref)? { + 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, } }; diff --git a/crates/ide/src/goto_declaration.rs b/crates/ide/src/goto_declaration.rs index 59306ac065..9cc67b13e9 100644 --- a/crates/ide/src/goto_declaration.rs +++ b/crates/ide/src/goto_declaration.rs @@ -23,12 +23,15 @@ pub(crate) fn goto_declaration( let parent = token.parent()?; let def = match_ast! { match parent { - ast::NameRef(name_ref) => { - let name_kind = NameRefClass::classify(&sema, &name_ref)?; - name_kind.referenced_local() + ast::NameRef(name_ref) => match NameRefClass::classify(&sema, &name_ref)? { + NameRefClass::Definition(def) => def, + NameRefClass::FieldShorthand { local_ref, field_ref: _ } => { + Definition::Local(local_ref) + } }, - ast::Name(name) => { - NameClass::classify(&sema, &name)?.defined_or_referenced_local() + ast::Name(name) => match NameClass::classify(&sema, &name)? { + NameClass::Definition(it) | NameClass::ConstReference(it) => it, + NameClass::PatFieldShorthand { local_def, field_ref: _ } => Definition::Local(local_def), }, _ => return None, } diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index e9ca233631..55177d77e9 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -60,11 +60,17 @@ pub(crate) fn goto_definition( reference_definition(&sema, Either::Right(&name_ref)) }, 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)) }, 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) } else { reference_definition(&sema, Either::Left(<)) @@ -139,7 +145,10 @@ pub(crate) fn reference_definition( |lifetime| NameRefClass::classify_lifetime(sema, lifetime), |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) } diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs index d110123045..bde0fbd176 100644 --- a/crates/ide/src/goto_implementation.rs +++ b/crates/ide/src/goto_implementation.rs @@ -28,11 +28,19 @@ pub(crate) fn goto_implementation( 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.defined_or_referenced_local()) - } + ast::NameLike::Name(name) => NameClass::classify(&sema, name).map(|class| match class { + NameClass::Definition(it) | NameClass::ConstReference(it) => it, + NameClass::PatFieldShorthand { local_def, field_ref: _ } => { + Definition::Local(local_def) + } + }), 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, }?; diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 8c0bbda536..49a06a2851 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -96,12 +96,21 @@ pub(crate) fn hover( 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).map(|class| class.defined_or_referenced_local()), - ast::NameRef(name_ref) => { - NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced_field()) - }, + ast::Name(name) => NameClass::classify(&sema, &name).map(|class| match class { + NameClass::Definition(it) | NameClass::ConstReference(it) => it, + 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( - || 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(), ), _ => { diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 9eeb2cf5af..6b08212c75 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -58,7 +58,15 @@ pub(crate) fn find_all_refs( let (def, is_literal_search) = 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 { (find_def(sema, &syntax, position.offset)?, false) }; @@ -116,17 +124,28 @@ pub(crate) fn find_def( offset: TextSize, ) -> Option { let def = match sema.find_node_at_offset_with_descend(syntax, offset)? { - 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::NameRef(name_ref) => match NameRefClass::classify(sema, &name_ref)? { + NameRefClass::Definition(def) => def, + NameRefClass::FieldShorthand { local_ref, field_ref: _ } => { + Definition::Local(local_ref) + } + }, + 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) - .map(|class| class.referenced_local()) + .and_then(|class| match class { + NameRefClass::Definition(it) => Some(it), + _ => None, + }) .or_else(|| { - NameClass::classify_lifetime(sema, &lifetime) - .map(|class| class.defined_or_referenced_local()) + NameClass::classify_lifetime(sema, &lifetime).and_then(|class| match class { + NameClass::Definition(it) => Some(it), + _ => None, + }) })?, }; Some(def) diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs index f19dcaeb80..f58be6d3fd 100644 --- a/crates/ide/src/rename.rs +++ b/crates/ide/src/rename.rs @@ -107,13 +107,19 @@ fn find_definition( { bail!("Renaming aliases is currently unsupported") } - ast::NameLike::Name(name) => { - NameClass::classify(sema, &name).map(|class| class.defined_or_referenced_local()) - } + ast::NameLike::Name(name) => NameClass::classify(sema, &name).map(|class| match class { + NameClass::Definition(it) | NameClass::ConstReference(it) => it, + NameClass::PatFieldShorthand { local_def, field_ref: _ } => { + Definition::Local(local_def) + } + }), ast::NameLike::NameRef(name_ref) => { - if let Some(def) = - NameRefClass::classify(sema, &name_ref).map(|class| class.referenced_local()) - { + if let Some(def) = NameRefClass::classify(sema, &name_ref).map(|class| match class { + 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 def.name(sema.db).map_or(false, |it| it.to_string() != name_ref.text()) { bail!("Renaming aliases is currently unsupported"); @@ -124,10 +130,15 @@ fn find_definition( } } 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(|| { - NameClass::classify_lifetime(sema, &lifetime) - .map(|it| it.defined_or_referenced_field()) + NameClass::classify_lifetime(sema, &lifetime).and_then(|it| match it { + NameClass::Definition(it) => Some(it), + _ => None, + }) }), } .ok_or_else(|| format_err!("No references found at position"))?; diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs index ea2db0b4eb..4f0b1f5b79 100644 --- a/crates/ide_assists/src/handlers/extract_function.rs +++ b/crates/ide_assists/src/handlers/extract_function.rs @@ -638,7 +638,12 @@ fn vars_used_in_body(ctx: &AssistContext, body: &FunctionBody) -> Vec { body.descendants() .filter_map(ast::NameRef::cast) .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 { Definition::Local(local) => Some(local), _ => None, diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index a72345564d..198b568ad8 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs @@ -133,26 +133,6 @@ impl NameClass { 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, name: &ast::Name) -> Option { let _p = profile::span("classify_name"); @@ -194,7 +174,12 @@ impl NameClass { }) .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 { let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?; let krate = sema.resolve_extern_crate(&extern_crate)?; @@ -316,26 +301,6 @@ pub enum 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. // It is primarily exercised via goto definition tests in `ide`. pub fn classify(