jose-elias-alvarez / nvim-lsp-ts-utils

Utilities to improve the TypeScript development experience for Neovim's built-in LSP client.
The Unlicense
438 stars 18 forks source link

Can't get formatting to work with null-ls #41

Closed omaranbari closed 3 years ago

omaranbari commented 3 years ago

Hola crack, I'd like to start by apologizing in advance for probably wasting your time.

I've been trying to get prettier (or prettierd) to work with null-ls and ts-utils, but to no avail.

Here is my configuration:

require("null-ls").setup {
    debug = true,
}

lspconfig.tsserver.setup {
    capabilities = capabilities,
    on_init = custom_init,
    filetypes = { "javascript", "javascriptreact", "javascript.jsx", "typescript", "typescriptreact", "typescript.tsx" },
    on_attach = function(client, bufnr)
        on_attach_common(client)
         -- disable tsserver formatting
         client.resolved_capabilities.document_formatting = false
         -- format on save
         vim.cmd("autocmd BufWritePost <buffer> lua vim.lsp.buf.formatting()")

        local ts_utils = require("nvim-lsp-ts-utils")

        -- defaults
        ts_utils.setup {
            print("setting up ts_utils"), 
            debug = true,
            disable_commands = false,
            enable_import_on_completion = true,
            import_all_timeout = 5000, -- ms

            -- eslint
            eslint_enable_code_actions = true,
            eslint_enable_disable_comments = true,
            eslint_bin = "eslint_d",
            eslint_config_fallback = nil,
            eslint_enable_diagnostics = true,

            -- formatting
            enable_formatting = true,
            formatter = "prettierd",
            formatter_config_fallback = "eslint_d",

            -- parentheses completion
            complete_parens = true,
            signature_help_in_parens = true,

            -- update imports on file move
            update_imports_on_move = true,
            require_confirmation_on_move = false,
            watch_dir = nil,
        }

        -- required to fix code action ranges
        ts_utils.setup_client(client)
        -- no default maps, so you may want to define some here
        vim.api.nvim_buf_set_keymap(bufnr, "n", "gs", ":TSLspOrganize<CR>", {silent = true})
        vim.api.nvim_buf_set_keymap(bufnr, "n", "qq", ":TSLspFixCurrent<CR>", {silent = true})
        vim.api.nvim_buf_set_keymap(bufnr, "n", "<leader>rf", ":TSLspRenameFile<CR>", {silent = true})
        vim.api.nvim_buf_set_keymap(bufnr, "n", "<leader>ia", ":TSLspImportAll<CR>", {silent = true})
    end
}

:LspInfo shows that both tsserver and null-ls are attached. (filetypes for null-ls is empty but I assume this is expected behavior).

With debug=true both on lsp-ts-utils and null-ls, :messages returns the following:

LSP Started
using system executable eslint_d
enabling null-ls eslint code actions integration
enabling null-ls eslint diagnostics integration
using system executable prettierd
enabling null-ls formatting integration
successfully registered null-ls integrations
attempting to watch root dir/home/omar/src/work/seera-c4i/seera-vue
git config found; scanning root dir
watching dir /home/omar/src/work/seera-c4i/seera-vue/client
watching dir /home/omar/src/work/...
running generators for method NULL_LS_DIAGNOSTICS
spawning command eslint_d with args:
{ "-f", "json", "--stdin", "--stdin-filename", "$FILENAME" }
LSP started.
error output: nil
output: Error: Failed to load plugin '@typescript-eslint' declared in '.eslintrc': Cannot find module '@typescript-eslint/eslint-plugin'
Require stack:
- /home/omar/src/work/seera-c4i/seera-vue/__placeholder__.js
Referenced from: /home/omar/src/work/...
output: nil
running generators for method NULL_LS_CODE_ACTION
error output: nil

prettier works from the command line.

If I switch to client.resolved_capabilities.document_formatting = true tsserver is able to format the file just fine.

I am running: NVIM v0.5.0-dev+1429-gb585f723b Build type: RelWithDebInfo LuaJIT 2.1.0-beta3

Thank you for your help.

omaranbari commented 3 years ago

With client.resolved_capabilities.document_formatting = true, if i run the format lua command and choose null-ls, I get the following messages:

received LSP formatting request
running generators for method NULL_LS_FORMATTING
spawning command prettier with args:
{ "--stdin-filepath", "$FILENAME" }
error output: nil
jose-elias-alvarez commented 3 years ago

Hmm, I see one potential error in your config, which is that formatter_config_fallback is set to "eslint_d" (if you're using Prettier, it should be a path to a .prettierrc file or nil). From your logs, though, it doesn't look like that's necessarily the issue, since it'll only use the fallback setting if it can't find a Prettier config file in the first place. Other than that, your config looks good and is working on my end.

With client.resolved_capabilities.document_formatting = true, if i run the format lua command and choose null-ls, I get the following messages:

So after this, there's no additional messages, both with prettier and prettierd? If so, that's really strange, and there might be something wrong with the debug log itself. Do you see the same message if you run the formatting command again?

Also, just to rule out project configuration issues, could you try creating an empty project with npm init -y, making a JavaScript file in it, and seeing if formatting works as expected?

omaranbari commented 3 years ago

Hi Jose Elias, my answers below

Hmm, I see one potential error in your config, which is that formatter_config_fallback is set to "eslint_d" (if you're using Prettier, it should be a path to a .prettierrc file or nil). From your logs, though, it doesn't look like that's necessarily the issue, since it'll only use the fallback setting if it can't find a Prettier config file in the first place. Other than that, your config looks good and is working on my end.

With client.resolved_capabilities.document_formatting = true, if i run the format lua command and choose null-ls, I get the following messages:

So after this, there's no additional messages, both with prettier and prettierd? If so, that's really strange, and there might be something wrong with the debug log itself. Do you see the same message if you run the formatting command again? No more messages after this. Also, just to rule out project configuration issues, could you try creating an empty project with npm init -y, making a JavaScript file in it, and seeing if formatting works as expected? I did this. Works with a javascript file but not a typescript file. Is this expected behavior?

jose-elias-alvarez commented 3 years ago

Works with a javascript file but not a typescript file. Is this expected behavior?

That's super strange and definitely should not be happening, and it indicates that something's up with Prettier itself. Could you try uninstalling and reinstalling the latest version of Prettier?

omaranbari commented 3 years ago

Now it doesn't work with either :( This is what I get

running generators for method NULL_LS_DIAGNOSTICS
spawning command eslint_d with args:
{ "-f", "json", "--stdin", "--stdin-filename", "$FILENAME" }
error output: nil
jose-elias-alvarez commented 3 years ago

That's what you see when you open the file, right? What do you see when you run :lua vim.lsp.buf.formatting()?

omaranbari commented 3 years ago

When it opens I get this:

LSP started.
setting up ts_utils
using system executable eslint_d
failed to resolve ESLint config
enabling null-ls eslint code actions integration
enabling null-ls eslint diagnostics integration
using system executable prettier
enabling null-ls formatting integration
successfully registered null-ls integrations
attempting to watch root dir/home/omar/src/personal/test-vim
git config not found; falling back to watch_dir
watch_dir is not set; watch aborted
running generators for method NULL_LS_DIAGNOSTICS
spawning command eslint_d with args:
{ "-f", "json", "--stdin", "--stdin-filename", "$FILENAME" }
error output: nil
output: Error: No ESLint configuration found in /home/omar/src/personal/t
est-vim.
output: nil
running generators for method NULL_LS_CODE_ACTION
error output: nil
output: Error: No ESLint configuration found in /home/omar/src/personal/t
est-vim.
output: nil

When I run the formatting command, I get:

received LSP formatting request
running generators for method NULL_LS_FORMATTING
spawning command prettier with args:
{ "--stdin-filepath", "$FILENAME", "--config" }
error output: nil
output: nil
omaranbari commented 3 years ago

Ok I narrowed it down to prettierd! Now it seems to work fine with prettier, but not prettierd. I'm sure I can live with this, but I'd be extremely happy to contribute further to this, at your service!

omaranbari commented 3 years ago

this is the output with prettierd:

received LSP formatting request
running generators for method NULL_LS_FORMATTING
spawning command prettierd with args:
{ "$FILENAME", "--config" }
running generators for method NULL_LS_CODE_ACTION
error output: nil
output: Error: No ESLint configuration found in /home/omar/src/personal/test-vim
.
output: nil
running generators for method NULL_LS_CODE_ACTION
error output: nil
output: Error: No ESLint configuration found in /home/omar/src/personal/test-vim
.
output: nil
error output: nil
output: nil
received edits from generators
{}
successfully applied edits
running generators for method NULL_LS_CODE_ACTION
error output: nil
output: Error: No ESLint configuration found in /home/omar/src/personal/test-vim
.
output: nil
running generators for method NULL_LS_CODE_ACTION
error output: nil
output: Error: No ESLint configuration found in /home/omar/src/personal/test-vim
.
output: nil
running generators for method NULL_LS_CODE_ACTION
error output: nil
output: Error: No ESLint configuration found in /home/omar/src/personal/test-vim
.
output: nil

The code i'm trying to format is:

                            const a     =2

Just extra spaces. Maybe prettierd only works in a git repo or needs a .prettierrc config file?

jose-elias-alvarez commented 3 years ago

Glad it's working with prettier, but I have no idea what's going on with prettierd, since everything is working as expected on my end (it should work outside of a Git repo and without a config file, just like vanilla prettier).

In this case, it looks like the command is running, but the output is empty, which is strange. What do you see when you run cat test-file.ts | prettierd test-file.ts from the command line, where test-file.ts is the name of the file that contains the code you're trying to format? Are you also running the latest version of prettierd?

Also, you helped me identify a small bug with the way the plugin sets formatter arguments (there shouldn't be a --config flag when you haven't set a fallback), so I just pushed that fix, but it doesn't seem to make a difference in this case, since prettierd works for me either way. I'd still try updating the plugin just to rule that out, too.

omaranbari commented 3 years ago

I think this is definitely related to: [[https://github.com/fsouza/prettierd/issues/183]] Running the test you suggested just hangs prettierd and nothing happens. Thank you so much for your help and I'm glad you caught a bug and this wasn't a complete waste of your time. Keep up the wonderful work, can't wait to start playing with null-ls.

jose-elias-alvarez commented 3 years ago

I suspected this was related to prettierd itself. If you have the ability to modify your project setup a bit, I really recommend setting up eslint_d as a formatter. Thanks for your patience debugging this!

omaranbari commented 3 years ago

I would love to give eslint_d a try as a formatter, it's great as a linter. Woulc you be open to sharing a sample .eslintrc for typescript or javascript?

jose-elias-alvarez commented 3 years ago

Sure, just follow the instructions under Recommended Configuration here.

omaranbari commented 3 years ago

Love it!!!! It's an order of magnitude faster than prettier, the configuration is much easier, and it eliminates the need for a package/config. Thank you so much

jose-elias-alvarez commented 3 years ago

No worries, happy to help!

jonleopard commented 3 years ago

Hey @omaranbari, mind posting your full config here? I just read the guide @jose-elias-alvarez wrote, but the formatting isn't working on save. I'd rather just use prettier_d and null-ls as well, so a peak at your config would help a lot.

Thanks!

omaranbari commented 3 years ago

Hi @jonleopard , of course it's my pleasure. However, I ended using eslint_d as the formatter as well as the linter on jose-elias' suggestion and it's working great once you set up a few rules. Here is my config:

lspconfig.tsserver.setup {
    capabilities = capabilities,
    on_init = custom_init,
    filetypes = { "javascript", "javascriptreact", "javascript.jsx", "typescript", "typescriptreact", "typescript.tsx" },
    on_attach = function(client, bufnr)
        on_attach_common(client)
         -- disable tsserver formatting
         client.resolved_capabilities.document_formatting = false
         -- format on save
         vim.cmd("autocmd BufWritePost <buffer> lua vim.lsp.buf.formatting()")

        local ts_utils = require("nvim-lsp-ts-utils")

        -- defaults
        ts_utils.setup {
            debug = false,
            disable_commands = false,
            enable_import_on_completion = true,
            import_all_timeout = 5000, -- ms

            -- eslint
            eslint_enable_code_actions = true,
            eslint_enable_disable_comments = true,
            eslint_bin = "eslint_d",
            eslint_config_fallback = nil,
            eslint_enable_diagnostics = true,

            -- formatting
            enable_formatting = true,
            formatter = "eslint_d",
            formatter_config_fallback = nil,

            -- parentheses completion
            complete_parens = true,
            signature_help_in_parens = true,

            -- update imports on file move
            update_imports_on_move = true,
            require_confirmation_on_move = false,
            watch_dir = nil,
        }

        -- required to fix code action ranges
        ts_utils.setup_client(client)
        -- no default maps, so you may want to define some here
        vim.api.nvim_buf_set_keymap(bufnr, "n", "gs", ":TSLspOrganize<CR>", {silent = true})
        vim.api.nvim_buf_set_keymap(bufnr, "n", "qq", ":TSLspFixCurrent<CR>", {silent = true})
        vim.api.nvim_buf_set_keymap(bufnr, "n", "<leader>rf", ":TSLspRenameFile<CR>", {silent = true})
        vim.api.nvim_buf_set_keymap(bufnr, "n", "<leader>ia", ":TSLspImportAll<CR>", {silent = true})
    end
}

Don't hesitate to ask if you need any other parts.

kkharji commented 3 years ago

... sadly this still an issue :(. eslint_d just take so much time and timeout happens

jose-elias-alvarez commented 3 years ago

@tami5 Can you open a separate issue and include reproduction steps? I'm using eslint_d constantly for work, so I wonder what's going on.

kkharji commented 3 years ago

@tami5 Can you open a separate issue and include reproduction steps? I'm using eslint_d constantly for work, so I wonder what's going on.

Sure thanks