aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model.rs74
-rw-r--r--crates/ra_hir/src/source_analyzer.rs70
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs17
-rw-r--r--crates/ra_ide/src/completion/complete_path.rs26
4 files changed, 102 insertions, 85 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 346118350..3b479356f 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -21,8 +21,8 @@ use hir_expand::{
21 MacroDefId, 21 MacroDefId,
22}; 22};
23use hir_ty::{ 23use hir_ty::{
24 autoderef, display::HirFormatter, expr::ExprValidator, method_resolution::implements_trait, 24 autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy,
25 ApplicationTy, Canonical, InEnvironment, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk, 25 Canonical, InEnvironment, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk,
26}; 26};
27use ra_db::{CrateId, Edition, FileId}; 27use ra_db::{CrateId, Edition, FileId};
28use ra_prof::profile; 28use ra_prof::profile;
@@ -120,7 +120,8 @@ impl_froms!(
120 BuiltinType 120 BuiltinType
121); 121);
122 122
123pub use hir_def::{attr::Attrs, visibility::Visibility}; 123pub use hir_def::{attr::Attrs, visibility::Visibility, AssocItemId};
124use rustc_hash::FxHashSet;
124 125
125impl Module { 126impl Module {
126 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module { 127 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module {
@@ -891,7 +892,13 @@ impl Type {
891 }; 892 };
892 893
893 let canonical_ty = Canonical { value: self.ty.value.clone(), num_vars: 0 }; 894 let canonical_ty = Canonical { value: self.ty.value.clone(), num_vars: 0 };
894 implements_trait(&canonical_ty, db, self.ty.environment.clone(), krate, std_future_trait) 895 method_resolution::implements_trait(
896 &canonical_ty,
897 db,
898 self.ty.environment.clone(),
899 krate,
900 std_future_trait,
901 )
895 } 902 }
896 903
897 // FIXME: this method is broken, as it doesn't take closures into account. 904 // FIXME: this method is broken, as it doesn't take closures into account.
@@ -1002,6 +1009,65 @@ impl Type {
1002 None 1009 None
1003 } 1010 }
1004 1011
1012 pub fn iterate_method_candidates<T>(
1013 &self,
1014 db: &impl HirDatabase,
1015 krate: Crate,
1016 traits_in_scope: &FxHashSet<TraitId>,
1017 name: Option<&Name>,
1018 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
1019 ) -> Option<T> {
1020 // There should be no inference vars in types passed here
1021 // FIXME check that?
1022 // FIXME replace Unknown by bound vars here
1023 let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 };
1024
1025 let env = self.ty.environment.clone();
1026 let krate = krate.id;
1027
1028 method_resolution::iterate_method_candidates(
1029 &canonical,
1030 db,
1031 env,
1032 krate,
1033 traits_in_scope,
1034 name,
1035 method_resolution::LookupMode::MethodCall,
1036 |ty, it| match it {
1037 AssocItemId::FunctionId(f) => callback(ty, f.into()),
1038 _ => None,
1039 },
1040 )
1041 }
1042
1043 pub fn iterate_path_candidates<T>(
1044 &self,
1045 db: &impl HirDatabase,
1046 krate: Crate,
1047 traits_in_scope: &FxHashSet<TraitId>,
1048 name: Option<&Name>,
1049 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
1050 ) -> Option<T> {
1051 // There should be no inference vars in types passed here
1052 // FIXME check that?
1053 // FIXME replace Unknown by bound vars here
1054 let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 };
1055
1056 let env = self.ty.environment.clone();
1057 let krate = krate.id;
1058
1059 method_resolution::iterate_method_candidates(
1060 &canonical,
1061 db,
1062 env,
1063 krate,
1064 traits_in_scope,
1065 name,
1066 method_resolution::LookupMode::Path,
1067 |ty, it| callback(ty, it.into()),
1068 )
1069 }
1070
1005 pub fn as_adt(&self) -> Option<Adt> { 1071 pub fn as_adt(&self) -> Option<Adt> {
1006 let (adt, _subst) = self.ty.value.as_adt()?; 1072 let (adt, _subst) = self.ty.value.as_adt()?;
1007 Some(adt.into()) 1073 Some(adt.into())
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 5707a5696..76e0bff34 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -16,12 +16,12 @@ use hir_def::{
16 expr::{ExprId, PatId}, 16 expr::{ExprId, PatId},
17 nameres::ModuleSource, 17 nameres::ModuleSource,
18 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, 18 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
19 AssocItemId, DefWithBodyId, 19 DefWithBodyId, TraitId,
20}; 20};
21use hir_expand::{ 21use hir_expand::{
22 hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, 22 hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind,
23}; 23};
24use hir_ty::{method_resolution, Canonical, InEnvironment, InferenceResult, TraitEnvironment, Ty}; 24use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment};
25use ra_prof::profile; 25use ra_prof::profile;
26use ra_syntax::{ 26use ra_syntax::{
27 ast::{self, AstNode}, 27 ast::{self, AstNode},
@@ -29,11 +29,11 @@ use ra_syntax::{
29 SyntaxKind::*, 29 SyntaxKind::*,
30 SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextUnit, 30 SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextUnit,
31}; 31};
32use rustc_hash::FxHashSet;
32 33
33use crate::{ 34use crate::{
34 db::HirDatabase, Adt, AssocItem, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, 35 db::HirDatabase, Adt, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, ImplBlock,
35 ImplBlock, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, 36 Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam,
36 TypeParam,
37}; 37};
38 38
39/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of 39/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
@@ -347,63 +347,9 @@ impl SourceAnalyzer {
347 .collect() 347 .collect()
348 } 348 }
349 349
350 pub fn iterate_method_candidates<T>( 350 /// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type
351 &self, 351 pub fn traits_in_scope(&self, db: &impl HirDatabase) -> FxHashSet<TraitId> {
352 db: &impl HirDatabase, 352 self.resolver.traits_in_scope(db)
353 ty: &Type,
354 name: Option<&Name>,
355 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
356 ) -> Option<T> {
357 // There should be no inference vars in types passed here
358 // FIXME check that?
359 // FIXME replace Unknown by bound vars here
360 let canonical = Canonical { value: ty.ty.value.clone(), num_vars: 0 };
361
362 let env = TraitEnvironment::lower(db, &self.resolver);
363 let krate = self.resolver.krate()?;
364 let traits_in_scope = self.resolver.traits_in_scope(db);
365
366 method_resolution::iterate_method_candidates(
367 &canonical,
368 db,
369 env,
370 krate,
371 &traits_in_scope,
372 name,
373 method_resolution::LookupMode::MethodCall,
374 |ty, it| match it {
375 AssocItemId::FunctionId(f) => callback(ty, f.into()),
376 _ => None,
377 },
378 )
379 }
380
381 pub fn iterate_path_candidates<T>(
382 &self,
383 db: &impl HirDatabase,
384 ty: &Type,
385 name: Option<&Name>,
386 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
387 ) -> Option<T> {
388 // There should be no inference vars in types passed here
389 // FIXME check that?
390 // FIXME replace Unknown by bound vars here
391 let canonical = Canonical { value: ty.ty.value.clone(), num_vars: 0 };
392
393 let env = TraitEnvironment::lower(db, &self.resolver);
394 let krate = self.resolver.krate()?;
395 let traits_in_scope = self.resolver.traits_in_scope(db);
396
397 method_resolution::iterate_method_candidates(
398 &canonical,
399 db,
400 env,
401 krate,
402 &traits_in_scope,
403 name,
404 method_resolution::LookupMode::Path,
405 |ty, it| callback(ty, it.into()),
406 )
407 } 353 }
408 354
409 pub fn expand( 355 pub fn expand(
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index 9ab43644e..2ca78c927 100644
--- a/crates/ra_ide/src/completion/complete_dot.rs
+++ b/crates/ra_ide/src/completion/complete_dot.rs
@@ -53,13 +53,16 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Ty
53} 53}
54 54
55fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { 55fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
56 let mut seen_methods = FxHashSet::default(); 56 if let Some(krate) = ctx.module.map(|it| it.krate()) {
57 ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { 57 let mut seen_methods = FxHashSet::default();
58 if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) { 58 let traits_in_scope = ctx.analyzer.traits_in_scope(ctx.db);
59 acc.add_function(ctx, func); 59 receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
60 } 60 if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) {
61 None::<()> 61 acc.add_function(ctx, func);
62 }); 62 }
63 None::<()>
64 });
65 }
63} 66}
64 67
65#[cfg(test)] 68#[cfg(test)]
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs
index 0dce9dc2d..af24e9f48 100644
--- a/crates/ra_ide/src/completion/complete_path.rs
+++ b/crates/ra_ide/src/completion/complete_path.rs
@@ -49,22 +49,24 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
49 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), 49 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
50 _ => unreachable!(), 50 _ => unreachable!(),
51 }; 51 };
52 ctx.analyzer.iterate_path_candidates(ctx.db, &ty, None, |_ty, item| {
53 match item {
54 hir::AssocItem::Function(func) => {
55 if !func.has_self_param(ctx.db) {
56 acc.add_function(ctx, func);
57 }
58 }
59 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
60 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
61 }
62 None::<()>
63 });
64 // Iterate assoc types separately 52 // Iterate assoc types separately
65 // FIXME: complete T::AssocType 53 // FIXME: complete T::AssocType
66 let krate = ctx.module.map(|m| m.krate()); 54 let krate = ctx.module.map(|m| m.krate());
67 if let Some(krate) = krate { 55 if let Some(krate) = krate {
56 let traits_in_scope = ctx.analyzer.traits_in_scope(ctx.db);
57 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
58 match item {
59 hir::AssocItem::Function(func) => {
60 if !func.has_self_param(ctx.db) {
61 acc.add_function(ctx, func);
62 }
63 }
64 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
65 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
66 }
67 None::<()>
68 });
69
68 ty.iterate_impl_items(ctx.db, krate, |item| { 70 ty.iterate_impl_items(ctx.db, krate, |item| {
69 match item { 71 match item {
70 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {} 72 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}