mfussenegger / nvim-lint

An asynchronous linter plugin for Neovim complementary to the built-in Language Server Protocol support.
GNU General Public License v3.0
2k stars 208 forks source link

Feature Request: Support taking file contents from function argument #364

Closed hkupty closed 1 year ago

hkupty commented 1 year ago

Hi! Thanks for the plugin!

In my current setup, I first run formatter.nvim then lint. Both run ktlint with input from stdin. For some files, I'm having errors when running this setup that looks like this:

Error executing vim.schedule lua callback: .../pack/packer/start/nvim-lint/lua/lint/linters/ktlint.lua:8: Expected value but found T_END at character 1
stack traceback:
        [C]: in function 'decode'
        .../pack/packer/start/nvim-lint/lua/lint/linters/ktlint.lua:8: in function 'parse'
        ...vim/site/pack/packer/start/nvim-lint/lua/lint/parser.lua:131: in function <...vim/site/pack/packer/start/nvim-lint/lua/lint/parser.lua:127>

but if I run :echo json_decode(system("ktlint --reporter=json " . expand("%"))) or :lua require("lint").try_lint() I don't get any errors. My assumption is that it has something to do with the async nature of formatter writing to the file while the linter is trying to check for issues.

formatter.nvim allows for a transform function, which runs with the formatted output. My idea was to use the formatted output and run that through a the linter before the format could write to the file, so there wouldn't be any race-conditions between reading and writing the file.

Thanks in advance, Henry

tmtd4c93aac commented 1 year ago

Are you running try_lint() on FormatterPost like described here?

hkupty commented 1 year ago

I think that's one way to solve the problem, as there's at least a guarantee that it'll run the linter after the formatting. I might have missed that autocommand, thanks for pointing it out.

I'm not sure though that it is true that I always want to run the linter after the formatter, but that might be the case. In my setup, I'm running both of them through a custom function, but I guess at that function I can have a flag which I then check on the autocmd handler then to determine whether I should run the linter or not.

Still, passing the content through the function would avoid a repeated read-write cycle.. Not super critical, but can save some battery in a long coding session maybe... idk.

I'm happy with the autcommand for now, but the suggestion stands. Feel free to close if you're not interested in the idea.

Best regards, Henry

mfussenegger commented 1 year ago

I've currently no plans to support this, but you can call most parsers directly anyway, as seen in the tests:

    local parser = require('lint.linters.php').parser
    local result = parser([[

Warning: The use statement with non-compound name 'Foo' has no effect in Standard input code on line 3

Warning: The use statement with non-compound name 'Bar' has no effect in Standard input code on line 4

No syntax errors detected in Standard input code
    ]], vim.api.nvim_get_current_buf())

You'd then just need to add a call to vim.diagnostic.set() with the result.