]> git.lizzy.rs Git - rust.git/blob - crates/ide/src/syntax_highlighting/format.rs
Replace state with function
[rust.git] / crates / ide / src / syntax_highlighting / format.rs
1 //! Syntax highlighting for format macro strings.
2 use syntax::{
3     ast::{self, FormatSpecifier, HasFormatSpecifier},
4     AstNode, AstToken, TextRange,
5 };
6
7 use crate::{syntax_highlighting::highlights::Highlights, HlRange, HlTag, SymbolKind};
8
9 pub(super) fn highlight_format_string(
10     stack: &mut Highlights,
11     string: &ast::String,
12     range: TextRange,
13 ) {
14     if is_format_string(string).is_none() {
15         return;
16     }
17
18     string.lex_format_specifier(|piece_range, kind| {
19         if let Some(highlight) = highlight_format_specifier(kind) {
20             stack.add(HlRange {
21                 range: piece_range + range.start(),
22                 highlight: highlight.into(),
23                 binding_hash: None,
24             });
25         }
26     });
27 }
28
29 fn is_format_string(string: &ast::String) -> Option<()> {
30     let parent = string.syntax().parent();
31
32     let name = parent.parent().and_then(ast::MacroCall::cast)?.path()?.segment()?.name_ref()?;
33     if !matches!(name.text().as_str(), "format_args" | "format_args_nl") {
34         return None;
35     }
36
37     let first_literal = parent
38         .children_with_tokens()
39         .filter_map(|it| it.as_token().cloned().and_then(ast::String::cast))
40         .next()?;
41     if &first_literal != string {
42         return None;
43     }
44
45     Some(())
46 }
47
48 fn highlight_format_specifier(kind: FormatSpecifier) -> Option<HlTag> {
49     Some(match kind {
50         FormatSpecifier::Open
51         | FormatSpecifier::Close
52         | FormatSpecifier::Colon
53         | FormatSpecifier::Fill
54         | FormatSpecifier::Align
55         | FormatSpecifier::Sign
56         | FormatSpecifier::NumberSign
57         | FormatSpecifier::DollarSign
58         | FormatSpecifier::Dot
59         | FormatSpecifier::Asterisk
60         | FormatSpecifier::QuestionMark => HlTag::FormatSpecifier,
61
62         FormatSpecifier::Integer | FormatSpecifier::Zero => HlTag::NumericLiteral,
63
64         FormatSpecifier::Identifier => HlTag::Symbol(SymbolKind::Local),
65     })
66 }