From ec1f7a37473a9471c929ef60f83cfcb32ae365a0 Mon Sep 17 00:00:00 2001 From: William Parsons-Heins Date: Sun, 26 May 2024 14:05:12 +0100 Subject: [PATCH 1/8] pull out all core typescript config into typescript.core --- lua/astrocommunity/pack/typescript/core.lua | 108 ++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 lua/astrocommunity/pack/typescript/core.lua diff --git a/lua/astrocommunity/pack/typescript/core.lua b/lua/astrocommunity/pack/typescript/core.lua new file mode 100644 index 000000000..0dfb23bed --- /dev/null +++ b/lua/astrocommunity/pack/typescript/core.lua @@ -0,0 +1,108 @@ +return { + { import = "astrocommunity.pack.json" }, + { import = "astrocommunity.lsp.nvim-lsp-file-operations" }, + { + "nvim-treesitter/nvim-treesitter", + optional = true, + opts = function(_, opts) + if opts.ensure_installed ~= "all" then + opts.ensure_installed = + require("astrocore").list_insert_unique(opts.ensure_installed, { "javascript", "typescript", "tsx", "jsdoc" }) + end + end, + }, + { + "AstroNvim/astrolsp", + ---@type AstroLSPOpts + opts = { + ---@diagnostic disable: missing-fields + config = { + vtsls = { + settings = { + typescript = { + updateImportsOnFileMove = { enabled = "always" }, + inlayHints = { + parameterNames = { enabled = "all" }, + parameterTypes = { enabled = true }, + variableTypes = { enabled = true }, + propertyDeclarationTypes = { enabled = true }, + functionLikeReturnTypes = { enabled = true }, + enumMemberValues = { enabled = true }, + }, + }, + javascript = { + updateImportsOnFileMove = { enabled = "always" }, + inlayHints = { + parameterNames = { enabled = "literals" }, + parameterTypes = { enabled = true }, + variableTypes = { enabled = true }, + propertyDeclarationTypes = { enabled = true }, + functionLikeReturnTypes = { enabled = true }, + enumMemberValues = { enabled = true }, + }, + }, + vtsls = { + enableMoveToFileCodeAction = true, + }, + }, + }, + }, + }, + }, + { + "williamboman/mason-lspconfig.nvim", + opts = function(_, opts) + opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, { "vtsls" }) + end, + }, + { + "jay-babu/mason-nvim-dap.nvim", + optional = true, + opts = function(_, opts) + opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, { "js" }) + end, + }, + { + "WhoIsSethDaniel/mason-tool-installer.nvim", + optional = true, + opts = function(_, opts) + opts.ensure_installed = + require("astrocore").list_insert_unique(opts.ensure_installed, { "vtsls", "js-debug-adapter" }) + end, + }, + { + "vuki656/package-info.nvim", + dependencies = { "MunifTanjim/nui.nvim" }, + opts = {}, + event = "BufRead package.json", + }, + { + "yioneko/nvim-vtsls", + lazy = true, + dependencies = { + "AstroNvim/astrocore", + opts = { + autocmds = { + nvim_vtsls = { + { + event = "LspAttach", + desc = "Load nvim-vtsls with vtsls", + callback = function(args) + if assert(vim.lsp.get_client_by_id(args.data.client_id)).name == "vtsls" then + require("vtsls")._on_attach(args.data.client_id, args.buf) + vim.api.nvim_del_augroup_by_name "nvim_vtsls" + end + end, + }, + }, + }, + }, + }, + config = function(_, opts) require("vtsls").config(opts) end, + }, + { + "dmmulroy/tsc.nvim", + cmd = "TSC", + opts = {}, + }, +} From e6cb57b1f571f8978c9ec5f1557729b7710542a3 Mon Sep 17 00:00:00 2001 From: William Parsons-Heins Date: Sun, 26 May 2024 14:06:02 +0100 Subject: [PATCH 2/8] refactor typescript.init to use typescript.core and then add eslint+prettier on top --- lua/astrocommunity/pack/typescript/init.lua | 99 ++------------------- 1 file changed, 5 insertions(+), 94 deletions(-) diff --git a/lua/astrocommunity/pack/typescript/init.lua b/lua/astrocommunity/pack/typescript/init.lua index 10fe79165..4f06ba5e3 100644 --- a/lua/astrocommunity/pack/typescript/init.lua +++ b/lua/astrocommunity/pack/typescript/init.lua @@ -27,9 +27,7 @@ local has_prettier = function(bufnr) if not lsp_rooter then lsp_rooter = rooter.resolve("lsp", { ignore = { - servers = function(client) - return not vim.tbl_contains({ "vtsls", "typescript-tools", "volar", "eslint", "tsserver" }, client.name) - end, + servers = function(client) return not vim.tbl_contains({ "eslint" }, client.name) end, }, }) end @@ -73,18 +71,7 @@ end local conform_formatter = function(bufnr) return has_prettier(bufnr) and { "prettierd" } or {} end return { - { import = "astrocommunity.pack.json" }, - { import = "astrocommunity.lsp.nvim-lsp-file-operations" }, - { - "nvim-treesitter/nvim-treesitter", - optional = true, - opts = function(_, opts) - if opts.ensure_installed ~= "all" then - opts.ensure_installed = - require("astrocore").list_insert_unique(opts.ensure_installed, { "javascript", "typescript", "tsx", "jsdoc" }) - end - end, - }, + { import = "astrocommunity.pack.typescript.core" }, { "AstroNvim/astrolsp", ---@type AstroLSPOpts @@ -99,44 +86,12 @@ return { }, }, }, - ---@diagnostic disable: missing-fields - config = { - vtsls = { - settings = { - typescript = { - updateImportsOnFileMove = { enabled = "always" }, - inlayHints = { - parameterNames = { enabled = "all" }, - parameterTypes = { enabled = true }, - variableTypes = { enabled = true }, - propertyDeclarationTypes = { enabled = true }, - functionLikeReturnTypes = { enabled = true }, - enumMemberValues = { enabled = true }, - }, - }, - javascript = { - updateImportsOnFileMove = { enabled = "always" }, - inlayHints = { - parameterNames = { enabled = "literals" }, - parameterTypes = { enabled = true }, - variableTypes = { enabled = true }, - propertyDeclarationTypes = { enabled = true }, - functionLikeReturnTypes = { enabled = true }, - enumMemberValues = { enabled = true }, - }, - }, - vtsls = { - enableMoveToFileCodeAction = true, - }, - }, - }, - }, }, }, { "williamboman/mason-lspconfig.nvim", opts = function(_, opts) - opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, { "vtsls", "eslint" }) + opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, { "eslint" }) end, }, { @@ -164,56 +119,12 @@ return { end end, }, - { - "jay-babu/mason-nvim-dap.nvim", - optional = true, - opts = function(_, opts) - opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, { "js" }) - end, - }, { "WhoIsSethDaniel/mason-tool-installer.nvim", optional = true, opts = function(_, opts) - opts.ensure_installed = require("astrocore").list_insert_unique( - opts.ensure_installed, - { "vtsls", "eslint-lsp", "prettierd", "js-debug-adapter" } - ) + opts.ensure_installed = + require("astrocore").list_insert_unique(opts.ensure_installed, { "eslint-lsp", "prettierd" }) end, }, - { - "vuki656/package-info.nvim", - dependencies = { "MunifTanjim/nui.nvim" }, - opts = {}, - event = "BufRead package.json", - }, - { - "yioneko/nvim-vtsls", - lazy = true, - dependencies = { - "AstroNvim/astrocore", - opts = { - autocmds = { - nvim_vtsls = { - { - event = "LspAttach", - desc = "Load nvim-vtsls with vtsls", - callback = function(args) - if assert(vim.lsp.get_client_by_id(args.data.client_id)).name == "vtsls" then - require("vtsls")._on_attach(args.data.client_id, args.buf) - vim.api.nvim_del_augroup_by_name "nvim_vtsls" - end - end, - }, - }, - }, - }, - }, - config = function(_, opts) require("vtsls").config(opts) end, - }, - { - "dmmulroy/tsc.nvim", - cmd = "TSC", - opts = {}, - }, } From d235232c6e0202c1b956daacc83a7a7758cdb559 Mon Sep 17 00:00:00 2001 From: William Parsons-Heins Date: Wed, 29 May 2024 18:33:24 +0100 Subject: [PATCH 3/8] first go at the biome pack... --- lua/astrocommunity/pack/typescript/biome.lua | 32 ++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 lua/astrocommunity/pack/typescript/biome.lua diff --git a/lua/astrocommunity/pack/typescript/biome.lua b/lua/astrocommunity/pack/typescript/biome.lua new file mode 100644 index 000000000..456fee151 --- /dev/null +++ b/lua/astrocommunity/pack/typescript/biome.lua @@ -0,0 +1,32 @@ +local has_biome = function() + local bufnr = vim.api.nvim_get_current_buf() + local rooter = require "astrocore.rooter" + + local biomejson_rooter = rooter.resolve { + "biome.json", + } + + return next(biomejson_rooter(bufnr)) +end + +return { + { import = "astrocommunity.pack.typescript.core" }, + { + "williamboman/mason-lspconfig.nvim", + opts = function(_, opts) + opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, { "biome" }) + end, + }, + { + "jay-babu/mason-null-ls.nvim", + opts = function(_, opts) + if not opts.handlers then opts.handlers = {} end + + if ~has_biome() then return end + + -- TODO: prettier should be off for all filetypes that biome supports, + -- currently this is { "javascript", "javascriptreact", "typescript", "typescriptreact", "json" } + opts.handlers.prettierd = function() end + end, + }, +} From d14d3384ba364168dac21caa5db9df192778d019 Mon Sep 17 00:00:00 2001 From: William Parsons-Heins Date: Wed, 29 May 2024 18:33:26 +0100 Subject: [PATCH 4/8] readme --- lua/astrocommunity/pack/typescript/README.md | 42 +++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/lua/astrocommunity/pack/typescript/README.md b/lua/astrocommunity/pack/typescript/README.md index c0c2a4f7c..06cb0bd98 100644 --- a/lua/astrocommunity/pack/typescript/README.md +++ b/lua/astrocommunity/pack/typescript/README.md @@ -1,5 +1,13 @@ # TypeScript Language Pack +> [!NOTE] +> The default functionality for this pack is to use eslint and prettier, if you want to use biome then use `typescript.biome`. +> If you don't want either, then use `typescript.core`. +> +> Both variants (default and biome) can be used in unison, and it will determine the appropriate config as best as it can. + +## Default + This plugin pack does the following: - Adds `typescript`, `javascript`, `tsx`, and `jsdoc` Treesitter parsers @@ -11,7 +19,7 @@ This plugin pack does the following: - Adds [package-info.nvim](https://github.com/vuki656/package-info.nvim) for project package management - Adds [nvim-lsp-file-operations](https://github.com/antosha417/nvim-lsp-file-operations) to handles file imports on rename or move within neo-tree -## How do I disable Eslint format on save? +### How do I disable Eslint format on save? To opt out of the Eslint format on save behaviour, you can disable the autocmd setup with the pack with this: @@ -26,3 +34,35 @@ return { }, } ``` + +## Biome + +This plugin pack does the following: + +- Adds `typescript`, `javascript`, `tsx`, and `jsdoc` Treesitter parsers +- Adds `vtsls` and `biome` language server +- Adds [JSON language support](../json) +- Adds support for dap for JS +- Adds [nvim-vtsls](https://github.com/yioneko/nvim-vtsls) for language specific tooling +- Adds [package-info.nvim](https://github.com/vuki656/package-info.nvim) for project package management +- Adds [nvim-lsp-file-operations](https://github.com/antosha417/nvim-lsp-file-operations) to handles file imports on rename or move within neo-tree + +### How do I use biome without mason? + +If you have biome as a dependency, then it's recommended to run the LSP through that dependency. This is because the biome linter and formatter +is prone to change between versions meaning your LSP can show different diagnostics compared to the actual version of biome you have installed. + +```lua +return { + "AstroNvim/astrolsp", + servers = { + "biome", + }, + config = { + biome = { + -- Use the package manager of your project: npx, yarn, pnpm, bun... + cmd = { "yarn", "biome", "lsp-proxy" } + } + } +} +``` From c4d9333b115ad844cb7bff948770af3515ade447 Mon Sep 17 00:00:00 2001 From: William Parsons-Heins Date: Wed, 29 May 2024 18:43:18 +0100 Subject: [PATCH 5/8] fix syntax problem --- lua/astrocommunity/pack/typescript/biome.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/astrocommunity/pack/typescript/biome.lua b/lua/astrocommunity/pack/typescript/biome.lua index 456fee151..68b28ae70 100644 --- a/lua/astrocommunity/pack/typescript/biome.lua +++ b/lua/astrocommunity/pack/typescript/biome.lua @@ -22,7 +22,7 @@ return { opts = function(_, opts) if not opts.handlers then opts.handlers = {} end - if ~has_biome() then return end + if not has_biome() then return end -- TODO: prettier should be off for all filetypes that biome supports, -- currently this is { "javascript", "javascriptreact", "typescript", "typescriptreact", "json" } From 0daabd161e6115a000a0794f17c2c6c85dea0f06 Mon Sep 17 00:00:00 2001 From: William Parsons-Heins Date: Wed, 29 May 2024 20:16:13 +0100 Subject: [PATCH 6/8] prefer typescript-biome instead of typescript.biome --- .../pack/typescript-biome/README.md | 31 +++++++++++++++++++ .../biome.lua => typescript-biome/init.lua} | 0 2 files changed, 31 insertions(+) create mode 100644 lua/astrocommunity/pack/typescript-biome/README.md rename lua/astrocommunity/pack/{typescript/biome.lua => typescript-biome/init.lua} (100%) diff --git a/lua/astrocommunity/pack/typescript-biome/README.md b/lua/astrocommunity/pack/typescript-biome/README.md new file mode 100644 index 000000000..de9b996d2 --- /dev/null +++ b/lua/astrocommunity/pack/typescript-biome/README.md @@ -0,0 +1,31 @@ +# TypeScript Biome Language Pack + +This plugin pack does the following: + +- Adds `typescript`, `javascript`, `tsx`, and `jsdoc` Treesitter parsers +- Adds `vtsls` and `biome` language server +- Adds [JSON language support](../json) +- Adds support for dap for JS +- Adds [nvim-vtsls](https://github.com/yioneko/nvim-vtsls) for language specific tooling +- Adds [package-info.nvim](https://github.com/vuki656/package-info.nvim) for project package management +- Adds [nvim-lsp-file-operations](https://github.com/antosha417/nvim-lsp-file-operations) to handles file imports on rename or move within neo-tree + +## How do I use biome without mason? + +If you have biome as a dependency, then it's recommended to run the LSP through that dependency. This is because the biome linter and formatter +is prone to change between versions meaning your LSP can show different diagnostics compared to the actual version of biome you have installed. + +```lua +return { + "AstroNvim/astrolsp", + servers = { + "biome", + }, + config = { + biome = { + -- Use the package manager of your project: npx, yarn, pnpm, bun... + cmd = { "yarn", "biome", "lsp-proxy" } + } + } +} +``` diff --git a/lua/astrocommunity/pack/typescript/biome.lua b/lua/astrocommunity/pack/typescript-biome/init.lua similarity index 100% rename from lua/astrocommunity/pack/typescript/biome.lua rename to lua/astrocommunity/pack/typescript-biome/init.lua From d836b57d419a6984eb8a596c2fd8b9b4489d4169 Mon Sep 17 00:00:00 2001 From: William Parsons-Heins Date: Wed, 29 May 2024 20:16:20 +0100 Subject: [PATCH 7/8] put the typescript readme back to how it was This reverts commit 1e9feeb259f75d38295580bf272f1f6e9d06a8df. --- lua/astrocommunity/pack/typescript/README.md | 42 +------------------- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/lua/astrocommunity/pack/typescript/README.md b/lua/astrocommunity/pack/typescript/README.md index 06cb0bd98..c0c2a4f7c 100644 --- a/lua/astrocommunity/pack/typescript/README.md +++ b/lua/astrocommunity/pack/typescript/README.md @@ -1,13 +1,5 @@ # TypeScript Language Pack -> [!NOTE] -> The default functionality for this pack is to use eslint and prettier, if you want to use biome then use `typescript.biome`. -> If you don't want either, then use `typescript.core`. -> -> Both variants (default and biome) can be used in unison, and it will determine the appropriate config as best as it can. - -## Default - This plugin pack does the following: - Adds `typescript`, `javascript`, `tsx`, and `jsdoc` Treesitter parsers @@ -19,7 +11,7 @@ This plugin pack does the following: - Adds [package-info.nvim](https://github.com/vuki656/package-info.nvim) for project package management - Adds [nvim-lsp-file-operations](https://github.com/antosha417/nvim-lsp-file-operations) to handles file imports on rename or move within neo-tree -### How do I disable Eslint format on save? +## How do I disable Eslint format on save? To opt out of the Eslint format on save behaviour, you can disable the autocmd setup with the pack with this: @@ -34,35 +26,3 @@ return { }, } ``` - -## Biome - -This plugin pack does the following: - -- Adds `typescript`, `javascript`, `tsx`, and `jsdoc` Treesitter parsers -- Adds `vtsls` and `biome` language server -- Adds [JSON language support](../json) -- Adds support for dap for JS -- Adds [nvim-vtsls](https://github.com/yioneko/nvim-vtsls) for language specific tooling -- Adds [package-info.nvim](https://github.com/vuki656/package-info.nvim) for project package management -- Adds [nvim-lsp-file-operations](https://github.com/antosha417/nvim-lsp-file-operations) to handles file imports on rename or move within neo-tree - -### How do I use biome without mason? - -If you have biome as a dependency, then it's recommended to run the LSP through that dependency. This is because the biome linter and formatter -is prone to change between versions meaning your LSP can show different diagnostics compared to the actual version of biome you have installed. - -```lua -return { - "AstroNvim/astrolsp", - servers = { - "biome", - }, - config = { - biome = { - -- Use the package manager of your project: npx, yarn, pnpm, bun... - cmd = { "yarn", "biome", "lsp-proxy" } - } - } -} -``` From a6a7b439cfcec8212678d6d391073540dc674afd Mon Sep 17 00:00:00 2001 From: William Parsons-Heins Date: Fri, 31 May 2024 20:39:52 +0100 Subject: [PATCH 8/8] if biome is setup then use that to format, else prettier --- .../pack/typescript-biome/init.lua | 111 +++++++++++++++++- 1 file changed, 106 insertions(+), 5 deletions(-) diff --git a/lua/astrocommunity/pack/typescript-biome/init.lua b/lua/astrocommunity/pack/typescript-biome/init.lua index 68b28ae70..f47ac0da3 100644 --- a/lua/astrocommunity/pack/typescript-biome/init.lua +++ b/lua/astrocommunity/pack/typescript-biome/init.lua @@ -1,4 +1,74 @@ -local has_biome = function() +local function decode_json(filename) + -- Open the file in read mode + local file = io.open(filename, "r") + if not file then + return false -- File doesn't exist or cannot be opened + end + + -- Read the contents of the file + local content = file:read "*all" + file:close() + + -- Parse the JSON content + local json_parsed, json = pcall(vim.fn.json_decode, content) + if not json_parsed or type(json) ~= "table" then + return false -- Invalid JSON format + end + return json +end + +local function check_json_key_exists(json, ...) return vim.tbl_get(json, ...) ~= nil end + +local lsp_rooter, prettierrc_rooter +local function has_prettier(bufnr) + if type(bufnr) ~= "number" then bufnr = vim.api.nvim_get_current_buf() end + + local rooter = require "astrocore.rooter" + + if not lsp_rooter then + lsp_rooter = rooter.resolve("lsp", { + ignore = { + servers = function(client) return not vim.tbl_contains({ "eslint" }, client.name) end, + }, + }) + end + + if not prettierrc_rooter then + prettierrc_rooter = rooter.resolve { + ".prettierrc", + ".prettierrc.json", + ".prettierrc.yml", + ".prettierrc.yaml", + ".prettierrc.json5", + ".prettierrc.js", + ".prettierrc.cjs", + "prettier.config.js", + ".prettierrc.mjs", + "prettier.config.mjs", + "prettier.config.cjs", + ".prettierrc.toml", + } + end + + local prettier_dependency = false + + for _, root in ipairs(require("astrocore").list_insert_unique(lsp_rooter(bufnr), { vim.fn.getcwd() })) do + local package_json = decode_json(root .. "/package.json") + if + package_json + and ( + check_json_key_exists(package_json, "dependencies", "prettier") + or check_json_key_exists(package_json, "devDependencies", "prettier") + ) + then + prettier_dependency = true + break + end + end + return prettier_dependency or next(prettierrc_rooter(bufnr)) +end + +local function has_biome() local bufnr = vim.api.nvim_get_current_buf() local rooter = require "astrocore.rooter" @@ -9,6 +79,17 @@ local has_biome = function() return next(biomejson_rooter(bufnr)) end +local biome_format_filetypes = { "javascript", "javascriptreact", "typescript", "typescriptreact", "json", "jsonc" } +local prettier_format_filetypes = { "javascript", "javascriptreact", "typescript", "typescriptreact" } + +local function null_ls_formatter(params) + -- prefer biome for the file types it can format + if has_biome() then return not vim.tbl_contains(biome_format_filetypes, params.filetype) end + + if vim.tbl_contains(prettier_format_filetypes, params.filetype) then return has_prettier(params.bufnr) end + return true +end + return { { import = "astrocommunity.pack.typescript.core" }, { @@ -19,14 +100,34 @@ return { }, { "jay-babu/mason-null-ls.nvim", + optional = true, opts = function(_, opts) if not opts.handlers then opts.handlers = {} end - if not has_biome() then return end + opts.handlers.prettierd = function(source_name, methods) + local null_ls = require "null-ls" + for _, method in ipairs(methods) do + null_ls.register(null_ls.builtins[method][source_name].with { runtime_condition = null_ls_formatter }) + end + end + end, + }, + { + "stevearc/conform.nvim", + optional = true, + opts = function(_, opts) + if not opts.formatters_by_ft then opts.formatters_by_ft = {} end + + for _, filetype in ipairs(biome_format_filetypes) do + opts.formatters_by_ft[filetype] = function() + -- let the biome lsp handle this + if has_biome() then return {} end + + if vim.tbl_contains(prettier_format_filetypes, filetype) and has_prettier() then return { "prettierd" } end - -- TODO: prettier should be off for all filetypes that biome supports, - -- currently this is { "javascript", "javascriptreact", "typescript", "typescriptreact", "json" } - opts.handlers.prettierd = function() end + return {} + end + end end, }, }