aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/syntax_highlighting/format.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/syntax_highlighting/format.rs')
-rw-r--r--crates/ide/src/syntax_highlighting/format.rs82
1 files changed, 36 insertions, 46 deletions
diff --git a/crates/ide/src/syntax_highlighting/format.rs b/crates/ide/src/syntax_highlighting/format.rs
index d807ad0ad..a74ca844b 100644
--- a/crates/ide/src/syntax_highlighting/format.rs
+++ b/crates/ide/src/syntax_highlighting/format.rs
@@ -1,60 +1,48 @@
1//! Syntax highlighting for format macro strings. 1//! Syntax highlighting for format macro strings.
2use syntax::{ 2use syntax::{
3 ast::{self, FormatSpecifier, HasFormatSpecifier}, 3 ast::{self, FormatSpecifier, HasFormatSpecifier},
4 AstNode, AstToken, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, 4 AstNode, AstToken, TextRange,
5}; 5};
6 6
7use crate::{HlRange, HlTag, SymbolKind}; 7use crate::{syntax_highlighting::highlights::Highlights, HlRange, HlTag, SymbolKind};
8 8
9use super::highlights::Highlights; 9pub(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 }
10 17
11#[derive(Default)] 18 string.lex_format_specifier(|piece_range, kind| {
12pub(super) struct FormatStringHighlighter { 19 if let Some(highlight) = highlight_format_specifier(kind) {
13 format_string: Option<SyntaxElement>, 20 stack.add(HlRange {
21 range: piece_range + range.start(),
22 highlight: highlight.into(),
23 binding_hash: None,
24 });
25 }
26 });
14} 27}
15 28
16impl FormatStringHighlighter { 29fn is_format_string(string: &ast::String) -> Option<()> {
17 pub(super) fn check_for_format_string(&mut self, parent: &SyntaxNode) { 30 let parent = string.syntax().parent();
18 // Check if macro takes a format string and remember it for highlighting later. 31
19 // The macros that accept a format string expand to a compiler builtin macros 32 let name = parent.parent().and_then(ast::MacroCall::cast)?.path()?.segment()?.name_ref()?;
20 // `format_args` and `format_args_nl`. 33 if !matches!(name.text().as_str(), "format_args" | "format_args_nl") {
21 if let Some(name) = parent 34 return None;
22 .parent()
23 .and_then(ast::MacroCall::cast)
24 .and_then(|mc| mc.path())
25 .and_then(|p| p.segment())
26 .and_then(|s| s.name_ref())
27 {
28 match name.text().as_str() {
29 "format_args" | "format_args_nl" => {
30 self.format_string = parent
31 .children_with_tokens()
32 .filter(|t| t.kind() != SyntaxKind::WHITESPACE)
33 .nth(1)
34 .filter(|e| ast::String::can_cast(e.kind()))
35 }
36 _ => {}
37 }
38 }
39 } 35 }
40 pub(super) fn highlight_format_string( 36
41 &self, 37 let first_literal = parent
42 stack: &mut Highlights, 38 .children_with_tokens()
43 string: &impl HasFormatSpecifier, 39 .filter_map(|it| it.as_token().cloned().and_then(ast::String::cast))
44 range: TextRange, 40 .next()?;
45 ) { 41 if &first_literal != string {
46 if self.format_string.as_ref() == Some(&SyntaxElement::from(string.syntax().clone())) { 42 return None;
47 string.lex_format_specifier(|piece_range, kind| {
48 if let Some(highlight) = highlight_format_specifier(kind) {
49 stack.add(HlRange {
50 range: piece_range + range.start(),
51 highlight: highlight.into(),
52 binding_hash: None,
53 });
54 }
55 });
56 }
57 } 43 }
44
45 Some(())
58} 46}
59 47
60fn highlight_format_specifier(kind: FormatSpecifier) -> Option<HlTag> { 48fn highlight_format_specifier(kind: FormatSpecifier) -> Option<HlTag> {
@@ -70,7 +58,9 @@ fn highlight_format_specifier(kind: FormatSpecifier) -> Option<HlTag> {
70 | FormatSpecifier::Dot 58 | FormatSpecifier::Dot
71 | FormatSpecifier::Asterisk 59 | FormatSpecifier::Asterisk
72 | FormatSpecifier::QuestionMark => HlTag::FormatSpecifier, 60 | FormatSpecifier::QuestionMark => HlTag::FormatSpecifier,
61
73 FormatSpecifier::Integer | FormatSpecifier::Zero => HlTag::NumericLiteral, 62 FormatSpecifier::Integer | FormatSpecifier::Zero => HlTag::NumericLiteral,
63
74 FormatSpecifier::Identifier => HlTag::Symbol(SymbolKind::Local), 64 FormatSpecifier::Identifier => HlTag::Symbol(SymbolKind::Local),
75 }) 65 })
76} 66}