aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/source_analyzer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/source_analyzer.rs')
-rw-r--r--crates/ra_hir/src/source_analyzer.rs52
1 files changed, 52 insertions, 0 deletions
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index c63d1b847..4b509f07c 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -226,6 +226,17 @@ impl SourceAnalyzer {
226 // This must be a normal source file rather than macro file. 226 // This must be a normal source file rather than macro file.
227 let hir_path = 227 let hir_path =
228 crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?; 228 crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?;
229
230 // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we
231 // trying to resolve foo::bar.
232 if let Some(outer_path) = path.syntax().parent().and_then(ast::Path::cast) {
233 if let Some(qualifier) = outer_path.qualifier() {
234 if path == &qualifier {
235 return resolve_hir_path_qualifier(db, &self.resolver, &hir_path);
236 }
237 }
238 }
239
229 resolve_hir_path(db, &self.resolver, &hir_path) 240 resolve_hir_path(db, &self.resolver, &hir_path)
230 } 241 }
231 242
@@ -404,6 +415,7 @@ pub(crate) fn resolve_hir_path(
404 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()), 415 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()),
405 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), 416 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
406 }); 417 });
418
407 let body_owner = resolver.body_owner(); 419 let body_owner = resolver.body_owner();
408 let values = 420 let values =
409 resolver.resolve_path_in_value_ns_fully(db.upcast(), path.mod_path()).and_then(|val| { 421 resolver.resolve_path_in_value_ns_fully(db.upcast(), path.mod_path()).and_then(|val| {
@@ -417,6 +429,7 @@ pub(crate) fn resolve_hir_path(
417 ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), 429 ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()),
418 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), 430 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
419 ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), 431 ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
432 ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()),
420 }; 433 };
421 Some(res) 434 Some(res)
422 }); 435 });
@@ -425,9 +438,48 @@ pub(crate) fn resolve_hir_path(
425 .resolve_module_path_in_items(db.upcast(), path.mod_path()) 438 .resolve_module_path_in_items(db.upcast(), path.mod_path())
426 .take_types() 439 .take_types()
427 .map(|it| PathResolution::Def(it.into())); 440 .map(|it| PathResolution::Def(it.into()));
441
428 types.or(values).or(items).or_else(|| { 442 types.or(values).or(items).or_else(|| {
429 resolver 443 resolver
430 .resolve_path_as_macro(db.upcast(), path.mod_path()) 444 .resolve_path_as_macro(db.upcast(), path.mod_path())
431 .map(|def| PathResolution::Macro(def.into())) 445 .map(|def| PathResolution::Macro(def.into()))
432 }) 446 })
433} 447}
448
449/// Resolves a path where we know it is a qualifier of another path.
450///
451/// For example, if we have:
452/// ```
453/// mod my {
454/// pub mod foo {
455/// struct Bar;
456/// }
457///
458/// pub fn foo() {}
459/// }
460/// ```
461/// then we know that `foo` in `my::foo::Bar` refers to the module, not the function.
462pub(crate) fn resolve_hir_path_qualifier(
463 db: &dyn HirDatabase,
464 resolver: &Resolver,
465 path: &crate::Path,
466) -> Option<PathResolution> {
467 let items = resolver
468 .resolve_module_path_in_items(db.upcast(), path.mod_path())
469 .take_types()
470 .map(|it| PathResolution::Def(it.into()));
471
472 if items.is_some() {
473 return items;
474 }
475
476 resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty {
477 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
478 TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }),
479 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => PathResolution::Def(Adt::from(it).into()),
480 TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
481 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
482 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()),
483 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
484 })
485}