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.rs51
1 files changed, 51 insertions, 0 deletions
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 {
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| {
@@ -426,9 +438,48 @@ pub(crate) fn resolve_hir_path(
426 .resolve_module_path_in_items(db.upcast(), path.mod_path()) 438 .resolve_module_path_in_items(db.upcast(), path.mod_path())
427 .take_types() 439 .take_types()
428 .map(|it| PathResolution::Def(it.into())); 440 .map(|it| PathResolution::Def(it.into()));
441
429 types.or(values).or(items).or_else(|| { 442 types.or(values).or(items).or_else(|| {
430 resolver 443 resolver
431 .resolve_path_as_macro(db.upcast(), path.mod_path()) 444 .resolve_path_as_macro(db.upcast(), path.mod_path())
432 .map(|def| PathResolution::Macro(def.into())) 445 .map(|def| PathResolution::Macro(def.into()))
433 }) 446 })
434} 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}