aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/code_model.rs88
-rw-r--r--crates/ra_hir/src/lib.rs4
-rw-r--r--crates/ra_hir/src/semantics.rs26
-rw-r--r--crates/ra_hir/src/semantics/source_to_def.rs2
-rw-r--r--crates/ra_hir/src/source_analyzer.rs55
5 files changed, 149 insertions, 26 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index af59aa1b6..4a06f3bcd 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::{
@@ -509,7 +532,7 @@ impl Adt {
509 Some(self.module(db).krate()) 532 Some(self.module(db).krate())
510 } 533 }
511 534
512 pub fn name(&self, db: &dyn HirDatabase) -> Name { 535 pub fn name(self, db: &dyn HirDatabase) -> Name {
513 match self { 536 match self {
514 Adt::Struct(s) => s.name(db), 537 Adt::Struct(s) => s.name(db),
515 Adt::Union(u) => u.name(db), 538 Adt::Union(u) => u.name(db),
@@ -614,6 +637,10 @@ impl Function {
614 db.function_data(self.id).params.clone() 637 db.function_data(self.id).params.clone()
615 } 638 }
616 639
640 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
641 db.function_data(self.id).is_unsafe
642 }
643
617 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 644 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
618 let _p = profile("Function::diagnostics"); 645 let _p = profile("Function::diagnostics");
619 let infer = db.infer(self.id.into()); 646 let infer = db.infer(self.id.into());
@@ -675,6 +702,10 @@ impl Static {
675 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 702 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
676 db.static_data(self.id).name.clone() 703 db.static_data(self.id).name.clone()
677 } 704 }
705
706 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
707 db.static_data(self.id).mutable
708 }
678} 709}
679 710
680#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 711#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -762,13 +793,12 @@ impl MacroDef {
762 793
763 /// Indicate it is a proc-macro 794 /// Indicate it is a proc-macro
764 pub fn is_proc_macro(&self) -> bool { 795 pub fn is_proc_macro(&self) -> bool {
765 match self.id.kind { 796 matches!(self.id.kind, MacroDefKind::CustomDerive(_))
766 hir_expand::MacroDefKind::Declarative => false, 797 }
767 hir_expand::MacroDefKind::BuiltIn(_) => false, 798
768 hir_expand::MacroDefKind::BuiltInDerive(_) => false, 799 /// Indicate it is a derive macro
769 hir_expand::MacroDefKind::BuiltInEager(_) => false, 800 pub fn is_derive_macro(&self) -> bool {
770 hir_expand::MacroDefKind::CustomDerive(_) => true, 801 matches!(self.id.kind, MacroDefKind::CustomDerive(_) | MacroDefKind::BuiltInDerive(_))
771 }
772 } 802 }
773} 803}
774 804
@@ -963,6 +993,17 @@ impl TypeParam {
963 ty: InEnvironment { value: ty, environment }, 993 ty: InEnvironment { value: ty, environment },
964 } 994 }
965 } 995 }
996
997 pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
998 let params = db.generic_defaults(self.id.parent);
999 let local_idx = hir_ty::param_idx(db, self.id)?;
1000 let resolver = self.id.parent.resolver(db.upcast());
1001 let environment = TraitEnvironment::lower(db, &resolver);
1002 params.get(local_idx).cloned().map(|ty| Type {
1003 krate: self.id.parent.module(db.upcast()).krate,
1004 ty: InEnvironment { value: ty, environment },
1005 })
1006 }
966} 1007}
967 1008
968// FIXME: rename from `ImplDef` to `Impl` 1009// FIXME: rename from `ImplDef` to `Impl`
@@ -981,15 +1022,15 @@ impl ImplDef {
981 impls.lookup_impl_defs_for_trait(trait_.id).map(Self::from).collect() 1022 impls.lookup_impl_defs_for_trait(trait_.id).map(Self::from).collect()
982 } 1023 }
983 1024
984 pub fn target_trait(&self, db: &dyn HirDatabase) -> Option<TypeRef> { 1025 pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> {
985 db.impl_data(self.id).target_trait.clone() 1026 db.impl_data(self.id).target_trait.clone()
986 } 1027 }
987 1028
988 pub fn target_type(&self, db: &dyn HirDatabase) -> TypeRef { 1029 pub fn target_type(self, db: &dyn HirDatabase) -> TypeRef {
989 db.impl_data(self.id).target_type.clone() 1030 db.impl_data(self.id).target_type.clone()
990 } 1031 }
991 1032
992 pub fn target_ty(&self, db: &dyn HirDatabase) -> Type { 1033 pub fn target_ty(self, db: &dyn HirDatabase) -> Type {
993 let impl_data = db.impl_data(self.id); 1034 let impl_data = db.impl_data(self.id);
994 let resolver = self.id.resolver(db.upcast()); 1035 let resolver = self.id.resolver(db.upcast());
995 let ctx = hir_ty::TyLoweringContext::new(db, &resolver); 1036 let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
@@ -1001,23 +1042,23 @@ impl ImplDef {
1001 } 1042 }
1002 } 1043 }
1003 1044
1004 pub fn items(&self, db: &dyn HirDatabase) -> Vec<AssocItem> { 1045 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
1005 db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect() 1046 db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect()
1006 } 1047 }
1007 1048
1008 pub fn is_negative(&self, db: &dyn HirDatabase) -> bool { 1049 pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
1009 db.impl_data(self.id).is_negative 1050 db.impl_data(self.id).is_negative
1010 } 1051 }
1011 1052
1012 pub fn module(&self, db: &dyn HirDatabase) -> Module { 1053 pub fn module(self, db: &dyn HirDatabase) -> Module {
1013 self.id.lookup(db.upcast()).container.module(db.upcast()).into() 1054 self.id.lookup(db.upcast()).container.module(db.upcast()).into()
1014 } 1055 }
1015 1056
1016 pub fn krate(&self, db: &dyn HirDatabase) -> Crate { 1057 pub fn krate(self, db: &dyn HirDatabase) -> Crate {
1017 Crate { id: self.module(db).id.krate } 1058 Crate { id: self.module(db).id.krate }
1018 } 1059 }
1019 1060
1020 pub fn is_builtin_derive(&self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { 1061 pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
1021 let src = self.source(db); 1062 let src = self.source(db);
1022 let item = src.file_id.is_builtin_derive(db.upcast())?; 1063 let item = src.file_id.is_builtin_derive(db.upcast())?;
1023 let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id); 1064 let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id);
@@ -1153,6 +1194,10 @@ impl Type {
1153 ) 1194 )
1154 } 1195 }
1155 1196
1197 pub fn is_raw_ptr(&self) -> bool {
1198 matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }))
1199 }
1200
1156 pub fn contains_unknown(&self) -> bool { 1201 pub fn contains_unknown(&self) -> bool {
1157 return go(&self.ty.value); 1202 return go(&self.ty.value);
1158 1203
@@ -1212,7 +1257,7 @@ impl Type {
1212 1257
1213 // This would be nicer if it just returned an iterator, but that runs into 1258 // This would be nicer if it just returned an iterator, but that runs into
1214 // lifetime problems, because we need to borrow temp `CrateImplDefs`. 1259 // lifetime problems, because we need to borrow temp `CrateImplDefs`.
1215 pub fn iterate_impl_items<T>( 1260 pub fn iterate_assoc_items<T>(
1216 self, 1261 self,
1217 db: &dyn HirDatabase, 1262 db: &dyn HirDatabase,
1218 krate: Crate, 1263 krate: Crate,
@@ -1320,12 +1365,13 @@ impl Type {
1320} 1365}
1321 1366
1322impl HirDisplay for Type { 1367impl HirDisplay for Type {
1323 fn hir_fmt(&self, f: &mut HirFormatter) -> std::fmt::Result { 1368 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
1324 self.ty.value.hir_fmt(f) 1369 self.ty.value.hir_fmt(f)
1325 } 1370 }
1326} 1371}
1327 1372
1328/// For IDE only 1373/// For IDE only
1374#[derive(Debug)]
1329pub enum ScopeDef { 1375pub enum ScopeDef {
1330 ModuleDef(ModuleDef), 1376 ModuleDef(ModuleDef),
1331 MacroDef(MacroDef), 1377 MacroDef(MacroDef),
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 312ef3814..3364a822f 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -62,6 +62,7 @@ pub use crate::{
62 62
63pub use hir_def::{ 63pub use hir_def::{
64 adt::StructKind, 64 adt::StructKind,
65 attr::Attrs,
65 body::scope::ExprScopes, 66 body::scope::ExprScopes,
66 builtin_type::BuiltinType, 67 builtin_type::BuiltinType,
67 docs::Documentation, 68 docs::Documentation,
@@ -70,6 +71,7 @@ pub use hir_def::{
70 type_ref::Mutability, 71 type_ref::Mutability,
71}; 72};
72pub use hir_expand::{ 73pub use hir_expand::{
73 name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, 74 hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId,
75 MacroFile, Origin,
74}; 76};
75pub use hir_ty::{display::HirDisplay, CallableDef}; 77pub use hir_ty::{display::HirDisplay, CallableDef};
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index a0a0f234b..7c1f79f27 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -8,7 +8,7 @@ use hir_def::{
8 resolver::{self, HasResolver, Resolver}, 8 resolver::{self, HasResolver, Resolver},
9 AsMacroCall, TraitId, 9 AsMacroCall, TraitId,
10}; 10};
11use hir_expand::ExpansionInfo; 11use hir_expand::{hygiene::Hygiene, ExpansionInfo};
12use hir_ty::associated_type_shorthand_candidates; 12use hir_ty::associated_type_shorthand_candidates;
13use itertools::Itertools; 13use itertools::Itertools;
14use ra_db::{FileId, FileRange}; 14use ra_db::{FileId, FileRange};
@@ -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};
@@ -246,6 +246,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
246 self.analyze(path.syntax()).resolve_path(self.db, path) 246 self.analyze(path.syntax()).resolve_path(self.db, path)
247 } 247 }
248 248
249 pub fn lower_path(&self, path: &ast::Path) -> Option<Path> {
250 let src = self.find_file(path.syntax().clone());
251 Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into()))
252 }
253
249 pub fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> { 254 pub fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> {
250 self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat) 255 self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat)
251 } 256 }
@@ -446,6 +451,23 @@ impl<'a, DB: HirDatabase> SemanticsScope<'a, DB> {
446 pub fn resolve_hir_path(&self, path: &Path) -> Option<PathResolution> { 451 pub fn resolve_hir_path(&self, path: &Path) -> Option<PathResolution> {
447 resolve_hir_path(self.db, &self.resolver, path) 452 resolve_hir_path(self.db, &self.resolver, path)
448 } 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 }
449} 471}
450 472
451// 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 74d64c97d..4b509f07c 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -224,7 +224,19 @@ impl SourceAnalyzer {
224 } 224 }
225 } 225 }
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 = crate::Path::from_ast(path.clone())?; 227 let hir_path =
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
228 resolve_hir_path(db, &self.resolver, &hir_path) 240 resolve_hir_path(db, &self.resolver, &hir_path)
229 } 241 }
230 242
@@ -403,6 +415,7 @@ pub(crate) fn resolve_hir_path(
403 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()), 415 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()),
404 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), 416 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
405 }); 417 });
418
406 let body_owner = resolver.body_owner(); 419 let body_owner = resolver.body_owner();
407 let values = 420 let values =
408 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| {
@@ -416,6 +429,7 @@ pub(crate) fn resolve_hir_path(
416 ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), 429 ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()),
417 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), 430 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
418 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()),
419 }; 433 };
420 Some(res) 434 Some(res)
421 }); 435 });
@@ -424,9 +438,48 @@ pub(crate) fn resolve_hir_path(
424 .resolve_module_path_in_items(db.upcast(), path.mod_path()) 438 .resolve_module_path_in_items(db.upcast(), path.mod_path())
425 .take_types() 439 .take_types()
426 .map(|it| PathResolution::Def(it.into())); 440 .map(|it| PathResolution::Def(it.into()));
441
427 types.or(values).or(items).or_else(|| { 442 types.or(values).or(items).or_else(|| {
428 resolver 443 resolver
429 .resolve_path_as_macro(db.upcast(), path.mod_path()) 444 .resolve_path_as_macro(db.upcast(), path.mod_path())
430 .map(|def| PathResolution::Macro(def.into())) 445 .map(|def| PathResolution::Macro(def.into()))
431 }) 446 })
432} 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}