mfussenegger / nvim-lint

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

Cannot modify golangci-lint args so to read .golangci.yml #532

Closed fredrikaverpil closed 7 months ago

fredrikaverpil commented 7 months ago

Hello πŸ‘‹

What's the problem?

I'm overriding require("lint").linters.golangcilint.args so to read a .golangci.yml config file which tells golangci-lint which linters to use. To be precise, I want to disable the fieldalignment (default) warning. Whatever I do to my .golangci.yml config, I keep seeing this kind of warning.

image

What did I do?

I'm trying to override require("lint").linters.golangcilint.args, so to inject --config <path-to-config-file> when a .golangci.yml file exists somewhere in my project.

If I disable all linters in the config file, I still see the default golangci-lint diagnostics in Neovim whereas I would've expected none to show:

linters:
  disable-all: true

If I instead run the golangci-lint command manually, I can clearly see that the config file has an effect on the linting output:

$ golangci-lint run --out-format json --config path/to/.golangci.yml internal/core/file.go
ERRO Running error: all linters were disabled, but no one linter was enabled: must enable at least one

What could be wrong? Can I not supply the arguments the way I do it, is something wrong in my lua code?

Here is the original, default, setup for golangcilint in this repo.

My setup

{
  "mfussenegger/nvim-lint",
  enabled = true,
  opts = function(_, opts)
    local linters = require("lint").linters

    linters.golangcilint.args = use_golangci_config_if_available(linters)

    local linters_by_ft = {
      protobuf = { "buf", "protolint" },
      python = { "mypy" },
      sh = { "shellcheck" },
      sql = { "sqlfluff" },
      yaml = { "yamllint" },
      go = { "golangcilint" },
    }

    -- extend opts.linters_by_ft
    for ft, linters_ in pairs(linters_by_ft) do
      opts.linters_by_ft[ft] = opts.linters_by_ft[ft] or {}
      vim.list_extend(opts.linters_by_ft[ft], linters_)
    end
  end,
}

Here are the helper functions:

local use_golangci_config_if_available = function(linters)
  local config_file = find_file(".golangci.yml")
  if config_file then
    print("Using golangci-lint config: " .. config_file)
    return {
      "run",
      "--out-format",
      "json",
      "--config",
      config_file,
      function()
        return vim.fn.fnamemodify(vim.api.nvim_buf_get_name(0), ":h")
      end,
    }
  else
    print("Using vanilla golangcilint args" .. vim.inspect(linters.golangcilint.args))
    return linters.golangcilint.args
  end
end

local function find_file(filename)
  local command = "fd --hidden --no-ignore '" .. filename .. "' " .. vim.fn.getcwd() .. " | head -n 1"
  local file = io.popen(command):read("*l")
  return file and file or nil
end

If I add in print statements, I can see how the .golangci.yml file is properly detected and I can see how the arguments are properly populated.

fredrikaverpil commented 7 months ago

I'm closing this as it does seem like the config file is ready properly - and this fieldalignment warning comes from something else entirely.

EDIT: looks like it's gopls which enables fieldalignment:

{
  "neovim/nvim-lspconfig",
  opts = {
    servers = {
      gopls = {
        keys = {
          -- Workaround for the lack of a DAP strategy in neotest-go: https://github.com/nvim-neotest/neotest-go/issues/12
          { "<leader>td", "<cmd>lua require('dap-go').debug_test()<CR>", desc = "Debug Nearest (Go)" },
        },
        settings = {
          gopls = {
            gofumpt = true,
            codelenses = {
              gc_details = false,
              generate = true,
              regenerate_cgo = true,
              run_govulncheck = true,
              test = true,
              tidy = true,
              upgrade_dependency = true,
              vendor = true,
            },
            hints = {
              assignVariableTypes = true,
              compositeLiteralFields = true,
              compositeLiteralTypes = true,
              constantValues = true,
              functionTypeParameters = true,
              parameterNames = true,
              rangeVariableTypes = true,
            },
            analyses = {
              fieldalignment = true,
              nilness = true,
              unusedparams = true,
              unusedwrite = true,
              useany = true,
            },
            usePlaceholders = true,
            completeUnimported = true,
            staticcheck = true,
            directoryFilters = { "-.git", "-.vscode", "-.idea", "-.vscode-test", "-node_modules" },
            semanticTokens = true,
          },
        },
      },
    },
    setup = {
      gopls = function(_, opts)
        -- workaround for gopls not supporting semanticTokensProvider
        -- https://github.com/golang/go/issues/54531#issuecomment-1464982242
        require("lazyvim.util").lsp.on_attach(function(client, _)
          if client.name == "gopls" then
            if not client.server_capabilities.semanticTokensProvider then
              local semantic = client.config.capabilities.textDocument.semanticTokens
              client.server_capabilities.semanticTokensProvider = {
                full = true,
                legend = {
                  tokenTypes = semantic.tokenTypes,
                  tokenModifiers = semantic.tokenModifiers,
                },
                range = true,
              }
            end
          end
        end)
        -- end workaround
      end,
    },
  },
}