diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 31 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 19 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 52 |
3 files changed, 101 insertions, 1 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 3fc2eccdd..840cfdfc8 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -148,6 +148,26 @@ impl ModuleDef { | |||
148 | ModuleDef::BuiltinType(_) => None, | 148 | ModuleDef::BuiltinType(_) => None, |
149 | } | 149 | } |
150 | } | 150 | } |
151 | |||
152 | pub fn definition_visibility(&self, db: &dyn HirDatabase) -> Option<Visibility> { | ||
153 | let module = match self { | ||
154 | ModuleDef::Module(it) => it.parent(db)?, | ||
155 | ModuleDef::Function(it) => return Some(it.visibility(db)), | ||
156 | ModuleDef::Adt(it) => it.module(db), | ||
157 | ModuleDef::EnumVariant(it) => { | ||
158 | let parent = it.parent_enum(db); | ||
159 | let module = it.module(db); | ||
160 | return module.visibility_of(db, &ModuleDef::Adt(Adt::Enum(parent))); | ||
161 | } | ||
162 | ModuleDef::Const(it) => return Some(it.visibility(db)), | ||
163 | ModuleDef::Static(it) => it.module(db), | ||
164 | ModuleDef::Trait(it) => it.module(db), | ||
165 | ModuleDef::TypeAlias(it) => return Some(it.visibility(db)), | ||
166 | ModuleDef::BuiltinType(_) => return None, | ||
167 | }; | ||
168 | |||
169 | module.visibility_of(db, self) | ||
170 | } | ||
151 | } | 171 | } |
152 | 172 | ||
153 | pub use hir_def::{ | 173 | pub use hir_def::{ |
@@ -969,6 +989,17 @@ impl TypeParam { | |||
969 | ty: InEnvironment { value: ty, environment }, | 989 | ty: InEnvironment { value: ty, environment }, |
970 | } | 990 | } |
971 | } | 991 | } |
992 | |||
993 | pub fn default(self, db: &dyn HirDatabase) -> Option<Type> { | ||
994 | let params = db.generic_defaults(self.id.parent); | ||
995 | let local_idx = hir_ty::param_idx(db, self.id)?; | ||
996 | let resolver = self.id.parent.resolver(db.upcast()); | ||
997 | let environment = TraitEnvironment::lower(db, &resolver); | ||
998 | params.get(local_idx).cloned().map(|ty| Type { | ||
999 | krate: self.id.parent.module(db.upcast()).krate, | ||
1000 | ty: InEnvironment { value: ty, environment }, | ||
1001 | }) | ||
1002 | } | ||
972 | } | 1003 | } |
973 | 1004 | ||
974 | // FIXME: rename from `ImplDef` to `Impl` | 1005 | // FIXME: rename from `ImplDef` to `Impl` |
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 515e5eb17..7c1f79f27 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -23,7 +23,7 @@ use crate::{ | |||
23 | db::HirDatabase, | 23 | db::HirDatabase, |
24 | diagnostics::Diagnostic, | 24 | diagnostics::Diagnostic, |
25 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, | 25 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, |
26 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, | 26 | source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, |
27 | AssocItem, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, | 27 | AssocItem, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, |
28 | Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, | 28 | Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, |
29 | }; | 29 | }; |
@@ -451,6 +451,23 @@ impl<'a, DB: HirDatabase> SemanticsScope<'a, DB> { | |||
451 | pub fn resolve_hir_path(&self, path: &Path) -> Option<PathResolution> { | 451 | pub fn resolve_hir_path(&self, path: &Path) -> Option<PathResolution> { |
452 | resolve_hir_path(self.db, &self.resolver, path) | 452 | resolve_hir_path(self.db, &self.resolver, path) |
453 | } | 453 | } |
454 | |||
455 | /// Resolves a path where we know it is a qualifier of another path. | ||
456 | /// | ||
457 | /// For example, if we have: | ||
458 | /// ``` | ||
459 | /// mod my { | ||
460 | /// pub mod foo { | ||
461 | /// struct Bar; | ||
462 | /// } | ||
463 | /// | ||
464 | /// pub fn foo() {} | ||
465 | /// } | ||
466 | /// ``` | ||
467 | /// then we know that `foo` in `my::foo::Bar` refers to the module, not the function. | ||
468 | pub fn resolve_hir_path_qualifier(&self, path: &Path) -> Option<PathResolution> { | ||
469 | resolve_hir_path_qualifier(self.db, &self.resolver, path) | ||
470 | } | ||
454 | } | 471 | } |
455 | 472 | ||
456 | // FIXME: Change `HasSource` trait to work with `Semantics` and remove this? | 473 | // FIXME: Change `HasSource` trait to work with `Semantics` and remove this? |
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 | } | ||