diff --git a/.luacheckrc b/.luacheckrc index 2805f45..d78d31a 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -2,6 +2,9 @@ ignore = { "631", -- max_line_length } +exclude_files = { + ".tests", +} globals = { "vim", "P" } read_globals = { "describe", diff --git a/README.md b/README.md index 7014182..fcf7905 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,9 @@ require("typescript-tools").setup { -- described below tsserver_format_options = {}, tsserver_file_preferences = {}, + -- mirror of https://github.com/microsoft/vscode/blob/885dba39a5f546c5077196a8c31b03d03a293b31/extensions/typescript-language-features/package.json#L145-L1266 + -- `typescript-tools.nvim` currently only supports `typescript.suggest.completeFunctionCalls` + vscode_configuration = { ["typescript.suggest.completeFunctionCalls"] = true }, }, } ``` diff --git a/lua/typescript-tools/config.lua b/lua/typescript-tools/config.lua index 81cc71c..b988ab6 100644 --- a/lua/typescript-tools/config.lua +++ b/lua/typescript-tools/config.lua @@ -1,3 +1,6 @@ +---@see https://github.com/microsoft/vscode/blob/885dba39a5f546c5077196a8c31b03d03a293b31/extensions/typescript-language-features/package.json#L145-L1266 +---@alias VsCodeConfiguration { typescript.suggest.completeFunctionCalls: boolean } + ---@class Settings ---@field plugin_name string ---@field separate_diagnostic_server boolean @@ -8,6 +11,7 @@ ---@field tsserver_format_options table|fun(filetype: string): table ---@field tsserver_file_preferences table|fun(filetype: string): table ---@field tsserver_max_memory number|"auto" +---@field vscode_configuration VsCodeConfiguration ---@field expose_as_code_action ("fix_all"| "add_missing_imports"| "remove_unused")[] local M = {} local __store = {} @@ -106,6 +110,7 @@ function M.load_settings(settings) { "number", "string" }, true, }, + ["settings.vscode_configuration"] = { settings.vscode_configuration, "table", true }, ["settings.expose_as_code_action"] = { settings.expose_as_code_action, "table", @@ -143,6 +148,10 @@ function M.load_settings(settings) __store.tsserver_max_memory = "auto" end + if not settings.vscode_configuration then + __store.vscode_configuration = {} + end + if not settings.expose_as_code_action then __store.expose_as_code_action = {} end diff --git a/lua/typescript-tools/protocol/text_document/completion/init.lua b/lua/typescript-tools/protocol/text_document/completion/init.lua index 77bd19a..e2a68bd 100644 --- a/lua/typescript-tools/protocol/text_document/completion/init.lua +++ b/lua/typescript-tools/protocol/text_document/completion/init.lua @@ -67,10 +67,10 @@ function M.handler(request, response, params) sortText = "\u{ffff}" .. item.sortText end - local should_create_snippet = item.isSnippet - or utils.should_create_function_snippet(kind, filetype) + local should_create_function_snippet = utils.should_create_function_snippet(kind, filetype) + local should_create_snippet = item.isSnippet or should_create_function_snippet local label = is_optional and (item.name .. "?") or item.name - label = should_create_snippet and (label .. "~") or label + label = should_create_function_snippet and (label .. "(...)") or label return { label = label, diff --git a/lua/typescript-tools/protocol/utils.lua b/lua/typescript-tools/protocol/utils.lua index 573e450..6b90246 100644 --- a/lua/typescript-tools/protocol/utils.lua +++ b/lua/typescript-tools/protocol/utils.lua @@ -231,6 +231,7 @@ function M.should_create_function_snippet(kind, filetype) local preferences = plugin_config.get_tsserver_file_preferences(filetype) return preferences.includeCompletionsWithSnippetText and (kind == c.CompletionItemKind.Function or kind == c.CompletionItemKind.Method) + and plugin_config.vscode_configuration["typescript.suggest.completeFunctionCalls"] end return M diff --git a/tests/requests_spec.lua b/tests/requests_spec.lua index e353b51..a44f5f7 100644 --- a/tests/requests_spec.lua +++ b/tests/requests_spec.lua @@ -1,6 +1,7 @@ local utils = require "tests.utils" local lsp_assert = require "tests.lsp_asserts" local mocks = require "tests.mocks" +local plugin_config = require "typescript-tools.config" local c = require "typescript-tools.protocol.constants" local methods = c.LspMethods local custom_methods = c.CustomMethods @@ -134,10 +135,11 @@ describe("Lsp request", function() utils.open_file "src/completion.ts" utils.wait_for_lsp_initialization() - local ret = vim.lsp.buf_request_sync(0, methods.Completion, { + local req = { textDocument = utils.get_text_document(), position = utils.make_position(0, 8), - }) + } + local ret = vim.lsp.buf_request_sync(0, methods.Completion, req) local result = lsp_assert.response(ret) @@ -147,36 +149,47 @@ describe("Lsp request", function() assert.is.True(#items >= 20) local completions = vim.tbl_map(function(it) - if it.label == "assert~" or it.label == "warn~" then - assert.are.same(it.insertTextFormat, c.InsertTextFormat.Snippet) + if it.kind == c.CompletionItemKind.Method or it.kind == c.CompletionItemKind.Function then + assert.are.same(it.insertTextFormat, c.InsertTextFormat.PlainText) end return it.label end, items) table.sort(completions) - assert.are.same(completions[1], "assert~") - assert.are.same(completions[#completions], "warn~") + assert.are.same(completions[1], "assert") + assert.are.same(completions[#completions], "warn") - ret = vim.lsp.buf_request_sync(0, methods.Completion, { - textDocument = utils.get_text_document(), - position = utils.make_position(0, 6), - }) + -- same test as above but with function snippets enabled + local prev_config = + plugin_config.vscode_configuration["typescript.suggest.completeFunctionCalls"] + plugin_config.vscode_configuration["typescript.suggest.completeFunctionCalls"] = true + + ret = vim.lsp.buf_request_sync(0, methods.Completion, req) result = lsp_assert.response(ret) - local can_complete_as_console = false - for _, item in ipairs(result.items) do - if item.label == "console" then - assert.are.same(item.insertTextFormat, c.InsertTextFormat.PlainText) - can_complete_as_console = true + assert.is.table(result.items) + + items = result.items + assert.is.True(#items >= 20) + + completions = vim.tbl_map(function(it) + if it.kind == c.CompletionItemKind.Method or it.kind == c.CompletionItemKind.Function then + assert.are.same(it.insertTextFormat, c.InsertTextFormat.Snippet) end - end - assert(can_complete_as_console) + return it.label + end, items) + table.sort(completions) + + assert.are.same(completions[1], "assert(...)") + assert.are.same(completions[#completions], "warn(...)") + + plugin_config.vscode_configuration["typescript.suggest.completeFunctionCalls"] = prev_config end) it("should return correct response for " .. methods.CompletionResolve, function() utils.open_file "src/completion.ts" utils.wait_for_lsp_initialization() - local ret = vim.lsp.buf_request_sync(0, methods.CompletionResolve, { + local req = { commitCharacters = { "(" }, data = { character = 8, @@ -186,37 +199,33 @@ describe("Lsp request", function() }, filterText = "warn", insertText = "warn", - insertTextFormat = c.InsertTextFormat.Snippet, + insertTextFormat = c.InsertTextFormat.PlainText, kind = c.CompletionItemKind.Function, label = "warn", sortText = "11", - }) + } + local ret = vim.lsp.buf_request_sync(0, methods.CompletionResolve, req) local result = lsp_assert.response(ret) assert.is.table(result) - assert.are.same(result.insertText, "warn($1)$0") + assert.are.same(result.insertText, "warn") assert.are.same(result.detail, "(method) Console.warn(...data: any[]): void") - ret = vim.lsp.buf_request_sync(0, methods.CompletionResolve, { - commitCharacters = { ".", "?" }, - data = { - character = 6, - entryNames = { "console" }, - file = vim.fs.dirname(vim.api.nvim_buf_get_name(0)) .. "/completion.ts", - line = 0, - }, - filterText = "console", - insertText = "console", - insertTextFormat = c.InsertTextFormat.PlainText, - kind = c.CompletionItemKind.Variable, - label = "console", - sortText = "15", - }) + -- same test as above but with function snippets enabled + local prev_config = + plugin_config.vscode_configuration["typescript.suggest.completeFunctionCalls"] + plugin_config.vscode_configuration["typescript.suggest.completeFunctionCalls"] = true + req.label = "warn(...)" + req.insertTextFormat = c.InsertTextFormat.Snippet + ret = vim.lsp.buf_request_sync(0, methods.CompletionResolve, req) result = lsp_assert.response(ret) + assert.is.table(result) - assert.are.same(result.insertText, "console") - assert.are.same(result.detail, "var console: Console") + assert.are.same(result.insertText, "warn($1)$0") + assert.are.same(result.detail, "(method) Console.warn(...data: any[]): void") + + plugin_config.vscode_configuration["typescript.suggest.completeFunctionCalls"] = prev_config end) it("should return correct response for " .. methods.SignatureHelp, function()