diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 757d1e397f5..1d6c471032b 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs @@ -216,13 +216,43 @@ pub(crate) fn resolve_path( if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { return Some(PathResolution::AssocItem(assoc.into())); } + if let Some(VariantId::EnumVariantId(variant)) = + self.infer.as_ref()?.variant_resolution_for_expr(expr_id) + { + return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); + } } + if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { let pat_id = self.pat_id(&path_pat.into())?; if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { return Some(PathResolution::AssocItem(assoc.into())); } + if let Some(VariantId::EnumVariantId(variant)) = + self.infer.as_ref()?.variant_resolution_for_pat(pat_id) + { + return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); + } } + + if let Some(rec_lit) = path.syntax().parent().and_then(ast::RecordLit::cast) { + let expr_id = self.expr_id(db, &rec_lit.into())?; + if let Some(VariantId::EnumVariantId(variant)) = + self.infer.as_ref()?.variant_resolution_for_expr(expr_id) + { + return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); + } + } + + if let Some(rec_pat) = path.syntax().parent().and_then(ast::RecordPat::cast) { + let pat_id = self.pat_id(&rec_pat.into())?; + if let Some(VariantId::EnumVariantId(variant)) = + self.infer.as_ref()?.variant_resolution_for_pat(pat_id) + { + return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); + } + } + // This must be a normal source file rather than macro file. let hir_path = crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?; diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 0798d2c3617..450ce0ba751 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -908,4 +908,84 @@ fn baz(foo: Foo) { "x: i32|x", ); } + + #[test] + fn goto_def_for_enum_variant_self_pattern_const() { + check_goto( + " + //- /lib.rs + enum Foo { + Bar, + } + impl Foo { + fn baz(self) { + match self { + Self::Bar<|> => {} + } + } + } + ", + "Bar ENUM_VARIANT FileId(1) 15..18 15..18", + "Bar|Bar", + ); + } + + #[test] + fn goto_def_for_enum_variant_self_pattern_record() { + check_goto( + " + //- /lib.rs + enum Foo { + Bar { val: i32 }, + } + impl Foo { + fn baz(self) -> i32 { + match self { + Self::Bar<|> { val } => {} + } + } + } + ", + "Bar ENUM_VARIANT FileId(1) 15..31 15..18", + "Bar { val: i32 }|Bar", + ); + } + + #[test] + fn goto_def_for_enum_variant_self_expr_const() { + check_goto( + " + //- /lib.rs + enum Foo { + Bar, + } + impl Foo { + fn baz(self) { + Self::Bar<|>; + } + } + ", + "Bar ENUM_VARIANT FileId(1) 15..18 15..18", + "Bar|Bar", + ); + } + + #[test] + fn goto_def_for_enum_variant_self_expr_record() { + check_goto( + " + //- /lib.rs + enum Foo { + Bar { val: i32 }, + } + impl Foo { + fn baz(self) { + Self::Bar<|> {val: 4}; + } + } + ", + "Bar ENUM_VARIANT FileId(1) 15..31 15..18", + "Bar { val: i32 }|Bar", + ); + } }