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

Code before:
  -- Set on_key callback, clearing first in case it was already registered.
  vim.on_key(nil, ns)
  vim.on_key(on_key, ns)

  -- Populate the buf handle data. We cannot use defaulttable here because then an empty table will
  -- be created for each unique keystroke
  local buf_handle = buf_handles[bufnr] or {}
  buf_handles[bufnr] = buf_handle

  local trigger = buf_handle[otf_capabilities.firstTriggerCharacter] or {}
  buf_handle[otf_capabilities.firstTriggerCharacter] = trigger
  trigger[client_id] = client

  for _, char in ipairs(otf_capabilities.moreTriggerCharacter or {}) do
    trigger = buf_handle[char] or {}
    buf_handle[char] = trigger
    trigger[client_id] = client
  end

  api.nvim_clear_autocmds({ group = augroup, buffer = bufnr })
  api.nvim_create_autocmd('LspDetach', {
    buffer = bufnr,
    desc = 'Detach on-type formatting module when the client detaches',
    group = augroup,
    callback = function(args)
      detach(args.data.client_id, bufnr)
    end,
  })
end

api.nvim_create_autocmd('LspAttach', {
  desc = 'Enable on-type formatting for all buffers this client attaches to',
  callback = function(ev)
    local buf = ev.buf
    local client = assert(lsp.get_client_by_id(ev.data.client_id))
    if not client._otf_enabled or not client:supports_method(method, buf) then
      return
    end

    attach(client, buf)
  end,
})

---@param enable boolean
---@param client vim.lsp.Client
local function toggle_for_client(enable, client)
  local handler = enable and attach or detach

  -- Toggle for buffers already attached.
  for bufnr, _ in pairs(client.attached_buffers) do
    handler(client, bufnr)

Review comment (suggestion):
The first parameter of the `detach` function should be `vim.lsp.Client`, not client id. This is throwing errors when the autocmd is triggered.

EDIT: typo

Code after:
  -- Populate the buf handle data. We cannot use defaulttable here because then an empty table will
  -- be created for each unique keystroke
  local buf_handle = buf_handles[bufnr] or {}
  buf_handles[bufnr] = buf_handle

  local trigger = buf_handle[otf_capabilities.firstTriggerCharacter] or {}
  buf_handle[otf_capabilities.firstTriggerCharacter] = trigger
  trigger[client_id] = client

  for _, char in ipairs(otf_capabilities.moreTriggerCharacter or {}) do
    trigger = buf_handle[char] or {}
    buf_handle[char] = trigger
    trigger[client_id] = client
  end

  api.nvim_clear_autocmds({ group = augroup, buffer = bufnr })
  api.nvim_create_autocmd('LspDetach', {
    buffer = bufnr,
    desc = 'Detach on-type formatting module when the client detaches',
    group = augroup,
    callback = function(args)
      local detached_client = assert(lsp.get_client_by_id(args.data.client_id))
      detach(detached_client, bufnr)
    end,
  })
end

api.nvim_create_autocmd('LspAttach', {
  desc = 'Enable on-type formatting for all buffers with individually-enabled clients.',
  callback = function(ev)
    local buf = ev.buf
    local client = assert(lsp.get_client_by_id(ev.data.client_id))
    if client._otf_enabled then
      attach(client, buf)
    end
  end,
})

---@param enable boolean
---@param client vim.lsp.Client
local function toggle_for_client(enable, client)
  local handler = enable and attach or detach

  -- Toggle for buffers already attached.
  for bufnr, _ in pairs(client.attached_buffers) do
    handler(client, bufnr)
  end

  client._otf_enabled = enable
end