about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2025-03-01 17:43:31 +0000
committerGitHub <noreply@github.com>2025-03-01 17:43:31 +0000
commita565f7f9c636309b5aa8a56478e117764dd3f4e0 (patch)
tree1d218032c4e57ed9bd4e86af1215d686a594d796
parente862daf7783c921681d5d3e57dd9f484fe418240 (diff)
parent28a5eeb157329fd45c31d7c5567bc48ecfdd4aa9 (diff)
downloadrust-a565f7f9c636309b5aa8a56478e117764dd3f4e0.tar.gz
rust-a565f7f9c636309b5aa8a56478e117764dd3f4e0.zip
Merge pull request #19257 from Veykril/push-myvwxskworsn
internal: Cleanup some syntax highlighting things
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/files.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/lib.rs54
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs49
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/lib.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/search.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/moniker.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs343
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs21
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/macro_.rs128
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html20
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html18
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html16
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html16
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html16
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html16
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html50
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html18
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html116
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs27
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs19
-rw-r--r--src/tools/rust-analyzer/crates/syntax/rust.ungram6
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/fixture.rs12
34 files changed, 485 insertions, 590 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
index 408d03ff718..a2d0ba3deb8 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -22,7 +22,7 @@ use hir_expand::{
     db::ExpandDatabase,
     proc_macro::{ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind},
     span_map::SpanMapRef,
-    InFile, MacroCallKind, MacroFileId, MacroFileIdExt,
+    InFile, MacroCallKind, MacroFileId, MacroFileIdExt, MacroKind,
 };
 use intern::Symbol;
 use itertools::Itertools;
@@ -211,7 +211,11 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
 
         if let Some(src) = src {
             if let Some(file_id) = src.file_id.macro_file() {
-                if file_id.is_attr_macro(&db) || file_id.is_custom_derive(&db) {
+                if let MacroKind::Derive
+                | MacroKind::DeriveBuiltIn
+                | MacroKind::Attr
+                | MacroKind::AttrBuiltIn = file_id.kind(&db)
+                {
                     let call = file_id.call_node(&db);
                     let mut show_spans = false;
                     let mut show_ctxt = false;
@@ -236,7 +240,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
     for impl_id in def_map[local_id].scope.impls() {
         let src = impl_id.lookup(&db).source(&db);
         if let Some(macro_file) = src.file_id.macro_file() {
-            if macro_file.is_builtin_derive(&db) {
+            if let MacroKind::DeriveBuiltIn | MacroKind::Derive = macro_file.kind(&db) {
                 let pp = pretty_print_macro_expansion(
                     src.value.syntax().clone(),
                     db.span_map(macro_file.into()).as_ref(),
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
index 13ddb0d4acc..f3bcc772682 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
@@ -10,7 +10,7 @@ use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
 
 use crate::{
     db::{self, ExpandDatabase},
-    map_node_range_up, map_node_range_up_rooted, span_for_offset, MacroFileIdExt,
+    map_node_range_up, map_node_range_up_rooted, span_for_offset, MacroFileIdExt, MacroKind,
 };
 
 /// `InFile<T>` stores a value of `T` inside a particular file/syntax tree.
@@ -276,7 +276,11 @@ impl<SN: Borrow<SyntaxNode>> InFile<SN> {
             HirFileIdRepr::FileId(file_id) => {
                 return Some(InRealFile { file_id, value: self.value.borrow().clone() })
             }
-            HirFileIdRepr::MacroFile(m) if m.is_attr_macro(db) => m,
+            HirFileIdRepr::MacroFile(m)
+                if matches!(m.kind(db), MacroKind::Attr | MacroKind::AttrBuiltIn) =>
+            {
+                m
+            }
             _ => return None,
         };
 
@@ -453,7 +457,7 @@ impl<N: AstNode> InFile<N> {
             }
             HirFileIdRepr::MacroFile(m) => m,
         };
-        if !file_id.is_attr_macro(db) {
+        if !matches!(file_id.kind(db), MacroKind::Attr | MacroKind::AttrBuiltIn) {
             return None;
         }
 
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
index 2c664029f61..41603e3c92e 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -416,6 +416,24 @@ impl HirFileIdExt for HirFileId {
     }
 }
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum MacroKind {
+    /// `macro_rules!` or Macros 2.0 macro.
+    Declarative,
+    /// A built-in function-like macro.
+    DeclarativeBuiltIn,
+    /// A custom derive.
+    Derive,
+    /// A builtin-in derive.
+    DeriveBuiltIn,
+    /// A procedural attribute macro.
+    Attr,
+    /// A built-in attribute macro.
+    AttrBuiltIn,
+    /// A function-like procedural macro.
+    ProcMacro,
+}
+
 pub trait MacroFileIdExt {
     fn is_env_or_option_env(&self, db: &dyn ExpandDatabase) -> bool;
     fn is_include_like_macro(&self, db: &dyn ExpandDatabase) -> bool;
@@ -427,15 +445,12 @@ pub trait MacroFileIdExt {
 
     fn expansion_info(self, db: &dyn ExpandDatabase) -> ExpansionInfo;
 
-    fn is_builtin_derive(&self, db: &dyn ExpandDatabase) -> bool;
-    fn is_custom_derive(&self, db: &dyn ExpandDatabase) -> bool;
+    fn kind(&self, db: &dyn ExpandDatabase) -> MacroKind;
 
     /// Return whether this file is an include macro
     fn is_include_macro(&self, db: &dyn ExpandDatabase) -> bool;
 
     fn is_eager(&self, db: &dyn ExpandDatabase) -> bool;
-    /// Return whether this file is an attr macro
-    fn is_attr_macro(&self, db: &dyn ExpandDatabase) -> bool;
 
     /// Return whether this file is the pseudo expansion of the derive attribute.
     /// See [`crate::builtin_attr_macro::derive_attr_expand`].
@@ -468,18 +483,18 @@ impl MacroFileIdExt for MacroFileId {
         ExpansionInfo::new(db, self)
     }
 
-    fn is_custom_derive(&self, db: &dyn ExpandDatabase) -> bool {
-        matches!(
-            db.lookup_intern_macro_call(self.macro_call_id).def.kind,
-            MacroDefKind::ProcMacro(_, _, ProcMacroKind::CustomDerive)
-        )
-    }
-
-    fn is_builtin_derive(&self, db: &dyn ExpandDatabase) -> bool {
-        matches!(
-            db.lookup_intern_macro_call(self.macro_call_id).def.kind,
-            MacroDefKind::BuiltInDerive(..)
-        )
+    fn kind(&self, db: &dyn ExpandDatabase) -> MacroKind {
+        match db.lookup_intern_macro_call(self.macro_call_id).def.kind {
+            MacroDefKind::Declarative(..) => MacroKind::Declarative,
+            MacroDefKind::BuiltIn(..) | MacroDefKind::BuiltInEager(..) => {
+                MacroKind::DeclarativeBuiltIn
+            }
+            MacroDefKind::BuiltInDerive(..) => MacroKind::DeriveBuiltIn,
+            MacroDefKind::ProcMacro(_, _, ProcMacroKind::CustomDerive) => MacroKind::Derive,
+            MacroDefKind::ProcMacro(_, _, ProcMacroKind::Attr) => MacroKind::Attr,
+            MacroDefKind::ProcMacro(_, _, ProcMacroKind::Bang) => MacroKind::ProcMacro,
+            MacroDefKind::BuiltInAttr(..) => MacroKind::AttrBuiltIn,
+        }
     }
 
     fn is_include_macro(&self, db: &dyn ExpandDatabase) -> bool {
@@ -507,13 +522,6 @@ impl MacroFileIdExt for MacroFileId {
         }
     }
 
-    fn is_attr_macro(&self, db: &dyn ExpandDatabase) -> bool {
-        matches!(
-            db.lookup_intern_macro_call(self.macro_call_id).def.kind,
-            MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, _, ProcMacroKind::Attr)
-        )
-    }
-
     fn is_derive_attr_pseudo_expansion(&self, db: &dyn ExpandDatabase) -> bool {
         let loc = db.lookup_intern_macro_call(self.macro_call_id);
         loc.def.is_attribute_derive()
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 727d31cffb5..55448d4ae86 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -142,7 +142,7 @@ pub use {
         name::Name,
         prettify_macro_expansion,
         proc_macro::{ProcMacros, ProcMacrosBuilder},
-        tt, ExpandResult, HirFileId, HirFileIdExt, MacroFileId, MacroFileIdExt,
+        tt, ExpandResult, HirFileId, HirFileIdExt, MacroFileId, MacroFileIdExt, MacroKind,
     },
     hir_ty::{
         consteval::ConstEvalError,
@@ -699,7 +699,10 @@ impl Module {
             let source_map = tree_source_maps.impl_(loc.id.value).item();
             let node = &tree[loc.id.value];
             let file_id = loc.id.file_id();
-            if file_id.macro_file().is_some_and(|it| it.is_builtin_derive(db.upcast())) {
+            if file_id
+                .macro_file()
+                .is_some_and(|it| it.kind(db.upcast()) == MacroKind::DeriveBuiltIn)
+            {
                 // these expansion come from us, diagnosing them is a waste of resources
                 // FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow
                 continue;
@@ -3050,20 +3053,6 @@ impl BuiltinType {
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub enum MacroKind {
-    /// `macro_rules!` or Macros 2.0 macro.
-    Declarative,
-    /// A built-in or custom derive.
-    Derive,
-    /// A built-in function-like macro.
-    BuiltIn,
-    /// A procedural attribute macro.
-    Attr,
-    /// A function-like procedural macro.
-    ProcMacro,
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct Macro {
     pub(crate) id: MacroId,
 }
@@ -3093,15 +3082,19 @@ impl Macro {
         match self.id {
             MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander {
                 MacroExpander::Declarative => MacroKind::Declarative,
-                MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
-                MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
-                MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
+                MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => {
+                    MacroKind::DeclarativeBuiltIn
+                }
+                MacroExpander::BuiltInAttr(_) => MacroKind::AttrBuiltIn,
+                MacroExpander::BuiltInDerive(_) => MacroKind::DeriveBuiltIn,
             },
             MacroId::MacroRulesId(it) => match it.lookup(db.upcast()).expander {
                 MacroExpander::Declarative => MacroKind::Declarative,
-                MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
-                MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
-                MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
+                MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => {
+                    MacroKind::DeclarativeBuiltIn
+                }
+                MacroExpander::BuiltInAttr(_) => MacroKind::AttrBuiltIn,
+                MacroExpander::BuiltInDerive(_) => MacroKind::DeriveBuiltIn,
             },
             MacroId::ProcMacroId(it) => match it.lookup(db.upcast()).kind {
                 ProcMacroKind::CustomDerive => MacroKind::Derive,
@@ -3112,10 +3105,10 @@ impl Macro {
     }
 
     pub fn is_fn_like(&self, db: &dyn HirDatabase) -> bool {
-        match self.kind(db) {
-            MacroKind::Declarative | MacroKind::BuiltIn | MacroKind::ProcMacro => true,
-            MacroKind::Attr | MacroKind::Derive => false,
-        }
+        matches!(
+            self.kind(db),
+            MacroKind::Declarative | MacroKind::DeclarativeBuiltIn | MacroKind::ProcMacro
+        )
     }
 
     pub fn is_builtin_derive(&self, db: &dyn HirDatabase) -> bool {
@@ -3155,11 +3148,11 @@ impl Macro {
     }
 
     pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
-        matches!(self.kind(db), MacroKind::Attr)
+        matches!(self.kind(db), MacroKind::Attr | MacroKind::AttrBuiltIn)
     }
 
     pub fn is_derive(&self, db: &dyn HirDatabase) -> bool {
-        matches!(self.kind(db), MacroKind::Derive)
+        matches!(self.kind(db), MacroKind::Derive | MacroKind::DeriveBuiltIn)
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index c9145f7d212..bb67fa63a1d 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -508,9 +508,7 @@ impl<'db> SemanticsImpl<'db> {
         })
     }
 
-    pub fn is_derive_annotated(&self, adt: &ast::Adt) -> bool {
-        let file_id = self.find_file(adt.syntax()).file_id;
-        let adt = InFile::new(file_id, adt);
+    pub fn is_derive_annotated(&self, adt: InFile<&ast::Adt>) -> bool {
         self.with_ctx(|ctx| ctx.has_derives(adt))
     }
 
@@ -551,10 +549,8 @@ impl<'db> SemanticsImpl<'db> {
         res.is_empty().not().then_some(res)
     }
 
-    pub fn is_attr_macro_call(&self, item: &ast::Item) -> bool {
-        let file_id = self.find_file(item.syntax()).file_id;
-        let src = InFile::new(file_id, item);
-        self.with_ctx(|ctx| ctx.item_to_macro_call(src).is_some())
+    pub fn is_attr_macro_call(&self, item: InFile<&ast::Item>) -> bool {
+        self.with_ctx(|ctx| ctx.item_to_macro_call(item).is_some())
     }
 
     /// Expand the macro call with a different token tree, mapping the `token_to_map` down into the
@@ -1526,8 +1522,13 @@ impl<'db> SemanticsImpl<'db> {
         self.analyze(field.syntax())?.resolve_record_pat_field(self.db, field)
     }
 
+    // FIXME: Replace this with `resolve_macro_call2`
     pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<Macro> {
         let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
+        self.resolve_macro_call2(macro_call)
+    }
+
+    pub fn resolve_macro_call2(&self, macro_call: InFile<&ast::MacroCall>) -> Option<Macro> {
         self.with_ctx(|ctx| {
             ctx.macro_call_to_macro_call(macro_call)
                 .and_then(|call| macro_call_to_macro_id(ctx, call))
@@ -1538,8 +1539,8 @@ impl<'db> SemanticsImpl<'db> {
         })
     }
 
-    pub fn is_proc_macro_call(&self, macro_call: &ast::MacroCall) -> bool {
-        self.resolve_macro_call(macro_call)
+    pub fn is_proc_macro_call(&self, macro_call: InFile<&ast::MacroCall>) -> bool {
+        self.resolve_macro_call2(macro_call)
             .is_some_and(|m| matches!(m.id, MacroId::ProcMacroId(..)))
     }
 
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
index 3a29232d331..96115eee6dc 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
@@ -252,10 +252,10 @@ pub enum SymbolKind {
 impl From<hir::MacroKind> for SymbolKind {
     fn from(it: hir::MacroKind) -> Self {
         match it {
-            hir::MacroKind::Declarative | hir::MacroKind::BuiltIn => SymbolKind::Macro,
+            hir::MacroKind::Declarative | hir::MacroKind::DeclarativeBuiltIn => SymbolKind::Macro,
             hir::MacroKind::ProcMacro => SymbolKind::ProcMacro,
-            hir::MacroKind::Derive => SymbolKind::Derive,
-            hir::MacroKind::Attr => SymbolKind::Attribute,
+            hir::MacroKind::Derive | hir::MacroKind::DeriveBuiltIn => SymbolKind::Derive,
+            hir::MacroKind::Attr | hir::MacroKind::AttrBuiltIn => SymbolKind::Attribute,
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
index 7963e8ae4f7..02cd8b8bdf5 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
@@ -373,7 +373,9 @@ impl Definition {
                         SearchScope::krate(db, module.krate())
                     }
                 }
-                hir::MacroKind::BuiltIn => SearchScope::crate_graph(db),
+                hir::MacroKind::AttrBuiltIn
+                | hir::MacroKind::DeriveBuiltIn
+                | hir::MacroKind::DeclarativeBuiltIn => SearchScope::crate_graph(db),
                 hir::MacroKind::Derive | hir::MacroKind::Attr | hir::MacroKind::ProcMacro => {
                     SearchScope::reverse_dependencies(db, module.krate())
                 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
index d88f7c5033e..8d2ca33bf25 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
@@ -635,12 +635,13 @@ fn filename_and_frag_for_def(
         }
         Definition::Macro(mac) => match mac.kind(db) {
             hir::MacroKind::Declarative
-            | hir::MacroKind::BuiltIn
+            | hir::MacroKind::AttrBuiltIn
+            | hir::MacroKind::DeclarativeBuiltIn
             | hir::MacroKind::Attr
             | hir::MacroKind::ProcMacro => {
                 format!("macro.{}.html", mac.name(db).as_str())
             }
-            hir::MacroKind::Derive => {
+            hir::MacroKind::Derive | hir::MacroKind::DeriveBuiltIn => {
                 format!("derive.{}.html", mac.name(db).as_str())
             }
         },
diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
index 66ea49a98a0..25d12a4c0b4 100644
--- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
@@ -184,11 +184,11 @@ pub(crate) fn def_to_kind(db: &RootDatabase, def: Definition) -> SymbolInformati
 
     match def {
         Definition::Macro(it) => match it.kind(db) {
-            MacroKind::Declarative => Macro,
-            MacroKind::Derive => Attribute,
-            MacroKind::BuiltIn => Macro,
-            MacroKind::Attr => Attribute,
-            MacroKind::ProcMacro => Macro,
+            MacroKind::Derive
+            | MacroKind::DeriveBuiltIn
+            | MacroKind::AttrBuiltIn
+            | MacroKind::Attr => Attribute,
+            MacroKind::Declarative | MacroKind::DeclarativeBuiltIn | MacroKind::ProcMacro => Macro,
         },
         Definition::Field(..) | Definition::TupleField(..) => Field,
         Definition::Module(..) | Definition::Crate(..) => Module,
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
index 1853e3a3407..519133e3ad1 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
@@ -7,7 +7,6 @@ mod escape;
 mod format;
 mod highlight;
 mod inject;
-mod macro_;
 
 mod html;
 #[cfg(test)]
@@ -15,14 +14,14 @@ mod tests;
 
 use std::ops::ControlFlow;
 
-use hir::{InRealFile, Name, Semantics};
+use hir::{HirFileIdExt, InFile, InRealFile, MacroFileIdExt, MacroKind, Name, Semantics};
 use ide_db::{FxHashMap, Ranker, RootDatabase, SymbolKind};
 use span::EditionedFileId;
 use syntax::{
     ast::{self, IsString},
     AstNode, AstToken, NodeOrToken,
     SyntaxKind::*,
-    SyntaxNode, TextRange, WalkEvent, T,
+    SyntaxNode, SyntaxToken, TextRange, WalkEvent, T,
 };
 
 use crate::{
@@ -30,7 +29,6 @@ use crate::{
         escape::{highlight_escape_byte, highlight_escape_char, highlight_escape_string},
         format::highlight_format_string,
         highlights::Highlights,
-        macro_::MacroHighlighter,
         tags::Highlight,
     },
     FileId, HlMod, HlOperator, HlPunct, HlTag,
@@ -221,7 +219,7 @@ pub(crate) fn highlight(
         Some(it) => it.krate(),
         None => return hl.to_vec(),
     };
-    traverse(&mut hl, &sema, config, file_id, &root, krate, range_to_highlight);
+    traverse(&mut hl, &sema, config, InRealFile::new(file_id, &root), krate, range_to_highlight);
     hl.to_vec()
 }
 
@@ -229,8 +227,7 @@ fn traverse(
     hl: &mut Highlights,
     sema: &Semantics<'_, RootDatabase>,
     config: HighlightConfig,
-    file_id: EditionedFileId,
-    root: &SyntaxNode,
+    InRealFile { file_id, value: root }: InRealFile<&SyntaxNode>,
     krate: hir::Crate,
     range_to_highlight: TextRange,
 ) {
@@ -252,18 +249,15 @@ fn traverse(
 
     let mut tt_level = 0;
     let mut attr_or_derive_item = None;
-    let mut current_macro: Option<ast::Macro> = None;
-    let mut macro_highlighter = MacroHighlighter::default();
 
     // FIXME: these are not perfectly accurate, we determine them by the real file's syntax tree
     // an attribute nested in a macro call will not emit `inside_attribute`
     let mut inside_attribute = false;
-    let mut inside_macro_call = false;
-    let mut inside_proc_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.
-    for event in root.preorder_with_tokens() {
+    let mut preorder = root.preorder_with_tokens();
+    while let Some(event) = preorder.next() {
         use WalkEvent::{Enter, Leave};
 
         let range = match &event {
@@ -275,16 +269,11 @@ fn traverse(
             continue;
         }
 
-        // set macro and attribute highlighting states
         match event.clone() {
-            Enter(NodeOrToken::Node(node))
-                if current_macro.is_none() && ast::TokenTree::can_cast(node.kind()) =>
-            {
+            Enter(NodeOrToken::Node(node)) if ast::TokenTree::can_cast(node.kind()) => {
                 tt_level += 1;
             }
-            Leave(NodeOrToken::Node(node))
-                if current_macro.is_none() && ast::TokenTree::can_cast(node.kind()) =>
-            {
+            Leave(NodeOrToken::Node(node)) if ast::TokenTree::can_cast(node.kind()) => {
                 tt_level -= 1;
             }
             Enter(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => {
@@ -297,28 +286,14 @@ fn traverse(
             Enter(NodeOrToken::Node(node)) => {
                 if let Some(item) = ast::Item::cast(node.clone()) {
                     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(ref macro_call) => {
-                            inside_macro_call = true;
-                            inside_proc_macro_call = sema.is_proc_macro_call(macro_call);
-                        }
                         _ => (),
                     }
 
                     if attr_or_derive_item.is_none() {
-                        if sema.is_attr_macro_call(&item) {
+                        if sema.is_attr_macro_call(InFile::new(file_id.into(), &item)) {
                             attr_or_derive_item = Some(AttrOrDerive::Attr(item));
                         } else {
                             let adt = match item {
@@ -328,7 +303,10 @@ fn traverse(
                                 _ => None,
                             };
                             match adt {
-                                Some(adt) if sema.is_derive_annotated(&adt) => {
+                                Some(adt)
+                                    if sema
+                                        .is_derive_annotated(InFile::new(file_id.into(), &adt)) =>
+                                {
                                     attr_or_derive_item =
                                         Some(AttrOrDerive::Derive(ast::Item::from(adt)));
                                 }
@@ -340,25 +318,11 @@ fn traverse(
             }
             Leave(NodeOrToken::Node(node)) if ast::Item::can_cast(node.kind()) => {
                 match ast::Item::cast(node.clone()) {
-                    Some(ast::Item::MacroRules(mac)) => {
-                        assert_eq!(current_macro, Some(mac.into()));
-                        current_macro = None;
-                        macro_highlighter = MacroHighlighter::default();
-                    }
-                    Some(ast::Item::MacroDef(mac)) => {
-                        assert_eq!(current_macro, Some(mac.into()));
-                        current_macro = None;
-                        macro_highlighter = MacroHighlighter::default();
-                    }
                     Some(item)
                         if attr_or_derive_item.as_ref().is_some_and(|it| *it.item() == item) =>
                     {
                         attr_or_derive_item = None;
                     }
-                    Some(ast::Item::MacroCall(_)) => {
-                        inside_macro_call = false;
-                        inside_proc_macro_call = false;
-                    }
                     _ => (),
                 }
             }
@@ -379,12 +343,6 @@ fn traverse(
             }
         };
 
-        if current_macro.is_some() {
-            if let Some(tok) = element.as_token() {
-                macro_highlighter.advance(tok);
-            }
-        }
-
         let element = match element.clone() {
             NodeOrToken::Node(n) => match ast::NameLike::cast(n) {
                 Some(n) => NodeOrToken::Node(n),
@@ -392,7 +350,7 @@ fn traverse(
             },
             NodeOrToken::Token(t) => NodeOrToken::Token(t),
         };
-        let token = element.as_token().cloned();
+        let original_token = element.as_token().cloned();
 
         // Descending tokens into macros is expensive even if no descending occurs, so make sure
         // that we actually are in a position where descending is possible.
@@ -405,144 +363,52 @@ fn traverse(
 
         let descended_element = if in_macro {
             // Attempt to descend tokens into macro-calls.
-            let res = match element {
-                NodeOrToken::Token(token) if token.kind() != COMMENT => {
-                    let ranker = Ranker::from_token(&token);
-
-                    let mut t = None;
-                    let mut r = 0;
-                    sema.descend_into_macros_breakable(
-                        InRealFile::new(file_id, token.clone()),
-                        |tok, _ctx| {
-                            // FIXME: Consider checking ctx transparency for being opaque?
-                            let tok = tok.value;
-                            let my_rank = ranker.rank_token(&tok);
-
-                            if my_rank >= Ranker::MAX_RANK {
-                                // a rank of 0b1110 means that we have found a maximally interesting
-                                // token so stop early.
-                                t = Some(tok);
-                                return ControlFlow::Break(());
-                            }
-
-                            // r = r.max(my_rank);
-                            // t = Some(t.take_if(|_| r < my_rank).unwrap_or(tok));
-                            match &mut t {
-                                Some(prev) if r < my_rank => {
-                                    *prev = tok;
-                                    r = my_rank;
-                                }
-                                Some(_) => (),
-                                None => {
-                                    r = my_rank;
-                                    t = Some(tok)
-                                }
-                            }
-                            ControlFlow::Continue(())
-                        },
-                    );
-
-                    let token = t.unwrap_or(token);
-                    match token.parent().and_then(ast::NameLike::cast) {
-                        // Remap the token into the wrapping single token nodes
-                        Some(parent) => match (token.kind(), parent.syntax().kind()) {
-                            (T![self] | T![ident], NAME | NAME_REF) => NodeOrToken::Node(parent),
-                            (T![self] | T![super] | T![crate] | T![Self], NAME_REF) => {
-                                NodeOrToken::Node(parent)
-                            }
-                            (INT_NUMBER, NAME_REF) => NodeOrToken::Node(parent),
-                            (LIFETIME_IDENT, LIFETIME) => NodeOrToken::Node(parent),
-                            _ => NodeOrToken::Token(token),
-                        },
-                        None => NodeOrToken::Token(token),
-                    }
-                }
-                e => e,
-            };
-            res
+            match element {
+                NodeOrToken::Token(token) => descend_token(sema, InRealFile::new(file_id, token)),
+                n => InFile::new(file_id.into(), n),
+            }
         } else {
-            element
+            InFile::new(file_id.into(), element)
         };
 
-        // FIXME: do proper macro def highlighting https://github.com/rust-lang/rust-analyzer/issues/6232
-        // Skip metavariables from being highlighted to prevent keyword highlighting in them
-        if descended_element.as_token().and_then(|t| macro_highlighter.highlight(t)).is_some() {
-            continue;
+        // string highlight injections
+        if let (Some(original_token), Some(descended_token)) =
+            (original_token, descended_element.value.as_token())
+        {
+            let control_flow = string_injections(
+                hl,
+                sema,
+                config,
+                file_id,
+                krate,
+                original_token,
+                descended_token,
+            );
+            if control_flow.is_break() {
+                continue;
+            }
         }
 
-        // string highlight injections, note this does not use the descended element as proc-macros
-        // can rewrite string literals which invalidates our indices
-        if let (Some(token), Some(descended_token)) = (token, descended_element.as_token()) {
-            if ast::String::can_cast(token.kind()) && ast::String::can_cast(descended_token.kind())
-            {
-                let string = ast::String::cast(token);
-                let string_to_highlight = ast::String::cast(descended_token.clone());
-                if let Some((string, expanded_string)) = string.zip(string_to_highlight) {
-                    if string.is_raw()
-                        && inject::ra_fixture(hl, sema, config, &string, &expanded_string).is_some()
-                    {
-                        continue;
-                    }
-                    highlight_format_string(
-                        hl,
-                        sema,
-                        krate,
-                        &string,
-                        &expanded_string,
-                        range,
-                        file_id.edition(),
-                    );
-
-                    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) {
-                    if !byte_string.is_raw() {
-                        highlight_escape_string(hl, &byte_string, range.start());
-                    }
+        let edition = descended_element.file_id.edition(sema.db);
+        let element = match descended_element.value {
+            NodeOrToken::Node(name_like) => {
+                let hl = highlight::name_like(
+                    sema,
+                    krate,
+                    &mut bindings_shadow_count,
+                    config.syntactic_name_ref_highlighting,
+                    name_like,
+                    edition,
+                );
+                if hl.is_some() && !in_macro {
+                    // skip highlighting the contained token of our name-like node
+                    // as that would potentially overwrite our result
+                    preorder.skip_subtree();
                 }
-            } 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())
-            } else if ast::Byte::can_cast(token.kind())
-                && ast::Byte::can_cast(descended_token.kind())
-            {
-                let Some(byte) = ast::Byte::cast(token) else {
-                    continue;
-                };
-
-                highlight_escape_byte(hl, &byte, range.start())
+                hl
             }
-        }
-
-        let element = match descended_element {
-            NodeOrToken::Node(name_like) => highlight::name_like(
-                sema,
-                krate,
-                &mut bindings_shadow_count,
-                config.syntactic_name_ref_highlighting,
-                name_like,
-                file_id.edition(),
-            ),
             NodeOrToken::Token(token) => {
-                highlight::token(sema, token, file_id.edition()).zip(Some(None))
+                highlight::token(sema, token, edition, tt_level > 0).zip(Some(None))
             }
         };
         if let Some((mut highlight, binding_hash)) = element {
@@ -551,13 +417,6 @@ fn traverse(
                 // let the editor do its highlighting for these tokens instead
                 continue;
             }
-            if highlight.tag == HlTag::UnresolvedReference
-                && matches!(attr_or_derive_item, Some(AttrOrDerive::Derive(_)) if inside_attribute)
-            {
-                // do not emit unresolved references in derive helpers if the token mapping maps to
-                // something unresolvable. FIXME: There should be a way to prevent that
-                continue;
-            }
 
             // apply config filtering
             if !filter_by_config(&mut highlight, config) {
@@ -567,8 +426,9 @@ fn traverse(
             if inside_attribute {
                 highlight |= HlMod::Attribute
             }
-            if inside_macro_call && tt_level > 0 {
-                if inside_proc_macro_call {
+            if let Some(m) = descended_element.file_id.macro_file() {
+                if let MacroKind::ProcMacro | MacroKind::Attr | MacroKind::Derive = m.kind(sema.db)
+                {
                     highlight |= HlMod::ProcMacro
                 }
                 highlight |= HlMod::Macro
@@ -579,6 +439,99 @@ fn traverse(
     }
 }
 
+fn string_injections(
+    hl: &mut Highlights,
+    sema: &Semantics<'_, RootDatabase>,
+    config: HighlightConfig,
+    file_id: EditionedFileId,
+    krate: hir::Crate,
+    token: SyntaxToken,
+    descended_token: &SyntaxToken,
+) -> ControlFlow<()> {
+    if !matches!(token.kind(), STRING | BYTE_STRING | BYTE | CHAR | C_STRING) {
+        return ControlFlow::Continue(());
+    }
+    if let Some(string) = ast::String::cast(token.clone()) {
+        if let Some(descended_string) = ast::String::cast(descended_token.clone()) {
+            if string.is_raw()
+                && inject::ra_fixture(hl, sema, config, &string, &descended_string).is_some()
+            {
+                return ControlFlow::Break(());
+            }
+            highlight_format_string(hl, sema, krate, &string, &descended_string, file_id.edition());
+
+            if !string.is_raw() {
+                highlight_escape_string(hl, &string);
+            }
+        }
+    } else if let Some(byte_string) = ast::ByteString::cast(token.clone()) {
+        if !byte_string.is_raw() {
+            highlight_escape_string(hl, &byte_string);
+        }
+    } else if let Some(c_string) = ast::CString::cast(token.clone()) {
+        if !c_string.is_raw() {
+            highlight_escape_string(hl, &c_string);
+        }
+    } else if let Some(char) = ast::Char::cast(token.clone()) {
+        highlight_escape_char(hl, &char)
+    } else if let Some(byte) = ast::Byte::cast(token) {
+        highlight_escape_byte(hl, &byte)
+    }
+    ControlFlow::Continue(())
+}
+
+fn descend_token(
+    sema: &Semantics<'_, RootDatabase>,
+    token: InRealFile<SyntaxToken>,
+) -> InFile<NodeOrToken<ast::NameLike, SyntaxToken>> {
+    if token.value.kind() == COMMENT {
+        return token.map(NodeOrToken::Token).into();
+    }
+    let ranker = Ranker::from_token(&token.value);
+
+    let mut t = None;
+    let mut r = 0;
+    sema.descend_into_macros_breakable(token.clone(), |tok, _ctx| {
+        // FIXME: Consider checking ctx transparency for being opaque?
+        let my_rank = ranker.rank_token(&tok.value);
+
+        if my_rank >= Ranker::MAX_RANK {
+            // a rank of 0b1110 means that we have found a maximally interesting
+            // token so stop early.
+            t = Some(tok);
+            return ControlFlow::Break(());
+        }
+
+        // r = r.max(my_rank);
+        // t = Some(t.take_if(|_| r < my_rank).unwrap_or(tok));
+        match &mut t {
+            Some(prev) if r < my_rank => {
+                *prev = tok;
+                r = my_rank;
+            }
+            Some(_) => (),
+            None => {
+                r = my_rank;
+                t = Some(tok)
+            }
+        }
+        ControlFlow::Continue(())
+    });
+
+    let token = t.unwrap_or_else(|| token.into());
+    token.map(|token| match token.parent().and_then(ast::NameLike::cast) {
+        // Remap the token into the wrapping single token nodes
+        Some(parent) => match (token.kind(), parent.syntax().kind()) {
+            (T![ident] | T![self], NAME)
+            | (T![ident] | T![self] | T![super] | T![crate] | T![Self], NAME_REF)
+            | (INT_NUMBER, NAME_REF)
+            | (LIFETIME_IDENT, LIFETIME) => NodeOrToken::Node(parent),
+            _ => NodeOrToken::Token(token),
+        },
+        None => NodeOrToken::Token(token),
+    })
+}
+
 fn filter_by_config(highlight: &mut Highlight, config: HighlightConfig) -> bool {
     match &mut highlight.tag {
         HlTag::StringLiteral if !config.strings => return false,
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs
index 552ce9cd8c3..094f88f3a86 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs
@@ -4,12 +4,9 @@ use crate::{HlRange, HlTag};
 use syntax::ast::{Byte, Char, IsString};
 use syntax::{AstToken, TextRange, TextSize};
 
-pub(super) fn highlight_escape_string<T: IsString>(
-    stack: &mut Highlights,
-    string: &T,
-    start: TextSize,
-) {
+pub(super) fn highlight_escape_string<T: IsString>(stack: &mut Highlights, string: &T) {
     let text = string.text();
+    let start = string.syntax().text_range().start();
     string.escaped_char_ranges(&mut |piece_range, char| {
         if text[piece_range.start().into()..].starts_with('\\') {
             let highlight = match char {
@@ -25,7 +22,7 @@ pub(super) fn highlight_escape_string<T: IsString>(
     });
 }
 
-pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char, start: TextSize) {
+pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char) {
     if char.value().is_err() {
         // We do not emit invalid escapes highlighting here. The lexer would likely be in a bad
         // state and this token contains junk, since `'` is not a reliable delimiter (consider
@@ -42,11 +39,14 @@ pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char, start:
         return;
     };
 
-    let range = TextRange::at(start + TextSize::from(1), TextSize::from(text.len() as u32));
+    let range = TextRange::at(
+        char.syntax().text_range().start() + TextSize::from(1),
+        TextSize::from(text.len() as u32),
+    );
     stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None })
 }
 
-pub(super) fn highlight_escape_byte(stack: &mut Highlights, byte: &Byte, start: TextSize) {
+pub(super) fn highlight_escape_byte(stack: &mut Highlights, byte: &Byte) {
     if byte.value().is_err() {
         // See `highlight_escape_char` for why no error highlighting here.
         return;
@@ -61,6 +61,9 @@ pub(super) fn highlight_escape_byte(stack: &mut Highlights, byte: &Byte, start:
         return;
     };
 
-    let range = TextRange::at(start + TextSize::from(2), TextSize::from(text.len() as u32));
+    let range = TextRange::at(
+        byte.syntax().text_range().start() + TextSize::from(2),
+        TextSize::from(text.len() as u32),
+    );
     stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None })
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs
index 43a6bdad7e9..c63043621c2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs
@@ -5,7 +5,7 @@ use ide_db::{
     SymbolKind,
 };
 use span::Edition;
-use syntax::{ast, TextRange};
+use syntax::{ast, AstToken};
 
 use crate::{
     syntax_highlighting::{highlight::highlight_def, highlights::Highlights},
@@ -18,15 +18,15 @@ pub(super) fn highlight_format_string(
     krate: hir::Crate,
     string: &ast::String,
     expanded_string: &ast::String,
-    range: TextRange,
     edition: Edition,
 ) {
     if is_format_string(expanded_string) {
+        let start = string.syntax().text_range().start();
         // FIXME: Replace this with the HIR info we have now.
         lex_format_specifiers(string, &mut |piece_range, kind| {
             if let Some(highlight) = highlight_format_specifier(kind) {
                 stack.add(HlRange {
-                    range: piece_range + range.start(),
+                    range: piece_range + start,
                     highlight: highlight.into(),
                     binding_hash: None,
                 });
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
index 194fde11601..127861a04bd 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
@@ -23,6 +23,7 @@ pub(super) fn token(
     sema: &Semantics<'_, RootDatabase>,
     token: SyntaxToken,
     edition: Edition,
+    in_tt: bool,
 ) -> Option<Highlight> {
     if let Some(comment) = ast::Comment::cast(token.clone()) {
         let h = HlTag::Comment;
@@ -40,13 +41,20 @@ pub(super) fn token(
         INT_NUMBER | FLOAT_NUMBER => HlTag::NumericLiteral.into(),
         BYTE => HlTag::ByteLiteral.into(),
         CHAR => HlTag::CharLiteral.into(),
-        IDENT if token.parent().and_then(ast::TokenTree::cast).is_some() => {
+        IDENT if in_tt => {
             // from this point on we are inside a token tree, this only happens for identifiers
             // that were not mapped down into macro invocations
             HlTag::None.into()
         }
         p if p.is_punct() => punctuation(sema, token, p),
-        k if k.is_keyword(edition) => keyword(sema, token, k)?,
+        k if k.is_keyword(edition) => {
+            if in_tt && token.prev_token().is_some_and(|t| t.kind() == T![$]) {
+                // we are likely within a macro definition where our keyword is a fragment name
+                HlTag::None.into()
+            } else {
+                keyword(sema, token, k)?
+            }
+        }
         _ => return None,
     };
     Some(highlight)
@@ -81,7 +89,7 @@ pub(super) fn name_like(
             Some(IdentClass::NameRefClass(NameRefClass::Definition(def, _))) => {
                 highlight_def(sema, krate, def, edition)
             }
-            // FIXME: Fallback for 'static and '_, as we do not resolve these yet
+            // FIXME: Fallback for '_, as we do not resolve these yet
             _ => SymbolKind::LifetimeParam.into(),
         },
     };
@@ -214,12 +222,6 @@ fn keyword(
         T![true] | T![false] => HlTag::BoolLiteral.into(),
         // crate is handled just as a token if it's in an `extern crate`
         T![crate] if parent_matches::<ast::ExternCrate>(&token) => h,
-        // self, crate, super and `Self` are handled as either a Name or NameRef already, unless they
-        // are inside unmapped token trees
-        T![self] | T![crate] | T![super] | T![Self] if parent_matches::<ast::NameRef>(&token) => {
-            return None
-        }
-        T![self] if parent_matches::<ast::Name>(&token) => return None,
         T![ref] => match token.parent().and_then(ast::IdentPat::cast) {
             Some(ident) if sema.is_unsafe_ident_pat(&ident) => h | HlMod::Unsafe,
             _ => h,
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/macro_.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/macro_.rs
deleted file mode 100644
index b441b4cc90e..00000000000
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/macro_.rs
+++ /dev/null
@@ -1,128 +0,0 @@
-//! Syntax highlighting for macro_rules!.
-use syntax::{SyntaxKind, SyntaxToken, TextRange, T};
-
-use crate::{HlRange, HlTag};
-
-#[derive(Default)]
-pub(super) struct MacroHighlighter {
-    state: Option<MacroMatcherParseState>,
-}
-
-impl MacroHighlighter {
-    pub(super) fn init(&mut self) {
-        self.state = Some(MacroMatcherParseState::default());
-    }
-
-    pub(super) fn advance(&mut self, token: &SyntaxToken) {
-        if let Some(state) = self.state.as_mut() {
-            update_macro_state(state, token);
-        }
-    }
-
-    pub(super) fn highlight(&self, token: &SyntaxToken) -> Option<HlRange> {
-        if let Some(state) = self.state.as_ref() {
-            if matches!(state.rule_state, RuleState::Matcher | RuleState::Expander) {
-                if let Some(range) = is_metavariable(token) {
-                    return Some(HlRange {
-                        range,
-                        highlight: HlTag::UnresolvedReference.into(),
-                        binding_hash: None,
-                    });
-                }
-            }
-        }
-        None
-    }
-}
-
-struct MacroMatcherParseState {
-    /// Opening and corresponding closing bracket of the matcher or expander of the current rule
-    paren_ty: Option<(SyntaxKind, SyntaxKind)>,
-    paren_level: usize,
-    rule_state: RuleState,
-    /// Whether we are inside the outer `{` `}` macro block that holds the rules
-    in_invoc_body: bool,
-}
-
-impl Default for MacroMatcherParseState {
-    fn default() -> Self {
-        MacroMatcherParseState {
-            paren_ty: None,
-            paren_level: 0,
-            in_invoc_body: false,
-            rule_state: RuleState::None,
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq)]
-enum RuleState {
-    Matcher,
-    Expander,
-    Between,
-    None,
-}
-
-impl RuleState {
-    fn transition(&mut self) {
-        *self = match self {
-            RuleState::Matcher => RuleState::Between,
-            RuleState::Expander => RuleState::None,
-            RuleState::Between => RuleState::Expander,
-            RuleState::None => RuleState::Matcher,
-        };
-    }
-}
-
-fn update_macro_state(state: &mut MacroMatcherParseState, tok: &SyntaxToken) {
-    if !state.in_invoc_body {
-        if tok.kind() == T!['{'] || tok.kind() == T!['('] {
-            state.in_invoc_body = true;
-        }
-        return;
-    }
-
-    match state.paren_ty {
-        Some((open, close)) => {
-            if tok.kind() == open {
-                state.paren_level += 1;
-            } else if tok.kind() == close {
-                state.paren_level -= 1;
-                if state.paren_level == 0 {
-                    state.rule_state.transition();
-                    state.paren_ty = None;
-                }
-            }
-        }
-        None => {
-            match tok.kind() {
-                T!['('] => {
-                    state.paren_ty = Some((T!['('], T![')']));
-                }
-                T!['{'] => {
-                    state.paren_ty = Some((T!['{'], T!['}']));
-                }
-                T!['['] => {
-                    state.paren_ty = Some((T!['['], T![']']));
-                }
-                _ => (),
-            }
-            if state.paren_ty.is_some() {
-                state.paren_level = 1;
-                state.rule_state.transition();
-            }
-        }
-    }
-}
-
-fn is_metavariable(token: &SyntaxToken) -> Option<TextRange> {
-    match token.kind() {
-        kind if kind.is_any_identifier() => {
-            if let Some(_dollar) = token.prev_token().filter(|t| t.kind() == T![$]) {
-                return Some(token.text_range());
-            }
-        }
-        _ => (),
-    };
-    None
-}
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html
index 15a6386aa3c..2bc22f960bd 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html
@@ -49,26 +49,26 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword unsafe">unsafe</span> <span class="brace">{</span>
         <span class="keyword">let</span> <span class="variable declaration">foo</span> <span class="operator">=</span> <span class="numeric_literal">1</span><span class="semicolon">;</span>
         <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">o</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
-        <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
+        <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span>
             <span class="string_literal macro">"%input = OpLoad _ {</span><span class="variable">0</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
             <span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"%result = "</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="string_literal macro">" _ %input"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
             <span class="string_literal macro">"OpStore {</span><span class="variable">1</span><span class="string_literal macro">} %result"</span><span class="comma macro">,</span>
             <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="operator macro">&</span><span class="variable macro">foo</span><span class="comma macro">,</span>
             <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="operator macro">&</span><span class="keyword macro">mut</span> <span class="variable macro mutable">o</span><span class="comma macro">,</span>
-        <span class="parenthesis macro">)</span><span class="semicolon">;</span>
+        <span class="parenthesis">)</span><span class="semicolon">;</span>
 
         <span class="keyword">let</span> <span class="variable declaration">thread_id</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
-        <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"
+        <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"
             mov {</span><span class="variable">0</span><span class="string_literal macro">}, gs:[0x30]
             mov {</span><span class="variable">0</span><span class="string_literal macro">}, [{</span><span class="variable">0</span><span class="string_literal macro">}+0x48]
-        "</span><span class="comma macro">,</span> <span class="keyword macro">out</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">thread_id</span><span class="comma macro">,</span> <span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">pure</span><span class="comma macro">,</span> <span class="keyword macro">readonly</span><span class="comma macro">,</span> <span class="keyword macro">nostack</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+        "</span><span class="comma macro">,</span> <span class="keyword macro">out</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">thread_id</span><span class="comma macro">,</span> <span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">pure</span><span class="comma macro">,</span> <span class="keyword macro">readonly</span><span class="comma macro">,</span> <span class="keyword macro">nostack</span><span class="parenthesis macro">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
         <span class="keyword">static</span> <span class="static declaration">UNMAP_BASE</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
         <span class="keyword const">const</span> <span class="constant const declaration">MEM_RELEASE</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
         <span class="keyword">static</span> <span class="static declaration">VirtualFree</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
         <span class="keyword const">const</span> <span class="constant const declaration">OffPtr</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
         <span class="keyword const">const</span> <span class="constant const declaration">OffFn</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
-        <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"
+        <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"
             push {</span><span class="variable">free_type</span><span class="string_literal macro">}
             push {</span><span class="variable">free_size</span><span class="string_literal macro">}
             push {</span><span class="variable">base</span><span class="string_literal macro">}
@@ -92,7 +92,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
             <span class="variable declaration macro">base</span> <span class="operator macro">=</span> <span class="keyword macro">sym</span> <span class="static macro">UNMAP_BASE</span><span class="comma macro">,</span>
             <span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">noreturn</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
-        <span class="parenthesis macro">)</span><span class="semicolon">;</span>
+        <span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
 <span class="comment">// taken from https://github.com/rust-embedded/cortex-m/blob/47921b51f8b960344fcfa1255a50a0d19efcde6d/cortex-m/src/asm.rs#L254-L274</span>
@@ -101,19 +101,19 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="comment">// Ensure thumb mode is set.</span>
     <span class="keyword">let</span> <span class="variable declaration">rv</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="value_param">rv</span> <span class="keyword">as</span> <span class="builtin_type">u32</span><span class="parenthesis">)</span> <span class="bitwise">|</span> <span class="numeric_literal">1</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">msp</span> <span class="operator">=</span> <span class="value_param">msp</span> <span class="keyword">as</span> <span class="builtin_type">u32</span><span class="semicolon">;</span>
-    <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
+    <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span>
         <span class="string_literal macro">"mrs {</span><span class="variable">tmp</span><span class="string_literal macro">}, CONTROL"</span><span class="comma macro">,</span>
         <span class="string_literal macro">"bics {</span><span class="variable">tmp</span><span class="string_literal macro">}, {</span><span class="variable">spsel</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
         <span class="string_literal macro">"msr CONTROL, {</span><span class="variable">tmp</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
         <span class="string_literal macro">"isb"</span><span class="comma macro">,</span>
         <span class="string_literal macro">"msr MSP, {</span><span class="variable">msp</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
         <span class="string_literal macro">"bx {</span><span class="variable">rv</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
-        <span class="comment macro">// `out(reg) _` is not permitted in a `noreturn` asm! call,</span>
-        <span class="comment macro">// so instead use `in(reg) 0` and don't restore it afterwards.</span>
+        <span class="comment">// `out(reg) _` is not permitted in a `noreturn` asm! call,</span>
+        <span class="comment">// so instead use `in(reg) 0` and don't restore it afterwards.</span>
         <span class="variable declaration macro">tmp</span> <span class="operator macro">=</span> <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="numeric_literal macro">0</span><span class="comma macro">,</span>
         <span class="variable declaration macro">spsel</span> <span class="operator macro">=</span> <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="numeric_literal macro">2</span><span class="comma macro">,</span>
         <span class="variable declaration macro">msp</span> <span class="operator macro">=</span> <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">msp</span><span class="comma macro">,</span>
         <span class="variable declaration macro">rv</span> <span class="operator macro">=</span> <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">rv</span><span class="comma macro">,</span>
         <span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">noreturn</span><span class="comma macro">,</span> <span class="keyword macro">nomem</span><span class="comma macro">,</span> <span class="keyword macro">nostack</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
-    <span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
index 485d44f97e1..e1d51dc0b71 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
@@ -45,20 +45,20 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
-<pre><code><span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute">allow</span><span class="parenthesis attribute">(</span><span class="none attribute">dead_code</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="tool_module attribute">rustfmt</span><span class="operator attribute">::</span><span class="tool_module attribute">skip</span><span class="attribute_bracket attribute">]</span>
+<pre><code><span class="attribute_bracket attribute macro proc_macro">#</span><span class="attribute_bracket attribute macro proc_macro">[</span><span class="builtin_attr attribute macro proc_macro">allow</span><span class="parenthesis attribute macro proc_macro">(</span><span class="none attribute macro proc_macro">dead_code</span><span class="parenthesis attribute macro proc_macro">)</span><span class="attribute_bracket attribute macro proc_macro">]</span>
+<span class="attribute_bracket attribute macro proc_macro">#</span><span class="attribute_bracket attribute macro proc_macro">[</span><span class="tool_module attribute macro proc_macro">rustfmt</span><span class="operator attribute macro proc_macro">::</span><span class="tool_module attribute macro proc_macro">skip</span><span class="attribute_bracket attribute macro proc_macro">]</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="module attribute crate_root library">proc_macros</span><span class="operator attribute">::</span><span class="attribute attribute library">identity</span><span class="attribute_bracket attribute">]</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Default</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute macro proc_macro">#</span><span class="attribute_bracket attribute macro proc_macro">[</span><span class="attribute attribute default_library library macro proc_macro">derive</span><span class="parenthesis attribute macro proc_macro">(</span><span class="derive attribute default_library library macro">Default</span><span class="parenthesis attribute macro proc_macro">)</span><span class="attribute_bracket attribute macro proc_macro">]</span>
 <span class="comment documentation">/// This is a doc comment</span>
 <span class="comment">// This is a normal comment</span>
 <span class="comment documentation">/// This is a doc comment</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute macro proc_macro">#</span><span class="attribute_bracket attribute macro proc_macro">[</span><span class="attribute attribute default_library library macro proc_macro">derive</span><span class="parenthesis attribute macro proc_macro">(</span><span class="derive attribute default_library library macro">Copy</span><span class="parenthesis attribute macro proc_macro">)</span><span class="attribute_bracket attribute macro proc_macro">]</span>
 <span class="comment">// This is another normal comment</span>
 <span class="comment documentation">/// This is another doc comment</span>
 <span class="comment">// This is another normal comment</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="comma attribute">,</span> <span class="unresolved_reference attribute">Unresolved</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute macro proc_macro">#</span><span class="attribute_bracket attribute macro proc_macro">[</span><span class="attribute attribute default_library library macro proc_macro">derive</span><span class="parenthesis attribute macro proc_macro">(</span><span class="derive attribute default_library library macro">Copy</span><span class="comma attribute macro proc_macro">,</span> <span class="unresolved_reference attribute macro">Unresolved</span><span class="parenthesis attribute macro proc_macro">)</span><span class="attribute_bracket attribute macro proc_macro">]</span>
 <span class="comment">// The reason for these being here is to test AttrIds</span>
-<span class="keyword">enum</span> <span class="enum declaration">Foo</span> <span class="brace">{</span>
-    <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="derive_helper attribute default_library library">default</span><span class="attribute_bracket attribute">]</span>
-    <span class="enum_variant declaration">Bar</span>
-<span class="brace">}</span></code></pre>
\ No newline at end of file
+<span class="keyword macro proc_macro">enum</span> <span class="enum declaration macro proc_macro">Foo</span> <span class="brace macro proc_macro">{</span>
+    <span class="attribute_bracket attribute macro proc_macro">#</span><span class="attribute_bracket attribute macro proc_macro">[</span><span class="derive_helper attribute default_library library macro proc_macro">default</span><span class="attribute_bracket attribute macro proc_macro">]</span>
+    <span class="enum_variant declaration macro proc_macro">Bar</span>
+<span class="brace macro proc_macro">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html
index c6eab90e42b..af29af3f03c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html
@@ -53,9 +53,9 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="brace">}</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
-    <span class="macro public">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro public">Foo</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">foo</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="struct declaration macro public">Foo</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="keyword">mod</span> <span class="module declaration">module</span> <span class="brace">{</span>
-        <span class="macro public">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro public">Bar</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+        <span class="macro public">foo</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="struct declaration macro public">Bar</span><span class="parenthesis">)</span><span class="semicolon">;</span>
         <span class="keyword">fn</span> <span class="function declaration">func</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="module">y</span><span class="operator">::</span><span class="struct public">Bar</span><span class="parenthesis">)</span> <span class="brace">{</span>
             <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span>
                 <span class="keyword">struct</span> <span class="struct declaration">Innerest</span><span class="angle">&lt;</span><span class="keyword">const</span> <span class="const_param const declaration">C</span><span class="colon">:</span> <span class="unresolved_reference">usize</span><span class="angle">&gt;</span> <span class="brace">{</span> <span class="field declaration">field</span><span class="colon">:</span> <span class="bracket">[</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="brace">{</span><span class="const_param const">C</span><span class="brace">}</span><span class="bracket">]</span> <span class="brace">}</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html
index 96cdb532dd5..6d8f6b3c6e3 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html
@@ -57,7 +57,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword const">const</span> <span class="brace">{</span>
         <span class="keyword">const</span> <span class="punctuation">|</span><span class="punctuation">|</span> <span class="brace">{</span><span class="brace">}</span>
     <span class="brace">}</span>
-    <span class="macro public">id</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
+    <span class="macro public">id</span><span class="macro_bang">!</span><span class="parenthesis">(</span>
         <span class="constant const macro">CONST_ITEM</span><span class="semicolon macro">;</span>
         <span class="const_param const macro">CONST_PARAM</span><span class="semicolon macro">;</span>
         <span class="keyword const macro">const</span> <span class="brace macro">{</span>
@@ -65,7 +65,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
         <span class="brace macro">}</span><span class="semicolon macro">;</span>
         <span class="operator macro">&</span><span class="keyword macro">raw</span> <span class="keyword macro">const</span> <span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon macro">;</span>
         <span class="keyword macro">const</span>
-    <span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="operator">.</span><span class="method const consuming trait">assoc_const_method</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 <span class="keyword">trait</span> <span class="trait declaration">ConstTrait</span> <span class="brace">{</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index eb77c14c2a5..263e4545fb5 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -105,7 +105,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">foo</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
     <span class="comment documentation">///</span>
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="comment injected">// calls bar on foo</span>
-    <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="macro injected">assert</span><span class="macro_bang injected">!</span><span class="parenthesis injected macro">(</span><span class="none injected macro">foo</span><span class="operator injected macro">.</span><span class="none injected macro">bar</span><span class="parenthesis injected macro">(</span><span class="parenthesis injected macro">)</span><span class="parenthesis injected macro">)</span><span class="semicolon injected">;</span>
+    <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="macro injected">assert</span><span class="macro_bang injected">!</span><span class="parenthesis injected">(</span><span class="none injected">foo</span><span class="operator injected">.</span><span class="none injected">bar</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
     <span class="comment documentation">///</span>
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">bar</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="variable injected">foo</span><span class="operator injected">.</span><span class="field injected">bar</span><span class="none injected"> </span><span class="logical injected">||</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="constant injected">bar</span><span class="semicolon injected">;</span>
     <span class="comment documentation">///</span>
@@ -156,8 +156,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="comment documentation">/// ```</span>
-<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">macro_rules</span><span class="macro_bang injected">!</span><span class="none injected"> </span><span class="macro declaration injected public">noop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="parenthesis injected">(</span><span class="punctuation injected">$</span><span class="none injected">expr</span><span class="colon injected">:</span><span class="none injected">expr</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="operator injected">=</span><span class="operator injected">&gt;</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="punctuation injected">$</span><span class="none injected">expr </span><span class="brace injected">}</span><span class="brace injected">}</span>
-<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="macro injected public">noop</span><span class="macro_bang injected">!</span><span class="parenthesis injected macro">(</span><span class="numeric_literal injected macro">1</span><span class="parenthesis injected macro">)</span><span class="semicolon injected">;</span>
+<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">macro_rules</span><span class="macro_bang injected">!</span><span class="none injected"> </span><span class="macro declaration injected public">noop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="parenthesis injected">(</span><span class="punctuation injected">$</span><span class="none injected">expr</span><span class="colon injected">:</span><span class="none injected">expr</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="operator injected">=</span><span class="operator injected">&gt;</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="punctuation injected">$</span><span class="none injected">expr</span><span class="none injected"> </span><span class="brace injected">}</span><span class="brace injected">}</span>
+<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="macro injected public">noop</span><span class="macro_bang injected">!</span><span class="parenthesis injected">(</span><span class="numeric_literal injected macro">1</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
 <span class="comment documentation">/// ```</span>
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">noop</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>
@@ -177,7 +177,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="comment documentation">///</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute">cfg_attr</span><span class="parenthesis attribute">(</span><span class="none attribute">feature</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"alloc"</span><span class="comma attribute">,</span> <span class="none attribute">doc</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"```rust"</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute">cfg_attr</span><span class="parenthesis attribute">(</span><span class="none attribute">not</span><span class="parenthesis attribute">(</span><span class="none attribute">feature</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"alloc"</span><span class="parenthesis attribute">)</span><span class="comma attribute">,</span> <span class="none attribute">doc</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"```ignore"</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
-<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="punctuation injected">_</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="function injected">example</span><span class="parenthesis injected">(</span><span class="operator injected">&</span><span class="module injected">alloc</span><span class="operator injected">::</span><span class="macro injected">vec</span><span class="macro_bang injected">!</span><span class="bracket injected macro">[</span><span class="numeric_literal injected macro">1</span><span class="comma injected macro">,</span><span class="none injected"> </span><span class="numeric_literal injected macro">2</span><span class="comma injected macro">,</span><span class="none injected"> </span><span class="numeric_literal injected macro">3</span><span class="bracket injected macro">]</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
+<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="punctuation injected">_</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="function injected">example</span><span class="parenthesis injected">(</span><span class="operator injected">&</span><span class="module injected">alloc</span><span class="operator injected">::</span><span class="macro injected">vec</span><span class="macro_bang injected">!</span><span class="bracket injected">[</span><span class="numeric_literal injected">1</span><span class="comma injected">,</span><span class="none injected"> </span><span class="numeric_literal injected">2</span><span class="comma injected">,</span><span class="none injected"> </span><span class="numeric_literal injected">3</span><span class="bracket injected">]</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
 <span class="comment documentation">/// ```</span>
 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration public">mix_and_match</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
index 9477d0d1b87..eb532a5639d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
@@ -78,7 +78,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
 <span class="keyword">use</span> <span class="self_keyword crate_root public">self</span><span class="operator">::</span><span class="struct">FooCopy</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="struct declaration">BarCopy</span><span class="brace">}</span><span class="semicolon">;</span>
 
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library macro">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="brace">{</span>
     <span class="field declaration">x</span><span class="colon">:</span> <span class="builtin_type">u32</span><span class="comma">,</span>
 <span class="brace">}</span>
@@ -151,7 +151,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword">let</span> <span class="variable callable declaration">bar</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="operator">::</span><span class="method associated consuming">baz</span><span class="semicolon">;</span>
 
     <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="numeric_literal">-</span><span class="numeric_literal">42</span><span class="comma">,</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="operator">.</span><span class="field">0</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="operator">.</span><span class="field library">0</span><span class="semicolon">;</span>
 
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="logical">!</span><span class="bool_literal">true</span><span class="semicolon">;</span>
 
@@ -170,7 +170,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="keyword">impl</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="angle">&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">T</span><span class="angle">&gt;</span> <span class="brace">{</span>
     <span class="keyword">fn</span> <span class="method associated consuming declaration">and</span><span class="angle">&lt;</span><span class="type_param declaration">U</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">other</span><span class="colon">:</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">U</span><span class="angle">&gt;</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="comma">,</span> <span class="type_param">U</span><span class="parenthesis">)</span><span class="angle">&gt;</span> <span class="brace">{</span>
         <span class="keyword control">match</span> <span class="value_param">other</span> <span class="brace">{</span>
-            <span class="enum_variant">None</span> <span class="operator">=&gt;</span> <span class="unresolved_reference">unimplemented</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma">,</span>
+            <span class="enum_variant">None</span> <span class="operator">=&gt;</span> <span class="unresolved_reference">unimplemented</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span>
             <span class="variable declaration">Nope</span> <span class="operator">=&gt;</span> <span class="variable">Nope</span><span class="comma">,</span>
         <span class="brace">}</span>
     <span class="brace">}</span>
@@ -184,7 +184,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="keyword async">async</span> <span class="keyword">fn</span> <span class="function async declaration">async_main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
     <span class="keyword">let</span> <span class="variable declaration">f1</span> <span class="operator">=</span> <span class="function async">learn_and_sing</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">f2</span> <span class="operator">=</span> <span class="unresolved_reference">dance</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="unresolved_reference">futures</span><span class="operator">::</span><span class="unresolved_reference">join</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">f1</span><span class="comma macro">,</span> <span class="none macro">f2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="unresolved_reference">futures</span><span class="operator">::</span><span class="unresolved_reference">join</span><span class="macro_bang">!</span><span class="parenthesis">(</span>f1<span class="comma">,</span> f2<span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="keyword">fn</span> <span class="function declaration">use_foo_items</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
@@ -196,7 +196,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword">let</span> <span class="variable declaration">control_flow</span> <span class="operator">=</span> <span class="module crate_root library">foo</span><span class="operator">::</span><span class="function library">identity</span><span class="parenthesis">(</span><span class="module crate_root library">foo</span><span class="operator">::</span><span class="enum library">ControlFlow</span><span class="operator">::</span><span class="enum_variant library">Continue</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
     <span class="keyword control">if</span> <span class="variable">control_flow</span><span class="operator">.</span><span class="method consuming library">should_die</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
-        <span class="module crate_root library">foo</span><span class="operator">::</span><span class="unresolved_reference">die</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+        <span class="module crate_root library">foo</span><span class="operator">::</span><span class="unresolved_reference">die</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
index 5fbed35192b..1f9422161de 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
@@ -51,7 +51,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r#"</span><span class="none injected">
 </span><span class="keyword injected">trait</span><span class="none injected"> </span><span class="trait declaration injected">Foo</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected">
     </span><span class="keyword injected">fn</span><span class="none injected"> </span><span class="function associated declaration injected static trait">foo</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected">
-        </span><span class="unresolved_reference injected">println</span><span class="macro_bang injected">!</span><span class="parenthesis injected macro">(</span><span class="string_literal injected macro">"2 + 2 = {}"</span><span class="comma injected macro">,</span><span class="none injected"> </span><span class="numeric_literal injected macro">4</span><span class="parenthesis injected macro">)</span><span class="semicolon injected">;</span><span class="none injected">
+        </span><span class="unresolved_reference injected">println</span><span class="macro_bang injected">!</span><span class="parenthesis injected">(</span><span class="string_literal injected">"2 + 2 = {}"</span><span class="comma injected">,</span><span class="none injected"> </span><span class="numeric_literal injected">4</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span><span class="none injected">
     </span><span class="brace injected">}</span><span class="none injected">
 </span><span class="brace injected">}</span><span class="string_literal">"#</span>
     <span class="parenthesis">)</span><span class="semicolon">;</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html
index 06817af1b1f..a846addba3f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html
@@ -46,8 +46,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
-    <span class="macro public">template</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">template</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">template</span><span class="macro_bang">!</span><span class="parenthesis">(</span>template<span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="module attribute crate_root library">proc_macros</span><span class="operator attribute">::</span><span class="attribute attribute library">issue_18089</span><span class="attribute_bracket attribute">]</span>
-<span class="keyword">fn</span> <span class="macro declaration public">template</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span></code></pre>
\ No newline at end of file
+<span class="keyword macro proc_macro">fn</span> <span class="macro declaration macro proc_macro public">template</span><span class="parenthesis macro proc_macro">(</span><span class="parenthesis macro proc_macro">)</span> <span class="brace macro proc_macro">{</span><span class="brace macro proc_macro">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html
index 2d3407dbcda..c3377614d72 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html
@@ -54,21 +54,21 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">void</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>discard<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span>
 <span class="keyword">fn</span> <span class="function declaration">__</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="unresolved_reference">Self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">Self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
 <span class="comment">// edition dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">try</span> <span class="none macro">async</span> <span class="none macro">await</span> <span class="none macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">try</span> <span class="none macro">async</span> <span class="none macro">await</span> <span class="none macro">gen</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// edition and context dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">dyn</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// builtin custom syntax</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// contextual</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// reserved</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre>
\ No newline at end of file
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span>'static 'self 'unsafe<span class="parenthesis">)</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html
index f8eb5d068a8..9b22500396b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html
@@ -54,21 +54,21 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">void</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>discard<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span>
 <span class="keyword">fn</span> <span class="function declaration">__</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="unresolved_reference">Self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">Self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
 <span class="comment">// edition dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// edition and context dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">dyn</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// builtin custom syntax</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// contextual</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// reserved</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre>
\ No newline at end of file
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span>'static 'self 'unsafe<span class="parenthesis">)</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html
index f8eb5d068a8..9b22500396b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html
@@ -54,21 +54,21 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">void</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>discard<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span>
 <span class="keyword">fn</span> <span class="function declaration">__</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="unresolved_reference">Self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">Self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
 <span class="comment">// edition dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// edition and context dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">dyn</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// builtin custom syntax</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// contextual</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// reserved</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre>
\ No newline at end of file
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span>'static 'self 'unsafe<span class="parenthesis">)</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html
index fca84017069..ac8353120e8 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html
@@ -54,21 +54,21 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">void</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>discard<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span>
 <span class="keyword">fn</span> <span class="function declaration">__</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="unresolved_reference">Self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">Self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
 <span class="comment">// edition dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="keyword macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="keyword macro">gen</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// edition and context dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">dyn</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// builtin custom syntax</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// contextual</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// reserved</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre>
\ No newline at end of file
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span>'static 'self 'unsafe<span class="parenthesis">)</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html
new file mode 100644
index 00000000000..694e54d2fa8
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html
@@ -0,0 +1,50 @@
+
+<style>
+body                { margin: 0; }
+pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
+
+.lifetime           { color: #DFAF8F; font-style: italic; }
+.label              { color: #DFAF8F; font-style: italic; }
+.comment            { color: #7F9F7F; }
+.documentation      { color: #629755; }
+.intra_doc_link     { font-style: italic; }
+.injected           { opacity: 0.65 ; }
+.struct, .enum      { color: #7CB8BB; }
+.enum_variant       { color: #BDE0F3; }
+.string_literal     { color: #CC9393; }
+.field              { color: #94BFF3; }
+.function           { color: #93E0E3; }
+.function.unsafe    { color: #BC8383; }
+.trait.unsafe       { color: #BC8383; }
+.operator.unsafe    { color: #BC8383; }
+.mutable.unsafe     { color: #BC8383; text-decoration: underline; }
+.keyword.unsafe     { color: #BC8383; font-weight: bold; }
+.macro.unsafe       { color: #BC8383; }
+.parameter          { color: #94BFF3; }
+.text               { color: #DCDCCC; }
+.type               { color: #7CB8BB; }
+.builtin_type       { color: #8CD0D3; }
+.type_param         { color: #DFAF8F; }
+.attribute          { color: #94BFF3; }
+.numeric_literal    { color: #BFEBBF; }
+.bool_literal       { color: #BFE6EB; }
+.macro              { color: #94BFF3; }
+.proc_macro         { color: #94BFF3; text-decoration: underline; }
+.derive             { color: #94BFF3; font-style: italic; }
+.module             { color: #AFD8AF; }
+.value_param        { color: #DCDCCC; }
+.variable           { color: #DCDCCC; }
+.format_specifier   { color: #CC696B; }
+.mutable            { text-decoration: underline; }
+.escape_sequence    { color: #94BFF3; }
+.keyword            { color: #F0DFAF; font-weight: bold; }
+.control            { font-style: italic; }
+.reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
+
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
+</style>
+<pre><code><span class="module crate_root library">lib2015</span><span class="operator">::</span><span class="macro library">void_2015</span><span class="macro_bang">!</span><span class="parenthesis">(</span>try async await <span class="none macro">gen</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+<span class="module crate_root library">lib2024</span><span class="operator">::</span><span class="macro library">void_2024</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+</code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
index f640a5e6ca7..f224435e961 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
@@ -47,21 +47,21 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 </style>
 <pre><code><span class="keyword">use</span> <span class="module crate_root library">proc_macros</span><span class="operator">::</span><span class="brace">{</span><span class="function library">mirror</span><span class="comma">,</span> <span class="function library">identity</span><span class="comma">,</span> <span class="derive library">DeriveIdentity</span><span class="brace">}</span><span class="semicolon">;</span>
 
-<span class="proc_macro library">mirror</span><span class="macro_bang">!</span> <span class="brace macro proc_macro">{</span>
+<span class="proc_macro library">mirror</span><span class="macro_bang">!</span> <span class="brace">{</span>
     <span class="brace macro proc_macro">{</span>
         <span class="comma macro proc_macro">,</span><span class="builtin_type macro proc_macro">i32</span> <span class="colon macro proc_macro">:</span><span class="field declaration macro proc_macro public">x</span> <span class="keyword macro proc_macro">pub</span>
         <span class="comma macro proc_macro">,</span><span class="builtin_type macro proc_macro">i32</span> <span class="colon macro proc_macro">:</span><span class="field declaration macro proc_macro public">y</span> <span class="keyword macro proc_macro">pub</span>
     <span class="brace macro proc_macro">}</span> <span class="struct declaration macro proc_macro">Foo</span> <span class="keyword macro proc_macro">struct</span>
-<span class="brace macro proc_macro">}</span>
+<span class="brace">}</span>
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">def_fn</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="brace">}</span>
 <span class="brace">}</span>
 
-<span class="macro public">def_fn</span><span class="macro_bang">!</span> <span class="brace macro">{</span>
+<span class="macro public">def_fn</span><span class="macro_bang">!</span> <span class="brace">{</span>
     <span class="keyword macro">fn</span> <span class="function declaration macro">bar</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="operator macro">-</span><span class="operator macro">&gt;</span> <span class="builtin_type macro">u32</span> <span class="brace macro">{</span>
         <span class="numeric_literal macro">100</span>
     <span class="brace macro">}</span>
-<span class="brace macro">}</span>
+<span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">dont_color_me_braces</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="numeric_literal">0</span><span class="brace">}</span>
@@ -100,16 +100,16 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="brace">}</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
-<span class="macro default_library library">include</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"foo/"</span><span class="comma macro">,</span> <span class="string_literal macro">"foo.rs"</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro default_library library">include</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"foo/"</span><span class="comma macro">,</span> <span class="string_literal macro">"foo.rs"</span><span class="parenthesis macro">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">S</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
     <span class="keyword">struct</span> <span class="struct declaration">TestLocal</span><span class="semicolon">;</span>
     <span class="comment">// regression test, TestLocal here used to not resolve</span>
-    <span class="keyword">let</span> <span class="punctuation">_</span><span class="colon">:</span> <span class="struct">S</span><span class="angle">&lt;</span><span class="macro public">id</span><span class="macro_bang">!</span><span class="bracket macro">[</span><span class="struct macro">TestLocal</span><span class="bracket macro">]</span><span class="angle">&gt;</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="punctuation">_</span><span class="colon">:</span> <span class="struct">S</span><span class="angle">&lt;</span><span class="macro public">id</span><span class="macro_bang">!</span><span class="bracket">[</span><span class="struct macro">TestLocal</span><span class="bracket">]</span><span class="angle">&gt;</span><span class="semicolon">;</span>
 
-    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">92</span><span class="comma macro">,</span><span class="parenthesis macro">)</span><span class="operator macro">.</span><span class="field library macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">dont_color_me_braces</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">noop</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro macro public">noop</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">92</span><span class="comma macro">,</span><span class="parenthesis macro">)</span><span class="operator macro">.</span><span class="field library macro">0</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">dont_color_me_braces</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">noop</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="macro macro public">noop</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 </code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index 1794d7dbfe2..539c74f6b57 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -99,86 +99,86 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
     <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="byte_literal">b'</span><span class="escape_sequence">\xFF</span><span class="byte_literal">'</span><span class="semicolon">;</span>
 
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>                 <span class="comment">// =&gt; "Hello"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "Hello, world!"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"The number is </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "The number is 1"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>          <span class="comment">// =&gt; "(3, 4)"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">value</span><span class="operator macro">=</span><span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>      <span class="comment">// =&gt; "4"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>           <span class="comment">// =&gt; "1 2"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">42</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>             <span class="comment">// =&gt; "0042" with leading zerosV</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "2 1 1 2"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">argument</span> <span class="operator macro">=</span> <span class="string_literal macro">"test"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "test"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span> <span class="operator macro">=</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>          <span class="comment">// =&gt; "2 1"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">a</span><span class="operator macro">=</span><span class="string_literal macro">"a"</span><span class="comma macro">,</span> <span class="variable declaration macro">b</span><span class="operator macro">=</span><span class="char_literal macro">'b'</span><span class="comma macro">,</span> <span class="variable declaration macro">c</span><span class="operator macro">=</span><span class="numeric_literal macro">3</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>  <span class="comment">// =&gt; "a 3 b"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>                       <span class="comment">// =&gt; "{2}"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">width</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">-</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">^</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">+</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">-</span><span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span>    <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span>   <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">prec</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="variable declaration macro">number</span> <span class="operator macro">=</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 fractional digits"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="numeric_literal macro">1234.56</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 right-aligned characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello"</span><span class="parenthesis">)</span><span class="semicolon">;</span>                 <span class="comment">// =&gt; "Hello"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "Hello, world!"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"The number is </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "The number is 1"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>          <span class="comment">// =&gt; "(3, 4)"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">value</span><span class="operator macro">=</span><span class="numeric_literal macro">4</span><span class="parenthesis">)</span><span class="semicolon">;</span>      <span class="comment">// =&gt; "4"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis">)</span><span class="semicolon">;</span>           <span class="comment">// =&gt; "1 2"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">42</span><span class="parenthesis">)</span><span class="semicolon">;</span>             <span class="comment">// =&gt; "0042" with leading zerosV</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "2 1 1 2"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">argument</span> <span class="operator macro">=</span> <span class="string_literal macro">"test"</span><span class="parenthesis">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "test"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span> <span class="operator macro">=</span> <span class="numeric_literal macro">2</span><span class="parenthesis">)</span><span class="semicolon">;</span>          <span class="comment">// =&gt; "2 1"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">a</span><span class="operator macro">=</span><span class="string_literal macro">"a"</span><span class="comma macro">,</span> <span class="variable declaration macro">b</span><span class="operator macro">=</span><span class="char_literal macro">'b'</span><span class="comma macro">,</span> <span class="variable declaration macro">c</span><span class="operator macro">=</span><span class="numeric_literal macro">3</span><span class="parenthesis">)</span><span class="semicolon">;</span>  <span class="comment">// =&gt; "a 3 b"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis">)</span><span class="semicolon">;</span>                       <span class="comment">// =&gt; "{2}"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">width</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">-</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">^</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">+</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">-</span><span class="numeric_literal macro">5</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span>    <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span>   <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">prec</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="variable declaration macro">number</span> <span class="operator macro">=</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 fractional digits"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="numeric_literal macro">1234.56</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 right-aligned characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"{}"</span>
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"{{}}"</span><span class="semicolon">;</span>
 
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">r"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">r"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
     <span class="comment">// escape sequences</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal macro">World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">\u{48}</span><span class="escape_sequence">\x65</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6F</span><span class="string_literal macro"> World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal macro">World"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">\u{48}</span><span class="escape_sequence">\x65</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6F</span><span class="string_literal macro"> World"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="invalid_escape_sequence">\xFF</span><span class="escape_sequence">\u{FF}</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// invalid non-UTF8 escape sequences</span>
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">b"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="escape_sequence">\xFF</span><span class="invalid_escape_sequence">\u{FF}</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// valid bytes, invalid unicodes</span>
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">c"</span><span class="escape_sequence">\u{FF}</span><span class="escape_sequence">\xFF</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// valid bytes, valid unicodes</span>
     <span class="keyword">let</span> <span class="variable declaration reference">backslash</span> <span class="operator">=</span> <span class="string_literal">r"\\"</span><span class="semicolon">;</span>
 
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">ничоси</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">ничоси</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">x</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> "</span><span class="comma macro">,</span> <span class="unresolved_reference macro">thingy</span><span class="comma macro">,</span> <span class="unresolved_reference macro">n2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro default_library library">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro default_library library">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"more </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro default_library library">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro default_library library">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> asdasd"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">toho</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">x</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> "</span><span class="comma macro">,</span> <span class="unresolved_reference macro">thingy</span><span class="comma macro">,</span> <span class="unresolved_reference macro">n2</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">panic</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">panic</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"more </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">assert</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="bool_literal macro">true</span><span class="comma">,</span> <span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">assert</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="bool_literal macro">true</span><span class="comma">,</span> <span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> asdasd"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">toho</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"{}fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">i</span><span class="colon">:</span> <span class="builtin_type">u64</span> <span class="operator">=</span> <span class="numeric_literal">3</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">o</span><span class="colon">:</span> <span class="builtin_type">u64</span><span class="semicolon">;</span>
-    <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
+    <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span>
         <span class="string_literal macro">"mov {</span><span class="variable">0</span><span class="string_literal macro">}, {</span><span class="variable">1</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
         <span class="string_literal macro">"add {</span><span class="variable">0</span><span class="string_literal macro">}, 5"</span><span class="comma macro">,</span>
         <span class="keyword macro">out</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">o</span><span class="comma macro">,</span>
         <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">i</span><span class="comma macro">,</span>
-    <span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="parenthesis">)</span><span class="semicolon">;</span>
 
     <span class="keyword const">const</span> <span class="constant const declaration">CONSTANT</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="colon">:</span>
     <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">m</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">CONSTANT</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">m</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="macro default_library library macro">format_args</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="macro macro public">toho</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">reuse_twice</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">CONSTANT</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">m</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="macro default_library library macro">format_args</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="macro macro public">toho</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">reuse_twice</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index d9beac30898..9a46d9f4025 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -92,13 +92,13 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="punctuation">_</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">u</span> <span class="operator">=</span> <span class="union">Union</span> <span class="brace">{</span> <span class="field">b</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="semicolon">;</span>
 
-    <span class="macro public">id</span><span class="macro_bang">!</span> <span class="brace macro">{</span>
+    <span class="macro public">id</span><span class="macro_bang">!</span> <span class="brace">{</span>
         <span class="keyword macro unsafe">unsafe</span> <span class="brace macro">{</span> <span class="macro macro public unsafe">unsafe_deref</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="brace macro">}</span>
-    <span class="brace macro">}</span><span class="semicolon">;</span>
+    <span class="brace">}</span><span class="semicolon">;</span>
 
     <span class="keyword unsafe">unsafe</span> <span class="brace">{</span>
-        <span class="macro public unsafe">unsafe_deref</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-        <span class="macro public unsafe">id</span><span class="macro_bang">!</span> <span class="brace macro">{</span> <span class="macro macro public unsafe">unsafe_deref</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="brace macro">}</span><span class="semicolon">;</span>
+        <span class="macro public unsafe">unsafe_deref</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+        <span class="macro public unsafe">id</span><span class="macro_bang">!</span> <span class="brace">{</span> <span class="macro macro public unsafe">unsafe_deref</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="brace">}</span><span class="semicolon">;</span>
 
         <span class="comment">// unsafe fn and method calls</span>
         <span class="function unsafe">unsafe_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
index 3775265f234..e48ca86c46b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
@@ -386,7 +386,7 @@ mod __ {
 }
 
 macro_rules! void {
-    ($($tt:tt)*) => {}
+    ($($tt:tt)*) => {discard!($($tt:tt)*)}
 }
 
 struct __ where Self:;
@@ -412,6 +412,31 @@ void!('static 'self 'unsafe)
 }
 
 #[test]
+fn test_keyword_macro_edition_highlighting() {
+    check_highlighting(
+        r#"
+//- /main.rs crate:main edition:2018 deps:lib2015,lib2024
+lib2015::void_2015!(try async await gen);
+lib2024::void_2024!(try async await gen);
+//- /lib2015.rs crate:lib2015 edition:2015
+#[macro_export]
+macro_rules! void_2015 {
+    ($($tt:tt)*) => {discard!($($tt:tt)*)}
+}
+
+//- /lib2024.rs crate:lib2024 edition:2024
+#[macro_export]
+macro_rules! void_2024 {
+    ($($tt:tt)*) => {discard!($($tt:tt)*)}
+}
+
+"#,
+        expect_file![format!("./test_data/highlight_keywords_macros.html")],
+        false,
+    );
+}
+
+#[test]
 fn test_string_highlighting() {
     // The format string detection is based on macro-expansion,
     // thus, we have to copy the macro definition from `std`
diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
index 79900425a17..e56e09eeb66 100644
--- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
@@ -147,9 +147,6 @@ pub enum SyntaxKind {
     C_STRING,
     FLOAT_NUMBER,
     INT_NUMBER,
-    RAW_BYTE_STRING,
-    RAW_C_STRING,
-    RAW_STRING,
     STRING,
     COMMENT,
     ERROR,
@@ -343,9 +340,6 @@ impl SyntaxKind {
             | C_STRING
             | FLOAT_NUMBER
             | INT_NUMBER
-            | RAW_BYTE_STRING
-            | RAW_C_STRING
-            | RAW_STRING
             | STRING
             | ABI
             | ADT
@@ -898,18 +892,7 @@ impl SyntaxKind {
         )
     }
     pub fn is_literal(self) -> bool {
-        matches!(
-            self,
-            BYTE | BYTE_STRING
-                | CHAR
-                | C_STRING
-                | FLOAT_NUMBER
-                | INT_NUMBER
-                | RAW_BYTE_STRING
-                | RAW_C_STRING
-                | RAW_STRING
-                | STRING
-        )
+        matches!(self, BYTE | BYTE_STRING | CHAR | C_STRING | FLOAT_NUMBER | INT_NUMBER | STRING)
     }
     pub fn from_keyword(ident: &str, edition: Edition) -> Option<SyntaxKind> {
         let kw = match ident {
diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram
index bbb8413cbc0..88d7beb897e 100644
--- a/src/tools/rust-analyzer/crates/syntax/rust.ungram
+++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram
@@ -438,9 +438,9 @@ MacroExpr =
 Literal =
   Attr* value:(
     '@int_number' | '@float_number'
-  | '@string' | '@raw_string'
-  | '@byte_string' | '@raw_byte_string'
-  | '@c_string' | '@raw_c_string'
+  | '@string'
+  | '@byte_string'
+  | '@c_string'
   | '@char' | '@byte'
   | 'true' | 'false'
   )
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
index daeb56c5835..7240069753e 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
@@ -218,16 +218,11 @@ impl FixtureWithProjectMeta {
                 );
             }
 
-            if line.starts_with("//-") {
+            if let Some(line) = line.strip_prefix("//-") {
                 let meta = Self::parse_meta_line(line);
                 res.push(meta);
             } else {
-                if line.starts_with("// ")
-                    && line.contains(':')
-                    && !line.contains("::")
-                    && !line.contains('.')
-                    && line.chars().all(|it| !it.is_uppercase())
-                {
+                if matches!(line.strip_prefix("// "), Some(l) if l.trim().starts_with('/')) {
                     panic!("looks like invalid metadata line: {line:?}");
                 }
 
@@ -242,8 +237,7 @@ impl FixtureWithProjectMeta {
 
     //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
     fn parse_meta_line(meta: &str) -> Fixture {
-        assert!(meta.starts_with("//-"));
-        let meta = meta["//-".len()..].trim();
+        let meta = meta.trim();
         let mut components = meta.split_ascii_whitespace();
 
         let path = components.next().expect("fixture meta must start with a path").to_owned();