aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-06-22 15:37:45 +0100
committerGitHub <[email protected]>2020-06-22 15:37:45 +0100
commit87615166af84a4822adc4686fd9ee44fafa51f53 (patch)
tree91494d99d4805fca96815079b8dd29d9d649beea
parent5a0331e5575034a145956f76316ee0fcdf72077e (diff)
parentbdf7e70820243812dd27d96c38fb6d5db359c2f1 (diff)
Merge #4900
4900: Self variant enum res fix r=BGluth a=BGluth Fixes #4789. This is my first PR for this project, so it's probably worth giving it an extra close look. A few things that I wasn't sure about: - Is `resolve_path` really the best place to perform this check? It seemed like a natural place, but perhaps there's a better place? - When handling the new variant `PathResolution::VariantDef`, I couldn't see an obvious variant of `TypeNs` to return in `in_type_ns` for Unions and Structs. Co-authored-by: BGluth <[email protected]>
-rw-r--r--crates/ra_hir/src/source_analyzer.rs30
-rw-r--r--crates/ra_ide/src/goto_definition.rs80
2 files changed, 110 insertions, 0 deletions
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 757d1e397..1d6c47103 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -216,13 +216,43 @@ impl SourceAnalyzer {
216 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { 216 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) {
217 return Some(PathResolution::AssocItem(assoc.into())); 217 return Some(PathResolution::AssocItem(assoc.into()));
218 } 218 }
219 if let Some(VariantId::EnumVariantId(variant)) =
220 self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
221 {
222 return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into())));
223 }
219 } 224 }
225
220 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { 226 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) {
221 let pat_id = self.pat_id(&path_pat.into())?; 227 let pat_id = self.pat_id(&path_pat.into())?;
222 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { 228 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
223 return Some(PathResolution::AssocItem(assoc.into())); 229 return Some(PathResolution::AssocItem(assoc.into()));
224 } 230 }
231 if let Some(VariantId::EnumVariantId(variant)) =
232 self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
233 {
234 return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into())));
235 }
236 }
237
238 if let Some(rec_lit) = path.syntax().parent().and_then(ast::RecordLit::cast) {
239 let expr_id = self.expr_id(db, &rec_lit.into())?;
240 if let Some(VariantId::EnumVariantId(variant)) =
241 self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
242 {
243 return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into())));
244 }
225 } 245 }
246
247 if let Some(rec_pat) = path.syntax().parent().and_then(ast::RecordPat::cast) {
248 let pat_id = self.pat_id(&rec_pat.into())?;
249 if let Some(VariantId::EnumVariantId(variant)) =
250 self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
251 {
252 return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into())));
253 }
254 }
255
226 // This must be a normal source file rather than macro file. 256 // This must be a normal source file rather than macro file.
227 let hir_path = 257 let hir_path =
228 crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?; 258 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 0798d2c36..450ce0ba7 100644
--- a/crates/ra_ide/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -908,4 +908,84 @@ mod tests {
908 "x: i32|x", 908 "x: i32|x",
909 ); 909 );
910 } 910 }
911
912 #[test]
913 fn goto_def_for_enum_variant_self_pattern_const() {
914 check_goto(
915 "
916 //- /lib.rs
917 enum Foo {
918 Bar,
919 }
920 impl Foo {
921 fn baz(self) {
922 match self {
923 Self::Bar<|> => {}
924 }
925 }
926 }
927 ",
928 "Bar ENUM_VARIANT FileId(1) 15..18 15..18",
929 "Bar|Bar",
930 );
931 }
932
933 #[test]
934 fn goto_def_for_enum_variant_self_pattern_record() {
935 check_goto(
936 "
937 //- /lib.rs
938 enum Foo {
939 Bar { val: i32 },
940 }
941 impl Foo {
942 fn baz(self) -> i32 {
943 match self {
944 Self::Bar<|> { val } => {}
945 }
946 }
947 }
948 ",
949 "Bar ENUM_VARIANT FileId(1) 15..31 15..18",
950 "Bar { val: i32 }|Bar",
951 );
952 }
953
954 #[test]
955 fn goto_def_for_enum_variant_self_expr_const() {
956 check_goto(
957 "
958 //- /lib.rs
959 enum Foo {
960 Bar,
961 }
962 impl Foo {
963 fn baz(self) {
964 Self::Bar<|>;
965 }
966 }
967 ",
968 "Bar ENUM_VARIANT FileId(1) 15..18 15..18",
969 "Bar|Bar",
970 );
971 }
972
973 #[test]
974 fn goto_def_for_enum_variant_self_expr_record() {
975 check_goto(
976 "
977 //- /lib.rs
978 enum Foo {
979 Bar { val: i32 },
980 }
981 impl Foo {
982 fn baz(self) {
983 Self::Bar<|> {val: 4};
984 }
985 }
986 ",
987 "Bar ENUM_VARIANT FileId(1) 15..31 15..18",
988 "Bar { val: i32 }|Bar",
989 );
990 }
911} 991}