Unnamed repository; edit this file 'description' to name the repository.
Add a language to fix Rust highlights in format-args macros
This is a bit hacky. Injections cannot stack on each other like highlights because layers can have their own injections. So this new language `rust-format-args-macro` emulates that. It unconditionally injects `rust-format-args` into all strings. Rust injects this new language into known format-args macros like `println!`. The downside is that this can cause false-positive highlights within these macros for strings which happen to contain format-args syntax println!("Hello, {}!", "{}"); // ^ format args syntax // ^ not format args syntax, but highlighted // as if it were :( This false-positive case is expected to be rare. Injecting this fake language fixes regular non-string highlights in macro invocations: macro invocations need to inject the entire token tree and use `injection.include-children` for proper highlighting.
Michael Davis 8 months ago
parent d2f37b1 · commit 86f10ae
-rw-r--r--book/src/generated/lang-support.md1
-rw-r--r--languages.toml6
-rw-r--r--runtime/queries/rust-format-args-macro/highlights.scm1
-rw-r--r--runtime/queries/rust-format-args-macro/indents.scm1
-rw-r--r--runtime/queries/rust-format-args-macro/injections.scm13
-rw-r--r--runtime/queries/rust-format-args-macro/locals.scm1
-rw-r--r--runtime/queries/rust-format-args-macro/textobjects.scm1
-rw-r--r--runtime/queries/rust/injections.scm61
8 files changed, 32 insertions, 53 deletions
diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md
index cc9e0e62..1c620e37 100644
--- a/book/src/generated/lang-support.md
+++ b/book/src/generated/lang-support.md
@@ -208,6 +208,7 @@
| ruby | ✓ | ✓ | ✓ | `ruby-lsp`, `solargraph` |
| rust | ✓ | ✓ | ✓ | `rust-analyzer` |
| rust-format-args | ✓ | | | |
+| rust-format-args-macro | ✓ | ✓ | ✓ | |
| sage | ✓ | ✓ | | |
| scala | ✓ | ✓ | ✓ | `metals` |
| scheme | ✓ | | ✓ | |
diff --git a/languages.toml b/languages.toml
index 5c37a0b7..670904fe 100644
--- a/languages.toml
+++ b/languages.toml
@@ -4446,6 +4446,12 @@ name = "rust-format-args"
source = { git = "https://github.com/nik-rev/tree-sitter-rust-format-args", rev = "84ffe550e261cf5ea40a0ec31849ba2443bae99f" }
[[language]]
+name = "rust-format-args-macro"
+scope = "source.rust-format-args-macro"
+file-types = []
+grammar = "rust"
+
+[[language]]
name = "clarity"
scope = "source.clar"
injection-regex = "clarity"
diff --git a/runtime/queries/rust-format-args-macro/highlights.scm b/runtime/queries/rust-format-args-macro/highlights.scm
new file mode 100644
index 00000000..ae55c7fa
--- /dev/null
+++ b/runtime/queries/rust-format-args-macro/highlights.scm
@@ -0,0 +1 @@
+; inherits: rust
diff --git a/runtime/queries/rust-format-args-macro/indents.scm b/runtime/queries/rust-format-args-macro/indents.scm
new file mode 100644
index 00000000..ae55c7fa
--- /dev/null
+++ b/runtime/queries/rust-format-args-macro/indents.scm
@@ -0,0 +1 @@
+; inherits: rust
diff --git a/runtime/queries/rust-format-args-macro/injections.scm b/runtime/queries/rust-format-args-macro/injections.scm
new file mode 100644
index 00000000..47db1345
--- /dev/null
+++ b/runtime/queries/rust-format-args-macro/injections.scm
@@ -0,0 +1,13 @@
+; inherits: rust
+
+; HACK: This language is the same as Rust but all strings are injected
+; with rust-format-args. Rust injects this into known macros which use
+; the format args syntax. This can cause false-positive highlights but
+; those are expected to be rare.
+
+([
+ (string_literal (string_content) @injection.content)
+ (raw_string_literal (string_content) @injection.content)
+ ]
+ (#set! injection.language "rust-format-args")
+ (#set! injection.include-children))
diff --git a/runtime/queries/rust-format-args-macro/locals.scm b/runtime/queries/rust-format-args-macro/locals.scm
new file mode 100644
index 00000000..ae55c7fa
--- /dev/null
+++ b/runtime/queries/rust-format-args-macro/locals.scm
@@ -0,0 +1 @@
+; inherits: rust
diff --git a/runtime/queries/rust-format-args-macro/textobjects.scm b/runtime/queries/rust-format-args-macro/textobjects.scm
new file mode 100644
index 00000000..ae55c7fa
--- /dev/null
+++ b/runtime/queries/rust-format-args-macro/textobjects.scm
@@ -0,0 +1 @@
+; inherits: rust
diff --git a/runtime/queries/rust/injections.scm b/runtime/queries/rust/injections.scm
index ba58bf36..af1970a9 100644
--- a/runtime/queries/rust/injections.scm
+++ b/runtime/queries/rust/injections.scm
@@ -103,8 +103,6 @@
; the `format_args!` syntax.
;
; This language is injected into a hard-coded set of macros.
-
-; 1st argument is `format_args!`
(
(macro_invocation
macro:
@@ -113,13 +111,11 @@
name: (_) @_macro_name)
(identifier) @_macro_name
]
- (token_tree . [
- (string_literal (string_content) @injection.content)
- (raw_string_literal (string_content) @injection.content)
- ]
- )
+ (token_tree) @injection.content
)
(#any-of? @_macro_name
+ ; 1st argument is `format_args!`
+
; std
"print" "println" "eprint" "eprintln"
"format" "format_args" "todo" "panic"
@@ -140,63 +136,22 @@
"eyre"
; miette
"miette"
- )
- (#set! injection.language "rust-format-args")
- (#set! injection.include-children)
-)
-; 2nd argument is `format_args!`
-(
- (macro_invocation
- macro:
- [
- (scoped_identifier
- name: (_) @_macro_name)
- (identifier) @_macro_name
- ]
- (token_tree
- . (_)
- . [
- (string_literal (string_content) @injection.content)
- (raw_string_literal (string_content) @injection.content)
- ]
- )
- )
- (#any-of? @_macro_name
+ ; 2nd argument is `format_args!`
+
; std
"write" "writeln" "assert" "debug_assert"
; defmt
"expect" "unwrap"
; ratatui
"span"
- )
- (#set! injection.language "rust-format-args")
- (#set! injection.include-children)
-)
-; 3rd argument is `format_args!`
-(
- (macro_invocation
- macro:
- [
- (scoped_identifier
- name: (_) @_macro_name)
- (identifier) @_macro_name
- ]
- (token_tree
- . (_)
- . (_)
- . [
- (string_literal (string_content) @injection.content)
- (raw_string_literal (string_content) @injection.content)
- ]
- )
- )
- (#any-of? @_macro_name
+ ; 3rd argument is `format_args!`
+
; std
"assert_eq" "debug_assert_eq" "assert_ne" "debug_assert_ne"
)
- (#set! injection.language "rust-format-args")
+ (#set! injection.language "rust-format-args-macro")
(#set! injection.include-children)
)