Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linting of injected langauges #439

Open
magnuslarsen opened this issue Oct 31, 2023 · 6 comments
Open

Linting of injected langauges #439

magnuslarsen opened this issue Oct 31, 2023 · 6 comments

Comments

@magnuslarsen
Copy link

I've been thinking for a while on how to implement "linting of injected languages" using the existing code-base as-is, and (in theory anyway) it's not too difficult, I would just like to bring it up for a discussing before actually trying to implement it

conform.nvim has the same feature, but for formatting, and we can just re-use the core logic here (getting the injected languages via treesitter). I see it sort of like this:

  1. Get the injected languages, and for each:
  2. Create a new hidden-scratch buffer, set ft to injected.language
  3. Set said scratch-buffer's content to injected.content (without additional new lines, see below)
  4. Call nvim_buf_call(scatch_bufnr, M.lint()) on the scratch-buffer
  5. Get all the diagnostics for scratch_bufnr (if LSP's are setup for the target language, these will also be picked up - feature?)
  6. Update the diagnostic' line_num to include the offset from the main buffer for each diagnostic (see below)
  7. vim.diagnostics.set() the diagnostics in the main buffer
  8. Sync/delete hidden buffers - I need to test what is fastest here

I know of otter.nvim which does something similar, but for a limited set of languages, and only includes LSP features (which I'm not interested in). Otter.nvim creates a hidden buffer, but using newlines as offset, which I personally do not like, because some linters requires the first line to be a shebang (see shellcheck as an example), which is impossible to satisfy using the newline-approach

Instead, I'd suggest making a new buffer without newlines, but instead bump the lnum of the diagnostic itself afterwards, so it matches in the main buffer (i.e. if the injected block starts a line 5 in the main buffer, bump the lnum of the diagnostic by 4 (offset - 1). This makes the shellcheck example possible to "fix"


Since nvim-lint's cmd-field can only return a path to an external command (or a function that returns said command), above requires a new field, which can take a pure-lua function
conform.nvim has command-field which is equivalent to nvim-lint's cmd field, but they also have a format-field, which accepts said pure-lua function (they also have a condition-field, which I think could also be useful here)

(having a linter field (pure-lua) would also allow new linter tools, for-example these two from null-ls, and this one I wrote, just before switching to nvim-lint/conform.nvim)

This bit is what is holding me back from writing the injected-linter; I'm not too comfortable adding logic to the core-logic :-)

@mfussenegger
Copy link
Owner

Relates a bit to #235

I'd first like to see if there's more interest in this, before considering it.

@JeanMertz
Copy link

It does appear there's a desire for this feature to be implemented. It currently has the highest number of votes.

@pete3n
Copy link

pete3n commented Jan 31, 2024

This would be awesome for languages like Nix where I often end up injecting Lua or shell scripts with unchecked '' ''; blocks.

@Doekeb
Copy link

Doekeb commented Oct 25, 2024

Throwing my hat in the ring here as well. Injected SQL is my use-case. I have almost a perfect setup with treesitter queries and conform. Linting is the only missing piece.

@catgoose
Copy link

Throwing my hat in the ring here as well. Injected SQL is my use-case. I have almost a perfect setup with treesitter queries and conform. Linting is the only missing piece.

Do you mind sharing?

@Doekeb
Copy link

Doekeb commented Oct 25, 2024

Do you mind sharing?

Sure!

  • My dotfiles are here
  • Treesitter SQL injection query here (just a simple query to detect a magic comment "-- !sql" inside a string and change the treesitter language to sql)
  • Conform config here (note the line ["*"] = { "injected" } in formatters_by_ft

I'm set up for SQL inside of Python, but you should be able to replicate with any language inside any other.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants