aboutsummaryrefslogtreecommitdiff
path: root/test/functional/plugin/lsp/completion_spec.lua
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
commit931bffbda3668ddc609fc1da8f9eb576b170aa52 (patch)
treed8c1843a95da5ea0bb4acc09f7e37843d9995c86 /test/functional/plugin/lsp/completion_spec.lua
parent142d9041391780ac15b89886a54015fdc5c73995 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-userreg.tar.gz
rneovim-userreg.tar.bz2
rneovim-userreg.zip
Merge remote-tracking branch 'upstream/master' into userreguserreg
Diffstat (limited to 'test/functional/plugin/lsp/completion_spec.lua')
-rw-r--r--test/functional/plugin/lsp/completion_spec.lua239
1 files changed, 239 insertions, 0 deletions
diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua
new file mode 100644
index 0000000000..9354654afe
--- /dev/null
+++ b/test/functional/plugin/lsp/completion_spec.lua
@@ -0,0 +1,239 @@
+---@diagnostic disable: no-unknown
+local helpers = require('test.functional.helpers')(after_each)
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+
+
+--- Convert completion results.
+---
+---@param line string line contents. Mark cursor position with `|`
+---@param candidates lsp.CompletionList|lsp.CompletionItem[]
+---@param lnum? integer 0-based, defaults to 0
+---@return {items: table[], server_start_boundary: integer?}
+local function complete(line, candidates, lnum)
+ lnum = lnum or 0
+ -- nvim_win_get_cursor returns 0 based column, line:find returns 1 based
+ local cursor_col = line:find("|") - 1
+ line = line:gsub("|", "")
+ return exec_lua([[
+ local line, cursor_col, lnum, result = ...
+ local line_to_cursor = line:sub(1, cursor_col)
+ local client_start_boundary = vim.fn.match(line_to_cursor, '\\k*$')
+ local items, server_start_boundary = require("vim.lsp._completion")._convert_results(
+ line,
+ lnum,
+ cursor_col,
+ client_start_boundary,
+ nil,
+ result,
+ "utf-16"
+ )
+ return {
+ items = items,
+ server_start_boundary = server_start_boundary
+ }
+ ]], line, cursor_col, lnum, candidates)
+end
+
+
+describe("vim.lsp._completion", function()
+ before_each(helpers.clear)
+
+ -- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
+ it('prefers textEdit over label as word', function()
+ local range0 = {
+ start = { line = 0, character = 0 },
+ ["end"] = { line = 0, character = 0 },
+ }
+ local completion_list = {
+ -- resolves into label
+ { label = 'foobar', sortText = 'a', documentation = 'documentation' },
+ {
+ label = 'foobar',
+ sortText = 'b',
+ documentation = { value = 'documentation' },
+ },
+ -- resolves into insertText
+ { label = 'foocar', sortText = 'c', insertText = 'foobar' },
+ { label = 'foocar', sortText = 'd', insertText = 'foobar' },
+ -- resolves into textEdit.newText
+ { label = 'foocar', sortText = 'e', insertText = 'foodar', textEdit = { newText = 'foobar', range = range0 } },
+ { label = 'foocar', sortText = 'f', textEdit = { newText = 'foobar', range = range0 } },
+ -- real-world snippet text
+ {
+ label = 'foocar',
+ sortText = 'g',
+ insertText = 'foodar',
+ insertTextFormat = 2,
+ textEdit = { newText = 'foobar(${1:place holder}, ${2:more ...holder{\\}})', range = range0 },
+ },
+ {
+ label = 'foocar',
+ sortText = 'h',
+ insertText = 'foodar(${1:var1} typ1, ${2:var2} *typ2) {$0\\}',
+ insertTextFormat = 2,
+ },
+ -- nested snippet tokens
+ {
+ label = 'foocar',
+ sortText = 'i',
+ insertText = 'foodar(${1:${2|typ1,typ2|}}) {$0\\}',
+ insertTextFormat = 2,
+ },
+ -- braced tabstop
+ { label = 'foocar', sortText = 'j', insertText = 'foodar()${0}', insertTextFormat = 2},
+ -- plain text
+ {
+ label = 'foocar',
+ sortText = 'k',
+ insertText = 'foodar(${1:var1})',
+ insertTextFormat = 1,
+ },
+ }
+ local expected = {
+ {
+ abbr = 'foobar',
+ word = 'foobar',
+ },
+ {
+ abbr = 'foobar',
+ word = 'foobar',
+ },
+ {
+ abbr = 'foocar',
+ word = 'foobar',
+ },
+ {
+ abbr = 'foocar',
+ word = 'foobar',
+ },
+ {
+ abbr = 'foocar',
+ word = 'foobar',
+ },
+ {
+ abbr = 'foocar',
+ word = 'foobar',
+ },
+ {
+ abbr = 'foocar',
+ word = 'foobar(place holder, more ...holder{})',
+ },
+ {
+ abbr = 'foocar',
+ word = 'foodar(var1 typ1, var2 *typ2) {}',
+ },
+ {
+ abbr = 'foocar',
+ word = 'foodar(typ1) {}',
+ },
+ {
+ abbr = 'foocar',
+ word = 'foodar()',
+ },
+ {
+ abbr = 'foocar',
+ word = 'foodar(${1:var1})',
+ },
+ }
+ local result = complete('|', completion_list)
+ result = vim.tbl_map(function(x)
+ return {
+ abbr = x.abbr,
+ word = x.word
+ }
+ end, result.items)
+ eq(expected, result)
+ end)
+ it("uses correct start boundary", function()
+ local completion_list = {
+ isIncomplete = false,
+ items = {
+ {
+ filterText = "this_thread",
+ insertText = "this_thread",
+ insertTextFormat = 1,
+ kind = 9,
+ label = " this_thread",
+ score = 1.3205767869949,
+ sortText = "4056f757this_thread",
+ textEdit = {
+ newText = "this_thread",
+ range = {
+ start = { line = 0, character = 7 },
+ ["end"] = { line = 0, character = 11 },
+ },
+ }
+ },
+ }
+ }
+ local expected = {
+ abbr = ' this_thread',
+ dup = 1,
+ empty = 1,
+ icase = 1,
+ kind = 'Module',
+ menu = '',
+ word = 'this_thread',
+ }
+ local result = complete(" std::this|", completion_list)
+ eq(7, result.server_start_boundary)
+ local item = result.items[1]
+ item.user_data = nil
+ eq(expected, item)
+ end)
+
+ it("should search from start boundary to cursor position", function()
+ local completion_list = {
+ isIncomplete = false,
+ items = {
+ {
+ filterText = "this_thread",
+ insertText = "this_thread",
+ insertTextFormat = 1,
+ kind = 9,
+ label = " this_thread",
+ score = 1.3205767869949,
+ sortText = "4056f757this_thread",
+ textEdit = {
+ newText = "this_thread",
+ range = {
+ start = { line = 0, character = 7 },
+ ["end"] = { line = 0, character = 11 },
+ },
+ }
+ },
+ {
+ filterText = "notthis_thread",
+ insertText = "notthis_thread",
+ insertTextFormat = 1,
+ kind = 9,
+ label = " notthis_thread",
+ score = 1.3205767869949,
+ sortText = "4056f757this_thread",
+ textEdit = {
+ newText = "notthis_thread",
+ range = {
+ start = { line = 0, character = 7 },
+ ["end"] = { line = 0, character = 11 },
+ },
+ }
+ },
+ }
+ }
+ local expected = {
+ abbr = ' this_thread',
+ dup = 1,
+ empty = 1,
+ icase = 1,
+ kind = 'Module',
+ menu = '',
+ word = 'this_thread',
+ }
+ local result = complete(" std::this|is", completion_list)
+ eq(1, #result.items)
+ local item = result.items[1]
+ item.user_data = nil
+ eq(expected, item)
+ end)
+end)