Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/syntax_highlighting.rs')
-rw-r--r--crates/ide/src/syntax_highlighting.rs160
1 files changed, 103 insertions, 57 deletions
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 454a250f3d..8c02fe8164 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -16,13 +16,19 @@ mod tests;
use hir::{Name, Semantics};
use ide_db::{FxHashMap, RootDatabase, SymbolKind};
use syntax::{
- ast, AstNode, AstToken, NodeOrToken, SyntaxKind::*, SyntaxNode, TextRange, WalkEvent, T,
+ ast::{self, IsString},
+ AstNode, AstToken, NodeOrToken,
+ SyntaxKind::*,
+ SyntaxNode, TextRange, WalkEvent, T,
};
use crate::{
syntax_highlighting::{
- escape::highlight_escape_string, format::highlight_format_string, highlights::Highlights,
- macro_::MacroHighlighter, tags::Highlight,
+ escape::{highlight_escape_char, highlight_escape_string},
+ format::highlight_format_string,
+ highlights::Highlights,
+ macro_::MacroHighlighter,
+ tags::Highlight,
},
FileId, HlMod, HlOperator, HlPunct, HlTag,
};
@@ -163,6 +169,7 @@ pub struct HighlightConfig {
// injected:: Emitted for doc-string injected highlighting like rust source blocks in documentation.
// intraDocLink:: Emitted for intra doc links in doc-strings.
// library:: Emitted for items that are defined outside of the current crate.
+// macro:: Emitted for tokens inside macro calls.
// mutable:: Emitted for mutable locals and statics as well as functions taking `&mut self`.
// public:: Emitted for items that are from the current crate and are `pub`.
// reference:: Emitted for locals behind a reference and functions taking `self` by reference.
@@ -237,6 +244,7 @@ fn traverse(
let mut current_macro: Option<ast::Macro> = None;
let mut macro_highlighter = MacroHighlighter::default();
let mut inside_attribute = false;
+ let mut inside_macro_call = false;
// Walk all nodes, keeping track of whether we are inside a macro or not.
// If in macro, expand it first and highlight the expanded code.
@@ -267,46 +275,50 @@ fn traverse(
inside_attribute = false
}
- Enter(NodeOrToken::Node(node)) if ast::Item::can_cast(node.kind()) => {
- match ast::Item::cast(node.clone()) {
- Some(ast::Item::MacroRules(mac)) => {
- macro_highlighter.init();
- current_macro = Some(mac.into());
- continue;
- }
- Some(ast::Item::MacroDef(mac)) => {
- macro_highlighter.init();
- current_macro = Some(mac.into());
- continue;
- }
- Some(item) => {
- if matches!(node.kind(), FN | CONST | STATIC) {
- bindings_shadow_count.clear();
+ Enter(NodeOrToken::Node(node)) => match ast::Item::cast(node.clone()) {
+ Some(item) => {
+ match item {
+ ast::Item::MacroRules(mac) => {
+ macro_highlighter.init();
+ current_macro = Some(mac.into());
+ continue;
+ }
+ ast::Item::MacroDef(mac) => {
+ macro_highlighter.init();
+ current_macro = Some(mac.into());
+ continue;
+ }
+ ast::Item::Fn(_) | ast::Item::Const(_) | ast::Item::Static(_) => {
+ bindings_shadow_count.clear()
+ }
+ ast::Item::MacroCall(_) => {
+ inside_macro_call = true;
}
+ _ => (),
+ }
- if attr_or_derive_item.is_none() {
- if sema.is_attr_macro_call(&item) {
- attr_or_derive_item = Some(AttrOrDerive::Attr(item));
- } else {
- let adt = match item {
- ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
- ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
- ast::Item::Union(it) => Some(ast::Adt::Union(it)),
- _ => None,
- };
- match adt {
- Some(adt) if sema.is_derive_annotated(&adt) => {
- attr_or_derive_item =
- Some(AttrOrDerive::Derive(ast::Item::from(adt)));
- }
- _ => (),
+ if attr_or_derive_item.is_none() {
+ if sema.is_attr_macro_call(&item) {
+ attr_or_derive_item = Some(AttrOrDerive::Attr(item));
+ } else {
+ let adt = match item {
+ ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
+ ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
+ ast::Item::Union(it) => Some(ast::Adt::Union(it)),
+ _ => None,
+ };
+ match adt {
+ Some(adt) if sema.is_derive_annotated(&adt) => {
+ attr_or_derive_item =
+ Some(AttrOrDerive::Derive(ast::Item::from(adt)));
}
+ _ => (),
}
}
}
- _ => (),
}
- }
+ _ => (),
+ },
Leave(NodeOrToken::Node(node)) if ast::Item::can_cast(node.kind()) => {
match ast::Item::cast(node.clone()) {
Some(ast::Item::MacroRules(mac)) => {
@@ -324,6 +336,9 @@ fn traverse(
{
attr_or_derive_item = None;
}
+ Some(ast::Item::MacroCall(_)) => {
+ inside_macro_call = false;
+ }
_ => (),
}
}
@@ -419,14 +434,35 @@ fn traverse(
continue;
}
highlight_format_string(hl, &string, &expanded_string, range);
- highlight_escape_string(hl, &string, range.start());
+
+ if !string.is_raw() {
+ highlight_escape_string(hl, &string, range.start());
+ }
}
} else if ast::ByteString::can_cast(token.kind())
&& ast::ByteString::can_cast(descended_token.kind())
{
if let Some(byte_string) = ast::ByteString::cast(token) {
- highlight_escape_string(hl, &byte_string, range.start());
+ if !byte_string.is_raw() {
+ highlight_escape_string(hl, &byte_string, range.start());
+ }
}
+ } else if ast::CString::can_cast(token.kind())
+ && ast::CString::can_cast(descended_token.kind())
+ {
+ if let Some(c_string) = ast::CString::cast(token) {
+ if !c_string.is_raw() {
+ highlight_escape_string(hl, &c_string, range.start());
+ }
+ }
+ } else if ast::Char::can_cast(token.kind())
+ && ast::Char::can_cast(descended_token.kind())
+ {
+ let Some(char) = ast::Char::cast(token) else {
+ continue;
+ };
+
+ highlight_escape_char(hl, &char, range.start())
}
}
@@ -455,32 +491,42 @@ fn traverse(
}
// apply config filtering
- match &mut highlight.tag {
- HlTag::StringLiteral if !config.strings => continue,
- // If punctuation is disabled, make the macro bang part of the macro call again.
- tag @ HlTag::Punctuation(HlPunct::MacroBang) => {
- if !config.macro_bang {
- *tag = HlTag::Symbol(SymbolKind::Macro);
- } else if !config.specialize_punctuation {
- *tag = HlTag::Punctuation(HlPunct::Other);
- }
- }
- HlTag::Punctuation(_) if !config.punctuation => continue,
- tag @ HlTag::Punctuation(_) if !config.specialize_punctuation => {
- *tag = HlTag::Punctuation(HlPunct::Other);
- }
- HlTag::Operator(_) if !config.operator && highlight.mods.is_empty() => continue,
- tag @ HlTag::Operator(_) if !config.specialize_operator => {
- *tag = HlTag::Operator(HlOperator::Other);
- }
- _ => (),
+ if !filter_by_config(&mut highlight, config) {
+ continue;
}
if inside_attribute {
highlight |= HlMod::Attribute
}
+ if inside_macro_call && tt_level > 0 {
+ highlight |= HlMod::Macro
+ }
hl.add(HlRange { range, highlight, binding_hash });
}
}
}
+
+fn filter_by_config(highlight: &mut Highlight, config: HighlightConfig) -> bool {
+ match &mut highlight.tag {
+ HlTag::StringLiteral if !config.strings => return false,
+ // If punctuation is disabled, make the macro bang part of the macro call again.
+ tag @ HlTag::Punctuation(HlPunct::MacroBang) => {
+ if !config.macro_bang {
+ *tag = HlTag::Symbol(SymbolKind::Macro);
+ } else if !config.specialize_punctuation {
+ *tag = HlTag::Punctuation(HlPunct::Other);
+ }
+ }
+ HlTag::Punctuation(_) if !config.punctuation => return false,
+ tag @ HlTag::Punctuation(_) if !config.specialize_punctuation => {
+ *tag = HlTag::Punctuation(HlPunct::Other);
+ }
+ HlTag::Operator(_) if !config.operator && highlight.mods.is_empty() => return false,
+ tag @ HlTag::Operator(_) if !config.specialize_operator => {
+ *tag = HlTag::Operator(HlOperator::Other);
+ }
+ _ => (),
+ }
+ true
+}