about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRyo Yoshida <low.ryoshida@gmail.com>2022-06-27 23:16:09 +0900
committerRyo Yoshida <low.ryoshida@gmail.com>2022-06-27 23:20:23 +0900
commit393a18b8ce4f8f4662174e51b3f3587a322f4ebe (patch)
tree1ee01fd5ebe7845bd34065efcfd7c74d9285810d
parent491e6eaf9e030d44fd0fa5f4a831199dc3257745 (diff)
downloadrust-393a18b8ce4f8f4662174e51b3f3587a322f4ebe.tar.gz
rust-393a18b8ce4f8f4662174e51b3f3587a322f4ebe.zip
fix: escape receiver texts in format string completion
-rw-r--r--crates/ide-completion/src/completions/postfix/format_like.rs16
1 files changed, 16 insertions, 0 deletions
diff --git a/crates/ide-completion/src/completions/postfix/format_like.rs b/crates/ide-completion/src/completions/postfix/format_like.rs
index b5ef87b8812..16f902489b5 100644
--- a/crates/ide-completion/src/completions/postfix/format_like.rs
+++ b/crates/ide-completion/src/completions/postfix/format_like.rs
@@ -115,6 +115,7 @@ impl FormatStrParser {
         // "{MyStruct { val_a: 0, val_b: 1 }}".
         let mut inexpr_open_count = 0;
 
+        // We need to escape '\' and '$'. See the comments on `get_receiver_text()` for detail.
         let mut chars = self.input.chars().peekable();
         while let Some(chr) = chars.next() {
             match (self.state, chr) {
@@ -127,6 +128,9 @@ impl FormatStrParser {
                     self.state = State::MaybeIncorrect;
                 }
                 (State::NotExpr, _) => {
+                    if matches!(chr, '\\' | '$') {
+                        self.output.push('\\');
+                    }
                     self.output.push(chr);
                 }
                 (State::MaybeIncorrect, '}') => {
@@ -150,6 +154,9 @@ impl FormatStrParser {
                     self.state = State::NotExpr;
                 }
                 (State::MaybeExpr, _) => {
+                    if matches!(chr, '\\' | '$') {
+                        current_expr.push('\\');
+                    }
                     current_expr.push(chr);
                     self.state = State::Expr;
                 }
@@ -187,6 +194,9 @@ impl FormatStrParser {
                     inexpr_open_count += 1;
                 }
                 (State::Expr, _) => {
+                    if matches!(chr, '\\' | '$') {
+                        current_expr.push('\\');
+                    }
                     current_expr.push(chr);
                 }
                 (State::FormatOpts, '}') => {
@@ -194,6 +204,9 @@ impl FormatStrParser {
                     self.state = State::NotExpr;
                 }
                 (State::FormatOpts, _) => {
+                    if matches!(chr, '\\' | '$') {
+                        self.output.push('\\');
+                    }
                     self.output.push(chr);
                 }
             }
@@ -241,8 +254,11 @@ mod tests {
     fn format_str_parser() {
         let test_vector = &[
             ("no expressions", expect![["no expressions"]]),
+            (r"no expressions with \$0$1", expect![r"no expressions with \\\$0\$1"]),
             ("{expr} is {2 + 2}", expect![["{} is {}; expr, 2 + 2"]]),
             ("{expr:?}", expect![["{:?}; expr"]]),
+            ("{expr:1$}", expect![[r"{:1\$}; expr"]]),
+            ("{$0}", expect![[r"{}; \$0"]]),
             ("{malformed", expect![["-"]]),
             ("malformed}", expect![["-"]]),
             ("{{correct", expect![["{{correct"]]),