Repository: rust-analyzer/rust-analyzer
Pull request #10412 (2021-10-01 10:35:00)

feat: highlight `asm!` as format string
![screenshot-2021-10-01-12:34:31](https://user-images.githubusercontent.com/1786438/135606261-a1cb6caf-0a7f-45f7-9dde-0275370b0889.png)

part of https://github.com/rust-analyzer/rust-analyzer/issues/10394

bors r+


Patch:
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 3d63e05195..a4ddafbf7a 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -267,13 +267,30 @@ fn format_args_expand(
 fn asm_expand(
     _db: &dyn AstDatabase,
     _id: MacroCallId,
-    _tt: &tt::Subtree,
+    tt: &tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
-    // both asm and llvm_asm don't return anything, so we can expand them to nothing,
-    // for now
-    let expanded = quote! {
+    // We expand all assembly snippets to `format_args!` invocations to get format syntax
+    // highlighting for them.
+
+    let krate = tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() };
+
+    let mut literals = Vec::new();
+    for tt in tt.token_trees.chunks(2) {
+        match tt {
+            [tt::TokenTree::Leaf(tt::Leaf::Literal(lit))]
+            | [tt::TokenTree::Leaf(tt::Leaf::Literal(lit)), tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', id: _, spacing: _ }))] =>
+            {
+                let krate = krate.clone();
+                literals.push(quote!(#krate::format_args!(#lit);));
+            }
+            _ => break,
+        }
+    }
+
+    let expanded = quote! {{
+        ##literals
         ()
-    };
+    }};
     ExpandResult::ok(expanded)
 }
 


Test patch:
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index f6d9d9aa14..4f67c4316a 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -82,6 +82,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">panic</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute">rustc_builtin_macro</span><span class="attribute attribute">]</span>
 <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">assert</span> <span class="brace">{</span><span class="brace">}</span>
+<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute">rustc_builtin_macro</span><span class="attribute attribute">]</span>
+<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">asm</span> <span class="brace">{</span><span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">toho</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented"</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
@@ -142,4 +144,5 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="macro">assert!</span><span class="parenthesis">(</span><span class="bool_literal">true</span><span class="comma">,</span> <span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="numeric_literal">1</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="macro">assert!</span><span class="parenthesis">(</span><span class="bool_literal">true</span><span class="comma">,</span> <span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> asdasd"</span><span class="comma">,</span> <span class="numeric_literal">1</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="macro">toho!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">fmt"</span><span class="comma">,</span> <span class="numeric_literal">0</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro">asm!</span><span class="parenthesis">(</span><span class="string_literal">"mov eax, </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index e7bfbcc604..fd8e1a0e21 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -477,6 +477,8 @@ mod panic {
 macro_rules! panic {}
 #[rustc_builtin_macro]
 macro_rules! assert {}
+#[rustc_builtin_macro]
+macro_rules! asm {}
 
 macro_rules! toho {
     () => ($crate::panic!("not yet implemented"));
@@ -537,6 +539,7 @@ fn main() {
     assert!(true, "{}", 1);
     assert!(true, "{} asdasd", 1);
     toho!("{}fmt", 0);
+    asm!("mov eax, {0}");
 }"#
         .trim(),
         expect_file!["./test_data/highlight_strings.html"],