diff --git a/plugins/by-name/typescript-tools/default.nix b/plugins/by-name/typescript-tools/default.nix index fc0fc21b..ec1d861b 100644 --- a/plugins/by-name/typescript-tools/default.nix +++ b/plugins/by-name/typescript-tools/default.nix @@ -1,24 +1,26 @@ { lib, - pkgs, - config, ... }: let inherit (lib.nixvim) defaultNullOpts; - cfg = config.plugins.typescript-tools; in -{ - options.plugins.typescript-tools = { - enable = lib.mkEnableOption "typescript-tools"; - package = lib.mkPackageOption pkgs "typescript-tools" { - default = [ - "vimPlugins" - "typescript-tools-nvim" - ]; - }; +lib.nixvim.neovim-plugin.mkNeovimPlugin { + name = "typescript-tools"; + originalName = "typescript-tools.nvim"; + package = "typescript-tools-nvim"; + + maintainers = [ lib.maintainers.khaneliman ]; + + # TODO:: introduced 10-22-2024: remove after 24.11 + optionsRenamedToSettings = [ + "onAttach" + "handlers" + ]; + + settingsOptions = { + on_attach = defaultNullOpts.mkLuaFn "__lspOnAttach" "Lua code to run when tsserver attaches to a buffer."; - onAttach = defaultNullOpts.mkLuaFn "__lspOnAttach" "Lua code to run when tsserver attaches to a buffer."; handlers = lib.mkOption { type = with lib.types; nullOr (attrsOf strLuaFn); default = null; @@ -34,9 +36,9 @@ in }; settings = { - separateDiagnosticServer = defaultNullOpts.mkBool true "Spawns an additional tsserver instance to calculate diagnostics"; + separate_diagnostic_server = defaultNullOpts.mkBool true "Spawns an additional tsserver instance to calculate diagnostics"; - publishDiagnosticOn = + publish_diagnostic_on = defaultNullOpts.mkEnum [ "change" @@ -47,7 +49,7 @@ in Either "change" or "insert_leave". Determines when the client asks the server about diagnostics ''; - exposeAsCodeAction = lib.mkOption { + expose_as_code_action = lib.mkOption { type = with lib.types; either (enum [ "all" ]) ( @@ -64,26 +66,26 @@ in description = "Specify what to expose as code actions."; }; - tsserverPath = lib.nixvim.mkNullOrStr '' + tsserver_path = lib.nixvim.mkNullOrStr '' Specify a custom path to `tsserver.js` file, if this is nil or file under path doesn't exist then standard path resolution strategy is applied ''; - tsserverPlugins = + tsserver_plugins = with lib.types; lib.nixvim.mkNullOrOption (listOf (maybeRaw str)) '' List of plugins for tsserver to load. See this plugins's README at https://github.com/pmizio/typescript-tools.nvim/#-styled-components-support ''; - tsserverMaxMemory = + tsserver_max_memory = lib.nixvim.mkNullOrOption (with lib.types; maybeRaw (either ints.unsigned (enum [ "auto" ]))) '' This value is passed to: https://nodejs.org/api/cli.html#--max-old-space-sizesize-in-megabytes Memory limit in megabytes or "auto"(basically no limit) ''; - tsserverFormatOptions = lib.mkOption { + tsserver_format_options = lib.mkOption { type = with lib.types; nullOr (attrsOf anything); default = null; description = "Configuration options that well be passed to the tsserver instance. Find available options [here](https://github.com/microsoft/TypeScript/blob/v5.0.4/src/server/protocol.ts#L3418)"; @@ -99,7 +101,7 @@ in }; }; - tsserverFilePreferences = lib.mkOption { + tsserver_file_references = lib.mkOption { type = with lib.types; nullOr (attrsOf anything); default = null; description = "Configuration options that well be passed to the tsserver instance. Find available options [here](https://github.com/microsoft/TypeScript/blob/v5.0.4/src/server/protocol.ts#L3439)"; @@ -113,15 +115,15 @@ in }; }; - tsserverLocale = defaultNullOpts.mkStr "en" '' + tsserver_locale = defaultNullOpts.mkStr "en" '' Locale of all tsserver messages. Supported locales here: https://github.com/microsoft/TypeScript/blob/3c221fc086be52b19801f6e8d82596d04607ede6/src/compiler/utilitiesPublic.ts#L620 ''; - completeFunctionCalls = defaultNullOpts.mkBool false '' + complete_function_calls = defaultNullOpts.mkBool false '' Mirror of VSCode's `typescript.suggest.completeFunctionCalls` ''; - includeCompletionsWithInsertText = defaultNullOpts.mkBool true '' + include_completions_with_insert_text = defaultNullOpts.mkBool true '' Mirror of VSCode's `typescript.suggest.completeFunctionCalls` ''; @@ -136,11 +138,11 @@ in "off" "WARNING: Experimental feature also in VSCode, disabled by default because it might impact server performance."; - disableMemberCodeLens = defaultNullOpts.mkBool true '' + disable_member_code_lens = defaultNullOpts.mkBool true '' By default code lenses are displayed on all referenceable values. Display less by removing member references from lenses. ''; - jsxCloseTag = { + jsx_close_tag = { enable = defaultNullOpts.mkBool false '' Functions similarly to `nvim-ts-autotag`. This is disabled by default to avoid conflicts. ''; @@ -156,38 +158,115 @@ in }; }; }; - config = lib.mkIf cfg.enable { - extraPlugins = [ cfg.package ]; - plugins.lsp.postConfig = - with cfg; - let - options = { - inherit handlers; - on_attach = onAttach; - - settings = with settings; { - separate_diagnostic_server = separateDiagnosticServer; - publish_diagnostic_on = publishDiagnosticOn; - expose_as_code_action = exposeAsCodeAction; - tsserver_path = tsserverPath; - tsserver_plugins = tsserverPlugins; - tsserver_max_memory = tsserverMaxMemory; - tsserver_format_options = tsserverFormatOptions; - tsserver_file_preferences = tsserverFilePreferences; - tsserver_locale = tsserverLocale; - complete_function_calls = completeFunctionCalls; - include_completions_with_insert_text = includeCompletionsWithInsertText; - code_lens = codeLens; - disable_member_code_lens = disableMemberCodeLens; - jsx_close_tag = with jsxCloseTag; { - inherit enable filetypes; - }; - }; - }; - in - '' - require('typescript-tools').setup(${lib.nixvim.toLuaObject options}) + settingsExample = { + handlers = { + "textDocument/publishDiagnostics" = '' + api.filter_diagnostics( + { 80006 } + ) ''; + }; + settings = { + tsserver_plugins = [ + "@styled/typescript-styled-plugin" + ]; + tsserver_file_preferences.__raw = '' + function(ft) + return { + includeInlayParameterNameHints = "all", + includeCompletionsForModuleExports = true, + quotePreference = "auto", + } + end + ''; + tsserver_format_options.__raw = '' + function(ft) + return { + allowIncompleteCompletions = false, + allowRenameOfImportPath = false, + } + end + ''; + }; }; + + # NOTE: call setup in lsp config + callSetup = false; + extraConfig = + cfg: + let + definedOpts = lib.filter (opt: lib.hasAttrByPath opt cfg.settings) [ + [ "separateDiagnosticServer" ] + [ "publishDiagnosticOn" ] + [ "exposeAsCodeAction" ] + [ "tsserverPath" ] + [ "tsserverPlugins" ] + [ "tsserverMaxMemory" ] + [ "tsserverFormatOptions" ] + [ "tsserverFilePreferences" ] + [ "tsserverLocale" ] + [ "completeFunctionCalls" ] + [ "includeCompletionsWithInsertText" ] + [ "codeLens" ] + [ "disableMemberCodeLens" ] + [ + "jsxCloseTag" + "enable" + ] + [ + "jsxCloseTag" + "filetypes" + ] + ]; + in + { + plugins.lsp.postConfig = + let + # TODO:: introduced 10-22-2024: remove after 24.11 + renamedSettings = lib.foldl' ( + acc: optPath: + let + snakeCasePath = builtins.map lib.nixvim.toSnakeCase optPath; + optValue = lib.getAttrFromPath optPath cfg.settings; + in + lib.recursiveUpdate acc (lib.setAttrByPath snakeCasePath optValue) + ) { } definedOpts; + + # Based on lib.filterAttrsRecursive + # TODO: Maybe move to nixvim's or upstream's lib? + filterAttrsRecursivePath = + predicate: set: path: + lib.listToAttrs ( + lib.concatMap ( + name: + let + path' = path ++ [ name ]; + v = set.${name}; + in + lib.optional (predicate path' v) { + inherit name; + value = if lib.isAttrs v then filterAttrsRecursivePath predicate v path' else v; + } + ) (lib.attrNames set) + ); + + setupOptions = + filterAttrsRecursivePath (path: value: !builtins.elem path definedOpts) cfg.settings [ ] + // { + settings = lib.recursiveUpdate cfg.settings.settings renamedSettings; + }; + in + '' + require('typescript-tools').setup(${lib.nixvim.toLuaObject setupOptions}) + ''; + + # TODO:: introduced 10-22-2024: remove after 24.11 + # Nested settings can't have normal mkRenamedOptionModule functionality so we can only + # alert the user that they are using the old values + warnings = lib.optional (definedOpts != [ ]) '' + Nixvim(plugins.typescript-tools): The following settings have moved under `plugins.typescript-tools.settings.settings` with snake_case: + ${lib.concatMapStringsSep "\n" (opt: " - ${lib.showOption (lib.toList opt)}") definedOpts} + ''; + }; } diff --git a/tests/test-sources/plugins/by-name/typescript-tools/default.nix b/tests/test-sources/plugins/by-name/typescript-tools/default.nix index 810ac290..89176c79 100644 --- a/tests/test-sources/plugins/by-name/typescript-tools/default.nix +++ b/tests/test-sources/plugins/by-name/typescript-tools/default.nix @@ -7,20 +7,20 @@ plugins.typescript-tools = { enable = true; settings = { - separateDiagnosticServer = true; - publishDiagnosticOn = "insert_leave"; - exposeAsCodeAction = null; - tsserverPath = null; - tsserverPlugins = null; - tsserverMaxMemory = "auto"; - tsserverFormatOptions = null; - tsserverFilePreferences = null; - tsserverLocale = "en"; - completeFunctionCalls = false; - includeCompletionsWithInsertText = true; - codeLens = "off"; - disableMemberCodeLens = true; - jsxCloseTag = { + separate_diagnostic_server = true; + publish_diagnostic_on = "insert_leave"; + expose_as_code_action = null; + tsserver_path = null; + tsserver_plugins = null; + tsserver_max_memory = "auto"; + tsserver_format_options = null; + tsserver_file_preferences = null; + tsserver_locale = "en"; + complete_function_calls = false; + include_completions_with_insert_text = true; + code_lens = "off"; + disable_member_code_lens = true; + jsx_close_tag = { enable = false; filetypes = [ "javascriptreact" @@ -30,4 +30,41 @@ }; }; }; + + example = { + plugins.typescript-tools = { + enable = true; + settings = { + handlers = { + "textDocument/publishDiagnostics" = '' + api.filter_diagnostics( + { 80006 } + ) + ''; + }; + settings = { + tsserver_plugins = [ + "@styled/typescript-styled-plugin" + ]; + tsserver_file_preferences.__raw = '' + function(ft) + return { + includeInlayParameterNameHints = "all", + includeCompletionsForModuleExports = true, + quotePreference = "auto", + } + end + ''; + tsserver_format_options.__raw = '' + function(ft) + return { + allowIncompleteCompletions = false, + allowRenameOfImportPath = false, + } + end + ''; + }; + }; + }; + }; }