]> git.lizzy.rs Git - rust.git/commitdiff
Replace state with function
authorAleksey Kladov <aleksey.kladov@gmail.com>
Sun, 10 Jan 2021 08:57:17 +0000 (11:57 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Sun, 10 Jan 2021 08:57:17 +0000 (11:57 +0300)
crates/ide/src/syntax_highlighting.rs
crates/ide/src/syntax_highlighting/format.rs

index b82e3775e1dbb841aa319fdc5627649dc38b2b5c..f2d4da78d006b4339349f588245bb322a1b00270 100644 (file)
@@ -24,7 +24,7 @@
 
 use crate::{
     syntax_highlighting::{
-        format::FormatStringHighlighter, highlights::Highlights,
+        format::highlight_format_string, highlights::Highlights,
         macro_rules::MacroRulesHighlighter, tags::Highlight,
     },
     FileId, HlMod, HlTag, SymbolKind,
@@ -88,7 +88,6 @@ fn traverse(
 
     let mut current_macro_call: Option<ast::MacroCall> = None;
     let mut current_macro_rules: Option<ast::MacroRules> = None;
-    let mut format_string_highlighter = FormatStringHighlighter::default();
     let mut macro_rules_highlighter = MacroRulesHighlighter::default();
     let mut inside_attribute = false;
 
@@ -120,7 +119,6 @@ fn traverse(
             WalkEvent::Leave(Some(mc)) => {
                 assert_eq!(current_macro_call, Some(mc));
                 current_macro_call = None;
-                format_string_highlighter = FormatStringHighlighter::default();
             }
             _ => (),
         }
@@ -175,8 +173,6 @@ fn traverse(
             let token = sema.descend_into_macros(token.clone());
             let parent = token.parent();
 
-            format_string_highlighter.check_for_format_string(&parent);
-
             // We only care Name and Name_ref
             match (token.kind(), parent.kind()) {
                 (IDENT, NAME) | (IDENT, NAME_REF) => parent.into(),
@@ -195,6 +191,10 @@ fn traverse(
             }
         }
 
+        if let Some(_) = macro_rules_highlighter.highlight(element_to_highlight.clone()) {
+            continue;
+        }
+
         if let Some((mut highlight, binding_hash)) = highlight::element(
             &sema,
             &mut bindings_shadow_count,
@@ -205,24 +205,20 @@ fn traverse(
                 highlight = highlight | HlMod::Attribute;
             }
 
-            if macro_rules_highlighter.highlight(element_to_highlight.clone()).is_none() {
-                hl.add(HlRange { range, highlight, binding_hash });
-            }
+            hl.add(HlRange { range, highlight, binding_hash });
+        }
 
-            if let Some(string) =
-                element_to_highlight.as_token().cloned().and_then(ast::String::cast)
-            {
-                format_string_highlighter.highlight_format_string(hl, &string, range);
-                // Highlight escape sequences
-                if let Some(char_ranges) = string.char_ranges() {
-                    for (piece_range, _) in char_ranges.iter().filter(|(_, char)| char.is_ok()) {
-                        if string.text()[piece_range.start().into()..].starts_with('\\') {
-                            hl.add(HlRange {
-                                range: piece_range + range.start(),
-                                highlight: HlTag::EscapeSequence.into(),
-                                binding_hash: None,
-                            });
-                        }
+        if let Some(string) = element_to_highlight.as_token().cloned().and_then(ast::String::cast) {
+            highlight_format_string(hl, &string, range);
+            // Highlight escape sequences
+            if let Some(char_ranges) = string.char_ranges() {
+                for (piece_range, _) in char_ranges.iter().filter(|(_, char)| char.is_ok()) {
+                    if string.text()[piece_range.start().into()..].starts_with('\\') {
+                        hl.add(HlRange {
+                            range: piece_range + range.start(),
+                            highlight: HlTag::EscapeSequence.into(),
+                            binding_hash: None,
+                        });
                     }
                 }
             }
index d807ad0ad5c33f7b3ec5491799117323dd1baa13..a74ca844b33f89f955e9d2e0327dfe1c9fd9b40f 100644 (file)
@@ -1,60 +1,48 @@
 //! Syntax highlighting for format macro strings.
 use syntax::{
     ast::{self, FormatSpecifier, HasFormatSpecifier},
-    AstNode, AstToken, SyntaxElement, SyntaxKind, SyntaxNode, TextRange,
+    AstNode, AstToken, TextRange,
 };
 
-use crate::{HlRange, HlTag, SymbolKind};
+use crate::{syntax_highlighting::highlights::Highlights, HlRange, HlTag, SymbolKind};
 
-use super::highlights::Highlights;
+pub(super) fn highlight_format_string(
+    stack: &mut Highlights,
+    string: &ast::String,
+    range: TextRange,
+) {
+    if is_format_string(string).is_none() {
+        return;
+    }
 
-#[derive(Default)]
-pub(super) struct FormatStringHighlighter {
-    format_string: Option<SyntaxElement>,
+    string.lex_format_specifier(|piece_range, kind| {
+        if let Some(highlight) = highlight_format_specifier(kind) {
+            stack.add(HlRange {
+                range: piece_range + range.start(),
+                highlight: highlight.into(),
+                binding_hash: None,
+            });
+        }
+    });
 }
 
-impl FormatStringHighlighter {
-    pub(super) fn check_for_format_string(&mut self, parent: &SyntaxNode) {
-        // Check if macro takes a format string and remember it for highlighting later.
-        // The macros that accept a format string expand to a compiler builtin macros
-        // `format_args` and `format_args_nl`.
-        if let Some(name) = parent
-            .parent()
-            .and_then(ast::MacroCall::cast)
-            .and_then(|mc| mc.path())
-            .and_then(|p| p.segment())
-            .and_then(|s| s.name_ref())
-        {
-            match name.text().as_str() {
-                "format_args" | "format_args_nl" => {
-                    self.format_string = parent
-                        .children_with_tokens()
-                        .filter(|t| t.kind() != SyntaxKind::WHITESPACE)
-                        .nth(1)
-                        .filter(|e| ast::String::can_cast(e.kind()))
-                }
-                _ => {}
-            }
-        }
+fn is_format_string(string: &ast::String) -> Option<()> {
+    let parent = string.syntax().parent();
+
+    let name = parent.parent().and_then(ast::MacroCall::cast)?.path()?.segment()?.name_ref()?;
+    if !matches!(name.text().as_str(), "format_args" | "format_args_nl") {
+        return None;
     }
-    pub(super) fn highlight_format_string(
-        &self,
-        stack: &mut Highlights,
-        string: &impl HasFormatSpecifier,
-        range: TextRange,
-    ) {
-        if self.format_string.as_ref() == Some(&SyntaxElement::from(string.syntax().clone())) {
-            string.lex_format_specifier(|piece_range, kind| {
-                if let Some(highlight) = highlight_format_specifier(kind) {
-                    stack.add(HlRange {
-                        range: piece_range + range.start(),
-                        highlight: highlight.into(),
-                        binding_hash: None,
-                    });
-                }
-            });
-        }
+
+    let first_literal = parent
+        .children_with_tokens()
+        .filter_map(|it| it.as_token().cloned().and_then(ast::String::cast))
+        .next()?;
+    if &first_literal != string {
+        return None;
     }
+
+    Some(())
 }
 
 fn highlight_format_specifier(kind: FormatSpecifier) -> Option<HlTag> {
@@ -70,7 +58,9 @@ fn highlight_format_specifier(kind: FormatSpecifier) -> Option<HlTag> {
         | FormatSpecifier::Dot
         | FormatSpecifier::Asterisk
         | FormatSpecifier::QuestionMark => HlTag::FormatSpecifier,
+
         FormatSpecifier::Integer | FormatSpecifier::Zero => HlTag::NumericLiteral,
+
         FormatSpecifier::Identifier => HlTag::Symbol(SymbolKind::Local),
     })
 }