Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-db/src/syntax_helpers/format_string.rs')
| -rw-r--r-- | crates/ide-db/src/syntax_helpers/format_string.rs | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/crates/ide-db/src/syntax_helpers/format_string.rs b/crates/ide-db/src/syntax_helpers/format_string.rs index 3c584a6cbc..819134a255 100644 --- a/crates/ide-db/src/syntax_helpers/format_string.rs +++ b/crates/ide-db/src/syntax_helpers/format_string.rs @@ -1,7 +1,7 @@ //! Tools to work with format string literals for the `format_args!` family of macros. use syntax::{ ast::{self, IsString}, - AstNode, AstToken, TextRange, + AstNode, AstToken, TextRange, TextSize, }; pub fn is_format_string(string: &ast::String) -> bool { @@ -48,6 +48,7 @@ pub enum FormatSpecifier { Dot, Asterisk, QuestionMark, + Escape, } pub fn lex_format_specifiers( @@ -66,7 +67,7 @@ pub fn lex_format_specifiers( // Format specifier, see syntax at https://doc.rust-lang.org/std/fmt/index.html#syntax if let Some((_, '{')) = chars.peek() { // Escaped format specifier, `{{` - chars.next(); + read_escaped_format_specifier(&mut chars, &mut callback); continue; } @@ -238,6 +239,11 @@ pub fn lex_format_specifiers( skip_char_and_emit(&mut chars, FormatSpecifier::Close, &mut callback); } continue; + } else if let '}' = first_char { + if let Some((_, '}')) = chars.peek() { + // Escaped format specifier, `}}` + read_escaped_format_specifier(&mut chars, &mut callback); + } } } @@ -288,4 +294,15 @@ pub fn lex_format_specifiers( } callback(range, FormatSpecifier::Identifier); } + + fn read_escaped_format_specifier<I, F>(chars: &mut std::iter::Peekable<I>, callback: &mut F) + where + I: Iterator<Item = (TextRange, char)>, + F: FnMut(TextRange, FormatSpecifier), + { + let (range, _) = chars.peek().unwrap(); + let offset = TextSize::from(1); + callback(TextRange::new(range.start() - offset, range.end()), FormatSpecifier::Escape); + chars.next(); + } } |