diff options
author | Igor Aleksanov <[email protected]> | 2020-09-12 15:32:19 +0100 |
---|---|---|
committer | Igor Aleksanov <[email protected]> | 2020-10-02 10:42:39 +0100 |
commit | e447b3a4a2bf089e5e3a190a532c17a4572ea013 (patch) | |
tree | cf5a0b06d5fffb5e95271cd6c818928ff2494b20 /crates/ide | |
parent | ea320141c6f87383880878b91182355c9ad7dc7b (diff) |
Improve checks for postfix suggestions
Diffstat (limited to 'crates/ide')
-rw-r--r-- | crates/ide/src/completion/complete_postfix.rs | 4 | ||||
-rw-r--r-- | crates/ide/src/completion/complete_postfix/format_like.rs | 26 | ||||
-rw-r--r-- | crates/ide/src/completion/completion_context.rs | 9 |
3 files changed, 23 insertions, 16 deletions
diff --git a/crates/ide/src/completion/complete_postfix.rs b/crates/ide/src/completion/complete_postfix.rs index 73a5f1439..599074254 100644 --- a/crates/ide/src/completion/complete_postfix.rs +++ b/crates/ide/src/completion/complete_postfix.rs | |||
@@ -211,9 +211,7 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
211 | ) | 211 | ) |
212 | .add_to(acc); | 212 | .add_to(acc); |
213 | 213 | ||
214 | if ctx.is_string_literal { | 214 | add_format_like_completions(acc, ctx, &dot_receiver, cap, &receiver_text); |
215 | add_format_like_completions(acc, ctx, &dot_receiver, cap, &receiver_text); | ||
216 | } | ||
217 | } | 215 | } |
218 | 216 | ||
219 | fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal: bool) -> String { | 217 | fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal: bool) -> String { |
diff --git a/crates/ide/src/completion/complete_postfix/format_like.rs b/crates/ide/src/completion/complete_postfix/format_like.rs index 93211a35f..6be3c2c92 100644 --- a/crates/ide/src/completion/complete_postfix/format_like.rs +++ b/crates/ide/src/completion/complete_postfix/format_like.rs | |||
@@ -27,7 +27,11 @@ pub(super) fn add_format_like_completions( | |||
27 | cap: SnippetCap, | 27 | cap: SnippetCap, |
28 | receiver_text: &str, | 28 | receiver_text: &str, |
29 | ) { | 29 | ) { |
30 | assert!(receiver_text.len() >= 2); | 30 | if !is_string_literal(receiver_text) { |
31 | // It's not a string literal, do not parse input. | ||
32 | return; | ||
33 | } | ||
34 | |||
31 | let input = &receiver_text[1..receiver_text.len() - 1]; | 35 | let input = &receiver_text[1..receiver_text.len() - 1]; |
32 | 36 | ||
33 | let mut parser = FormatStrParser::new(input); | 37 | let mut parser = FormatStrParser::new(input); |
@@ -42,6 +46,20 @@ pub(super) fn add_format_like_completions( | |||
42 | } | 46 | } |
43 | } | 47 | } |
44 | 48 | ||
49 | /// Checks whether provided item is a string literal. | ||
50 | fn is_string_literal(item: &str) -> bool { | ||
51 | if item.len() < 2 { | ||
52 | return false; | ||
53 | } | ||
54 | if item.chars().nth(0) != Some('"') || item.chars().nth(item.len() - 1) != Some('"') { | ||
55 | return false; | ||
56 | } | ||
57 | |||
58 | true | ||
59 | } | ||
60 | |||
61 | /// Parser for a format-like string. It is more allowing in terms of string contents, | ||
62 | /// as we expect variable placeholders to be filled with expressions. | ||
45 | #[derive(Debug)] | 63 | #[derive(Debug)] |
46 | pub struct FormatStrParser { | 64 | pub struct FormatStrParser { |
47 | input: String, | 65 | input: String, |
@@ -127,7 +145,7 @@ impl FormatStrParser { | |||
127 | pub fn parse(&mut self) -> Result<(), ()> { | 145 | pub fn parse(&mut self) -> Result<(), ()> { |
128 | let mut current_expr = String::new(); | 146 | let mut current_expr = String::new(); |
129 | 147 | ||
130 | let mut placeholders_count = 0; | 148 | let mut placeholder_id = 1; |
131 | 149 | ||
132 | // Count of open braces inside of an expression. | 150 | // Count of open braces inside of an expression. |
133 | // We assume that user knows what they're doing, thus we treat it like a correct pattern, e.g. | 151 | // We assume that user knows what they're doing, thus we treat it like a correct pattern, e.g. |
@@ -163,8 +181,8 @@ impl FormatStrParser { | |||
163 | (State::MaybeExpr, '}') => { | 181 | (State::MaybeExpr, '}') => { |
164 | // This is an empty sequence '{}'. Replace it with placeholder. | 182 | // This is an empty sequence '{}'. Replace it with placeholder. |
165 | self.output.push(chr); | 183 | self.output.push(chr); |
166 | self.extracted_expressions.push(format!("${}", placeholders_count)); | 184 | self.extracted_expressions.push(format!("${}", placeholder_id)); |
167 | placeholders_count += 1; | 185 | placeholder_id += 1; |
168 | self.state = State::NotExpr; | 186 | self.state = State::NotExpr; |
169 | } | 187 | } |
170 | (State::MaybeExpr, _) => { | 188 | (State::MaybeExpr, _) => { |
diff --git a/crates/ide/src/completion/completion_context.rs b/crates/ide/src/completion/completion_context.rs index 842d1987c..101be8eb5 100644 --- a/crates/ide/src/completion/completion_context.rs +++ b/crates/ide/src/completion/completion_context.rs | |||
@@ -74,8 +74,6 @@ pub(crate) struct CompletionContext<'a> { | |||
74 | pub(super) is_pattern_call: bool, | 74 | pub(super) is_pattern_call: bool, |
75 | /// If this is a macro call, i.e. the () are already there. | 75 | /// If this is a macro call, i.e. the () are already there. |
76 | pub(super) is_macro_call: bool, | 76 | pub(super) is_macro_call: bool, |
77 | /// If this is a string literal, like "lorem ipsum". | ||
78 | pub(super) is_string_literal: bool, | ||
79 | pub(super) is_path_type: bool, | 77 | pub(super) is_path_type: bool, |
80 | pub(super) has_type_args: bool, | 78 | pub(super) has_type_args: bool, |
81 | pub(super) attribute_under_caret: Option<ast::Attr>, | 79 | pub(super) attribute_under_caret: Option<ast::Attr>, |
@@ -158,7 +156,6 @@ impl<'a> CompletionContext<'a> { | |||
158 | is_call: false, | 156 | is_call: false, |
159 | is_pattern_call: false, | 157 | is_pattern_call: false, |
160 | is_macro_call: false, | 158 | is_macro_call: false, |
161 | is_string_literal: false, | ||
162 | is_path_type: false, | 159 | is_path_type: false, |
163 | has_type_args: false, | 160 | has_type_args: false, |
164 | dot_receiver_is_ambiguous_float_literal: false, | 161 | dot_receiver_is_ambiguous_float_literal: false, |
@@ -473,12 +470,6 @@ impl<'a> CompletionContext<'a> { | |||
473 | } else { | 470 | } else { |
474 | false | 471 | false |
475 | }; | 472 | }; |
476 | |||
477 | self.is_string_literal = if let Some(ast::Expr::Literal(l)) = &self.dot_receiver { | ||
478 | matches!(l.kind(), ast::LiteralKind::String { .. }) | ||
479 | } else { | ||
480 | false | ||
481 | }; | ||
482 | } | 473 | } |
483 | if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { | 474 | if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { |
484 | // As above | 475 | // As above |