summaryrefslogtreecommitdiff
path: root/mut/neovim/pack/plugins/start/blink.cmp/lua/blink/cmp/sources/lsp/completion.lua
blob: 5d542806afa3a4b9aeb2122674bee5368e6b83e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
local async = require('blink.cmp.lib.async')
local known_defaults = {
  'commitCharacters',
  'insertTextFormat',
  'insertTextMode',
  'data',
}
local CompletionTriggerKind = vim.lsp.protocol.CompletionTriggerKind

local completion = {}

--- @param context blink.cmp.Context
--- @param client vim.lsp.Client
--- @return blink.cmp.Task
function completion.get_completion_for_client(context, client)
  return async.task.new(function(resolve)
    local params = vim.lsp.util.make_position_params(0, client.offset_encoding)
    params.context = {
      triggerKind = context.trigger.kind == 'trigger_character' and CompletionTriggerKind.TriggerCharacter
        or CompletionTriggerKind.Invoked,
    }
    if context.trigger.kind == 'trigger_character' then params.context.triggerCharacter = context.trigger.character end

    local _, request_id = client.request('textDocument/completion', params, function(err, result)
      if err or result == nil then
        resolve({ is_incomplete_forward = true, is_incomplete_backward = true, items = {} })
        return
      end

      local items = result.items or result
      local default_edit_range = result.itemDefaults and result.itemDefaults.editRange
      for _, item in ipairs(items) do
        item.client_id = client.id

        -- score offset for deprecated items
        -- todo: make configurable
        if item.deprecated or (item.tags and vim.tbl_contains(item.tags, 1)) then item.score_offset = -2 end

        -- set defaults
        for key, value in pairs(result.itemDefaults or {}) do
          if vim.tbl_contains(known_defaults, key) then item[key] = item[key] or value end
        end
        if default_edit_range and item.textEdit == nil then
          local new_text = item.textEditText or item.insertText or item.label
          if default_edit_range.replace ~= nil then
            item.textEdit = {
              replace = default_edit_range.replace,
              insert = default_edit_range.insert,
              newText = new_text,
            }
          else
            item.textEdit = {
              range = result.itemDefaults.editRange,
              newText = new_text,
            }
          end
        end
      end

      resolve({
        is_incomplete_forward = result.isIncomplete or false,
        is_incomplete_backward = true,
        items = items,
      })
    end)

    -- cancellation function
    return function()
      if request_id ~= nil then client.cancel_request(request_id) end
    end
  end)
end

return completion