neoclide/coc.nvim

Allow for dynamic resolve of languageId value

asmodeus812 opened this issue · 0 comments

Describe the bug

There is an issue with the way coc handles the languageId, at the moment one can only have one hard coded predefined language id that is sent to all running servers, g:coc_filetype_map is not very useful either in this regard, since it is also global for all clients. However this is a problem, because there are scertain servers such as https://github.com/spring-projects/sts4/blob/992a7c742838a381443a5a86ed0327523b1f3086/vscode-extensions/vscode-spring-boot/lib/Main.ts#L25-L30. Which require a very specific name for the languageId send for the document, we can not simply override yml or yaml in this case because that will break other language servers where the ft is expected to be yml.

Proposition

There should be way to define a custom langugeId resolver per client, so that we can send the correct value for that specific client only. And not affect the globlal ft system.

Other solutions

Below is an example of how neovim does it, each client has the ability to be configured with a custom callback which will be invoked (where needed) to obtain the languge id on the fly or fallback to the default filetype if no callback for get_languge_id was provided.

local neovim_language_server_config = {
  -- cmd = bootls_cmd(),
  name = "spring-boot",
  filetypes = { "java", "yaml", "jproperties" },
  -- root_dir = root_dir,
  init_options = {
    -- workspaceFolders = root_dir,
    enableJdtClasspath = false,
  },
  settings = {
    spring_boot = {},
  },
  handlers = {},
  commands = {},
  get_language_id = function(bufnr, filetype)
    if filetype == "yaml" then
      local filename = vim.api.nvim_buf_get_name(bufnr)
      if util.is_application_yml_file(filename) then
        return "spring-boot-properties-yaml"
      end
    elseif filetype == "jproperties" then
      local filename = vim.api.nvim_buf_get_name(bufnr)
      if util.is_application_properties_file(filename) then
        return "spring-boot-properties"
      end
    end
    return filetype
  end,
}

From neovim core

function Client:_text_document_did_open_handler(bufnr)
  changetracking.init(self, bufnr)
  if not vim.tbl_get(self.server_capabilities, 'textDocumentSync', 'openClose') then
    return
  end
  if not api.nvim_buf_is_loaded(bufnr) then
    return
  end
  local filetype = vim.bo[bufnr].filetype

  local params = {
    textDocument = {
      version = 0,
      uri = vim.uri_from_bufnr(bufnr),
      languageId = self.get_language_id(bufnr, filetype),
      text = lsp._buf_get_full_text(bufnr),
    },
  }
  self.notify(ms.textDocument_didOpen, params)
  lsp.util.buf_versions[bufnr] = params.textDocument.version

  -- Next chance we get, we should re-do the diagnostics
  vim.schedule(function()
    -- Protect against a race where the buffer disappears
    -- between `did_open_handler` and the scheduled function firing.
    if api.nvim_buf_is_valid(bufnr) then
      local namespace = lsp.diagnostic.get_namespace(self.id)
      vim.diagnostic.show(namespace, bufnr)
    end
  end)
end