From 3f42b2e837c4672a0fbe953e14ae2fd3fe6fc3b6 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 15 May 2020 17:15:40 +0200 Subject: Handle `Self` in values and patterns I.e. - `Self(x)` or `Self` in tuple/unit struct impls - `Self::Variant(x)` or `Self::Variant` in enum impls - the same in patterns Fixes #4454. --- crates/ra_hir/src/source_analyzer.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'crates/ra_hir/src/source_analyzer.rs') diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index c63d1b847..c862a4f48 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs @@ -417,6 +417,7 @@ pub(crate) fn resolve_hir_path( ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), + ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()), }; Some(res) }); -- cgit v1.2.3 From 001a86dc03104b75df732d69257d22526cf422b7 Mon Sep 17 00:00:00 2001 From: Hasan Ali Date: Fri, 15 May 2020 22:23:49 +0100 Subject: Fix completion and hover for module and function of same name --- crates/ra_hir/src/source_analyzer.rs | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'crates/ra_hir/src/source_analyzer.rs') diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index c862a4f48..4b509f07c 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs @@ -226,6 +226,17 @@ impl SourceAnalyzer { // 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))?; + + // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we + // trying to resolve foo::bar. + if let Some(outer_path) = path.syntax().parent().and_then(ast::Path::cast) { + if let Some(qualifier) = outer_path.qualifier() { + if path == &qualifier { + return resolve_hir_path_qualifier(db, &self.resolver, &hir_path); + } + } + } + resolve_hir_path(db, &self.resolver, &hir_path) } @@ -404,6 +415,7 @@ pub(crate) fn resolve_hir_path( TypeNs::BuiltinType(it) => PathResolution::Def(it.into()), TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), }); + let body_owner = resolver.body_owner(); let values = resolver.resolve_path_in_value_ns_fully(db.upcast(), path.mod_path()).and_then(|val| { @@ -426,9 +438,48 @@ pub(crate) fn resolve_hir_path( .resolve_module_path_in_items(db.upcast(), path.mod_path()) .take_types() .map(|it| PathResolution::Def(it.into())); + types.or(values).or(items).or_else(|| { resolver .resolve_path_as_macro(db.upcast(), path.mod_path()) .map(|def| PathResolution::Macro(def.into())) }) } + +/// Resolves a path where we know it is a qualifier of another path. +/// +/// For example, if we have: +/// ``` +/// mod my { +/// pub mod foo { +/// struct Bar; +/// } +/// +/// pub fn foo() {} +/// } +/// ``` +/// then we know that `foo` in `my::foo::Bar` refers to the module, not the function. +pub(crate) fn resolve_hir_path_qualifier( + db: &dyn HirDatabase, + resolver: &Resolver, + path: &crate::Path, +) -> Option { + let items = resolver + .resolve_module_path_in_items(db.upcast(), path.mod_path()) + .take_types() + .map(|it| PathResolution::Def(it.into())); + + if items.is_some() { + return items; + } + + resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty { + TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), + TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), + TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => PathResolution::Def(Adt::from(it).into()), + TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), + TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), + TypeNs::BuiltinType(it) => PathResolution::Def(it.into()), + TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), + }) +} -- cgit v1.2.3