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

Linter/Fixer #9

Open
kristijanhusak opened this issue Sep 8, 2020 · 38 comments
Open

Linter/Fixer #9

kristijanhusak opened this issue Sep 8, 2020 · 38 comments
Labels
help wanted Extra attention is needed idea

Comments

@kristijanhusak
Copy link

kristijanhusak commented Sep 8, 2020

What?
Basically https://github.com/dense-analysis/ale, but only linter and fixer. Other things are already implemented via lsp.

Why?
Linting is a thing that runs almost constantly, especially when real time execution is enabled. I believe having it in lua would improve the performance.

Potential existing implementations:

Potential pitfalls:
Migrating all linter/fixer implementations that exist in ale, from vimscript to lua.
Guess it can be done slowly over time.

I'm not a lua developer, but I can definitely help on this.

@kristijanhusak kristijanhusak added help wanted Extra attention is needed idea labels Sep 8, 2020
@wbthomason
Copy link
Collaborator

Just to clarify, this differs from the LSP-provided diagnostics in that it focuses on running standalone linters?

@kristijanhusak
Copy link
Author

@wbthomason yeah, standalone linters and fixers. For example, most JS projects use eslint for linting, and prettier for fixing.

@carlitux
Copy link

carlitux commented Sep 8, 2020

@kristijanhusak I just started using https://github.com/neovim/nvim-lspconfig#diagnosticls right now dealing with some issues configuring but looks like it is a replacement of ale. But I still need some time to confirm that is an alternative.

@kristijanhusak
Copy link
Author

@carlitux I wasn't aware of that. I'll give it a try, thanks!

@carlitux
Copy link

@kristijanhusak were you able to setup? I had many issues diagnosticls

@kristijanhusak
Copy link
Author

@carlitux i haven't tried yet. Will get back to you when i try it.

@weilbith
Copy link

weilbith commented Sep 15, 2020

How you describe "fixers" sounds actually more like a code formatter. At least that's what your example Prettier is doing. It does not fix your code. It just makes it standardized formatted. But it would deny to format if there are syntax errors for example.
A tool that support this would be neoformat

@wbthomason
Copy link
Collaborator

Also https://github.com/mhartington/formatter.nvim

@carlitux
Copy link

@wbthomason plans to support linters?

@wbthomason
Copy link
Collaborator

@carlitux Sorry, support linters in what? formatter.nvim is not my project; this repo is just a place to collect ideas for people to adopt and implement.

@carlitux
Copy link

@wbthomason sorry, I didn't read well. Thanks!

@kristijanhusak
Copy link
Author

@carlitux I managed to set up linting with eslint, and prettier, with this config:

nvim_lsp.diagnosticls.setup{
  filetypes={'javascript'},
  init_options = {
    linters = {
      eslint = {
        command = './node_modules/.bin/eslint',
        rootPatterns = {'.git'},
        debounce = 100,
        args = {
          '--stdin',
          '--stdin-filename',
          '%filepath',
          '--format',
          'json'
        },
        sourceName = 'eslint',
        parseJson = {
          errorsRoot = '[0].messages',
          line = 'line',
          column = 'column',
          endLine = 'endLine',
          endColumn = 'endColumn',
          message = '${message} [${ruleId}]',
          security = 'severity'
        },
        securities = {
          [2] = 'error',
          [1] = 'warning',
        },
      },
    },
    filetypes = {
      javascript = 'eslint'
    },
    formatters = {
      prettier = {
        command = "./node_modules/.bin/prettier",
        args = {"--stdin-filepath" ,"%filepath", '--single-quote', '--print-width 120'}
      }
    },
    formatFiletypes = {
      javascript = "prettier"
    },
  }
}

I wasn't able to set up eslint fix or prettier-eslint, it failed to spawn those, even though I have them installed. Linting looked fine.
It doesn't work for me because I thought it supports textDocument/range_formatting, which is the only thing I'm currently missing from Ale.

@carlitux
Copy link

@kristijanhusak issues with 'textDocument/definition' or 'textDocument/documentSymbol'? for me breaks others

@kristijanhusak
Copy link
Author

@carlitux I didn't try to run any other LSP server besides it. Most likely there would be some issues in that case.
I don't think it can work if you have more than 1 LSP per filetype.

@vinnyA3
Copy link

vinnyA3 commented Sep 18, 2020

Great stuff .. the config you posted worked perfectly @kristijanhusak

It would be nice to see the bugs worked out with multiple LSPs & single files. I was running a JS lang server & diagnosticls; unfortunately, ran into similar issues as @carlitux .

Here's one of multiple LSP bugs that's currently being addressed: neovim/neovim#12764

@lucastrvsn
Copy link

@carlitux I managed to set up linting with eslint, and prettier, with this config:

nvim_lsp.diagnosticls.setup{
  filetypes={'javascript'},
  init_options = {
    linters = {
      eslint = {
        command = './node_modules/.bin/eslint',
        rootPatterns = {'.git'},
        debounce = 100,
        args = {
          '--stdin',
          '--stdin-filename',
          '%filepath',
          '--format',
          'json'
        },
        sourceName = 'eslint',
        parseJson = {
          errorsRoot = '[0].messages',
          line = 'line',
          column = 'column',
          endLine = 'endLine',
          endColumn = 'endColumn',
          message = '${message} [${ruleId}]',
          security = 'severity'
        },
        securities = {
          [2] = 'error',
          [1] = 'warning',
        },
      },
    },
    filetypes = {
      javascript = 'eslint'
    },
    formatters = {
      prettier = {
        command = "./node_modules/.bin/prettier",
        args = {"--stdin-filepath" ,"%filepath", '--single-quote', '--print-width 120'}
      }
    },
    formatFiletypes = {
      javascript = "prettier"
    },
  }
}

I wasn't able to set up eslint fix or prettier-eslint, it failed to spawn those, even though I have them installed. Linting looked fine.
It doesn't work for me because I thought it supports textDocument/range_formatting, which is the only thing I'm currently missing from Ale.

Awesome! I was trying to do this today and this worked really well. Maybe we need some docs for right configuration?

@carlitux
Copy link

Great stuff .. the config you posted worked perfectly @kristijanhusak

It would be nice to see the bugs worked out with multiple LSPs & single files. I was running a JS lang server & diagnosticls; unfortunately, ran into similar issues as @carlitux .

Here's one of multiple LSP bugs that's currently being addressed: neovim/neovim#12764

looks like this is fixed and working really well, just trying to find the best way to format before save right now with this config

  if client.resolved_capabilities.document_formatting then
    vim.cmd("autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_sync{}")
  end

@matu3ba
Copy link

matu3ba commented Dec 25, 2020

Newer programming languages provide one tool for the linting. Older programming languages have many.

Is the goal to simplify or give any sort of reference on this?

@kristijanhusak
Copy link
Author

kristijanhusak commented Dec 26, 2020

@matu3ba literally a tool same as Ale mentioned in the first comment, but only the linter and fixer part. Ale has some other things that are not necessary since they are already implemented (LSP for example).

@icew4ll
Copy link

icew4ll commented Feb 13, 2021

Does the linter/fixer need to be in lua when there is already an option to use the efm-languageserver (written in go) with lspconfig? The suggestion to use efm-language server for linting and formatting in neovim was made here efm-languageserver. I have been using this solution for a variety of languages and it works very well my implementation can be referenced here dots.

@fsouza
Copy link

fsouza commented Feb 26, 2021

nvim-lint is promising: https://github.com/mfussenegger/nvim-lint/

@matu3ba
Copy link

matu3ba commented Mar 4, 2021

I would suggest to keep linter and fixer separate programs as the fixer rewrites the file with the possibilities to mess up your files.
(So I prefer to invoke simple binaries that may optionally read a project-local config and always work/never fail as to limit any possibilities of errors.)

The linter should only do static code analysis (on source- or intermediate representation) of the code.

@fsouza
Copy link

fsouza commented Mar 4, 2021

@matu3ba agreed, right now I'm looking at nvim-lint and formatter.nvim as two strong candidates, but I still use efm personally.

@FardeenCodes
Copy link

Can anyone help me setting up nvim-lint for pylint(python)

@wbthomason
Copy link
Collaborator

Can anyone help me setting up nvim-lint for pylint(python)

I would suggest that you ask on the nvim-lint repo - this repo is for gathering wishes and candidates for their fulfillment.

@sarmong
Copy link

sarmong commented Jan 3, 2022

You can try using null-ls. This plugin allows pretty much anything to be hooked up to the existing lsp protocol.

It includes plenty of builtins for different linters an formatters

@luisiacc
Copy link

luisiacc commented Jan 29, 2022

I guess this is already done right? via what @sarmong mentioned, https://github.com/jose-elias-alvarez/null-ls.nvim

@mjlbach
Copy link

mjlbach commented Jan 29, 2022

I would recommend nvim-lint, between the two of these what else are people missing?

@kristijanhusak
Copy link
Author

I'm currently using https://github.com/creativenull/diagnosticls-configs-nvim, which provides predefined configs for diagnosticls.

@gegoune
Copy link

gegoune commented Jan 30, 2022

@mjlbach Would you mind elaborating a bit on why you recommend using nvim-lint over null-ls, please? Genuinely curious.

@mjlbach
Copy link

mjlbach commented Jan 30, 2022

  • I don't think a linter, formatter, and (now) completion source should be part of the same plugin. It makes sense in the case of a language server, because a language server inherently shares components (parsing the files and updating with changes) but linters/formatters are usually entirely separate and run out of process. nvim-lint has a clear focus/lack of feature creep.
  • The nvim-lint core is extremely readable/small/clean (~350 LoC), it's around 10x smaller than null-ls (~3K LoC)
  • By virtue of that scope, nvim-lint doesn't touch the LSP code. It doesn't inject itself as a language server, it doesn't hijack buf_request, the rpc loop, etc. This has caused me (personally) headaches in the past from user bug reports.

IMO People just want OOTB configurations for linters/formatters,which is what null-ls happens to provide in a single plugin. I don't think these should be in the same plugin, and I certainly don't think it should be forced into the language server protocol.

nvim-lint also provides linters OOTB but not formatters. I think nvim-lint + a dedicated formatter plugin like formatter.nvim is the way to go.

@gegoune
Copy link

gegoune commented Jan 30, 2022

Thanks you very much for taking time to describe it in such detail. Really appreciated.

@Mte90
Copy link

Mte90 commented Jan 30, 2022

I see that the difference between null-ls and nvim-lint is that the first one is for linter and fixer and the second only for linters.

so there is a plugin just for fixers/formatters? something where you define a filetype and what to execute should be enough.

@bb010g
Copy link

bb010g commented Feb 2, 2022

I really want a Neovim Lua ecosystem equivalent to ALE's amazing auto-configuration (not auto-installation) of linters, fixers, and language servers. It's amazingly nice to be able to recommend to a new person that they should use a combo like packer.nvim + plenary.nvim + vim-polyglot + nvim-treesitter (ensure_installed = "maintained") + ALE and have an immediately rich, quick-starting editor for most situations without having to keep fiddling with config; currently there's no combo to replace ALE there. (Bonus points if it can auto-configure for DAP as well as LSP.)

Both null-ls.nvim and nvim-lint follow the current pattern and don't provide auto-configuration for linters.

@mjlbach
Copy link

mjlbach commented Feb 2, 2022

I'm not sure I understand. Do you want users to have to opt-out of linters?

require('lint').linters_by_ft = {  markdown = {'vale',} }
vim.cmd [[ au BufWritePost * lua require('lint').try_lint() ]]

Does not seem like much configuration at all.

@bb010g
Copy link

bb010g commented Feb 2, 2022

@mjlbach That is how ALE generally works, yes. (ALE will disable tools by default if they're found to be poor fits for auto-detection.)

" Only run linters named in ale_linters settings.
let g:ale_linters_explicit = 1

I'd be fine with having auto-detection be opt-in; the complete lack of it is what I'm missing. I should note that :ALEInfo works with the auto-detection system to tell you what's enabled or disabled for your buffer and what it's tried so far and what's failed (generally it stops trying a tool after failure), as well as a log of tool invocations. That does a lot to keep it from surprising you. This is also where you'll see that certain tools were disabled by default, so you can figure out for a tool you're missing whether you can just turn it on or if you should submit a patch upstream adding a configuration for that tool.

Auto-detection is really nice when tools are only installed project-locally (e.g. via nix-shell), as two projects can run different sets of tools for the same language, and auto-detection keeps warnings from popping up repeatedly about missing executables as you switch between directories. Additionally, nix-shell means that I don't look at what linters or language servers a project has set up in its shell.nix when starting most of the time; they'll just be present once I enter the shell, ALE will find them, and things will just work. This is a sore spot with current null-ls.nvim; I have a helper function to create the explicit executable condition for each source I use so I won't get a varying amount of missing tool warnings popping up when I open a buffer.

It's also just annoying when I know these plugins know which tools work for which languages and can easily & quickly figure out what I have installed. It's boilerplate that I shouldn't have to write. Also, when you use a lot of languages, the boilerplate adds up.

I think being able to enable or disable auto-detection globally or buffer-locally and by language/filetype and tool would work (Again, you can mostly refer to what ALE currently has in terms of options.)

I do think tool auto-detection could be split out into a separate plugin that can be shared between other plugins that need to deal with detecting the tools and their appropriate configuration & directories; the ALE situation of everything being in one plugin doesn't need to be emulated.

@mfussenegger
Copy link

I do think tool auto-detection could be split out into a separate plugin that can be shared between other plugins that need to deal with detecting the tools and their appropriate configuration & directories; the ALE situation of everything being in one plugin doesn't need to be emulated.

Agreed, someone could create a nvim-lint-autoconf on top of nvim-lint for that.
I have no plans to extend nvim-lint itself with something like that for now

@ajitid
Copy link

ajitid commented Feb 19, 2022

nvim-lint also provides linters OOTB but not formatters. I think nvim-lint + a dedicated formatter plugin like formatter.nvim is the way to go.

Funnily enough, the maintainer of formatter.nvim once recommended to use efm. See this and this.

And somebody is collating quick configs for it: https://github.com/creativenull/efmls-configs-nvim

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed idea
Projects
None yet
Development

No branches or pull requests