Repository: neovim/neovim
File: runtime/lua/vim/lsp/completion.lua (Lua)

Code before:
    local row_changed = new_cursor_row ~= cursor_row
    local mode = api.nvim_get_mode().mode
    if row_changed or not (mode == 'i' or mode == 'ic') then
      return
    end

    local line = api.nvim_get_current_line()
    local line_to_cursor = line:sub(1, cursor_col)
    local word_boundary = vim.fn.match(line_to_cursor, '\\k*$')

    local matches = {}

    local server_start_boundary --- @type integer?
    for client_id, response in pairs(responses) do
      local client = lsp.get_client_by_id(client_id)
      if response.err then
        local msg = ('%s: %s %s'):format(
          client and client.name or 'UNKNOWN',
          response.err.code or 'NO_CODE',
          response.err.message
        )
        vim.notify_once(msg, vim.log.levels.WARN)
      end

      local result = response.result
      if result and #result.items > 0 then
        Context.isIncomplete = Context.isIncomplete or result.isIncomplete
        local encoding = client and client.offset_encoding or 'utf-16'
        local client_matches, tmp_server_start_boundary
        client_matches, tmp_server_start_boundary = M._convert_results(
          line,
          cursor_row - 1,
          cursor_col,
          client_id,
          word_boundary,
          nil,
          result,
          encoding
        )

        server_start_boundary = tmp_server_start_boundary or server_start_boundary
        vim.list_extend(matches, client_matches)
      end
    end

    --- @type table[]
    local prev_matches = vim.fn.complete_info({ 'items', 'matches' })['items']

    --- @param prev_match table
    prev_matches = vim.tbl_filter(function(prev_match)
      local client_id = vim.tbl_get(prev_match, 'user_data', 'nvim', 'lsp', 'client_id')

Review comment (suggestion):
In other words, I missed the `CompletionItem[]` response form (above https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionList) and we haven't had it in test cases so far.

Code after:
    local row_changed = new_cursor_row ~= cursor_row
    local mode = api.nvim_get_mode().mode
    if row_changed or not (mode == 'i' or mode == 'ic') then
      return
    end

    local line = api.nvim_get_current_line()
    local line_to_cursor = line:sub(1, cursor_col)
    local word_boundary = vim.fn.match(line_to_cursor, '\\k*$')

    local matches = {}

    local server_start_boundary --- @type integer?
    for client_id, response in pairs(responses) do
      local client = lsp.get_client_by_id(client_id)
      if response.err then
        local msg = ('%s: %s %s'):format(
          client and client.name or 'UNKNOWN',
          response.err.code or 'NO_CODE',
          response.err.message
        )
        vim.notify_once(msg, vim.log.levels.WARN)
      end

      local result = response.result
      if result and #(result.items or result) > 0 then
        Context.isIncomplete = Context.isIncomplete or result.isIncomplete
        local encoding = client and client.offset_encoding or 'utf-16'
        local client_matches, tmp_server_start_boundary
        client_matches, tmp_server_start_boundary = M._convert_results(
          line,
          cursor_row - 1,
          cursor_col,
          client_id,
          word_boundary,
          nil,
          result,
          encoding
        )

        server_start_boundary = tmp_server_start_boundary or server_start_boundary
        vim.list_extend(matches, client_matches)
      end
    end

    --- @type table[]
    local prev_matches = vim.fn.complete_info({ 'items', 'matches' })['items']

    --- @param prev_match table
    prev_matches = vim.tbl_filter(function(prev_match)
      local client_id = vim.tbl_get(prev_match, 'user_data', 'nvim', 'lsp', 'client_id')