diff options
Diffstat (limited to 'crates/ra_hir/src/source_analyzer.rs')
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 52 |
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. | ||
462 | pub(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 | } | ||