aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/code_model.rs61
-rw-r--r--crates/ra_hir/src/semantics.rs19
-rw-r--r--crates/ra_hir/src/semantics/source_to_def.rs2
-rw-r--r--crates/ra_hir/src/source_analyzer.rs52
4 files changed, 120 insertions, 14 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index af59aa1b6..840cfdfc8 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -19,11 +19,14 @@ use hir_def::{
19use hir_expand::{ 19use hir_expand::{
20 diagnostics::DiagnosticSink, 20 diagnostics::DiagnosticSink,
21 name::{name, AsName}, 21 name::{name, AsName},
22 MacroDefId, 22 MacroDefId, MacroDefKind,
23}; 23};
24use hir_ty::{ 24use hir_ty::{
25 autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy, 25 autoderef,
26 Canonical, InEnvironment, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor, 26 display::{HirDisplayError, HirFormatter},
27 expr::ExprValidator,
28 method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty,
29 TyDefId, TypeCtor,
27}; 30};
28use ra_db::{CrateId, CrateName, Edition, FileId}; 31use ra_db::{CrateId, CrateName, Edition, FileId};
29use ra_prof::profile; 32use ra_prof::profile;
@@ -145,6 +148,26 @@ impl ModuleDef {
145 ModuleDef::BuiltinType(_) => None, 148 ModuleDef::BuiltinType(_) => None,
146 } 149 }
147 } 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 }
148} 171}
149 172
150pub use hir_def::{ 173pub use hir_def::{
@@ -675,6 +698,10 @@ impl Static {
675 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 698 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
676 db.static_data(self.id).name.clone() 699 db.static_data(self.id).name.clone()
677 } 700 }
701
702 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
703 db.static_data(self.id).mutable
704 }
678} 705}
679 706
680#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 707#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -762,13 +789,12 @@ impl MacroDef {
762 789
763 /// Indicate it is a proc-macro 790 /// Indicate it is a proc-macro
764 pub fn is_proc_macro(&self) -> bool { 791 pub fn is_proc_macro(&self) -> bool {
765 match self.id.kind { 792 matches!(self.id.kind, MacroDefKind::CustomDerive(_))
766 hir_expand::MacroDefKind::Declarative => false, 793 }
767 hir_expand::MacroDefKind::BuiltIn(_) => false, 794
768 hir_expand::MacroDefKind::BuiltInDerive(_) => false, 795 /// Indicate it is a derive macro
769 hir_expand::MacroDefKind::BuiltInEager(_) => false, 796 pub fn is_derive_macro(&self) -> bool {
770 hir_expand::MacroDefKind::CustomDerive(_) => true, 797 matches!(self.id.kind, MacroDefKind::CustomDerive(_) | MacroDefKind::BuiltInDerive(_))
771 }
772 } 798 }
773} 799}
774 800
@@ -963,6 +989,17 @@ impl TypeParam {
963 ty: InEnvironment { value: ty, environment }, 989 ty: InEnvironment { value: ty, environment },
964 } 990 }
965 } 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 }
966} 1003}
967 1004
968// FIXME: rename from `ImplDef` to `Impl` 1005// FIXME: rename from `ImplDef` to `Impl`
@@ -1212,7 +1249,7 @@ impl Type {
1212 1249
1213 // This would be nicer if it just returned an iterator, but that runs into 1250 // This would be nicer if it just returned an iterator, but that runs into
1214 // lifetime problems, because we need to borrow temp `CrateImplDefs`. 1251 // lifetime problems, because we need to borrow temp `CrateImplDefs`.
1215 pub fn iterate_impl_items<T>( 1252 pub fn iterate_assoc_items<T>(
1216 self, 1253 self,
1217 db: &dyn HirDatabase, 1254 db: &dyn HirDatabase,
1218 krate: Crate, 1255 krate: Crate,
@@ -1320,7 +1357,7 @@ impl Type {
1320} 1357}
1321 1358
1322impl HirDisplay for Type { 1359impl HirDisplay for Type {
1323 fn hir_fmt(&self, f: &mut HirFormatter) -> std::fmt::Result { 1360 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
1324 self.ty.value.hir_fmt(f) 1361 self.ty.value.hir_fmt(f)
1325 } 1362 }
1326} 1363}
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/semantics/source_to_def.rs b/crates/ra_hir/src/semantics/source_to_def.rs
index 6f3b5b2da..8af64fdc1 100644
--- a/crates/ra_hir/src/semantics/source_to_def.rs
+++ b/crates/ra_hir/src/semantics/source_to_def.rs
@@ -151,7 +151,7 @@ impl SourceToDefCtx<'_, '_> {
151 let krate = self.file_to_def(file_id)?.krate; 151 let krate = self.file_to_def(file_id)?.krate;
152 let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); 152 let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value);
153 let ast_id = Some(AstId::new(src.file_id, file_ast_id)); 153 let ast_id = Some(AstId::new(src.file_id, file_ast_id));
154 Some(MacroDefId { krate: Some(krate), ast_id, kind }) 154 Some(MacroDefId { krate: Some(krate), ast_id, kind, local_inner: false })
155 } 155 }
156 156
157 pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { 157 pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
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}