Custom Injections in Neovim Treesitter with Tagged Template Literals

1.9k Views Asked by At

I'm trying to write a custom injection for Neovim's Treesitter that will highlight tagged template literals as SQL code.

The code in question looks like this:

import sql from "postgres"
const query = sql` SELECT * FROM my_table`

I'd like to tell Treesitter to parse this tagged template literal as SQL code. This is possible using Treesitter's custom injections; in fact the library uses this same technique to inject syntax for GraphQL tagged template literals, which I believe happens in this file here.

I've written a configuration file at ~/.config/nvim/after/queries/ecma/injections.scm that's quite similar to the GraphQL query, and although Treesitter is recognizing the file, the injection isn't working at all. Does anyone have a solution to this? Ideally, Treesitter would see the sql tagged template literal and interpret the body of the function with the SQL parser.

3

There are 3 best solutions below

0
On

Similar to what @brotify-force said, but my own SQL injection for Python was not working until I realized what the issue was.

~/.config/nvim/after/queries/python/injections.scm

; extends

(assignment 
  left: (identifier) @_id (#match? @_id "sql")
  right: (string) @sql
)

My original query used @id, but it seems like if you have any captures not starting with an underscore besides the language capture, the Neovim Treesitter machinery gets confused.

Update: Treesitter / Neovim 12/2023 I recently noticed my SQL injections were broken. It looks like maybe there were changes to what symbols get parsed by treesitter as well as some special syntax to indicate the injected language, etc.

My updated file at ~/.config/nvim/after/queries/python/injections.scm:

; extends

(assignment 
    left: (identifier) @_id
    right: (string (string_content) @injection.content)
    (#match? @_id "sql")
    (#set! injection.language "sql"))
0
On

I've been trying to do something similar but for template strings that just happen to contain SQL. I was inspired by a VSCode plugin that syntax highlights any template string that has a comment like /*sql*/ in front of it. Here's what I came up with.

; extends
(
 (comment) @_comment-text
 (#match? @_comment-text "sql")
 (template_string) @ql
)

I do wish there was a proper sql module for tree-sitter, and it looks like one is in the works, but the ql module will do for now.

0
On

to make tree sitter use injections in your after/ folder, your injections.scm file should contain ; extends as first line.

Took me many hours to figure it out, it's now documented right here