diff options
| -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 |
