From 73684a4ae2ff5251bbff35109d2c9ad40fe4ef01 Mon Sep 17 00:00:00 2001 From: unexge Date: Sat, 6 Jun 2020 22:16:59 +0300 Subject: [PATCH 1/4] Add goto def for enum variant field --- crates/ra_ide/src/goto_definition.rs | 19 +++++++++++++++++++ crates/ra_ide_db/src/defs.rs | 6 ++++++ 2 files changed, 25 insertions(+) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index a6c86e99c95e..693344c3147d 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -886,4 +886,23 @@ mod tests { "x", ) } + + #[test] + fn goto_def_for_enum_variant_field() { + check_goto( + " + //- /lib.rs + enum Foo { + Bar { x: i32 } + } + fn baz(foo: Foo) { + match foo { + Foo::Bar { x<|> } => x + }; + } + ", + "x RECORD_FIELD_DEF FileId(1) 21..27 21..22", + "x: i32|x", + ); + } } diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs index 1db60b87fb82..52233937ce9b 100644 --- a/crates/ra_ide_db/src/defs.rs +++ b/crates/ra_ide_db/src/defs.rs @@ -126,6 +126,12 @@ fn classify_name_inner(sema: &Semantics, name: &ast::Name) -> Opti Some(name_ref_class.definition()) }, ast::BindPat(it) => { + if let Some(record_field_pat) = it.syntax().parent().and_then(ast::RecordFieldPat::cast) { + return Some(Definition::Field( + sema.resolve_record_field_pat(&record_field_pat)? + )); + } + let local = sema.to_def(&it)?; Some(Definition::Local(local)) }, From c5d5d2185816d90ad1420fe544d93150cb9c9a48 Mon Sep 17 00:00:00 2001 From: unexge Date: Mon, 8 Jun 2020 14:46:58 +0300 Subject: [PATCH 2/4] Add `FieldShorthand` variant to `NameClass` --- crates/ra_ide/src/goto_definition.rs | 2 +- crates/ra_ide/src/syntax_highlighting.rs | 1 + crates/ra_ide_db/src/defs.rs | 56 +++++++++++++----------- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 693344c3147d..620d2dedd3de 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -39,7 +39,7 @@ pub(crate) fn goto_definition( reference_definition(&sema, &name_ref).to_vec() }, ast::Name(name) => { - let def = classify_name(&sema, &name)?.definition(); + let def = classify_name(&sema, &name)?.into_definition()?; let nav = def.try_to_nav(sema.db)?; vec![nav] }, diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 19ecd54d6cf2..f6b52c35d7f5 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -363,6 +363,7 @@ fn highlight_element( highlight_name(db, def) | HighlightModifier::Definition } Some(NameClass::ConstReference(def)) => highlight_name(db, def), + Some(NameClass::FieldShorthand { .. }) => HighlightTag::Field.into(), None => highlight_name_by_syntax(name) | HighlightModifier::Definition, } } diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs index 52233937ce9b..853d856e790a 100644 --- a/crates/ra_ide_db/src/defs.rs +++ b/crates/ra_ide_db/src/defs.rs @@ -82,6 +82,10 @@ pub enum NameClass { Definition(Definition), /// `None` in `if let None = Some(82) {}` ConstReference(Definition), + FieldShorthand { + local: Local, + field: Definition, + }, } impl NameClass { @@ -89,12 +93,14 @@ impl NameClass { match self { NameClass::Definition(it) => Some(it), NameClass::ConstReference(_) => None, + NameClass::FieldShorthand { local: _, field } => Some(field), } } pub fn definition(self) -> Definition { match self { NameClass::Definition(it) | NameClass::ConstReference(it) => it, + NameClass::FieldShorthand { local, field: _ } => Definition::Local(local), } } } @@ -102,18 +108,14 @@ impl NameClass { pub fn classify_name(sema: &Semantics, name: &ast::Name) -> Option { let _p = profile("classify_name"); - if let Some(bind_pat) = name.syntax().parent().and_then(ast::BindPat::cast) { + let parent = name.syntax().parent()?; + + if let Some(bind_pat) = ast::BindPat::cast(parent.clone()) { if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) { return Some(NameClass::ConstReference(Definition::ModuleDef(def))); } } - classify_name_inner(sema, name).map(NameClass::Definition) -} - -fn classify_name_inner(sema: &Semantics, name: &ast::Name) -> Option { - let parent = name.syntax().parent()?; - match_ast! { match parent { ast::Alias(it) => { @@ -123,69 +125,71 @@ fn classify_name_inner(sema: &Semantics, name: &ast::Name) -> Opti let name_ref = path_segment.name_ref()?; let name_ref_class = classify_name_ref(sema, &name_ref)?; - Some(name_ref_class.definition()) + Some(NameClass::Definition(name_ref_class.definition())) }, ast::BindPat(it) => { + let local = sema.to_def(&it)?; + if let Some(record_field_pat) = it.syntax().parent().and_then(ast::RecordFieldPat::cast) { - return Some(Definition::Field( - sema.resolve_record_field_pat(&record_field_pat)? - )); + if let Some(field) = sema.resolve_record_field_pat(&record_field_pat) { + let field = Definition::Field(field); + return Some(NameClass::FieldShorthand { local, field }); + } } - let local = sema.to_def(&it)?; - Some(Definition::Local(local)) + Some(NameClass::Definition(Definition::Local(local))) }, ast::RecordFieldDef(it) => { let field: hir::Field = sema.to_def(&it)?; - Some(Definition::Field(field)) + Some(NameClass::Definition(Definition::Field(field))) }, ast::Module(it) => { let def = sema.to_def(&it)?; - Some(Definition::ModuleDef(def.into())) + Some(NameClass::Definition(Definition::ModuleDef(def.into()))) }, ast::StructDef(it) => { let def: hir::Struct = sema.to_def(&it)?; - Some(Definition::ModuleDef(def.into())) + Some(NameClass::Definition(Definition::ModuleDef(def.into()))) }, ast::UnionDef(it) => { let def: hir::Union = sema.to_def(&it)?; - Some(Definition::ModuleDef(def.into())) + Some(NameClass::Definition(Definition::ModuleDef(def.into()))) }, ast::EnumDef(it) => { let def: hir::Enum = sema.to_def(&it)?; - Some(Definition::ModuleDef(def.into())) + Some(NameClass::Definition(Definition::ModuleDef(def.into()))) }, ast::TraitDef(it) => { let def: hir::Trait = sema.to_def(&it)?; - Some(Definition::ModuleDef(def.into())) + Some(NameClass::Definition(Definition::ModuleDef(def.into()))) }, ast::StaticDef(it) => { let def: hir::Static = sema.to_def(&it)?; - Some(Definition::ModuleDef(def.into())) + Some(NameClass::Definition(Definition::ModuleDef(def.into()))) }, ast::EnumVariant(it) => { let def: hir::EnumVariant = sema.to_def(&it)?; - Some(Definition::ModuleDef(def.into())) + Some(NameClass::Definition(Definition::ModuleDef(def.into()))) }, ast::FnDef(it) => { let def: hir::Function = sema.to_def(&it)?; - Some(Definition::ModuleDef(def.into())) + Some(NameClass::Definition(Definition::ModuleDef(def.into()))) }, ast::ConstDef(it) => { let def: hir::Const = sema.to_def(&it)?; - Some(Definition::ModuleDef(def.into())) + Some(NameClass::Definition(Definition::ModuleDef(def.into()))) }, ast::TypeAliasDef(it) => { let def: hir::TypeAlias = sema.to_def(&it)?; - Some(Definition::ModuleDef(def.into())) + Some(NameClass::Definition(Definition::ModuleDef(def.into()))) }, ast::MacroCall(it) => { let def = sema.to_def(&it)?; - Some(Definition::Macro(def)) + Some(NameClass::Definition(Definition::Macro(def))) }, ast::TypeParam(it) => { let def = sema.to_def(&it)?; - Some(Definition::TypeParam(def)) + Some(NameClass::Definition(Definition::TypeParam(def))) }, _ => None, } From 4edf736eb23c2d94a8c65a83a83201590e847b3f Mon Sep 17 00:00:00 2001 From: unexge Date: Mon, 8 Jun 2020 15:37:12 +0300 Subject: [PATCH 3/4] Swap `into_definition` and `definition` semantics for `FieldShorthand` variant --- crates/ra_ide_db/src/defs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs index 853d856e790a..1826f3ac6517 100644 --- a/crates/ra_ide_db/src/defs.rs +++ b/crates/ra_ide_db/src/defs.rs @@ -93,14 +93,14 @@ impl NameClass { match self { NameClass::Definition(it) => Some(it), NameClass::ConstReference(_) => None, - NameClass::FieldShorthand { local: _, field } => Some(field), + NameClass::FieldShorthand { local, field: _ } => Some(Definition::Local(local)), } } pub fn definition(self) -> Definition { match self { NameClass::Definition(it) | NameClass::ConstReference(it) => it, - NameClass::FieldShorthand { local, field: _ } => Definition::Local(local), + NameClass::FieldShorthand { local: _, field } => field, } } } From 48b6dd0b332d43268796b30128502e618b5b975e Mon Sep 17 00:00:00 2001 From: unexge Date: Mon, 8 Jun 2020 15:38:10 +0300 Subject: [PATCH 4/4] Use explicit match for extracting def from `classify_name` --- crates/ra_ide/src/goto_definition.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 620d2dedd3de..0798d2c36170 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -1,6 +1,6 @@ use hir::Semantics; use ra_ide_db::{ - defs::{classify_name, classify_name_ref}, + defs::{classify_name, classify_name_ref, NameClass}, symbol_index, RootDatabase, }; use ra_syntax::{ @@ -39,7 +39,10 @@ pub(crate) fn goto_definition( reference_definition(&sema, &name_ref).to_vec() }, ast::Name(name) => { - let def = classify_name(&sema, &name)?.into_definition()?; + let def = match classify_name(&sema, &name)? { + NameClass::Definition(def) | NameClass::ConstReference(def) => def, + NameClass::FieldShorthand { local: _, field } => field, + }; let nav = def.try_to_nav(sema.db)?; vec![nav] },