about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-01-13 19:18:47 +0000
committerGitHub <noreply@github.com>2022-01-13 19:18:47 +0000
commitb4c31481a554d0132003228ba319bd9476fe85ae (patch)
tree0429796e6e1a95863e67c6ee27c89d1dbabbfd78
parent07ded2aef0b286c106fbd36d4e0e56ed7924639e (diff)
parentc3148cb396bdcdb9802c56c95946093408bf8fc2 (diff)
downloadrust-b4c31481a554d0132003228ba319bd9476fe85ae.tar.gz
rust-b4c31481a554d0132003228ba319bd9476fe85ae.zip
Merge #11276
11276: internal: Slightly cleanup HasFormatSpecifier::lex_format_specifier r=Veykril a=Veykril

bors r+

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
-rw-r--r--crates/syntax/src/ast/token_ext.rs359
1 files changed, 146 insertions, 213 deletions
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs
index cc7e5150b36..3b0a1c5ddcd 100644
--- a/crates/syntax/src/ast/token_ext.rs
+++ b/crates/syntax/src/ast/token_ext.rs
@@ -288,124 +288,142 @@ pub trait HasFormatSpecifier: AstToken {
             Some(char_ranges) => char_ranges,
             None => return,
         };
-        let mut chars = char_ranges.iter().peekable();
+        let mut chars = char_ranges
+            .iter()
+            .filter_map(|(range, res)| Some((*range, *res.as_ref().ok()?)))
+            .peekable();
 
         while let Some((range, first_char)) = chars.next() {
-            match first_char {
-                Ok('{') => {
-                    // Format specifier, see syntax at https://doc.rust-lang.org/std/fmt/index.html#syntax
-                    if let Some((_, Ok('{'))) = chars.peek() {
-                        // Escaped format specifier, `{{`
-                        chars.next();
-                        continue;
-                    }
+            if let '{' = first_char {
+                // 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();
+                    continue;
+                }
 
-                    callback(*range, FormatSpecifier::Open);
+                callback(range, FormatSpecifier::Open);
 
-                    // check for integer/identifier
-                    match chars
-                        .peek()
-                        .and_then(|next| next.1.as_ref().ok())
-                        .copied()
-                        .unwrap_or_default()
-                    {
-                        '0'..='9' => {
-                            // integer
-                            read_integer(&mut chars, &mut callback);
+                // check for integer/identifier
+                let (_, int_char) = chars.peek().copied().unwrap_or_default();
+                match int_char {
+                    // integer
+                    '0'..='9' => read_integer(&mut chars, &mut callback),
+                    // identifier
+                    c if c == '_' || c.is_alphabetic() => {
+                        read_identifier(&mut chars, &mut callback)
+                    }
+                    _ => {}
+                }
+
+                if let Some((_, ':')) = chars.peek() {
+                    skip_char_and_emit(&mut chars, FormatSpecifier::Colon, &mut callback);
+
+                    // check for fill/align
+                    let mut cloned = chars.clone().take(2);
+                    let (_, first) = cloned.next().unwrap_or_default();
+                    let (_, second) = cloned.next().unwrap_or_default();
+                    match second {
+                        '<' | '^' | '>' => {
+                            // alignment specifier, first char specifies fillment
+                            skip_char_and_emit(&mut chars, FormatSpecifier::Fill, &mut callback);
+                            skip_char_and_emit(&mut chars, FormatSpecifier::Align, &mut callback);
                         }
-                        c if c == '_' || c.is_alphabetic() => {
-                            // identifier
-                            read_identifier(&mut chars, &mut callback);
+                        _ => {
+                            if let '<' | '^' | '>' = first {
+                                skip_char_and_emit(
+                                    &mut chars,
+                                    FormatSpecifier::Align,
+                                    &mut callback,
+                                );
+                            }
+                        }
+                    }
+
+                    // check for sign
+                    match chars.peek().copied().unwrap_or_default().1 {
+                        '+' | '-' => {
+                            skip_char_and_emit(&mut chars, FormatSpecifier::Sign, &mut callback);
                         }
                         _ => {}
                     }
 
-                    if let Some((_, Ok(':'))) = chars.peek() {
-                        skip_char_and_emit(&mut chars, FormatSpecifier::Colon, &mut callback);
-
-                        // check for fill/align
-                        let mut cloned = chars.clone().take(2);
-                        let first = cloned
-                            .next()
-                            .and_then(|next| next.1.as_ref().ok())
-                            .copied()
-                            .unwrap_or_default();
-                        let second = cloned
-                            .next()
-                            .and_then(|next| next.1.as_ref().ok())
-                            .copied()
-                            .unwrap_or_default();
-                        match second {
-                            '<' | '^' | '>' => {
-                                // alignment specifier, first char specifies fillment
+                    // check for `#`
+                    if let Some((_, '#')) = chars.peek() {
+                        skip_char_and_emit(&mut chars, FormatSpecifier::NumberSign, &mut callback);
+                    }
+
+                    // check for `0`
+                    let mut cloned = chars.clone().take(2);
+                    let first = cloned.next().map(|next| next.1);
+                    let second = cloned.next().map(|next| next.1);
+
+                    if first == Some('0') && second != Some('$') {
+                        skip_char_and_emit(&mut chars, FormatSpecifier::Zero, &mut callback);
+                    }
+
+                    // width
+                    match chars.peek().copied().unwrap_or_default().1 {
+                        '0'..='9' => {
+                            read_integer(&mut chars, &mut callback);
+                            if let Some((_, '$')) = chars.peek() {
                                 skip_char_and_emit(
                                     &mut chars,
-                                    FormatSpecifier::Fill,
+                                    FormatSpecifier::DollarSign,
                                     &mut callback,
                                 );
+                            }
+                        }
+                        c if c == '_' || c.is_alphabetic() => {
+                            read_identifier(&mut chars, &mut callback);
+
+                            if chars.peek().map(|&(_, c)| c) == Some('?') {
                                 skip_char_and_emit(
                                     &mut chars,
-                                    FormatSpecifier::Align,
+                                    FormatSpecifier::QuestionMark,
                                     &mut callback,
                                 );
                             }
-                            _ => match first {
-                                '<' | '^' | '>' => {
+
+                            // can be either width (indicated by dollar sign, or type in which case
+                            // the next sign has to be `}`)
+                            let next = chars.peek().map(|&(_, c)| c);
+
+                            match next {
+                                Some('$') => skip_char_and_emit(
+                                    &mut chars,
+                                    FormatSpecifier::DollarSign,
+                                    &mut callback,
+                                ),
+                                Some('}') => {
                                     skip_char_and_emit(
                                         &mut chars,
-                                        FormatSpecifier::Align,
+                                        FormatSpecifier::Close,
                                         &mut callback,
                                     );
+                                    continue;
                                 }
-                                _ => {}
-                            },
+                                _ => continue,
+                            };
                         }
+                        _ => {}
+                    }
 
-                        // check for sign
-                        match chars
-                            .peek()
-                            .and_then(|next| next.1.as_ref().ok())
-                            .copied()
-                            .unwrap_or_default()
-                        {
-                            '+' | '-' => {
+                    // precision
+                    if let Some((_, '.')) = chars.peek() {
+                        skip_char_and_emit(&mut chars, FormatSpecifier::Dot, &mut callback);
+
+                        match chars.peek().copied().unwrap_or_default().1 {
+                            '*' => {
                                 skip_char_and_emit(
                                     &mut chars,
-                                    FormatSpecifier::Sign,
+                                    FormatSpecifier::Asterisk,
                                     &mut callback,
                                 );
                             }
-                            _ => {}
-                        }
-
-                        // check for `#`
-                        if let Some((_, Ok('#'))) = chars.peek() {
-                            skip_char_and_emit(
-                                &mut chars,
-                                FormatSpecifier::NumberSign,
-                                &mut callback,
-                            );
-                        }
-
-                        // check for `0`
-                        let mut cloned = chars.clone().take(2);
-                        let first = cloned.next().and_then(|next| next.1.as_ref().ok()).copied();
-                        let second = cloned.next().and_then(|next| next.1.as_ref().ok()).copied();
-
-                        if first == Some('0') && second != Some('$') {
-                            skip_char_and_emit(&mut chars, FormatSpecifier::Zero, &mut callback);
-                        }
-
-                        // width
-                        match chars
-                            .peek()
-                            .and_then(|next| next.1.as_ref().ok())
-                            .copied()
-                            .unwrap_or_default()
-                        {
                             '0'..='9' => {
                                 read_integer(&mut chars, &mut callback);
-                                if let Some((_, Ok('$'))) = chars.peek() {
+                                if let Some((_, '$')) = chars.peek() {
                                     skip_char_and_emit(
                                         &mut chars,
                                         FormatSpecifier::DollarSign,
@@ -415,160 +433,75 @@ pub trait HasFormatSpecifier: AstToken {
                             }
                             c if c == '_' || c.is_alphabetic() => {
                                 read_identifier(&mut chars, &mut callback);
-
-                                if chars.peek().and_then(|next| next.1.as_ref().ok()).copied()
-                                    == Some('?')
-                                {
-                                    skip_char_and_emit(
-                                        &mut chars,
-                                        FormatSpecifier::QuestionMark,
-                                        &mut callback,
-                                    );
+                                if chars.peek().map(|&(_, c)| c) != Some('$') {
+                                    continue;
                                 }
-
-                                // can be either width (indicated by dollar sign, or type in which case
-                                // the next sign has to be `}`)
-                                let next =
-                                    chars.peek().and_then(|next| next.1.as_ref().ok()).copied();
-
-                                match next {
-                                    Some('$') => skip_char_and_emit(
-                                        &mut chars,
-                                        FormatSpecifier::DollarSign,
-                                        &mut callback,
-                                    ),
-                                    Some('}') => {
-                                        skip_char_and_emit(
-                                            &mut chars,
-                                            FormatSpecifier::Close,
-                                            &mut callback,
-                                        );
-                                        continue;
-                                    }
-                                    _ => continue,
-                                };
+                                skip_char_and_emit(
+                                    &mut chars,
+                                    FormatSpecifier::DollarSign,
+                                    &mut callback,
+                                );
+                            }
+                            _ => {
+                                continue;
                             }
-                            _ => {}
                         }
+                    }
 
-                        // precision
-                        if let Some((_, Ok('.'))) = chars.peek() {
-                            skip_char_and_emit(&mut chars, FormatSpecifier::Dot, &mut callback);
-
-                            match chars
-                                .peek()
-                                .and_then(|next| next.1.as_ref().ok())
-                                .copied()
-                                .unwrap_or_default()
-                            {
-                                '*' => {
-                                    skip_char_and_emit(
-                                        &mut chars,
-                                        FormatSpecifier::Asterisk,
-                                        &mut callback,
-                                    );
-                                }
-                                '0'..='9' => {
-                                    read_integer(&mut chars, &mut callback);
-                                    if let Some((_, Ok('$'))) = chars.peek() {
-                                        skip_char_and_emit(
-                                            &mut chars,
-                                            FormatSpecifier::DollarSign,
-                                            &mut callback,
-                                        );
-                                    }
-                                }
-                                c if c == '_' || c.is_alphabetic() => {
-                                    read_identifier(&mut chars, &mut callback);
-                                    if chars.peek().and_then(|next| next.1.as_ref().ok()).copied()
-                                        != Some('$')
-                                    {
-                                        continue;
-                                    }
-                                    skip_char_and_emit(
-                                        &mut chars,
-                                        FormatSpecifier::DollarSign,
-                                        &mut callback,
-                                    );
-                                }
-                                _ => {
-                                    continue;
-                                }
-                            }
+                    // type
+                    match chars.peek().copied().unwrap_or_default().1 {
+                        '?' => {
+                            skip_char_and_emit(
+                                &mut chars,
+                                FormatSpecifier::QuestionMark,
+                                &mut callback,
+                            );
                         }
+                        c if c == '_' || c.is_alphabetic() => {
+                            read_identifier(&mut chars, &mut callback);
 
-                        // type
-                        match chars
-                            .peek()
-                            .and_then(|next| next.1.as_ref().ok())
-                            .copied()
-                            .unwrap_or_default()
-                        {
-                            '?' => {
+                            if chars.peek().map(|&(_, c)| c) == Some('?') {
                                 skip_char_and_emit(
                                     &mut chars,
                                     FormatSpecifier::QuestionMark,
                                     &mut callback,
                                 );
                             }
-                            c if c == '_' || c.is_alphabetic() => {
-                                read_identifier(&mut chars, &mut callback);
-
-                                if chars.peek().and_then(|next| next.1.as_ref().ok()).copied()
-                                    == Some('?')
-                                {
-                                    skip_char_and_emit(
-                                        &mut chars,
-                                        FormatSpecifier::QuestionMark,
-                                        &mut callback,
-                                    );
-                                }
-                            }
-                            _ => {}
                         }
-                    }
-
-                    match chars.peek() {
-                        Some((_, Ok('}'))) => {
-                            skip_char_and_emit(&mut chars, FormatSpecifier::Close, &mut callback);
-                        }
-                        Some((_, _)) | None => continue,
+                        _ => {}
                     }
                 }
-                _ => {
-                    while let Some((_, Ok(next_char))) = chars.peek() {
-                        if next_char == &'{' {
-                            break;
-                        }
-                        chars.next();
-                    }
+
+                if let Some((_, '}')) = chars.peek() {
+                    skip_char_and_emit(&mut chars, FormatSpecifier::Close, &mut callback);
                 }
-            };
+                continue;
+            }
         }
 
-        fn skip_char_and_emit<'a, I, F>(
+        fn skip_char_and_emit<I, F>(
             chars: &mut std::iter::Peekable<I>,
             emit: FormatSpecifier,
             callback: &mut F,
         ) where
-            I: Iterator<Item = &'a (TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>,
+            I: Iterator<Item = (TextRange, char)>,
             F: FnMut(TextRange, FormatSpecifier),
         {
             let (range, _) = chars.next().unwrap();
-            callback(*range, emit);
+            callback(range, emit);
         }
 
-        fn read_integer<'a, I, F>(chars: &mut std::iter::Peekable<I>, callback: &mut F)
+        fn read_integer<I, F>(chars: &mut std::iter::Peekable<I>, callback: &mut F)
         where
-            I: Iterator<Item = &'a (TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>,
+            I: Iterator<Item = (TextRange, char)>,
             F: FnMut(TextRange, FormatSpecifier),
         {
             let (mut range, c) = chars.next().unwrap();
-            assert!(c.as_ref().unwrap().is_ascii_digit());
-            while let Some((r, Ok(next_char))) = chars.peek() {
+            assert!(c.is_ascii_digit());
+            while let Some(&(r, next_char)) = chars.peek() {
                 if next_char.is_ascii_digit() {
                     chars.next();
-                    range = range.cover(*r);
+                    range = range.cover(r);
                 } else {
                     break;
                 }
@@ -576,17 +509,17 @@ pub trait HasFormatSpecifier: AstToken {
             callback(range, FormatSpecifier::Integer);
         }
 
-        fn read_identifier<'a, I, F>(chars: &mut std::iter::Peekable<I>, callback: &mut F)
+        fn read_identifier<I, F>(chars: &mut std::iter::Peekable<I>, callback: &mut F)
         where
-            I: Iterator<Item = &'a (TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>,
+            I: Iterator<Item = (TextRange, char)>,
             F: FnMut(TextRange, FormatSpecifier),
         {
             let (mut range, c) = chars.next().unwrap();
-            assert!(c.as_ref().unwrap().is_alphabetic() || *c.as_ref().unwrap() == '_');
-            while let Some((r, Ok(next_char))) = chars.peek() {
-                if *next_char == '_' || next_char.is_ascii_digit() || next_char.is_alphabetic() {
+            assert!(c.is_alphabetic() || c == '_');
+            while let Some(&(r, next_char)) = chars.peek() {
+                if next_char == '_' || next_char.is_ascii_digit() || next_char.is_alphabetic() {
                     chars.next();
-                    range = range.cover(*r);
+                    range = range.cover(r);
                 } else {
                     break;
                 }