diff options
Diffstat (limited to 'runtime/lua/vim/lsp.lua')
-rw-r--r-- | runtime/lua/vim/lsp.lua | 75 |
1 files changed, 36 insertions, 39 deletions
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 841c365cbe..f0845bfc80 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -42,6 +42,8 @@ lsp._request_name_to_capability = { ['textDocument/prepareCallHierarchy'] = 'call_hierarchy'; ['textDocument/rename'] = 'rename'; ['textDocument/codeAction'] = 'code_action'; + ['textDocument/codeLens'] = 'code_lens'; + ['codeLens/resolve'] = 'code_lens_resolve'; ['workspace/executeCommand'] = 'execute_command'; ['textDocument/references'] = 'find_references'; ['textDocument/rangeFormatting'] = 'document_range_formatting'; @@ -228,6 +230,7 @@ local function validate_client_config(config) before_init = { config.before_init, "f", true }; offset_encoding = { config.offset_encoding, "s", true }; flags = { config.flags, "t", true }; + get_language_id = { config.get_language_id, "f", true }; } local cmd, cmd_args = lsp._cmd_parts(config.cmd) @@ -262,18 +265,29 @@ end --@param bufnr (Number) Number of the buffer, or 0 for current --@param client Client object local function text_document_did_open_handler(bufnr, client) + local use_incremental_sync = ( + if_nil(client.config.flags.allow_incremental_sync, true) + and client.resolved_capabilities.text_document_did_change == protocol.TextDocumentSyncKind.Incremental + ) + if use_incremental_sync then + if not client._cached_buffers then + client._cached_buffers = {} + end + client._cached_buffers[bufnr] = nvim_buf_get_lines(bufnr, 0, -1, true) + end if not client.resolved_capabilities.text_document_open_close then return end if not vim.api.nvim_buf_is_loaded(bufnr) then return end + local filetype = nvim_buf_get_option(bufnr, 'filetype') + local params = { textDocument = { version = 0; uri = vim.uri_from_bufnr(bufnr); - -- TODO make sure our filetypes are compatible with languageId names. - languageId = nvim_buf_get_option(bufnr, 'filetype'); + languageId = client.config.get_language_id(bufnr, filetype); text = buf_get_full_text(bufnr); } } @@ -400,6 +414,9 @@ end --- --@param name (string, default=client-id) Name in log messages. --- +--@param get_language_id function(bufnr, filetype) -> language ID as string. +--- Defaults to the filetype. +--- --@param offset_encoding (default="utf-16") One of "utf-8", "utf-16", --- or "utf-32" which is the encoding that the LSP server expects. Client does --- not verify this is correct. @@ -438,16 +455,7 @@ end --@param trace: "off" | "messages" | "verbose" | nil passed directly to the language --- server in the initialize request. Invalid/empty values will default to "off" --@param flags: A table with flags for the client. The current (experimental) flags are: ---- - allow_incremental_sync (bool, default false): Allow using on_line callbacks for lsp ---- ---- <pre> ---- -- In attach function for the client, you can do: ---- local custom_attach = function(client) ---- if client.config.flags then ---- client.config.flags.allow_incremental_sync = true ---- end ---- end ---- </pre> +--- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits --- --@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be --- fully initialized. Use `on_init` to do any actions once @@ -459,6 +467,11 @@ function lsp.start_client(config) config.flags = config.flags or {} config.settings = config.settings or {} + -- By default, get_language_id just returns the exact filetype it is passed. + -- It is possible to pass in something that will calculate a different filetype, + -- to be sent by the client. + config.get_language_id = config.get_language_id or function(_, filetype) return filetype end + local client_id = next_client_id() local handlers = config.handlers or {} @@ -808,7 +821,6 @@ end --- Notify all attached clients that a buffer has changed. local text_document_did_change_handler do - local encoding_index = { ["utf-8"] = 1; ["utf-16"] = 2; ["utf-32"] = 3; } text_document_did_change_handler = function(_, bufnr, changedtick, firstline, lastline, new_lastline, old_byte_size, old_utf32_size, old_utf16_size) @@ -827,23 +839,12 @@ do util.buf_versions[bufnr] = changedtick -- Lazy initialize these because clients may not even need them. local incremental_changes = once(function(client) - local size_index = encoding_index[client.offset_encoding] - local length = select(size_index, old_byte_size, old_utf16_size, old_utf32_size) - local lines = nvim_buf_get_lines(bufnr, firstline, new_lastline, true) - - -- This is necessary because we are specifying the full line including the - -- newline in range. Therefore, we must replace the newline as well. - if #lines > 0 then - table.insert(lines, '') - end - return { - range = { - start = { line = firstline, character = 0 }; - ["end"] = { line = lastline, character = 0 }; - }; - rangeLength = length; - text = table.concat(lines, '\n'); - }; + local lines = nvim_buf_get_lines(bufnr, 0, -1, true) + local startline = math.min(firstline + 1, math.min(#client._cached_buffers[bufnr], #lines)) + local endline = math.min(-(#lines - new_lastline), -1) + local incremental_change = vim.lsp.util.compute_diff(client._cached_buffers[bufnr], lines, startline, endline) + client._cached_buffers[bufnr] = lines + return incremental_change end) local full_changes = once(function() return { @@ -851,19 +852,12 @@ do }; end) local uri = vim.uri_from_bufnr(bufnr) - for_each_buffer_client(bufnr, function(client, _client_id) - local allow_incremental_sync = if_nil(client.config.flags.allow_incremental_sync, false) - + for_each_buffer_client(bufnr, function(client) + local allow_incremental_sync = if_nil(client.config.flags.allow_incremental_sync, true) local text_document_did_change = client.resolved_capabilities.text_document_did_change local changes if text_document_did_change == protocol.TextDocumentSyncKind.None then return - --[=[ TODO(ashkan) there seem to be problems with the byte_sizes sent by - -- neovim right now so only send the full content for now. In general, we - -- can assume that servers *will* support both versions anyway, as there - -- is no way to specify the sync capability by the client. - -- See https://github.com/palantir/python-language-server/commit/cfd6675bc10d5e8dbc50fc50f90e4a37b7178821#diff-f68667852a14e9f761f6ebf07ba02fc8 for an example of pyls handling both. - --]=] elseif not allow_incremental_sync or text_document_did_change == protocol.TextDocumentSyncKind.Full then changes = full_changes(client) elseif text_document_did_change == protocol.TextDocumentSyncKind.Incremental then @@ -931,6 +925,9 @@ function lsp.buf_attach_client(bufnr, client_id) if client.resolved_capabilities.text_document_open_close then client.notify('textDocument/didClose', params) end + if client._cached_buffers then + client._cached_buffers[bufnr] = nil + end end) util.buf_versions[bufnr] = nil all_buffer_active_clients[bufnr] = nil |