diff options
author | Evgenii P <[email protected]> | 2019-08-02 19:53:51 +0100 |
---|---|---|
committer | Evgenii P <[email protected]> | 2019-08-02 19:53:51 +0100 |
commit | ab7774545cb5e45064c907429417bdee8d89f4d4 (patch) | |
tree | 21642a3ffe5cf19191513609c0e09bdc90ca9777 | |
parent | 30bc3b93bec06256350b66869f2885ee71c3bedd (diff) |
Use future lang item instead of hardcoded std::future::Future
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 41 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_dot.rs | 17 |
2 files changed, 21 insertions, 37 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 67cb19615..7720329e3 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -24,6 +24,7 @@ use crate::{ | |||
24 | BodySourceMap, | 24 | BodySourceMap, |
25 | }, | 25 | }, |
26 | ids::LocationCtx, | 26 | ids::LocationCtx, |
27 | lang_item::LangItemTarget, | ||
27 | ty::method_resolution::implements_trait, | 28 | ty::method_resolution::implements_trait, |
28 | AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HirDatabase, HirFileId, | 29 | AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HirDatabase, HirFileId, |
29 | MacroDef, Module, Name, Path, PerNs, Resolver, Static, Struct, Trait, Ty, | 30 | MacroDef, Module, Name, Path, PerNs, Resolver, Static, Struct, Trait, Ty, |
@@ -410,40 +411,18 @@ impl SourceAnalyzer { | |||
410 | crate::ty::autoderef(db, &self.resolver, canonical).map(|canonical| canonical.value) | 411 | crate::ty::autoderef(db, &self.resolver, canonical).map(|canonical| canonical.value) |
411 | } | 412 | } |
412 | 413 | ||
413 | /// Checks that particular type `ty` implements `std::future::Future` trait. | 414 | /// Checks that particular type `ty` implements `Future` trait (`future_trait` lang item). |
414 | /// This function is used in `.await` syntax completion. | 415 | /// This function is used in `.await` syntax completion. |
415 | pub fn impls_future(&self, db: &impl HirDatabase, ty: Ty) -> bool { | 416 | pub fn impls_future(&self, db: &impl HirDatabase, ty: Ty) -> bool { |
416 | // Search for std::future::Future trait in scope | 417 | let krate = self.resolver.krate(); |
417 | let future_trait = self | 418 | if let Some(krate) = krate { |
418 | .resolver | 419 | let future_trait = match db.lang_item(krate, "future_trait".into()) { |
419 | .traits_in_scope(db) | 420 | Some(LangItemTarget::Trait(t)) => t, |
420 | .into_iter() | 421 | _ => return false, |
421 | .filter(|t| { | 422 | }; |
422 | let std = t | ||
423 | .module(db) | ||
424 | .parent(db) | ||
425 | .and_then(|m| m.name(db).and_then(|n| Some(n.to_string() == "std"))) | ||
426 | .unwrap_or(false); | ||
427 | |||
428 | let future = t | ||
429 | .module(db) | ||
430 | .name(db) | ||
431 | .and_then(|n| Some(n.to_string() == "future")) | ||
432 | .unwrap_or(false); | ||
433 | |||
434 | let future_trait = | ||
435 | t.name(db).and_then(|n| Some(n.to_string() == "Future")).unwrap_or(false); | ||
436 | |||
437 | std && future && future_trait | ||
438 | }) | ||
439 | .nth(0); | ||
440 | 423 | ||
441 | if let Some(trait_) = future_trait { | 424 | let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 }; |
442 | let krate = self.resolver.krate(); | 425 | return implements_trait(&canonical_ty, db, &self.resolver, krate, future_trait); |
443 | if let Some(krate) = krate { | ||
444 | let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 }; | ||
445 | return implements_trait(&canonical_ty, db, &self.resolver, krate, trait_); | ||
446 | } | ||
447 | } | 426 | } |
448 | 427 | ||
449 | false | 428 | false |
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 1dbbdb1bc..93e5d816d 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs | |||
@@ -37,7 +37,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { | |||
37 | } | 37 | } |
38 | complete_methods(acc, ctx, receiver_ty.clone()); | 38 | complete_methods(acc, ctx, receiver_ty.clone()); |
39 | 39 | ||
40 | // Suggest .await syntax for types that implement std::future::Future | 40 | // Suggest .await syntax for types that implement Future trait |
41 | if ctx.analyzer.impls_future(ctx.db, receiver_ty) { | 41 | if ctx.analyzer.impls_future(ctx.db, receiver_ty) { |
42 | postfix_reference(ctx, ".await", "expr.await", &format!("{}.await", receiver_text)) | 42 | postfix_reference(ctx, ".await", "expr.await", &format!("{}.await", receiver_text)) |
43 | .add_to(acc); | 43 | .add_to(acc); |
@@ -441,9 +441,14 @@ mod tests { | |||
441 | fn test_completion_await_impls_future() { | 441 | fn test_completion_await_impls_future() { |
442 | assert_debug_snapshot_matches!( | 442 | assert_debug_snapshot_matches!( |
443 | do_ref_completion( | 443 | do_ref_completion( |
444 | r" | 444 | r###" |
445 | // Mock Future trait from stdlib | 445 | // Mock Future trait from stdlib |
446 | pub mod std { pub mod future { pub trait Future {} } } | 446 | pub mod std { |
447 | pub mod future { | ||
448 | #[lang = "future_trait"] | ||
449 | pub trait Future {} | ||
450 | } | ||
451 | } | ||
447 | 452 | ||
448 | use std::future::*; | 453 | use std::future::*; |
449 | struct A {} | 454 | struct A {} |
@@ -452,13 +457,13 @@ mod tests { | |||
452 | fn foo(a: A) { | 457 | fn foo(a: A) { |
453 | a.<|> | 458 | a.<|> |
454 | } | 459 | } |
455 | "), | 460 | "###), |
456 | @r###" | 461 | @r###" |
457 | ⋮[ | 462 | ⋮[ |
458 | ⋮ CompletionItem { | 463 | ⋮ CompletionItem { |
459 | ⋮ label: ".await", | 464 | ⋮ label: ".await", |
460 | ⋮ source_range: [249; 249), | 465 | ⋮ source_range: [358; 358), |
461 | ⋮ delete: [247; 249), | 466 | ⋮ delete: [356; 358), |
462 | ⋮ insert: "a.await", | 467 | ⋮ insert: "a.await", |
463 | ⋮ detail: "expr.await", | 468 | ⋮ detail: "expr.await", |
464 | ⋮ }, | 469 | ⋮ }, |