aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_ide_api/src/completion/complete_postfix.rs109
1 files changed, 57 insertions, 52 deletions
diff --git a/crates/ra_ide_api/src/completion/complete_postfix.rs b/crates/ra_ide_api/src/completion/complete_postfix.rs
index 60ed3518b..4f9565441 100644
--- a/crates/ra_ide_api/src/completion/complete_postfix.rs
+++ b/crates/ra_ide_api/src/completion/complete_postfix.rs
@@ -1,5 +1,9 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{Ty, TypeCtor};
4use ra_syntax::{ast::AstNode, TextRange, TextUnit};
5use ra_text_edit::TextEdit;
6
3use crate::{ 7use crate::{
4 completion::{ 8 completion::{
5 completion_context::CompletionContext, 9 completion_context::CompletionContext,
@@ -7,9 +11,53 @@ use crate::{
7 }, 11 },
8 CompletionItem, 12 CompletionItem,
9}; 13};
10use hir::{Ty, TypeCtor}; 14
11use ra_syntax::{ast::AstNode, TextRange, TextUnit}; 15pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
12use ra_text_edit::TextEdit; 16 let dot_receiver = match &ctx.dot_receiver {
17 Some(it) => it,
18 None => return,
19 };
20
21 let receiver_text = if ctx.dot_receiver_is_ambiguous_float_literal {
22 let text = dot_receiver.syntax().text();
23 let without_dot = ..text.len() - TextUnit::of_char('.');
24 text.slice(without_dot).to_string()
25 } else {
26 dot_receiver.syntax().text().to_string()
27 };
28
29 let receiver_ty = ctx.analyzer.type_of(ctx.db, &dot_receiver);
30
31 if is_bool_or_unknown(receiver_ty) {
32 postfix_snippet(ctx, "if", "if expr {}", &format!("if {} {{$0}}", receiver_text))
33 .add_to(acc);
34 postfix_snippet(
35 ctx,
36 "while",
37 "while expr {}",
38 &format!("while {} {{\n$0\n}}", receiver_text),
39 )
40 .add_to(acc);
41 }
42
43 postfix_snippet(ctx, "not", "!expr", &format!("!{}", receiver_text)).add_to(acc);
44
45 postfix_snippet(ctx, "ref", "&expr", &format!("&{}", receiver_text)).add_to(acc);
46 postfix_snippet(ctx, "refm", "&mut expr", &format!("&mut {}", receiver_text)).add_to(acc);
47
48 postfix_snippet(
49 ctx,
50 "match",
51 "match expr {}",
52 &format!("match {} {{\n ${{1:_}} => {{$0\\}},\n}}", receiver_text),
53 )
54 .add_to(acc);
55
56 postfix_snippet(ctx, "dbg", "dbg!(expr)", &format!("dbg!({})", receiver_text)).add_to(acc);
57
58 postfix_snippet(ctx, "box", "Box::new(expr)", &format!("Box::new({})", receiver_text))
59 .add_to(acc);
60}
13 61
14fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder { 62fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder {
15 let edit = { 63 let edit = {
@@ -24,62 +72,19 @@ fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet:
24} 72}
25 73
26fn is_bool_or_unknown(ty: Option<Ty>) -> bool { 74fn is_bool_or_unknown(ty: Option<Ty>) -> bool {
27 if let Some(ty) = ty { 75 match &ty {
28 match ty { 76 Some(Ty::Apply(app)) if app.ctor == TypeCtor::Bool => true,
29 Ty::Apply(at) => match at.ctor { 77 Some(Ty::Unknown) | None => true,
30 TypeCtor::Bool => true, 78 Some(_) => false,
31 _ => false,
32 },
33 Ty::Unknown => true,
34 _ => false,
35 }
36 } else {
37 true
38 }
39}
40
41pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
42 if let Some(dot_receiver) = &ctx.dot_receiver {
43 let receiver_text = if ctx.dot_receiver_is_ambiguous_float_literal {
44 let text = dot_receiver.syntax().text();
45 let without_dot = ..text.len() - TextUnit::of_char('.');
46 text.slice(without_dot).to_string()
47 } else {
48 dot_receiver.syntax().text().to_string()
49 };
50 let receiver_ty = ctx.analyzer.type_of(ctx.db, &dot_receiver);
51 if is_bool_or_unknown(receiver_ty) {
52 postfix_snippet(ctx, "if", "if expr {}", &format!("if {} {{$0}}", receiver_text))
53 .add_to(acc);
54 postfix_snippet(
55 ctx,
56 "while",
57 "while expr {}",
58 &format!("while {} {{\n$0\n}}", receiver_text),
59 )
60 .add_to(acc);
61 }
62 postfix_snippet(ctx, "not", "!expr", &format!("!{}", receiver_text)).add_to(acc);
63 postfix_snippet(ctx, "ref", "&expr", &format!("&{}", receiver_text)).add_to(acc);
64 postfix_snippet(ctx, "refm", "&mut expr", &format!("&mut {}", receiver_text)).add_to(acc);
65 postfix_snippet(
66 ctx,
67 "match",
68 "match expr {}",
69 &format!("match {} {{\n ${{1:_}} => {{$0\\}},\n}}", receiver_text),
70 )
71 .add_to(acc);
72 postfix_snippet(ctx, "dbg", "dbg!(expr)", &format!("dbg!({})", receiver_text)).add_to(acc);
73 postfix_snippet(ctx, "box", "Box::new(expr)", &format!("Box::new({})", receiver_text))
74 .add_to(acc);
75 } 79 }
76} 80}
77 81
78#[cfg(test)] 82#[cfg(test)]
79mod tests { 83mod tests {
80 use crate::completion::{do_completion, CompletionItem, CompletionKind};
81 use insta::assert_debug_snapshot; 84 use insta::assert_debug_snapshot;
82 85
86 use crate::completion::{do_completion, CompletionItem, CompletionKind};
87
83 fn do_postfix_completion(code: &str) -> Vec<CompletionItem> { 88 fn do_postfix_completion(code: &str) -> Vec<CompletionItem> {
84 do_completion(code, CompletionKind::Postfix) 89 do_completion(code, CompletionKind::Postfix)
85 } 90 }