moves to eslint lsp
This commit is contained in:
parent
91dd752b66
commit
11eca2baa5
5 changed files with 217 additions and 71 deletions
|
|
@ -13,7 +13,7 @@
|
||||||
"lualine.nvim": { "branch": "master", "commit": "b8c23159c0161f4b89196f74ee3a6d02cdc3a955" },
|
"lualine.nvim": { "branch": "master", "commit": "b8c23159c0161f4b89196f74ee3a6d02cdc3a955" },
|
||||||
"mini.diff": { "branch": "main", "commit": "7077b636d642fcd5cd48554e187a251883239660" },
|
"mini.diff": { "branch": "main", "commit": "7077b636d642fcd5cd48554e187a251883239660" },
|
||||||
"mini.icons": { "branch": "main", "commit": "f9a177c11daa7829389b7b6eaaec8b8a5c47052d" },
|
"mini.icons": { "branch": "main", "commit": "f9a177c11daa7829389b7b6eaaec8b8a5c47052d" },
|
||||||
"mini.pairs": { "branch": "main", "commit": "6e1cc569130f25b2c6fa16d8b21b31ddb1420a4a" },
|
"mini.pairs": { "branch": "main", "commit": "3738ea30ff33e0cbf2983dc67319a5468d25b0a9" },
|
||||||
"none-ls-extras.nvim": { "branch": "main", "commit": "924fe88a9983c7d90dbb31fc4e3129a583ea0a90" },
|
"none-ls-extras.nvim": { "branch": "main", "commit": "924fe88a9983c7d90dbb31fc4e3129a583ea0a90" },
|
||||||
"none-ls.nvim": { "branch": "main", "commit": "df778107fd2f0503f5606363ce13437132056d54" },
|
"none-ls.nvim": { "branch": "main", "commit": "df778107fd2f0503f5606363ce13437132056d54" },
|
||||||
"nvim-surround": { "branch": "main", "commit": "a868c256c861044beb9794b4dd126480dcdfbdad" },
|
"nvim-surround": { "branch": "main", "commit": "a868c256c861044beb9794b4dd126480dcdfbdad" },
|
||||||
|
|
@ -21,9 +21,9 @@
|
||||||
"nvim-web-devicons": { "branch": "master", "commit": "6e51ca170563330e063720449c21f43e27ca0bc1" },
|
"nvim-web-devicons": { "branch": "master", "commit": "6e51ca170563330e063720449c21f43e27ca0bc1" },
|
||||||
"oil.nvim": { "branch": "master", "commit": "07f80ad645895af849a597d1cac897059d89b686" },
|
"oil.nvim": { "branch": "master", "commit": "07f80ad645895af849a597d1cac897059d89b686" },
|
||||||
"plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" },
|
"plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" },
|
||||||
"render-markdown.nvim": { "branch": "main", "commit": "e76eb2e4262f0f0a1a7bd7a454dd7d44f1299afd" },
|
"render-markdown.nvim": { "branch": "main", "commit": "95994ad668786cd75d0ee6d0b7178bce7c3ca146" },
|
||||||
"rose-pine": { "branch": "main", "commit": "72a04c4065345b51b56aed4859ea1d884f734097" },
|
"rose-pine": { "branch": "main", "commit": "72a04c4065345b51b56aed4859ea1d884f734097" },
|
||||||
"schemastore.nvim": { "branch": "main", "commit": "2ae6d27897c60265d4ad3f33e286528d519098fd" },
|
"schemastore.nvim": { "branch": "main", "commit": "fb58187b76d8e086f08686b872b50f52eac57818" },
|
||||||
"snacks.nvim": { "branch": "main", "commit": "bc0630e43be5699bb94dadc302c0d21615421d93" },
|
"snacks.nvim": { "branch": "main", "commit": "bc0630e43be5699bb94dadc302c0d21615421d93" },
|
||||||
"substitute.nvim": { "branch": "main", "commit": "9db749a880e3dd3b0eb57f698aa8f1e1630e1f25" },
|
"substitute.nvim": { "branch": "main", "commit": "9db749a880e3dd3b0eb57f698aa8f1e1630e1f25" },
|
||||||
"todo-comments.nvim": { "branch": "main", "commit": "304a8d204ee787d2544d8bc23cd38d2f929e7cc5" },
|
"todo-comments.nvim": { "branch": "main", "commit": "304a8d204ee787d2544d8bc23cd38d2f929e7cc5" },
|
||||||
|
|
|
||||||
185
modules/nvim/config/lsp/eslint.lua
Normal file
185
modules/nvim/config/lsp/eslint.lua
Normal file
|
|
@ -0,0 +1,185 @@
|
||||||
|
local utils = require("dnsc.utils")
|
||||||
|
local lsp = vim.lsp
|
||||||
|
|
||||||
|
local eslint_config_files = {
|
||||||
|
".eslintrc",
|
||||||
|
".eslintrc.js",
|
||||||
|
".eslintrc.cjs",
|
||||||
|
".eslintrc.yaml",
|
||||||
|
".eslintrc.yml",
|
||||||
|
".eslintrc.json",
|
||||||
|
"eslint.config.js",
|
||||||
|
"eslint.config.mjs",
|
||||||
|
"eslint.config.cjs",
|
||||||
|
"eslint.config.ts",
|
||||||
|
"eslint.config.mts",
|
||||||
|
"eslint.config.cts",
|
||||||
|
}
|
||||||
|
|
||||||
|
---@type vim.lsp.Config
|
||||||
|
return {
|
||||||
|
cmd = { "vscode-eslint-language-server", "--stdio" },
|
||||||
|
filetypes = {
|
||||||
|
"javascript",
|
||||||
|
"javascriptreact",
|
||||||
|
"javascript.jsx",
|
||||||
|
"typescript",
|
||||||
|
"typescriptreact",
|
||||||
|
"typescript.tsx",
|
||||||
|
"vue",
|
||||||
|
"svelte",
|
||||||
|
"astro",
|
||||||
|
"htmlangular",
|
||||||
|
},
|
||||||
|
workspace_required = true,
|
||||||
|
on_attach = function(client, bufnr)
|
||||||
|
vim.api.nvim_buf_create_user_command(0, "LspEslintFixAll", function()
|
||||||
|
client:request_sync("workspace/executeCommand", {
|
||||||
|
command = "eslint.applyAllFixes",
|
||||||
|
arguments = {
|
||||||
|
{
|
||||||
|
uri = vim.uri_from_bufnr(bufnr),
|
||||||
|
version = lsp.util.buf_versions[bufnr],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil, bufnr)
|
||||||
|
end, {})
|
||||||
|
end,
|
||||||
|
root_dir = function(bufnr, on_dir)
|
||||||
|
-- The project root is where the LSP can be started from
|
||||||
|
-- As stated in the documentation above, this LSP supports monorepos and simple projects.
|
||||||
|
-- We select then from the project root, which is identified by the presence of a package
|
||||||
|
-- manager lock file.
|
||||||
|
local root_markers = { "package-lock.json", "yarn.lock", "pnpm-lock.yaml", "bun.lockb", "bun.lock", "deno.lock" }
|
||||||
|
-- Give the root markers equal priority by wrapping them in a table
|
||||||
|
root_markers = vim.fn.has("nvim-0.11.3") == 1 and { root_markers } or root_markers
|
||||||
|
local project_root = vim.fs.root(bufnr, root_markers)
|
||||||
|
if not project_root then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- We know that the buffer is using ESLint if it has a config file
|
||||||
|
-- in its directory tree.
|
||||||
|
--
|
||||||
|
-- Eslint used to support package.json files as config files, but it doesn't anymore.
|
||||||
|
-- We keep this for backward compatibility.
|
||||||
|
local filename = vim.api.nvim_buf_get_name(bufnr)
|
||||||
|
local eslint_config_files_with_package_json =
|
||||||
|
utils.insert_package_json(eslint_config_files, "eslintConfig", filename)
|
||||||
|
local is_buffer_using_eslint = vim.fs.find(eslint_config_files_with_package_json, {
|
||||||
|
path = filename,
|
||||||
|
type = "file",
|
||||||
|
limit = 1,
|
||||||
|
upward = true,
|
||||||
|
stop = vim.fs.dirname(project_root),
|
||||||
|
})[1]
|
||||||
|
if not is_buffer_using_eslint then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
on_dir(project_root)
|
||||||
|
end,
|
||||||
|
-- Refer to https://github.com/Microsoft/vscode-eslint#settings-options for documentation.
|
||||||
|
settings = {
|
||||||
|
validate = "on",
|
||||||
|
packageManager = nil,
|
||||||
|
useESLintClass = false,
|
||||||
|
experimental = {
|
||||||
|
useFlatConfig = false,
|
||||||
|
},
|
||||||
|
codeActionOnSave = {
|
||||||
|
enable = false,
|
||||||
|
mode = "all",
|
||||||
|
},
|
||||||
|
format = true,
|
||||||
|
quiet = false,
|
||||||
|
onIgnoredFiles = "off",
|
||||||
|
rulesCustomizations = {},
|
||||||
|
run = "onType",
|
||||||
|
problems = {
|
||||||
|
shortenToSingleLine = false,
|
||||||
|
},
|
||||||
|
-- nodePath configures the directory in which the eslint server should start its node_modules resolution.
|
||||||
|
-- This path is relative to the workspace folder (root dir) of the server instance.
|
||||||
|
nodePath = "",
|
||||||
|
-- use the workspace folder location or the file location (if no workspace folder is open) as the working directory
|
||||||
|
workingDirectory = { mode = "auto" },
|
||||||
|
codeAction = {
|
||||||
|
disableRuleComment = {
|
||||||
|
enable = true,
|
||||||
|
location = "separateLine",
|
||||||
|
},
|
||||||
|
showDocumentation = {
|
||||||
|
enable = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
before_init = function(_, config)
|
||||||
|
-- The "workspaceFolder" is a VSCode concept. It limits how far the
|
||||||
|
-- server will traverse the file system when locating the ESLint config
|
||||||
|
-- file (e.g., .eslintrc).
|
||||||
|
local root_dir = config.root_dir
|
||||||
|
|
||||||
|
if root_dir then
|
||||||
|
config.settings = config.settings or {}
|
||||||
|
config.settings.workspaceFolder = {
|
||||||
|
uri = root_dir,
|
||||||
|
name = vim.fn.fnamemodify(root_dir, ":t"),
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Support flat config files
|
||||||
|
-- They contain 'config' in the file name
|
||||||
|
local flat_config_files = vim.tbl_filter(function(file)
|
||||||
|
return file:match("config")
|
||||||
|
end, eslint_config_files)
|
||||||
|
|
||||||
|
for _, file in ipairs(flat_config_files) do
|
||||||
|
local found_files = vim.fn.globpath(root_dir, file, true, true)
|
||||||
|
|
||||||
|
-- Filter out files inside node_modules
|
||||||
|
local filtered_files = {}
|
||||||
|
for _, found_file in ipairs(found_files) do
|
||||||
|
if string.find(found_file, "[/\\]node_modules[/\\]") == nil then
|
||||||
|
table.insert(filtered_files, found_file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #filtered_files > 0 then
|
||||||
|
config.settings.experimental = config.settings.experimental or {}
|
||||||
|
config.settings.experimental.useFlatConfig = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Support Yarn2 (PnP) projects
|
||||||
|
local pnp_cjs = root_dir .. "/.pnp.cjs"
|
||||||
|
local pnp_js = root_dir .. "/.pnp.js"
|
||||||
|
if vim.uv.fs_stat(pnp_cjs) or vim.uv.fs_stat(pnp_js) then
|
||||||
|
local cmd = config.cmd
|
||||||
|
config.cmd = vim.list_extend({ "yarn", "exec" }, cmd)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
handlers = {
|
||||||
|
["eslint/openDoc"] = function(_, result)
|
||||||
|
if result then
|
||||||
|
vim.ui.open(result.url)
|
||||||
|
end
|
||||||
|
return {}
|
||||||
|
end,
|
||||||
|
["eslint/confirmESLintExecution"] = function(_, result)
|
||||||
|
if not result then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return 4 -- approved
|
||||||
|
end,
|
||||||
|
["eslint/probeFailed"] = function()
|
||||||
|
vim.notify("[lspconfig] ESLint probe failed.", vim.log.levels.WARN)
|
||||||
|
return {}
|
||||||
|
end,
|
||||||
|
["eslint/noLibrary"] = function()
|
||||||
|
vim.notify("[lspconfig] Unable to find ESLint library.", vim.log.levels.WARN)
|
||||||
|
return {}
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ vim.lsp.enable("nil_ls")
|
||||||
vim.lsp.enable("astro")
|
vim.lsp.enable("astro")
|
||||||
vim.lsp.enable("tailwindcss")
|
vim.lsp.enable("tailwindcss")
|
||||||
vim.lsp.enable("gopls")
|
vim.lsp.enable("gopls")
|
||||||
|
vim.lsp.enable("eslint")
|
||||||
|
|
||||||
vim.diagnostic.config({
|
vim.diagnostic.config({
|
||||||
virtual_text = false,
|
virtual_text = false,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ end
|
||||||
|
|
||||||
function search_ancestors(startpath, func)
|
function search_ancestors(startpath, func)
|
||||||
if nvim_eleven then
|
if nvim_eleven then
|
||||||
validate('func', func, 'function')
|
validate("func", func, "function")
|
||||||
end
|
end
|
||||||
if func(startpath) then
|
if func(startpath) then
|
||||||
return startpath
|
return startpath
|
||||||
|
|
@ -36,13 +36,13 @@ function search_ancestors(startpath, func)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function escape_wildcards(path)
|
local function escape_wildcards(path)
|
||||||
return path:gsub('([%[%]%?%*])', '\\%1')
|
return path:gsub("([%[%]%?%*])", "\\%1")
|
||||||
end
|
end
|
||||||
|
|
||||||
function strip_archive_subpath(path)
|
function strip_archive_subpath(path)
|
||||||
-- Matches regex from zip.vim / tar.vim
|
-- Matches regex from zip.vim / tar.vim
|
||||||
path = vim.fn.substitute(path, 'zipfile://\\(.\\{-}\\)::[^\\\\].*$', '\\1', '')
|
path = vim.fn.substitute(path, "zipfile://\\(.\\{-}\\)::[^\\\\].*$", "\\1", "")
|
||||||
path = vim.fn.substitute(path, 'tarfile:\\(.\\{-}\\)::.*$', '\\1', '')
|
path = vim.fn.substitute(path, "tarfile:\\(.\\{-}\\)::.*$", "\\1", "")
|
||||||
return path
|
return path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -125,9 +125,32 @@ local function compile_project()
|
||||||
vim.cmd("startinsert")
|
vim.cmd("startinsert")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function root_markers_with_field(root_files, new_names, field, fname)
|
||||||
|
local path = vim.fn.fnamemodify(fname, ":h")
|
||||||
|
local found = vim.fs.find(new_names, { path = path, upward = true })
|
||||||
|
|
||||||
|
for _, f in ipairs(found or {}) do
|
||||||
|
-- Match the given `field`.
|
||||||
|
for line in io.lines(f) do
|
||||||
|
if line:find(field) then
|
||||||
|
root_files[#root_files + 1] = vim.fs.basename(f)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return root_files
|
||||||
|
end
|
||||||
|
|
||||||
|
local function insert_package_json(root_files, field, fname)
|
||||||
|
return root_markers_with_field(root_files, { "package.json", "package.json5" }, field, fname)
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
compile_project = compile_project,
|
compile_project = compile_project,
|
||||||
filter = filter,
|
filter = filter,
|
||||||
filterReactDTS = filterReactDTS,
|
filterReactDTS = filterReactDTS,
|
||||||
root_pattern = root_pattern
|
root_pattern = root_pattern,
|
||||||
|
insert_package_json = insert_package_json,
|
||||||
|
root_markers_with_field = root_markers_with_field,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
return {
|
|
||||||
"nvimtools/none-ls.nvim",
|
|
||||||
dependencies = {
|
|
||||||
"nvimtools/none-ls-extras.nvim",
|
|
||||||
},
|
|
||||||
config = function()
|
|
||||||
local null_ls = require("null-ls")
|
|
||||||
local utils = require("dnsc.utils")
|
|
||||||
|
|
||||||
local string_starts_with = function(str, start)
|
|
||||||
return string.sub(str, 1, #start) == start
|
|
||||||
end
|
|
||||||
|
|
||||||
local create_runtime_condition = function(config_names)
|
|
||||||
local bufnr_cache = {}
|
|
||||||
local config_path_cache = {}
|
|
||||||
|
|
||||||
return function(params)
|
|
||||||
if bufnr_cache[params.bufnr] ~= nil then
|
|
||||||
return bufnr_cache[params.bufnr]
|
|
||||||
else
|
|
||||||
for _, cached_config_path in ipairs(config_path_cache) do
|
|
||||||
if string_starts_with(params.bufname, cached_config_path) then
|
|
||||||
bufnr_cache[params.bufnr] = true
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local config_path = utils.root_pattern(config_names)(params.bufname)
|
|
||||||
|
|
||||||
local has_config = config_path ~= nil
|
|
||||||
if has_config then
|
|
||||||
table.insert(config_path_cache, config_path)
|
|
||||||
end
|
|
||||||
bufnr_cache[params.bufnr] = has_config
|
|
||||||
|
|
||||||
return has_config
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local eslint_runtime_condition = create_runtime_condition({
|
|
||||||
".eslintrc.cjs",
|
|
||||||
".eslintrc.js",
|
|
||||||
".eslintrc.json",
|
|
||||||
".eslintrc.yaml",
|
|
||||||
".eslintrc.yml",
|
|
||||||
"eslint.config.mjs",
|
|
||||||
"eslint.config.js",
|
|
||||||
"eslint.config.ts",
|
|
||||||
"eslint.config.mts",
|
|
||||||
})
|
|
||||||
|
|
||||||
null_ls.setup({
|
|
||||||
sources = {
|
|
||||||
require("none-ls.code_actions.eslint_d"),
|
|
||||||
require("none-ls.diagnostics.eslint_d").with({
|
|
||||||
runtime_condition = eslint_runtime_condition,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue