You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Neovim中null-ls多源格式化与诊断异常问题求助

Neovim中null-ls搭配多语言LSP异常排查

问题描述

我尝试在Neovim中使用null-ls搭配多个源实现代码格式化与诊断功能,终端运行node file.js/file.ts一切正常,但在Neovim中打开文件时总会出现异常(未明确具体问题)。已完成null-ls和lspconfig的配置,支持JavaScript、TypeScript、Python、C++、Go、Shell脚本等多语言,且确认所有所需二进制文件(Prettier、ESLint等)已正确安装,但问题仍未解决。

配置文件

null-ls.lua

return {
    {
        'jose-elias-alvarez/null-ls.nvim',
        event = "BufRead",
        dependencies = { 'nvim-lua/plenary.nvim' },
        config = function()
            local null_ls = require('null-ls')

            null_ls.setup({
                sources = {
                    -- JavaScript/TypeScript
                    null_ls.builtins.formatting.prettier.with({ command = "/opt/homebrew/bin/prettier" }), -- Specify Prettier path
                    null_ls.builtins.formatting.eslint_d,
                    null_ls.builtins.diagnostics.eslint_d,
                    null_ls.builtins.code_actions.eslint_d,

                    -- Python
                    null_ls.builtins.formatting.black,
                    null_ls.builtins.formatting.isort,
                    null_ls.builtins.diagnostics.flake8,
                    null_ls.builtins.diagnostics.mypy,

                    -- C/C++
                    null_ls.builtins.formatting.clang_format,
                    null_ls.builtins.diagnostics.cppcheck,

                    -- Go
                    null_ls.builtins.formatting.gofmt,
                    null_ls.builtins.formatting.goimports,
                    null_ls.builtins.diagnostics.golangci_lint,

                    -- Shell scripts
                    null_ls.builtins.formatting.shfmt,
                    null_ls.builtins.diagnostics.shellcheck
                },

                on_attach = function(client, bufnr)
                    if client.name == "null-ls" then
                        vim.api.nvim_buf_set_option(bufnr, "formatexpr", "v:lua.vim.lsp.formatexpr()")
                    end
                end,

                settings = {
                    ["null-ls"] = {
                        setup = {
                            formatting = {
                                prettier = {
                                    tab_width = 2,
                                    single_quote = true,
                                    trailing_comma = "es5"
                                }
                            }
                        }
                    }
                }
            })

            -- Keymap for formatting with null-ls
            vim.keymap.set('n', '<leader>gf', function() vim.lsp.buf.format() end, { noremap = true, silent = true })
        end
    }
}

lsp-config.lua

return {
    {
        "williamboman/mason.nvim",
        config = function()
            require("mason").setup({
                ui = {
                    border = "rounded",
                    icons = {
                        package_installed = "✓",
                        package_pending = "➜",
                        package_uninstalled = "✗"
                    }
                }
            })
        end
    },
    {
        "williamboman/mason-lspconfig.nvim",
        config = function()
            require("mason-lspconfig").setup({
                ensure_installed = {
                    "clangd",
                    "lua_ls",
                    "gopls",
                    "pyright",
                    "ts_ls" -- Use ts_ls instead of tsserver
                },
                automatic_installation = true
            })
        end
    },
    {
        "neovim/nvim-lspconfig",
        config = function()
            local lspconfig = require("lspconfig")

            -- Global LSP settings
            vim.diagnostic.config({
                virtual_text = true,
                signs = true,
                update_in_insert = false,
                underline = true,
                severity_sort = true,
                float = {
                    border = 'rounded',
                    source = 'always'
                }
            })

            -- Grammarly specific setup with error handling
            local grammarly_ok, _ = pcall(function()
                lspconfig.grammarly.setup({
                    cmd = { "grammarly-languageserver", "--stdio" },
                    filetypes = {
                        "markdown",
                        "text",
                        "tex",
                        "latex"
                    },
                    root_dir = function()
                        return vim.loop.cwd()
                    end,
                    init_options = {
                        clientId = "client_BaDkMgx4X19X9UxxYRCXZo"
                    },
                    settings = {
                        grammarly = {
                            autoActivate = true,
                            suggestions = {
                                writing_style = "default",
                                dialect = "american"
                            }
                        }
                    }
                })
            end)

            if not grammarly_ok then
                vim.notify("Failed to setup Grammarly LSP", vim.log.levels.ERROR)
            end

            -- Setup other LSP servers
            lspconfig.lua_ls.setup({})
            lspconfig.clangd.setup({})
            lspconfig.gopls.setup({})
            lspconfig.pyright.setup({})
            lspconfig.ts_ls.setup({})

            -- Key mappings
            vim.keymap.set('n', '<leader>ca', vim.lsp.buf.code_action, { desc = "Code Action" })
            vim.keymap.set('n', 'gd', vim.lsp.buf.definition, { desc = "Go to Definition" })
            vim.keymap.set('n', 'K', vim.lsp.buf.hover, { desc = "Hover Information" })
            vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, { desc = "Go to Implementation" })
            vim.keymap.set('n', '<leader>rn', vim.lsp.buf.rename, { desc = "Rename" })
        end
    }
}

排查与修复建议

  • 查看null-ls日志:执行:NullLsLog,日志会显示详细错误信息,比如二进制文件找不到、权限不足、配置解析失败等,这是定位问题的核心步骤。
  • 禁用LSP自带的格式化功能:比如ts_ls(原tsserver)本身支持格式化,会和null-ls的prettier/eslint_d冲突,需要在ts_ls的setup中禁用:
    lspconfig.ts_ls.setup({
      on_attach = function(client, bufnr)
        -- 禁用ts_ls的格式化能力,交给null-ls处理
        client.server_capabilities.documentFormattingProvider = false
        client.server_capabilities.documentRangeFormattingProvider = false
      end
    })
    
  • 验证源加载状态:执行:NullLsInfo,查看每个null-ls源的状态是active还是error,如果有源加载失败,根据提示修复。
  • 修正Prettier配置方式:你的null-ls配置中,prettier的设置放在了settings里,这不符合null-ls的配置逻辑,正确做法是通过extra_args传入:
    null_ls.builtins.formatting.prettier.with({
      command = "/opt/homebrew/bin/prettier",
      extra_args = {
        "--tab-width", "2",
        "--single-quote",
        "--trailing-comma", "es5"
      }
    })
    
  • 检查Neovim环境变量:Neovim的PATH可能和终端不一致,执行:echo $PATH确认是否包含brew等二进制文件的路径,若缺失可在init.lua中手动添加:
    vim.env.PATH = "/opt/homebrew/bin:" .. vim.env.PATH
    
  • 逐个排查源:暂时注释掉部分null-ls源,只保留JS/TS相关的prettier和eslint_d,测试是否正常,再逐步添加其他源,定位是哪个源导致的异常。

内容的提问来源于stack exchange,提问作者Nauman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 07:20:59