From c417b98f02004a10819111903882482b39e50d17 Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sat, 3 Aug 2019 01:15:43 +0700 Subject: Implement completion for the .await syntax --- crates/ra_ide_api/src/completion/complete_dot.rs | 80 +++++++++++++++++++++--- 1 file changed, 70 insertions(+), 10 deletions(-) (limited to 'crates/ra_ide_api/src/completion/complete_dot.rs') diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 536ba36df..b6579be63 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -1,19 +1,49 @@ use hir::{AdtDef, Ty, TypeCtor}; -use crate::completion::{CompletionContext, Completions}; +use crate::{completion::{ + completion_context::CompletionContext, + completion_item::Completions, +}, CompletionItem}; +use ra_syntax::ast::AstNode; +use ra_text_edit::TextEditBuilder; use rustc_hash::FxHashSet; +use crate::completion::completion_item::{Builder, CompletionKind}; +use ra_syntax::TextRange; -/// Complete dot accesses, i.e. fields or methods (currently only fields). +/// Applies postfix edition but with CompletionKind::Reference +fn postfix_reference(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder { + let edit = { + let receiver_range = + ctx.dot_receiver.as_ref().expect("no receiver available").syntax().text_range(); + let delete_range = TextRange::from_to(receiver_range.start(), ctx.source_range().end()); + let mut builder = TextEditBuilder::default(); + builder.replace(delete_range, snippet.to_string()); + builder.finish() + }; + CompletionItem::new(CompletionKind::Reference, ctx.source_range(), label) + .detail(detail) + .snippet_edit(edit) +} + +/// Complete dot accesses, i.e. fields or methods (and .await syntax). pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { - let receiver_ty = - match ctx.dot_receiver.as_ref().and_then(|it| ctx.analyzer.type_of(ctx.db, it)) { - Some(it) => it, - None => return, - }; - if !ctx.is_call { - complete_fields(acc, ctx, receiver_ty.clone()); + if let Some(dot_receiver) = &ctx.dot_receiver { + let receiver_text = dot_receiver.syntax().text().to_string(); + let receiver_ty = ctx.analyzer.type_of(ctx.db, &dot_receiver); + + if let Some(receiver_ty) = receiver_ty { + if !ctx.is_call { + complete_fields(acc, ctx, receiver_ty.clone()); + } + complete_methods(acc, ctx, receiver_ty.clone()); + + // Suggest .await syntax for types that implement std::future::Future + if ctx.analyzer.impls_future(ctx.db, receiver_ty) { + postfix_reference(ctx, ".await", "expr.await", &format!("{}.await", receiver_text)) + .add_to(acc); + } + } } - complete_methods(acc, ctx, receiver_ty); } fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { @@ -406,4 +436,34 @@ mod tests { "### ); } + + #[test] + fn test_completion_await_impls_future() { + assert_debug_snapshot_matches!( + do_ref_completion( + r" + // Mock Future trait from stdlib + pub mod std { pub mod future { pub trait Future {} } } + + use std::future::*; + struct A {} + impl Future for A {} + + fn foo(a: A) { + a.<|> + } + "), + @r###" + ⋮[ + ⋮ CompletionItem { + ⋮ label: ".await", + ⋮ source_range: [249; 249), + ⋮ delete: [247; 249), + ⋮ insert: "a.await", + ⋮ detail: "expr.await", + ⋮ }, + ⋮] + "### + ) + } } -- cgit v1.2.3 From 30bc3b93bec06256350b66869f2885ee71c3bedd Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sat, 3 Aug 2019 01:16:20 +0700 Subject: rustfmt --- crates/ra_ide_api/src/completion/complete_dot.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'crates/ra_ide_api/src/completion/complete_dot.rs') diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index b6579be63..1dbbdb1bc 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -1,14 +1,14 @@ use hir::{AdtDef, Ty, TypeCtor}; -use crate::{completion::{ - completion_context::CompletionContext, - completion_item::Completions, -}, CompletionItem}; +use crate::completion::completion_item::{Builder, CompletionKind}; +use crate::{ + completion::{completion_context::CompletionContext, completion_item::Completions}, + CompletionItem, +}; use ra_syntax::ast::AstNode; +use ra_syntax::TextRange; use ra_text_edit::TextEditBuilder; use rustc_hash::FxHashSet; -use crate::completion::completion_item::{Builder, CompletionKind}; -use ra_syntax::TextRange; /// Applies postfix edition but with CompletionKind::Reference fn postfix_reference(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder { -- cgit v1.2.3 From ab7774545cb5e45064c907429417bdee8d89f4d4 Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sat, 3 Aug 2019 01:53:51 +0700 Subject: Use future lang item instead of hardcoded std::future::Future --- crates/ra_ide_api/src/completion/complete_dot.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'crates/ra_ide_api/src/completion/complete_dot.rs') 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) { } complete_methods(acc, ctx, receiver_ty.clone()); - // Suggest .await syntax for types that implement std::future::Future + // Suggest .await syntax for types that implement Future trait if ctx.analyzer.impls_future(ctx.db, receiver_ty) { postfix_reference(ctx, ".await", "expr.await", &format!("{}.await", receiver_text)) .add_to(acc); @@ -441,9 +441,14 @@ mod tests { fn test_completion_await_impls_future() { assert_debug_snapshot_matches!( do_ref_completion( - r" + r###" // Mock Future trait from stdlib - pub mod std { pub mod future { pub trait Future {} } } + pub mod std { + pub mod future { + #[lang = "future_trait"] + pub trait Future {} + } + } use std::future::*; struct A {} @@ -452,13 +457,13 @@ mod tests { fn foo(a: A) { a.<|> } - "), + "###), @r###" ⋮[ ⋮ CompletionItem { ⋮ label: ".await", - ⋮ source_range: [249; 249), - ⋮ delete: [247; 249), + ⋮ source_range: [358; 358), + ⋮ delete: [356; 358), ⋮ insert: "a.await", ⋮ detail: "expr.await", ⋮ }, -- cgit v1.2.3 From 40facb559a1f12ae608439041c9b3629ea633b77 Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sat, 3 Aug 2019 02:40:59 +0700 Subject: Change postfix completion to keyword completion --- crates/ra_ide_api/src/completion/complete_dot.rs | 30 +++++++----------------- 1 file changed, 8 insertions(+), 22 deletions(-) (limited to 'crates/ra_ide_api/src/completion/complete_dot.rs') diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 93e5d816d..272a38f11 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -10,25 +10,9 @@ use ra_syntax::TextRange; use ra_text_edit::TextEditBuilder; use rustc_hash::FxHashSet; -/// Applies postfix edition but with CompletionKind::Reference -fn postfix_reference(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder { - let edit = { - let receiver_range = - ctx.dot_receiver.as_ref().expect("no receiver available").syntax().text_range(); - let delete_range = TextRange::from_to(receiver_range.start(), ctx.source_range().end()); - let mut builder = TextEditBuilder::default(); - builder.replace(delete_range, snippet.to_string()); - builder.finish() - }; - CompletionItem::new(CompletionKind::Reference, ctx.source_range(), label) - .detail(detail) - .snippet_edit(edit) -} - /// Complete dot accesses, i.e. fields or methods (and .await syntax). pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { if let Some(dot_receiver) = &ctx.dot_receiver { - let receiver_text = dot_receiver.syntax().text().to_string(); let receiver_ty = ctx.analyzer.type_of(ctx.db, &dot_receiver); if let Some(receiver_ty) = receiver_ty { @@ -39,7 +23,9 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { // Suggest .await syntax for types that implement Future trait if ctx.analyzer.impls_future(ctx.db, receiver_ty) { - postfix_reference(ctx, ".await", "expr.await", &format!("{}.await", receiver_text)) + CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") + .detail("expr.await") + .insert_text("await") .add_to(acc); } } @@ -440,7 +426,7 @@ mod tests { #[test] fn test_completion_await_impls_future() { assert_debug_snapshot_matches!( - do_ref_completion( + do_completion( r###" // Mock Future trait from stdlib pub mod std { @@ -457,14 +443,14 @@ mod tests { fn foo(a: A) { a.<|> } - "###), + "###, CompletionKind::Keyword), @r###" ⋮[ ⋮ CompletionItem { - ⋮ label: ".await", + ⋮ label: "await", ⋮ source_range: [358; 358), - ⋮ delete: [356; 358), - ⋮ insert: "a.await", + ⋮ delete: [358; 358), + ⋮ insert: "await", ⋮ detail: "expr.await", ⋮ }, ⋮] -- cgit v1.2.3 From 957de26a1dba7134a6b3b340681880060aa90b3c Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sat, 3 Aug 2019 02:48:36 +0700 Subject: do fixup: remove unused imports in complete_dot.rs --- crates/ra_ide_api/src/completion/complete_dot.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'crates/ra_ide_api/src/completion/complete_dot.rs') diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 272a38f11..e8fd37bca 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -1,13 +1,10 @@ use hir::{AdtDef, Ty, TypeCtor}; -use crate::completion::completion_item::{Builder, CompletionKind}; +use crate::completion::completion_item::CompletionKind; use crate::{ completion::{completion_context::CompletionContext, completion_item::Completions}, CompletionItem, }; -use ra_syntax::ast::AstNode; -use ra_syntax::TextRange; -use ra_text_edit::TextEditBuilder; use rustc_hash::FxHashSet; /// Complete dot accesses, i.e. fields or methods (and .await syntax). -- cgit v1.2.3 From 6a94f203fc5e2dc6f48a592c26b48f3a98638d77 Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sat, 3 Aug 2019 17:07:20 +0700 Subject: Use std::future::Future trait from stdlib --- crates/ra_ide_api/src/completion/complete_dot.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'crates/ra_ide_api/src/completion/complete_dot.rs') diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index e8fd37bca..9a3b353a9 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -425,28 +425,25 @@ mod tests { assert_debug_snapshot_matches!( do_completion( r###" - // Mock Future trait from stdlib - pub mod std { - pub mod future { - #[lang = "future_trait"] - pub trait Future {} - } - } - + //- /main.rs use std::future::*; struct A {} impl Future for A {} - fn foo(a: A) { a.<|> } + + //- /std/lib.rs + pub mod future { + pub trait Future {} + } "###, CompletionKind::Keyword), @r###" ⋮[ ⋮ CompletionItem { ⋮ label: "await", - ⋮ source_range: [358; 358), - ⋮ delete: [358; 358), + ⋮ source_range: [74; 74), + ⋮ delete: [74; 74), ⋮ insert: "await", ⋮ detail: "expr.await", ⋮ }, -- cgit v1.2.3 From d610adfc2bfe3d4e9fec61b7a5bc02cfea503384 Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sun, 4 Aug 2019 08:03:17 +0700 Subject: Employ early return pattern more --- crates/ra_ide_api/src/completion/complete_dot.rs | 34 +++++++++++++----------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'crates/ra_ide_api/src/completion/complete_dot.rs') diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 9a3b353a9..d43ff2eec 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -9,23 +9,27 @@ use rustc_hash::FxHashSet; /// Complete dot accesses, i.e. fields or methods (and .await syntax). pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { - if let Some(dot_receiver) = &ctx.dot_receiver { - let receiver_ty = ctx.analyzer.type_of(ctx.db, &dot_receiver); + let dot_receiver = match &ctx.dot_receiver { + Some(expr) => expr, + _ => return, + }; - if let Some(receiver_ty) = receiver_ty { - if !ctx.is_call { - complete_fields(acc, ctx, receiver_ty.clone()); - } - complete_methods(acc, ctx, receiver_ty.clone()); + let receiver_ty = match ctx.analyzer.type_of(ctx.db, &dot_receiver) { + Some(ty) => ty, + _ => return, + }; - // Suggest .await syntax for types that implement Future trait - if ctx.analyzer.impls_future(ctx.db, receiver_ty) { - CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") - .detail("expr.await") - .insert_text("await") - .add_to(acc); - } - } + if !ctx.is_call { + complete_fields(acc, ctx, receiver_ty.clone()); + } + complete_methods(acc, ctx, receiver_ty.clone()); + + // Suggest .await syntax for types that implement Future trait + if ctx.analyzer.impls_future(ctx.db, receiver_ty) { + CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") + .detail("expr.await") + .insert_text("await") + .add_to(acc); } } -- cgit v1.2.3