diff options
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_postfix.rs | 109 |
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 | ||
3 | use hir::{Ty, TypeCtor}; | ||
4 | use ra_syntax::{ast::AstNode, TextRange, TextUnit}; | ||
5 | use ra_text_edit::TextEdit; | ||
6 | |||
3 | use crate::{ | 7 | use 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 | }; |
10 | use hir::{Ty, TypeCtor}; | 14 | |
11 | use ra_syntax::{ast::AstNode, TextRange, TextUnit}; | 15 | pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { |
12 | use 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 | ||
14 | fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder { | 62 | fn 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 | ||
26 | fn is_bool_or_unknown(ty: Option<Ty>) -> bool { | 74 | fn 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 | |||
41 | pub(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)] |
79 | mod tests { | 83 | mod 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 | } |