mirror of
				https://github.com/NotAShelf/nvf.git
				synced 2025-10-31 02:52:37 +00:00 
			
		
		
		
	language/ts: migrate to vim.lsp.servers
This commit is contained in:
		
					parent
					
						
							
								a2ce78fa90
							
						
					
				
			
			
				commit
				
					
						76c031bbda
					
				
			
		
					 1 changed files with 169 additions and 63 deletions
				
			
		|  | @ -4,73 +4,177 @@ | ||||||
|   lib, |   lib, | ||||||
|   ... |   ... | ||||||
| }: let | }: let | ||||||
|   inherit (builtins) attrNames; |   inherit (builtins) attrNames elem; | ||||||
|   inherit (lib.options) mkEnableOption mkOption; |   inherit (lib.options) mkEnableOption mkOption; | ||||||
|   inherit (lib.modules) mkIf mkMerge; |   inherit (lib.modules) mkIf mkMerge; | ||||||
|   inherit (lib.lists) isList; |  | ||||||
|   inherit (lib.meta) getExe; |   inherit (lib.meta) getExe; | ||||||
|   inherit (lib.types) enum either listOf package str bool; |   inherit (lib.types) enum listOf package bool; | ||||||
|   inherit (lib.nvim.lua) expToLua toLuaObject; |   inherit (lib.generators) mkLuaInline; | ||||||
|  |   inherit (lib.nvim.attrsets) mapListToAttrs; | ||||||
|  |   inherit (lib.nvim.lua) toLuaObject; | ||||||
|   inherit (lib.nvim.types) mkGrammarOption diagnostics mkPluginSetupOption; |   inherit (lib.nvim.types) mkGrammarOption diagnostics mkPluginSetupOption; | ||||||
|   inherit (lib.nvim.dag) entryAnywhere; |   inherit (lib.nvim.dag) entryAnywhere entryBefore; | ||||||
| 
 | 
 | ||||||
|   cfg = config.vim.languages.ts; |   cfg = config.vim.languages.ts; | ||||||
| 
 | 
 | ||||||
|   defaultServer = "ts_ls"; |   defaultServers = ["ts_ls"]; | ||||||
|   servers = { |   servers = let | ||||||
|     ts_ls = { |     ts_ls = { | ||||||
|       package = pkgs.typescript-language-server; |       cmd = [(getExe pkgs.typescript-language-server) "--stdio"]; | ||||||
|       lspConfig = '' |       init_options = {hostInfo = "neovim";}; | ||||||
|         lspconfig.ts_ls.setup { |       filetypes = [ | ||||||
|           capabilities = capabilities, |         "javascript" | ||||||
|           on_attach = function(client, bufnr) |         "javascriptreact" | ||||||
|             attach_keymaps(client, bufnr); |         "javascript.jsx" | ||||||
|             client.server_capabilities.documentFormattingProvider = false; |         "typescript" | ||||||
|           end, |         "typescriptreact" | ||||||
|           cmd = ${ |         "typescript.tsx" | ||||||
|           if isList cfg.lsp.package |       ]; | ||||||
|           then expToLua cfg.lsp.package |       root_markers = ["tsconfig.json" "jsconfig.json" "package.json" ".git"]; | ||||||
|           else ''{"${cfg.lsp.package}/bin/typescript-language-server", "--stdio"}'' |       handlers = { | ||||||
|         } |         # handle rename request for certain code actions like extracting functions / types | ||||||
|         } |         "_typescript.rename" = mkLuaInline '' | ||||||
|  |           function(_, result, ctx) | ||||||
|  |             local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) | ||||||
|  |             vim.lsp.util.show_document({ | ||||||
|  |               uri = result.textDocument.uri, | ||||||
|  |               range = { | ||||||
|  |                 start = result.position, | ||||||
|  |                 ['end'] = result.position, | ||||||
|  |               }, | ||||||
|  |             }, client.offset_encoding) | ||||||
|  |             vim.lsp.buf.rename() | ||||||
|  |             return vim.NIL | ||||||
|  |           end | ||||||
|         ''; |         ''; | ||||||
|       }; |       }; | ||||||
|  |       on_attach = mkLuaInline '' | ||||||
|  |         function(client, bufnr) | ||||||
|  |           default_on_attach(client, bufnr); | ||||||
| 
 | 
 | ||||||
|     denols = { |           -- ts_ls provides `source.*` code actions that apply to the whole file. These only appear in | ||||||
|       package = pkgs.deno; |           -- `vim.lsp.buf.code_action()` if specified in `context.only`. | ||||||
|       lspConfig = '' |           vim.api.nvim_buf_create_user_command(0, 'LspTypescriptSourceAction', function() | ||||||
|         vim.g.markdown_fenced_languages = { "ts=typescript" } |             local source_actions = vim.tbl_filter(function(action) | ||||||
|         lspconfig.denols.setup { |               return vim.startswith(action, 'source.') | ||||||
|           capabilities = capabilities; |             end, client.server_capabilities.codeActionProvider.codeActionKinds) | ||||||
|           on_attach = attach_keymaps, | 
 | ||||||
|           cmd = ${ |             vim.lsp.buf.code_action({ | ||||||
|           if isList cfg.lsp.package |               context = { | ||||||
|           then expToLua cfg.lsp.package |                 only = source_actions, | ||||||
|           else ''{"${cfg.lsp.package}/bin/deno", "lsp"}'' |               }, | ||||||
|         } |             }) | ||||||
|         } |           end, {}) | ||||||
|  |         end | ||||||
|       ''; |       ''; | ||||||
|     }; |     }; | ||||||
| 
 |   in { | ||||||
|  |     inherit ts_ls; | ||||||
|     # Here for backwards compatibility. Still consider tsserver a valid |     # Here for backwards compatibility. Still consider tsserver a valid | ||||||
|     # configuration in the enum, but assert if it's set to *properly* |     # configuration in the enum, but assert if it's set to *properly* | ||||||
|     # redirect the user to the correct server. |     # redirect the user to the correct server. | ||||||
|     tsserver = { |     tsserver = ts_ls; | ||||||
|       package = pkgs.typescript-language-server; | 
 | ||||||
|       lspConfig = '' |     denols = { | ||||||
|         lspconfig.ts_ls.setup { |       cmd = [(getExe pkgs.deno) "lsp"]; | ||||||
|           capabilities = capabilities; |       cmd_env = {NO_COLOR = true;}; | ||||||
|           on_attach = attach_keymaps, |       filetypes = [ | ||||||
|           cmd = ${ |         "javascript" | ||||||
|           if isList cfg.lsp.package |         "javascriptreact" | ||||||
|           then expToLua cfg.lsp.package |         "javascript.jsx" | ||||||
|           else ''{"${cfg.lsp.package}/bin/typescript-language-server", "--stdio"}'' |         "typescript" | ||||||
|         } |         "typescriptreact" | ||||||
|         } |         "typescript.tsx" | ||||||
|  |       ]; | ||||||
|  |       root_markers = ["deno.json" "deno.jsonc" ".git"]; | ||||||
|  |       settings = { | ||||||
|  |         deno = { | ||||||
|  |           enable = true; | ||||||
|  |           suggest = { | ||||||
|  |             imports = { | ||||||
|  |               hosts = { | ||||||
|  |                 "https://deno.land" = true; | ||||||
|  |               }; | ||||||
|  |             }; | ||||||
|  |           }; | ||||||
|  |         }; | ||||||
|  |       }; | ||||||
|  |       handlers = { | ||||||
|  |         "textDocument/definition" = mkLuaInline "nvf_denols_handler"; | ||||||
|  |         "textDocument/typeDefinition" = mkLuaInline "nvf_denols_handler"; | ||||||
|  |         "textDocument/references" = mkLuaInline "nvf_denols_handler"; | ||||||
|  |       }; | ||||||
|  |       on_attach = mkLuaInline '' | ||||||
|  |         function(client, bufnr) | ||||||
|  |           default_on_attach(client, bufnr) | ||||||
|  |           vim.api.nvim_buf_create_user_command(0, 'LspDenolsCache', function() | ||||||
|  |             client:exec_cmd({ | ||||||
|  |               command = 'deno.cache', | ||||||
|  |               arguments = { {}, vim.uri_from_bufnr(bufnr) }, | ||||||
|  |             }, { bufnr = bufnr }, function(err, _result, ctx) | ||||||
|  |               if err then | ||||||
|  |                 local uri = ctx.params.arguments[2] | ||||||
|  |                 vim.api.nvim_err_writeln('cache command failed for ' .. vim.uri_to_fname(uri)) | ||||||
|  |               end | ||||||
|  |             end) | ||||||
|  |           end, { | ||||||
|  |             desc = 'Cache a module and all of its dependencies.', | ||||||
|  |           }) | ||||||
|  |         end | ||||||
|       ''; |       ''; | ||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  |   denols_handlers = '' | ||||||
|  |     local function nvf_denols_virtual_text_document_handler(uri, res, client) | ||||||
|  |       if not res then | ||||||
|  |         return nil | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       local lines = vim.split(res.result, '\n') | ||||||
|  |       local bufnr = vim.uri_to_bufnr(uri) | ||||||
|  | 
 | ||||||
|  |       local current_buf = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) | ||||||
|  |       if #current_buf ~= 0 then | ||||||
|  |         return nil | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) | ||||||
|  |       vim.api.nvim_set_option_value('readonly', true, { buf = bufnr }) | ||||||
|  |       vim.api.nvim_set_option_value('modified', false, { buf = bufnr }) | ||||||
|  |       vim.api.nvim_set_option_value('modifiable', false, { buf = bufnr }) | ||||||
|  |       vim.lsp.buf_attach_client(bufnr, client.id) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     local function nvf_denols_virtual_text_document(uri, client) | ||||||
|  |       local params = { | ||||||
|  |         textDocument = { | ||||||
|  |           uri = uri, | ||||||
|  |         }, | ||||||
|  |       } | ||||||
|  |       local result = client.request_sync('deno/virtualTextDocument', params) | ||||||
|  |       nvf_denols_virtual_text_document_handler(uri, result, client) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     local function nvf_denols_handler(err, result, ctx, config) | ||||||
|  |       if not result or vim.tbl_isempty(result) then | ||||||
|  |         return nil | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       local client = vim.lsp.get_client_by_id(ctx.client_id) | ||||||
|  |       for _, res in pairs(result) do | ||||||
|  |         local uri = res.uri or res.targetUri | ||||||
|  |         if uri:match '^deno:' then | ||||||
|  |           nvf_denols_virtual_text_document(uri, client) | ||||||
|  |           res['uri'] = uri | ||||||
|  |           res['targetUri'] = uri | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       vim.lsp.handlers[ctx.method](err, result, ctx, config) | ||||||
|  |     end | ||||||
|  |   ''; | ||||||
|  | 
 | ||||||
|   # TODO: specify packages |   # TODO: specify packages | ||||||
|   defaultFormat = "prettier"; |   defaultFormat = "prettier"; | ||||||
|   formats = { |   formats = { | ||||||
|  | @ -122,17 +226,10 @@ in { | ||||||
|     lsp = { |     lsp = { | ||||||
|       enable = mkEnableOption "Typescript/Javascript LSP support" // {default = config.vim.lsp.enable;}; |       enable = mkEnableOption "Typescript/Javascript LSP support" // {default = config.vim.lsp.enable;}; | ||||||
| 
 | 
 | ||||||
|       server = mkOption { |       servers = mkOption { | ||||||
|  |         type = singleOrListOf (enum (attrNames servers)); | ||||||
|  |         default = defaultServers; | ||||||
|         description = "Typescript/Javascript LSP server to use"; |         description = "Typescript/Javascript LSP server to use"; | ||||||
|         type = enum (attrNames servers); |  | ||||||
|         default = defaultServer; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       package = mkOption { |  | ||||||
|         description = "Typescript/Javascript LSP server package, or the command to run as a list of strings"; |  | ||||||
|         example = ''[lib.getExe pkgs.jdt-language-server "-data" "~/.cache/jdtls/workspace"]''; |  | ||||||
|         type = either package (listOf str); |  | ||||||
|         default = servers.${cfg.lsp.server}.package; |  | ||||||
|       }; |       }; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  | @ -190,8 +287,17 @@ in { | ||||||
|     }) |     }) | ||||||
| 
 | 
 | ||||||
|     (mkIf cfg.lsp.enable { |     (mkIf cfg.lsp.enable { | ||||||
|       vim.lsp.lspconfig.enable = true; |       vim.lsp.servers = | ||||||
|       vim.lsp.lspconfig.sources.ts-lsp = servers.${cfg.lsp.server}.lspConfig; |         mapListToAttrs (name: { | ||||||
|  |           inherit name; | ||||||
|  |           value = servers.${name}; | ||||||
|  |         }) | ||||||
|  |         cfg.lsp.servers; | ||||||
|  |     }) | ||||||
|  | 
 | ||||||
|  |     (mkIf (cfg.lsp.enable && elem "denols" cfg.lsp.servers) { | ||||||
|  |       vim.globals.markdown_fenced_languages = ["ts=typescript"]; | ||||||
|  |       vim.luaConfigRC.denols_handlers = entryBefore ["lsp-servers"] denols_handlers; | ||||||
|     }) |     }) | ||||||
| 
 | 
 | ||||||
|     (mkIf cfg.format.enable { |     (mkIf cfg.format.enable { | ||||||
|  | @ -234,7 +340,7 @@ in { | ||||||
|     { |     { | ||||||
|       assertions = [ |       assertions = [ | ||||||
|         { |         { | ||||||
|           assertion = cfg.lsp.enable -> cfg.lsp.server != "tsserver"; |           assertion = cfg.lsp.enable -> !(elem "tsserver" cfg.lsp.servers); | ||||||
|           message = '' |           message = '' | ||||||
|             As of a recent lspconfig update, the `tsserver` configuration has been renamed |             As of a recent lspconfig update, the `tsserver` configuration has been renamed | ||||||
|             to `ts_ls` to match upstream behaviour of `lspconfig`, and the name `tsserver` |             to `ts_ls` to match upstream behaviour of `lspconfig`, and the name `tsserver` | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Ching Pei Yang
				Ching Pei Yang