From e447b3a4a2bf089e5e3a190a532c17a4572ea013 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Sat, 12 Sep 2020 17:32:19 +0300 Subject: Improve checks for postfix suggestions --- crates/ide/src/completion/complete_postfix.rs | 4 +--- .../src/completion/complete_postfix/format_like.rs | 26 ++++++++++++++++++---- crates/ide/src/completion/completion_context.rs | 9 -------- 3 files changed, 23 insertions(+), 16 deletions(-) (limited to 'crates') 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) { ) .add_to(acc); - if ctx.is_string_literal { - add_format_like_completions(acc, ctx, &dot_receiver, cap, &receiver_text); - } + add_format_like_completions(acc, ctx, &dot_receiver, cap, &receiver_text); } 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( cap: SnippetCap, receiver_text: &str, ) { - assert!(receiver_text.len() >= 2); + if !is_string_literal(receiver_text) { + // It's not a string literal, do not parse input. + return; + } + let input = &receiver_text[1..receiver_text.len() - 1]; let mut parser = FormatStrParser::new(input); @@ -42,6 +46,20 @@ pub(super) fn add_format_like_completions( } } +/// Checks whether provided item is a string literal. +fn is_string_literal(item: &str) -> bool { + if item.len() < 2 { + return false; + } + if item.chars().nth(0) != Some('"') || item.chars().nth(item.len() - 1) != Some('"') { + return false; + } + + true +} + +/// Parser for a format-like string. It is more allowing in terms of string contents, +/// as we expect variable placeholders to be filled with expressions. #[derive(Debug)] pub struct FormatStrParser { input: String, @@ -127,7 +145,7 @@ impl FormatStrParser { pub fn parse(&mut self) -> Result<(), ()> { let mut current_expr = String::new(); - let mut placeholders_count = 0; + let mut placeholder_id = 1; // Count of open braces inside of an expression. // 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 { (State::MaybeExpr, '}') => { // This is an empty sequence '{}'. Replace it with placeholder. self.output.push(chr); - self.extracted_expressions.push(format!("${}", placeholders_count)); - placeholders_count += 1; + self.extracted_expressions.push(format!("${}", placeholder_id)); + placeholder_id += 1; self.state = State::NotExpr; } (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> { pub(super) is_pattern_call: bool, /// If this is a macro call, i.e. the () are already there. pub(super) is_macro_call: bool, - /// If this is a string literal, like "lorem ipsum". - pub(super) is_string_literal: bool, pub(super) is_path_type: bool, pub(super) has_type_args: bool, pub(super) attribute_under_caret: Option, @@ -158,7 +156,6 @@ impl<'a> CompletionContext<'a> { is_call: false, is_pattern_call: false, is_macro_call: false, - is_string_literal: false, is_path_type: false, has_type_args: false, dot_receiver_is_ambiguous_float_literal: false, @@ -473,12 +470,6 @@ impl<'a> CompletionContext<'a> { } else { false }; - - self.is_string_literal = if let Some(ast::Expr::Literal(l)) = &self.dot_receiver { - matches!(l.kind(), ast::LiteralKind::String { .. }) - } else { - false - }; } if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { // As above -- cgit v1.2.3