mirror of
https://github.com/neovim/neovim.git
synced 2026-06-15 16:23:48 +00:00
backport fix(lsp): send didClose, didOpen when languageId changes (#39519)
fix(lsp): send didClose, didOpen when languageId changes
Problem:
If a buffer's filetype changes after the LSP client has already
attached (e.g. from json to jsonc via a modeline), but the client
supports both filetypes, it stays attached. It does not notify the
server of the new languageId, causing the server to incorrectly process
the file using the old languageId.
Solution:
Save the languageId used during textDocument/didOpen, and send
textDocument/didClose + textDocument/didOpen when buffer's languageId
changed.
Lsp spec:
0003fb53f1/_specifications/lsp/3.18/textDocument/didOpen.md (L5)
> If the language id of a document changes, the client
> needs to send a textDocument/didClose to the server followed by a
> textDocument/didOpen with the new language id if the server handles
> the new language id as well.
AI-assisted: Gemini 3.1 Pro
Co-authored-by: phanium <91544758+phanen@users.noreply.github.com>
This commit is contained in:
@@ -1706,7 +1706,8 @@ Lua module: vim.lsp.client *lsp-client*
|
||||
*vim.lsp.Client*
|
||||
|
||||
Fields: ~
|
||||
• {attached_buffers} (`table<integer,true>`)
|
||||
• {attached_buffers} (`table<integer,string>`) Each buffer's last
|
||||
used `languageId`.
|
||||
• {cancel_request} (`fun(self: vim.lsp.Client, id: integer): boolean`)
|
||||
See |Client:cancel_request()|.
|
||||
• {capabilities} (`lsp.ClientCapabilities`) Capabilities
|
||||
|
||||
@@ -1523,7 +1523,7 @@ vim.str_utfindex({s}, {encoding}, {index}, {strict_indexing})
|
||||
==============================================================================
|
||||
Lua module: vim.inspector *vim.inspector*
|
||||
|
||||
vim.inspect_pos({bufnr}, {row}, {col}, {filter}) *vim.inspect_pos()*
|
||||
vim.inspect_pos({buf}, {row}, {col}, {filter}) *vim.inspect_pos()*
|
||||
Get all the items at a given buffer position.
|
||||
|
||||
Can also be pretty-printed with `:Inspect!`. *:Inspect!*
|
||||
@@ -1532,7 +1532,7 @@ vim.inspect_pos({bufnr}, {row}, {col}, {filter}) *vim.inspect_pos()*
|
||||
Since: 0.9.0
|
||||
|
||||
Parameters: ~
|
||||
• {bufnr} (`integer?`) defaults to the current buffer
|
||||
• {buf} (`integer?`) defaults to the current buffer
|
||||
• {row} (`integer?`) row to inspect, 0-based. Defaults to the row of
|
||||
the current cursor
|
||||
• {col} (`integer?`) col to inspect, 0-based. Defaults to the col of
|
||||
@@ -1559,7 +1559,7 @@ vim.inspect_pos({bufnr}, {row}, {col}, {filter}) *vim.inspect_pos()*
|
||||
• row: the row used to get the items
|
||||
• col: the col used to get the items
|
||||
|
||||
vim.show_pos({bufnr}, {row}, {col}, {filter}) *vim.show_pos()*
|
||||
vim.show_pos({buf}, {row}, {col}, {filter}) *vim.show_pos()*
|
||||
Show all the items at a given buffer position.
|
||||
|
||||
Can also be shown with `:Inspect`. *:Inspect*
|
||||
@@ -1573,7 +1573,7 @@ vim.show_pos({bufnr}, {row}, {col}, {filter}) *vim.show_pos()*
|
||||
Since: 0.9.0
|
||||
|
||||
Parameters: ~
|
||||
• {bufnr} (`integer?`) defaults to the current buffer
|
||||
• {buf} (`integer?`) defaults to the current buffer
|
||||
• {row} (`integer?`) row to inspect, 0-based. Defaults to the row of
|
||||
the current cursor
|
||||
• {col} (`integer?`) col to inspect, 0-based. Defaults to the col of
|
||||
@@ -2923,11 +2923,11 @@ vim.hl.priorities *vim.hl.priorities*
|
||||
symbols or `on_yank` autocommands
|
||||
|
||||
*vim.hl.range()*
|
||||
vim.hl.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts})
|
||||
vim.hl.range({buf}, {ns}, {higroup}, {start}, {finish}, {opts})
|
||||
Apply highlight group to range of text.
|
||||
|
||||
Parameters: ~
|
||||
• {bufnr} (`integer`) Buffer number to apply highlighting to
|
||||
• {buf} (`integer`) Buffer number to apply highlighting to
|
||||
• {ns} (`integer`) Namespace to add highlight to
|
||||
• {higroup} (`string`) Highlight group to use for highlighting
|
||||
• {start} (`[integer,integer]|string`) Start of region as a (line,
|
||||
@@ -4609,14 +4609,14 @@ within a single line.
|
||||
|
||||
|
||||
*regex:match_line()*
|
||||
regex:match_line({bufnr}, {line_idx}, {start}, {end_})
|
||||
Matches line at `line_idx` (zero-based) in buffer `bufnr`. Match is
|
||||
regex:match_line({buf}, {line_idx}, {start}, {end_})
|
||||
Matches line at `line_idx` (zero-based) in buffer `buf`. Match is
|
||||
restricted to byte index range `start` and `end_` if given, otherwise see
|
||||
|regex:match_str()|. Returned byte indices are relative to `start` if
|
||||
given.
|
||||
|
||||
Parameters: ~
|
||||
• {bufnr} (`integer`)
|
||||
• {buf} (`integer`)
|
||||
• {line_idx} (`integer`)
|
||||
• {start} (`integer?`)
|
||||
• {end_} (`integer?`)
|
||||
@@ -5237,11 +5237,11 @@ vim.uri_encode({str}, {rfc}) *vim.uri_encode()*
|
||||
Return: ~
|
||||
(`string`) encoded string
|
||||
|
||||
vim.uri_from_bufnr({bufnr}) *vim.uri_from_bufnr()*
|
||||
vim.uri_from_bufnr({buf}) *vim.uri_from_bufnr()*
|
||||
Gets a URI from a bufnr.
|
||||
|
||||
Parameters: ~
|
||||
• {bufnr} (`integer`)
|
||||
• {buf} (`integer`)
|
||||
|
||||
Return: ~
|
||||
(`string`) URI
|
||||
|
||||
@@ -61,6 +61,7 @@ LSP
|
||||
• Values < 0 are now treated as `nil` instead of 0.
|
||||
• Values outside the range of `signatures[activeSignature].parameters`
|
||||
are now treated as `nil` instead of `#signatures[activeSignature].parameters`
|
||||
• `client.attached_buffers[buf]` now stores `languageId` string (was boolean).
|
||||
|
||||
LUA
|
||||
|
||||
|
||||
@@ -964,18 +964,17 @@ foldexpr({lnum}) *vim.treesitter.foldexpr()*
|
||||
Return: ~
|
||||
(`string`)
|
||||
|
||||
*vim.treesitter.get_captures_at_cursor()*
|
||||
get_captures_at_cursor({winnr})
|
||||
get_captures_at_cursor({win}) *vim.treesitter.get_captures_at_cursor()*
|
||||
Returns a list of highlight capture names under the cursor
|
||||
|
||||
Parameters: ~
|
||||
• {winnr} (`integer?`) |window-ID| or 0 for current window (default)
|
||||
• {win} (`integer?`) |window-ID| or 0 for current window (default)
|
||||
|
||||
Return: ~
|
||||
(`string[]`) List of capture names
|
||||
|
||||
*vim.treesitter.get_captures_at_pos()*
|
||||
get_captures_at_pos({bufnr}, {row}, {col})
|
||||
get_captures_at_pos({buf}, {row}, {col})
|
||||
Returns a list of highlight captures at the given position
|
||||
|
||||
Each capture is represented by a table containing the capture name as a
|
||||
@@ -983,9 +982,9 @@ get_captures_at_pos({bufnr}, {row}, {col})
|
||||
`conceal`, ...; empty if none are defined), and the id of the capture.
|
||||
|
||||
Parameters: ~
|
||||
• {bufnr} (`integer`) Buffer number (0 for current buffer)
|
||||
• {row} (`integer`) Position row
|
||||
• {col} (`integer`) Position column
|
||||
• {buf} (`integer`) Buffer number (0 for current buffer)
|
||||
• {row} (`integer`) Position row
|
||||
• {col} (`integer`) Position column
|
||||
|
||||
Return: ~
|
||||
(`{capture: string, lang: string, metadata: vim.treesitter.query.TSMetadata, id: integer}[]`)
|
||||
@@ -1044,7 +1043,7 @@ get_node_text({node}, {source}, {opts})
|
||||
Return: ~
|
||||
(`string`)
|
||||
|
||||
get_parser({bufnr}, {lang}, {opts}) *vim.treesitter.get_parser()*
|
||||
get_parser({buf}, {lang}, {opts}) *vim.treesitter.get_parser()*
|
||||
Returns the parser for a specific buffer and attaches it to the buffer
|
||||
|
||||
If needed, this will create the parser.
|
||||
@@ -1052,11 +1051,11 @@ get_parser({bufnr}, {lang}, {opts}) *vim.treesitter.get_parser()*
|
||||
If no parser can be created, nil (and an error message) is returned.
|
||||
|
||||
Parameters: ~
|
||||
• {bufnr} (`integer?`) Buffer the parser should be tied to (default:
|
||||
current buffer)
|
||||
• {lang} (`string?`) Language of this parser (default: from buffer
|
||||
filetype)
|
||||
• {opts} (`table?`) Options to pass to the created language tree
|
||||
• {buf} (`integer?`) Buffer the parser should be tied to (default:
|
||||
current buffer)
|
||||
• {lang} (`string?`) Language of this parser (default: from buffer
|
||||
filetype)
|
||||
• {opts} (`table?`) Options to pass to the created language tree
|
||||
|
||||
Return (multiple): ~
|
||||
(`vim.treesitter.LanguageTree?`) object to use for parsing
|
||||
@@ -1156,7 +1155,7 @@ node_contains({node}, {range}) *vim.treesitter.node_contains()*
|
||||
Return: ~
|
||||
(`boolean`) True if the {node} contains the {range}
|
||||
|
||||
start({bufnr}, {lang}) *vim.treesitter.start()*
|
||||
start({buf}, {lang}) *vim.treesitter.start()*
|
||||
Starts treesitter highlighting for a buffer
|
||||
|
||||
Can be used in an ftplugin or FileType autocommand.
|
||||
@@ -1178,17 +1177,17 @@ start({bufnr}, {lang}) *vim.treesitter.start()*
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {bufnr} (`integer?`) Buffer to be highlighted (default: current
|
||||
buffer)
|
||||
• {lang} (`string?`) Language of the parser (default: from buffer
|
||||
filetype)
|
||||
• {buf} (`integer?`) Buffer to be highlighted (default: current
|
||||
buffer)
|
||||
• {lang} (`string?`) Language of the parser (default: from buffer
|
||||
filetype)
|
||||
|
||||
stop({bufnr}) *vim.treesitter.stop()*
|
||||
stop({buf}) *vim.treesitter.stop()*
|
||||
Stops treesitter highlighting for a buffer
|
||||
|
||||
Parameters: ~
|
||||
• {bufnr} (`integer?`) Buffer to stop highlighting (default: current
|
||||
buffer)
|
||||
• {buf} (`integer?`) Buffer to stop highlighting (default: current
|
||||
buffer)
|
||||
|
||||
|
||||
==============================================================================
|
||||
|
||||
@@ -308,15 +308,15 @@ M.properties = properties
|
||||
|
||||
--- @private
|
||||
--- Configure the given buffer with options from an `.editorconfig` file
|
||||
--- @param bufnr integer Buffer number to configure
|
||||
function M.config(bufnr)
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
if not vim.api.nvim_buf_is_valid(bufnr) then
|
||||
--- @param buf integer Buffer number to configure
|
||||
function M.config(buf)
|
||||
buf = buf or vim.api.nvim_get_current_buf()
|
||||
if not vim.api.nvim_buf_is_valid(buf) then
|
||||
return
|
||||
end
|
||||
|
||||
local path = vim.fs.normalize(vim.api.nvim_buf_get_name(bufnr))
|
||||
if vim.bo[bufnr].buftype ~= '' or not vim.bo[bufnr].modifiable or path == '' then
|
||||
local path = vim.fs.normalize(vim.api.nvim_buf_get_name(buf))
|
||||
if vim.bo[buf].buftype ~= '' or not vim.bo[buf].modifiable or path == '' then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -339,7 +339,7 @@ function M.config(bufnr)
|
||||
local func = M.properties[opt]
|
||||
if func then
|
||||
--- @type boolean, string?
|
||||
local ok, err = pcall(func, bufnr, val, opts)
|
||||
local ok, err = pcall(func, buf, val, opts)
|
||||
if ok then
|
||||
applied[opt] = val
|
||||
else
|
||||
@@ -349,7 +349,7 @@ function M.config(bufnr)
|
||||
end
|
||||
end
|
||||
|
||||
vim.b[bufnr].editorconfig = applied
|
||||
vim.b[buf].editorconfig = applied
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -1669,14 +1669,14 @@ function vim._with(context, f)
|
||||
return vim._with_c(context, callback)
|
||||
end
|
||||
|
||||
--- @param bufnr? integer
|
||||
--- @param buf? integer
|
||||
--- @return integer
|
||||
function vim._resolve_bufnr(bufnr)
|
||||
if bufnr == nil or bufnr == 0 then
|
||||
function vim._resolve_bufnr(buf)
|
||||
if buf == nil or buf == 0 then
|
||||
return vim.api.nvim_get_current_buf()
|
||||
end
|
||||
vim.validate('bufnr', bufnr, 'number')
|
||||
return bufnr
|
||||
vim.validate('buf', buf, 'number')
|
||||
return buf
|
||||
end
|
||||
|
||||
--- @generic T
|
||||
|
||||
@@ -30,7 +30,7 @@ local defaults = {
|
||||
---Can also be pretty-printed with `:Inspect!`. [:Inspect!]()
|
||||
---
|
||||
---@since 11
|
||||
---@param bufnr? integer defaults to the current buffer
|
||||
---@param buf? integer defaults to the current buffer
|
||||
---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor
|
||||
---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor
|
||||
---@param filter? vim._inspector.Filter Table with key-value pairs to filter the items
|
||||
@@ -42,27 +42,27 @@ local defaults = {
|
||||
--- - buffer: the buffer used to get the items
|
||||
--- - row: the row used to get the items
|
||||
--- - col: the col used to get the items
|
||||
function vim.inspect_pos(bufnr, row, col, filter)
|
||||
function vim.inspect_pos(buf, row, col, filter)
|
||||
filter = vim.tbl_deep_extend('force', defaults, filter or {})
|
||||
|
||||
bufnr = bufnr or 0
|
||||
buf = buf or 0
|
||||
if row == nil or col == nil then
|
||||
-- get the row/col from the first window displaying the buffer
|
||||
local win = bufnr == 0 and vim.api.nvim_get_current_win() or vim.fn.bufwinid(bufnr)
|
||||
local win = buf == 0 and vim.api.nvim_get_current_win() or vim.fn.bufwinid(buf)
|
||||
if win == -1 then
|
||||
error('row/col is required for buffers not visible in a window')
|
||||
end
|
||||
local cursor = vim.api.nvim_win_get_cursor(win)
|
||||
row, col = cursor[1] - 1, cursor[2]
|
||||
end
|
||||
bufnr = vim._resolve_bufnr(bufnr)
|
||||
buf = vim._resolve_bufnr(buf)
|
||||
|
||||
local results = {
|
||||
treesitter = {}, --- @type table[]
|
||||
syntax = {}, --- @type table[]
|
||||
extmarks = {},
|
||||
semantic_tokens = {},
|
||||
buffer = bufnr,
|
||||
buffer = buf,
|
||||
row = row,
|
||||
col = col,
|
||||
}
|
||||
@@ -79,7 +79,7 @@ function vim.inspect_pos(bufnr, row, col, filter)
|
||||
|
||||
-- treesitter
|
||||
if filter.treesitter then
|
||||
for _, capture in pairs(vim.treesitter.get_captures_at_pos(bufnr, row, col)) do
|
||||
for _, capture in pairs(vim.treesitter.get_captures_at_pos(buf, row, col)) do
|
||||
--- @diagnostic disable-next-line: inject-field
|
||||
capture.hl_group = '@' .. capture.capture .. '.' .. capture.lang
|
||||
results.treesitter[#results.treesitter + 1] = resolve_hl(capture)
|
||||
@@ -87,8 +87,8 @@ function vim.inspect_pos(bufnr, row, col, filter)
|
||||
end
|
||||
|
||||
-- syntax
|
||||
if filter.syntax and vim.api.nvim_buf_is_valid(bufnr) then
|
||||
vim._with({ buf = bufnr }, function()
|
||||
if filter.syntax and vim.api.nvim_buf_is_valid(buf) then
|
||||
vim._with({ buf = buf }, function()
|
||||
for _, i1 in ipairs(vim.fn.synstack(row + 1, col + 1)) do
|
||||
results.syntax[#results.syntax + 1] =
|
||||
resolve_hl({ hl_group = vim.fn.synIDattr(i1, 'name') })
|
||||
@@ -124,7 +124,7 @@ function vim.inspect_pos(bufnr, row, col, filter)
|
||||
end
|
||||
|
||||
-- All overlapping extmarks at this position:
|
||||
local extmarks = vim.api.nvim_buf_get_extmarks(bufnr, -1, { row, col }, { row, col }, {
|
||||
local extmarks = vim.api.nvim_buf_get_extmarks(buf, -1, { row, col }, { row, col }, {
|
||||
details = true,
|
||||
overlap = true,
|
||||
})
|
||||
@@ -159,12 +159,12 @@ end
|
||||
---```
|
||||
---
|
||||
---@since 11
|
||||
---@param bufnr? integer defaults to the current buffer
|
||||
---@param buf? integer defaults to the current buffer
|
||||
---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor
|
||||
---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor
|
||||
---@param filter? vim._inspector.Filter
|
||||
function vim.show_pos(bufnr, row, col, filter)
|
||||
local items = vim.inspect_pos(bufnr, row, col, filter)
|
||||
function vim.show_pos(buf, row, col, filter)
|
||||
local items = vim.inspect_pos(buf, row, col, filter)
|
||||
|
||||
local lines = { {} }
|
||||
|
||||
|
||||
@@ -27,13 +27,13 @@ local regex = {} -- luacheck: no unused
|
||||
--- @return integer? # match end (byte index), or `nil` if no match
|
||||
function regex:match_str(str) end
|
||||
|
||||
--- Matches line at `line_idx` (zero-based) in buffer `bufnr`. Match is restricted to byte index
|
||||
--- Matches line at `line_idx` (zero-based) in buffer `buf`. Match is restricted to byte index
|
||||
--- range `start` and `end_` if given, otherwise see |regex:match_str()|. Returned byte indices are
|
||||
--- relative to `start` if given.
|
||||
--- @param bufnr integer
|
||||
--- @param buf integer
|
||||
--- @param line_idx integer
|
||||
--- @param start? integer
|
||||
--- @param end_? integer
|
||||
--- @return integer? # match start (byte index) relative to `start`, or `nil` if no match
|
||||
--- @return integer? # match end (byte index) relative to `start`, or `nil` if no match
|
||||
function regex:match_line(bufnr, line_idx, start, end_) end
|
||||
function regex:match_line(buf, line_idx, start, end_) end
|
||||
|
||||
@@ -41,34 +41,34 @@ local function starsetf(ft, priority)
|
||||
end
|
||||
|
||||
--- Get a line range from the buffer.
|
||||
---@param bufnr integer The buffer to get the lines from
|
||||
---@param buf integer The buffer to get the lines from
|
||||
---@param start_lnum integer|nil The line number of the first line (inclusive, 1-based)
|
||||
---@param end_lnum integer|nil The line number of the last line (inclusive, 1-based)
|
||||
---@return string[] # Array of lines
|
||||
function M._getlines(bufnr, start_lnum, end_lnum)
|
||||
if not bufnr or bufnr < 0 then
|
||||
function M._getlines(buf, start_lnum, end_lnum)
|
||||
if not buf or buf < 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
if start_lnum then
|
||||
return api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum or start_lnum, false)
|
||||
return api.nvim_buf_get_lines(buf, start_lnum - 1, end_lnum or start_lnum, false)
|
||||
end
|
||||
|
||||
-- Return all lines
|
||||
return api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||
return api.nvim_buf_get_lines(buf, 0, -1, false)
|
||||
end
|
||||
|
||||
--- Get a single line from the buffer.
|
||||
---@param bufnr integer The buffer to get the lines from
|
||||
---@param buf integer The buffer to get the lines from
|
||||
---@param start_lnum integer The line number of the first line (inclusive, 1-based)
|
||||
---@return string
|
||||
function M._getline(bufnr, start_lnum)
|
||||
if not bufnr or bufnr < 0 then
|
||||
function M._getline(buf, start_lnum)
|
||||
if not buf or buf < 0 then
|
||||
return ''
|
||||
end
|
||||
|
||||
-- Return a single line
|
||||
return api.nvim_buf_get_lines(bufnr, start_lnum - 1, start_lnum, false)[1] or ''
|
||||
return api.nvim_buf_get_lines(buf, start_lnum - 1, start_lnum, false)[1] or ''
|
||||
end
|
||||
|
||||
--- Check whether a string matches any of the given Lua patterns.
|
||||
@@ -90,12 +90,12 @@ end
|
||||
|
||||
--- Get the next non-whitespace line in the buffer.
|
||||
---
|
||||
---@param bufnr integer The buffer to get the line from
|
||||
---@param buf integer The buffer to get the line from
|
||||
---@param start_lnum integer The line number of the first line to start from (inclusive, 1-based)
|
||||
---@return string|nil line The first non-blank line if found or `nil` otherwise
|
||||
---@return integer|nil lnum The line number of the first non-blank line or `nil`
|
||||
function M._nextnonblank(bufnr, start_lnum)
|
||||
for off, line in ipairs(M._getlines(bufnr, start_lnum, -1)) do
|
||||
function M._nextnonblank(buf, start_lnum)
|
||||
for off, line in ipairs(M._getlines(buf, start_lnum, -1)) do
|
||||
if not line:find('^%s*$') then
|
||||
return line, start_lnum + off - 1
|
||||
end
|
||||
|
||||
@@ -38,7 +38,7 @@ M.priorities = {
|
||||
|
||||
--- Apply highlight group to range of text.
|
||||
---
|
||||
---@param bufnr integer Buffer number to apply highlighting to
|
||||
---@param buf integer Buffer number to apply highlighting to
|
||||
---@param ns integer Namespace to add highlight to
|
||||
---@param higroup string Highlight group to use for highlighting
|
||||
---@param start [integer,integer]|string Start of region as a (line, column) tuple or string accepted by |getpos()|
|
||||
@@ -48,7 +48,7 @@ M.priorities = {
|
||||
--- highlight has left
|
||||
--- @return fun()? range_clear A function which allows clearing the highlight manually.
|
||||
--- nil is returned if timeout is not specified
|
||||
function M.range(bufnr, ns, higroup, start, finish, opts)
|
||||
function M.range(buf, ns, higroup, start, finish, opts)
|
||||
opts = opts or {}
|
||||
local regtype = opts.regtype or 'v'
|
||||
local inclusive = opts.inclusive or false
|
||||
@@ -59,20 +59,20 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
|
||||
|
||||
local pos1 = type(start) == 'string' and vim.fn.getpos(start)
|
||||
or {
|
||||
bufnr,
|
||||
buf,
|
||||
start[1] + 1,
|
||||
start[2] ~= -1 and start[2] ~= v_maxcol and start[2] + 1 or v_maxcol,
|
||||
0,
|
||||
}
|
||||
local pos2 = type(finish) == 'string' and vim.fn.getpos(finish)
|
||||
or {
|
||||
bufnr,
|
||||
buf,
|
||||
finish[1] + 1,
|
||||
finish[2] ~= -1 and start[2] ~= v_maxcol and finish[2] + 1 or v_maxcol,
|
||||
0,
|
||||
}
|
||||
|
||||
local buf_line_count = api.nvim_buf_line_count(bufnr)
|
||||
local buf_line_count = api.nvim_buf_line_count(buf)
|
||||
pos1[2] = math.min(pos1[2], buf_line_count)
|
||||
pos2[2] = math.min(pos2[2], buf_line_count)
|
||||
|
||||
@@ -80,7 +80,7 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
|
||||
return
|
||||
end
|
||||
|
||||
vim._with({ buf = bufnr }, function()
|
||||
vim._with({ buf = buf }, function()
|
||||
if pos1[3] ~= v_maxcol then
|
||||
local max_col1 = vim.fn.col({ pos1[2], '$' })
|
||||
pos1[3] = math.min(pos1[3], max_col1)
|
||||
@@ -119,7 +119,7 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
|
||||
local end_col = res[2][3]
|
||||
table.insert(
|
||||
extmarks,
|
||||
api.nvim_buf_set_extmark(bufnr, ns, start_row, start_col, {
|
||||
api.nvim_buf_set_extmark(buf, ns, start_row, start_col, {
|
||||
hl_group = higroup,
|
||||
end_row = end_row,
|
||||
end_col = end_col,
|
||||
@@ -130,11 +130,11 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
|
||||
end
|
||||
|
||||
local range_hl_clear = function()
|
||||
if not api.nvim_buf_is_valid(bufnr) then
|
||||
if not api.nvim_buf_is_valid(buf) then
|
||||
return
|
||||
end
|
||||
for _, mark in ipairs(extmarks) do
|
||||
api.nvim_buf_del_extmark(bufnr, ns, mark)
|
||||
api.nvim_buf_del_extmark(buf, ns, mark)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -531,9 +531,20 @@ local function lsp_enable_callback(bufnr)
|
||||
lsp.is_enabled(client.name)
|
||||
-- Check that the client is managed by vim.lsp.config before deciding to detach it!
|
||||
and lsp.config[client.name]
|
||||
and not can_start(bufnr, lsp.config[client.name], false)
|
||||
then
|
||||
lsp.buf_detach_client(bufnr, client.id)
|
||||
if can_start(bufnr, lsp.config[client.name], false) then
|
||||
-- When switch between lsp supported filetype (e.g. json to jsonc like #39498),
|
||||
-- client should send `textDocument/didClose` + `textDocument/didOpen` with new language id
|
||||
local new_language_id = client.get_language_id(bufnr, vim.bo[bufnr].filetype)
|
||||
local old_language_id = client.attached_buffers[bufnr] ---@type string?
|
||||
if old_language_id and old_language_id ~= new_language_id then
|
||||
client:_text_document_did_close_handler(bufnr)
|
||||
client.attached_buffers[bufnr] = new_language_id
|
||||
client:_text_document_did_open_handler(bufnr)
|
||||
end
|
||||
else
|
||||
lsp.buf_detach_client(bufnr, client.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1002,7 +1013,7 @@ function lsp.buf_attach_client(bufnr, client_id)
|
||||
return true
|
||||
end
|
||||
|
||||
client.attached_buffers[bufnr] = true
|
||||
client.attached_buffers[bufnr] = client.get_language_id(bufnr, vim.bo[bufnr].filetype)
|
||||
|
||||
-- This is our first time attaching this client to this buffer.
|
||||
-- Send didOpen for the client if it is initialized. If it isn't initialized
|
||||
|
||||
@@ -154,7 +154,8 @@ local all_clients = {}
|
||||
|
||||
--- @class vim.lsp.Client
|
||||
---
|
||||
--- @field attached_buffers table<integer,true>
|
||||
--- Each buffer's last used `languageId`.
|
||||
--- @field attached_buffers table<integer,string>
|
||||
---
|
||||
--- Capabilities provided by the client (editor or tool), at startup.
|
||||
--- @field capabilities lsp.ClientCapabilities
|
||||
@@ -1109,6 +1110,18 @@ function Client:exec_cmd(cmd, context, handler)
|
||||
self:request('workspace/executeCommand', params, handler, context.bufnr)
|
||||
end
|
||||
|
||||
--- Default handler for the 'textDocument/didClose' LSP notification.
|
||||
---
|
||||
--- @param buf integer Number of the buffer, or 0 for current
|
||||
function Client:_text_document_did_close_handler(buf)
|
||||
if not self:supports_method('textDocument/didClose') then
|
||||
return
|
||||
end
|
||||
local uri = vim.uri_from_bufnr(buf)
|
||||
local params = { textDocument = { uri = uri } }
|
||||
self:notify('textDocument/didClose', params)
|
||||
end
|
||||
|
||||
--- Default handler for the 'textDocument/didOpen' LSP notification.
|
||||
---
|
||||
--- @param bufnr integer Number of the buffer, or 0 for current
|
||||
@@ -1177,7 +1190,7 @@ function Client:on_attach(bufnr)
|
||||
end
|
||||
end)
|
||||
|
||||
self.attached_buffers[bufnr] = true
|
||||
self.attached_buffers[bufnr] = self:_get_language_id(bufnr)
|
||||
end
|
||||
|
||||
--- @private
|
||||
@@ -1368,11 +1381,7 @@ function Client:_on_detach(bufnr)
|
||||
|
||||
changetracking.reset_buf(self, bufnr)
|
||||
|
||||
if self:supports_method('textDocument/didClose') then
|
||||
local uri = vim.uri_from_bufnr(bufnr)
|
||||
local params = { textDocument = { uri = uri } }
|
||||
self:notify('textDocument/didClose', params)
|
||||
end
|
||||
self:_text_document_did_close_handler(bufnr)
|
||||
|
||||
self.attached_buffers[bufnr] = nil
|
||||
|
||||
|
||||
@@ -114,13 +114,13 @@ local Tabstop = {}
|
||||
---
|
||||
--- @package
|
||||
--- @param index integer
|
||||
--- @param bufnr integer
|
||||
--- @param buf integer
|
||||
--- @param placement integer
|
||||
--- @param range Range4
|
||||
--- @param choices? string[]
|
||||
--- @return vim.snippet.Tabstop
|
||||
function Tabstop.new(index, bufnr, placement, range, choices)
|
||||
local extmark_id = vim.api.nvim_buf_set_extmark(bufnr, snippet_ns, range[1], range[2], {
|
||||
function Tabstop.new(index, buf, placement, range, choices)
|
||||
local extmark_id = vim.api.nvim_buf_set_extmark(buf, snippet_ns, range[1], range[2], {
|
||||
right_gravity = true,
|
||||
end_right_gravity = false,
|
||||
end_line = range[3],
|
||||
@@ -130,7 +130,7 @@ function Tabstop.new(index, bufnr, placement, range, choices)
|
||||
|
||||
local self = setmetatable({
|
||||
extmark_id = extmark_id,
|
||||
bufnr = bufnr,
|
||||
bufnr = buf,
|
||||
index = index,
|
||||
placement = placement,
|
||||
choices = choices,
|
||||
@@ -216,17 +216,17 @@ local Session = {}
|
||||
--- Creates a new snippet session in the current buffer.
|
||||
---
|
||||
--- @package
|
||||
--- @param bufnr integer
|
||||
--- @param buf integer
|
||||
--- @param snippet_extmark integer
|
||||
--- @param tabstop_data table<integer, { placement: integer, range: Range4, choices?: string[] }[]>
|
||||
--- @return vim.snippet.Session
|
||||
function Session.new(bufnr, snippet_extmark, tabstop_data)
|
||||
function Session.new(buf, snippet_extmark, tabstop_data)
|
||||
local self = setmetatable({
|
||||
bufnr = bufnr,
|
||||
bufnr = buf,
|
||||
extmark_id = snippet_extmark,
|
||||
tabstops = {},
|
||||
tabstop_placements = {},
|
||||
current_tabstop = Tabstop.new(0, bufnr, 0, { 0, 0, 0, 0 }),
|
||||
current_tabstop = Tabstop.new(0, buf, 0, { 0, 0, 0, 0 }),
|
||||
tab_keymaps = { i = nil, s = nil },
|
||||
shift_tab_keymaps = { i = nil, s = nil },
|
||||
}, { __index = Session })
|
||||
|
||||
@@ -26,23 +26,23 @@ M.minimum_language_version = vim._ts_get_minimum_language_version()
|
||||
---
|
||||
--- It is not recommended to use this; use |get_parser()| instead.
|
||||
---
|
||||
---@param bufnr integer Buffer the parser will be tied to (0 for current buffer)
|
||||
---@param buf integer Buffer the parser will be tied to (0 for current buffer)
|
||||
---@param lang string Language of the parser
|
||||
---@param opts (table|nil) Options to pass to the created language tree
|
||||
---
|
||||
---@return vim.treesitter.LanguageTree object to use for parsing
|
||||
function M._create_parser(bufnr, lang, opts)
|
||||
bufnr = vim._resolve_bufnr(bufnr)
|
||||
function M._create_parser(buf, lang, opts)
|
||||
buf = vim._resolve_bufnr(buf)
|
||||
|
||||
local self = LanguageTree.new(bufnr, lang, opts)
|
||||
local self = LanguageTree.new(buf, lang, opts)
|
||||
|
||||
local function bytes_cb(_, ...)
|
||||
self:_on_bytes(...)
|
||||
end
|
||||
|
||||
local function detach_cb(_, ...)
|
||||
if parsers[bufnr] == self then
|
||||
parsers[bufnr] = nil
|
||||
if parsers[buf] == self then
|
||||
parsers[buf] = nil
|
||||
end
|
||||
self:_on_detach(...)
|
||||
end
|
||||
@@ -72,41 +72,41 @@ end
|
||||
---
|
||||
--- If no parser can be created, nil (and an error message) is returned.
|
||||
---
|
||||
---@param bufnr (integer|nil) Buffer the parser should be tied to (default: current buffer)
|
||||
---@param buf (integer|nil) Buffer the parser should be tied to (default: current buffer)
|
||||
---@param lang (string|nil) Language of this parser (default: from buffer filetype)
|
||||
---@param opts (table|nil) Options to pass to the created language tree
|
||||
---
|
||||
---@return vim.treesitter.LanguageTree? object to use for parsing
|
||||
---@return string? error message, if applicable
|
||||
function M.get_parser(bufnr, lang, opts)
|
||||
function M.get_parser(buf, lang, opts)
|
||||
opts = opts or {}
|
||||
|
||||
bufnr = vim._resolve_bufnr(bufnr)
|
||||
buf = vim._resolve_bufnr(buf)
|
||||
|
||||
if not valid_lang(lang) then
|
||||
lang = M.language.get_lang(vim.bo[bufnr].filetype)
|
||||
lang = M.language.get_lang(vim.bo[buf].filetype)
|
||||
end
|
||||
|
||||
if not valid_lang(lang) then
|
||||
if not parsers[bufnr] then
|
||||
if not parsers[buf] then
|
||||
return nil,
|
||||
string.format('Parser not found for buffer %s: language could not be determined', bufnr)
|
||||
string.format('Parser not found for buffer %s: language could not be determined', buf)
|
||||
end
|
||||
elseif parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then
|
||||
if not api.nvim_buf_is_loaded(bufnr) then
|
||||
return nil, string.format('Buffer %s must be loaded to create parser', bufnr)
|
||||
elseif parsers[buf] == nil or parsers[buf]:lang() ~= lang then
|
||||
if not api.nvim_buf_is_loaded(buf) then
|
||||
return nil, string.format('Buffer %s must be loaded to create parser', buf)
|
||||
end
|
||||
local parser = vim.F.npcall(M._create_parser, bufnr, lang, opts)
|
||||
local parser = vim.F.npcall(M._create_parser, buf, lang, opts)
|
||||
if not parser then
|
||||
return nil,
|
||||
string.format('Parser could not be created for buffer %s and language "%s"', bufnr, lang)
|
||||
string.format('Parser could not be created for buffer %s and language "%s"', buf, lang)
|
||||
end
|
||||
parsers[bufnr] = parser
|
||||
parsers[buf] = parser
|
||||
end
|
||||
|
||||
parsers[bufnr]:register_cbs(opts.buf_attach_cbs)
|
||||
parsers[buf]:register_cbs(opts.buf_attach_cbs)
|
||||
|
||||
return parsers[bufnr]
|
||||
return parsers[buf]
|
||||
end
|
||||
|
||||
--- Returns a string parser
|
||||
@@ -268,14 +268,14 @@ end
|
||||
--- language, a table of metadata (`priority`, `conceal`, ...; empty if none are defined), and the
|
||||
--- id of the capture.
|
||||
---
|
||||
---@param bufnr integer Buffer number (0 for current buffer)
|
||||
---@param buf integer Buffer number (0 for current buffer)
|
||||
---@param row integer Position row
|
||||
---@param col integer Position column
|
||||
---
|
||||
---@return {capture: string, lang: string, metadata: vim.treesitter.query.TSMetadata, id: integer}[]
|
||||
function M.get_captures_at_pos(bufnr, row, col)
|
||||
bufnr = vim._resolve_bufnr(bufnr)
|
||||
local buf_highlighter = M.highlighter.active[bufnr]
|
||||
function M.get_captures_at_pos(buf, row, col)
|
||||
buf = vim._resolve_bufnr(buf)
|
||||
local buf_highlighter = M.highlighter.active[buf]
|
||||
|
||||
if not buf_highlighter then
|
||||
return {}
|
||||
@@ -328,13 +328,13 @@ end
|
||||
|
||||
--- Returns a list of highlight capture names under the cursor
|
||||
---
|
||||
---@param winnr (integer|nil): |window-ID| or 0 for current window (default)
|
||||
---@param win (integer|nil): |window-ID| or 0 for current window (default)
|
||||
---
|
||||
---@return string[] List of capture names
|
||||
function M.get_captures_at_cursor(winnr)
|
||||
winnr = winnr or 0
|
||||
local bufnr = api.nvim_win_get_buf(winnr)
|
||||
local cursor = api.nvim_win_get_cursor(winnr)
|
||||
function M.get_captures_at_cursor(win)
|
||||
win = win or 0
|
||||
local bufnr = api.nvim_win_get_buf(win)
|
||||
local cursor = api.nvim_win_get_cursor(win)
|
||||
|
||||
local data = M.get_captures_at_pos(bufnr, cursor[1] - 1, cursor[2])
|
||||
|
||||
@@ -434,30 +434,30 @@ end
|
||||
--- })
|
||||
--- ```
|
||||
---
|
||||
---@param bufnr integer? Buffer to be highlighted (default: current buffer)
|
||||
---@param buf integer? Buffer to be highlighted (default: current buffer)
|
||||
---@param lang string? Language of the parser (default: from buffer filetype)
|
||||
function M.start(bufnr, lang)
|
||||
bufnr = vim._resolve_bufnr(bufnr)
|
||||
function M.start(buf, lang)
|
||||
buf = vim._resolve_bufnr(buf)
|
||||
-- Ensure buffer is loaded. `:edit` over `bufload()` to show swapfile prompt.
|
||||
if not api.nvim_buf_is_loaded(bufnr) then
|
||||
if api.nvim_buf_get_name(bufnr) ~= '' then
|
||||
pcall(api.nvim_buf_call, bufnr, vim.cmd.edit)
|
||||
if not api.nvim_buf_is_loaded(buf) then
|
||||
if api.nvim_buf_get_name(buf) ~= '' then
|
||||
pcall(api.nvim_buf_call, buf, vim.cmd.edit)
|
||||
else
|
||||
vim.fn.bufload(bufnr)
|
||||
vim.fn.bufload(buf)
|
||||
end
|
||||
end
|
||||
local parser = assert(M.get_parser(bufnr, lang))
|
||||
local parser = assert(M.get_parser(buf, lang))
|
||||
M.highlighter.new(parser)
|
||||
end
|
||||
|
||||
--- Stops treesitter highlighting for a buffer
|
||||
---
|
||||
---@param bufnr (integer|nil) Buffer to stop highlighting (default: current buffer)
|
||||
function M.stop(bufnr)
|
||||
bufnr = vim._resolve_bufnr(bufnr)
|
||||
---@param buf (integer|nil) Buffer to stop highlighting (default: current buffer)
|
||||
function M.stop(buf)
|
||||
buf = vim._resolve_bufnr(buf)
|
||||
|
||||
if M.highlighter.active[bufnr] then
|
||||
M.highlighter.active[bufnr]:destroy()
|
||||
if M.highlighter.active[buf] then
|
||||
M.highlighter.active[buf]:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@ local FoldInfo = {}
|
||||
FoldInfo.__index = FoldInfo
|
||||
|
||||
---@private
|
||||
---@param bufnr integer
|
||||
function FoldInfo.new(bufnr)
|
||||
---@param buf integer
|
||||
function FoldInfo.new(buf)
|
||||
return setmetatable({
|
||||
levels0 = {},
|
||||
levels = {},
|
||||
parser = ts.get_parser(bufnr, nil),
|
||||
parser = ts.get_parser(buf, nil),
|
||||
}, FoldInfo)
|
||||
end
|
||||
|
||||
|
||||
@@ -69,24 +69,20 @@ end
|
||||
|
||||
--- Create a new treesitter view.
|
||||
---
|
||||
---@param bufnr integer Source buffer number
|
||||
---@param buf integer Source buffer number
|
||||
---@param lang string|nil Language of source buffer
|
||||
---
|
||||
---@return vim.treesitter.dev.TSTreeView|nil
|
||||
---@return string|nil Error message, if any
|
||||
---
|
||||
---@package
|
||||
function TSTreeView:new(bufnr, lang)
|
||||
bufnr = bufnr or 0
|
||||
lang = lang or vim.treesitter.language.get_lang(vim.bo[bufnr].filetype)
|
||||
local parser = vim.treesitter.get_parser(bufnr, lang)
|
||||
function TSTreeView:new(buf, lang)
|
||||
buf = buf or 0
|
||||
lang = lang or vim.treesitter.language.get_lang(vim.bo[buf].filetype)
|
||||
local parser = vim.treesitter.get_parser(buf, lang)
|
||||
if not parser then
|
||||
return nil,
|
||||
string.format(
|
||||
'Failed to create TSTreeView for buffer %s: no parser for lang "%s"',
|
||||
bufnr,
|
||||
lang
|
||||
)
|
||||
string.format('Failed to create TSTreeView for buffer %s: no parser for lang "%s"', buf, lang)
|
||||
end
|
||||
|
||||
-- For each child tree (injected language), find the root of the tree and locate the node within
|
||||
@@ -232,10 +228,10 @@ end
|
||||
---
|
||||
--- Calling this function computes the text that is displayed for each node.
|
||||
---
|
||||
---@param bufnr integer Buffer number to write into.
|
||||
---@param buf integer Buffer number to write into.
|
||||
---@package
|
||||
function TSTreeView:draw(bufnr)
|
||||
vim.bo[bufnr].modifiable = true
|
||||
function TSTreeView:draw(buf)
|
||||
vim.bo[buf].modifiable = true
|
||||
local lines = {} ---@type string[]
|
||||
local lang_hl_marks = {} ---@type table[]
|
||||
|
||||
@@ -284,18 +280,18 @@ function TSTreeView:draw(bufnr)
|
||||
lines[i] = line
|
||||
end
|
||||
|
||||
api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
||||
api.nvim_buf_set_lines(buf, 0, -1, false, lines)
|
||||
|
||||
api.nvim_buf_clear_namespace(bufnr, decor_ns, 0, -1)
|
||||
api.nvim_buf_clear_namespace(buf, decor_ns, 0, -1)
|
||||
|
||||
for i, m in ipairs(lang_hl_marks) do
|
||||
api.nvim_buf_set_extmark(bufnr, decor_ns, i - 1, m.col, {
|
||||
api.nvim_buf_set_extmark(buf, decor_ns, i - 1, m.col, {
|
||||
hl_group = 'Title',
|
||||
end_col = m.end_col,
|
||||
})
|
||||
end
|
||||
|
||||
vim.bo[bufnr].modifiable = false
|
||||
vim.bo[buf].modifiable = false
|
||||
end
|
||||
|
||||
--- Get node {i} from this View.
|
||||
|
||||
@@ -1231,7 +1231,7 @@ function LanguageTree:_edit(
|
||||
end
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param buf integer
|
||||
---@param changed_tick integer
|
||||
---@param start_row integer
|
||||
---@param start_col integer
|
||||
@@ -1243,7 +1243,7 @@ end
|
||||
---@param new_col integer
|
||||
---@param new_byte integer
|
||||
function LanguageTree:_on_bytes(
|
||||
bufnr,
|
||||
buf,
|
||||
changed_tick,
|
||||
start_row,
|
||||
start_col,
|
||||
@@ -1260,7 +1260,7 @@ function LanguageTree:_on_bytes(
|
||||
|
||||
self:_log(
|
||||
'on_bytes',
|
||||
bufnr,
|
||||
buf,
|
||||
changed_tick,
|
||||
start_row,
|
||||
start_col,
|
||||
@@ -1288,7 +1288,7 @@ function LanguageTree:_on_bytes(
|
||||
|
||||
self:_do_callback(
|
||||
'bytes',
|
||||
bufnr,
|
||||
buf,
|
||||
changed_tick,
|
||||
start_row,
|
||||
start_col,
|
||||
|
||||
@@ -77,10 +77,10 @@ function M.uri_from_fname(path)
|
||||
end
|
||||
|
||||
---Gets a URI from a bufnr.
|
||||
---@param bufnr integer
|
||||
---@param buf integer
|
||||
---@return string URI
|
||||
function M.uri_from_bufnr(bufnr)
|
||||
local fname = vim.api.nvim_buf_get_name(bufnr)
|
||||
function M.uri_from_bufnr(buf)
|
||||
local fname = vim.api.nvim_buf_get_name(buf)
|
||||
local volume_path = fname:match('^([a-zA-Z]:).*')
|
||||
local is_windows = volume_path ~= nil
|
||||
local scheme ---@type string?
|
||||
|
||||
123
src/gen/lint.lua
123
src/gen/lint.lua
@@ -25,6 +25,8 @@ local banned_verbs = {
|
||||
disable = 'enable',
|
||||
exit = 'cancel', -- or "stop"
|
||||
-- format = 'fmt',
|
||||
-- hide = '?',
|
||||
-- show = '?',
|
||||
list = 'get',
|
||||
notify = 'print', -- or "echo"
|
||||
pretty = 'fmt',
|
||||
@@ -57,40 +59,10 @@ local legacy_names = {
|
||||
nvim_list_uis = true,
|
||||
nvim_list_wins = true,
|
||||
},
|
||||
['runtime/lua/vim/diagnostic.lua'] = {
|
||||
count = true,
|
||||
get = true,
|
||||
hide = true,
|
||||
reset = true,
|
||||
set = true,
|
||||
show = true,
|
||||
status = true,
|
||||
},
|
||||
['runtime/lua/editorconfig.lua'] = {
|
||||
config = true,
|
||||
},
|
||||
['runtime/lua/vim/uri.lua'] = {
|
||||
uri_from_bufnr = true,
|
||||
uri_to_bufnr = true,
|
||||
},
|
||||
['runtime/lua/vim/snippet.lua'] = {
|
||||
new = true,
|
||||
},
|
||||
['runtime/lua/vim/hl.lua'] = {
|
||||
range = true,
|
||||
},
|
||||
['runtime/lua/vim/filetype.lua'] = {
|
||||
_getline = true,
|
||||
_getlines = true,
|
||||
_nextnonblank = true,
|
||||
},
|
||||
['runtime/lua/vim/_meta/regex.lua'] = {
|
||||
match_line = true,
|
||||
},
|
||||
['runtime/lua/vim/_inspector.lua'] = {
|
||||
['vim.inspect_pos'] = true,
|
||||
['vim.show_pos'] = true,
|
||||
},
|
||||
['runtime/lua/vim/_core/shared.lua'] = {
|
||||
_ensure_list = true,
|
||||
_list_insert = true,
|
||||
@@ -100,97 +72,23 @@ local legacy_names = {
|
||||
tbl_contains = true,
|
||||
},
|
||||
['runtime/lua/vim/lsp.lua'] = {
|
||||
_buf_get_full_text = true,
|
||||
_buf_get_line_ending = true,
|
||||
_set_defaults = true,
|
||||
buf_attach_client = true,
|
||||
buf_detach_client = true,
|
||||
buf_is_attached = true,
|
||||
buf_notify = true,
|
||||
buf_request = true,
|
||||
buf_request_all = true,
|
||||
buf_request_sync = true,
|
||||
},
|
||||
['runtime/lua/vim/lsp/_folding_range.lua'] = {
|
||||
new = true,
|
||||
},
|
||||
['runtime/lua/vim/lsp/_changetracking.lua'] = {
|
||||
_send_did_save = true,
|
||||
flush = true,
|
||||
init = true,
|
||||
reset_buf = true,
|
||||
send_changes = true,
|
||||
},
|
||||
['runtime/lua/vim/lsp/_capability.lua'] = {
|
||||
new = true,
|
||||
},
|
||||
['runtime/lua/vim/lsp/semantic_tokens.lua'] = {
|
||||
_start = true,
|
||||
force_refresh = true,
|
||||
get_at_pos = true,
|
||||
highlight_token = true,
|
||||
new = true,
|
||||
},
|
||||
['runtime/lua/vim/lsp/document_color.lua'] = {
|
||||
new = true,
|
||||
},
|
||||
['runtime/lua/vim/lsp/diagnostic.lua'] = {
|
||||
_enable = true,
|
||||
_refresh = true,
|
||||
get_line_diagnostics = true,
|
||||
},
|
||||
['runtime/lua/vim/lsp/completion.lua'] = {
|
||||
enable = true,
|
||||
request = true,
|
||||
},
|
||||
['runtime/lua/vim/lsp/codelens.lua'] = {
|
||||
new = true,
|
||||
},
|
||||
['runtime/lua/vim/lsp/client.lua'] = {
|
||||
_get_registrations = true,
|
||||
_on_detach = true,
|
||||
_on_exit = true,
|
||||
_process_request = true,
|
||||
_process_static_registrations = true,
|
||||
_remove_workspace_folder = true,
|
||||
_text_document_did_open_handler = true,
|
||||
on_attach = true,
|
||||
request = true,
|
||||
request_sync = true,
|
||||
supports_method = true,
|
||||
},
|
||||
['runtime/lua/vim/lsp/util.lua'] = {
|
||||
_make_line_range_params = true,
|
||||
apply_text_edits = true,
|
||||
buf_clear_references = true,
|
||||
buf_highlight_references = true,
|
||||
get_effective_tabstop = true,
|
||||
make_given_range_params = true,
|
||||
make_position_params = true,
|
||||
make_text_document_params = true,
|
||||
symbols_to_items = true,
|
||||
},
|
||||
['runtime/lua/vim/lsp/rpc.lua'] = {
|
||||
_notify = true,
|
||||
},
|
||||
['runtime/lua/vim/treesitter.lua'] = {
|
||||
_create_parser = true,
|
||||
get_captures_at_cursor = true,
|
||||
get_captures_at_pos = true,
|
||||
get_parser = true,
|
||||
node_contains = true,
|
||||
start = true,
|
||||
stop = true,
|
||||
},
|
||||
['runtime/lua/vim/treesitter/languagetree.lua'] = {
|
||||
_on_bytes = true,
|
||||
},
|
||||
['runtime/lua/vim/treesitter/dev.lua'] = {
|
||||
draw = true,
|
||||
new = true,
|
||||
},
|
||||
['runtime/lua/vim/treesitter/_fold.lua'] = {
|
||||
new = true,
|
||||
},
|
||||
['runtime/lua/vim/treesitter/highlighter.lua'] = {
|
||||
for_each_highlight_state = true,
|
||||
@@ -232,7 +130,7 @@ local legacy_fields = {
|
||||
bufnr = true,
|
||||
},
|
||||
['TS.Heading'] = {
|
||||
bufnr = true,
|
||||
bufnr = true, -- Passed to setloclist().
|
||||
},
|
||||
['vim.treesitter.get_node.Opts'] = {
|
||||
bufnr = true,
|
||||
@@ -282,14 +180,13 @@ function M.lint_names(source, api_funs, keysets, classes)
|
||||
local src_legacy = legacy_names[source] or {}
|
||||
for _, fun in ipairs(api_funs) do
|
||||
if fun.name and fun.params and not fun.deprecated and not fun.deprecated_since then
|
||||
-- Positional parameter names.
|
||||
if not src_legacy[fun.name] then
|
||||
for _, p in ipairs(fun.params) do
|
||||
local want_name = banned_nouns[p.name]
|
||||
if want_name then
|
||||
local msg = '%s: %s(): param "%s" should be renamed to "%s"'
|
||||
errors[#errors + 1] = fmt(msg, source, fun.name, p.name, want_name)
|
||||
end
|
||||
-- Positional parameter names: always checked (no legacy allowed).
|
||||
-- Exception: "bufnr" is allowed as a param name.
|
||||
for _, p in ipairs(fun.params) do
|
||||
local want_name = banned_nouns[p.name]
|
||||
if want_name and p.name ~= 'bufnr' then
|
||||
local msg = '%s: %s(): param "%s" should be renamed to "%s"'
|
||||
errors[#errors + 1] = fmt(msg, source, fun.name, p.name, want_name)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -4526,6 +4526,52 @@ describe('LSP', function()
|
||||
eq({ 0, 'foo', 1, 'bar' }, count_clients())
|
||||
end)
|
||||
|
||||
it('sends didClose and didOpen when languageId changes', function()
|
||||
exec_lua(create_server_definition)
|
||||
|
||||
local tmp1 = t.tmpname(true)
|
||||
|
||||
exec_lua(function()
|
||||
_G.server = _G._create_server({
|
||||
handlers = {
|
||||
initialize = function(_, _, callback)
|
||||
callback(nil, { capabilities = { textDocumentSync = { openClose = true } } })
|
||||
end,
|
||||
},
|
||||
})
|
||||
vim.lsp.config('foo', { cmd = _G.server.cmd, filetypes = { 'foo', 'bar' } })
|
||||
vim.lsp.enable('foo')
|
||||
vim.cmd.edit(tmp1)
|
||||
end)
|
||||
|
||||
local function test_messages()
|
||||
local opens = 0
|
||||
local closes = 0
|
||||
local msgs = exec_lua([[ return _G.server.messages ]])
|
||||
local num_clients = exec_lua([[ return #vim.lsp.get_clients() ]])
|
||||
for _, msg in ipairs(msgs) do
|
||||
opens = opens + (msg.method == 'textDocument/didOpen' and 1 or 0)
|
||||
closes = closes + (msg.method == 'textDocument/didClose' and 1 or 0)
|
||||
end
|
||||
return { opens, 'did_open', closes, 'did_close', num_clients, 'clients' }
|
||||
end
|
||||
|
||||
-- No filetype on the buffer yet.
|
||||
eq({ 0, 'did_open', 0, 'did_close', 0, 'clients' }, test_messages())
|
||||
|
||||
-- Set the filetype to 'foo', confirm didOpen is sent.
|
||||
exec_lua([[vim.bo.filetype = 'foo']])
|
||||
retry(nil, 1000, function()
|
||||
eq({ 1, 'did_open', 0, 'did_close', 1, 'clients' }, test_messages())
|
||||
end)
|
||||
|
||||
-- Set to anohter lsp-supported filetype 'bar', confirm didClose and didOpen are sent.
|
||||
exec_lua([[vim.bo.filetype = 'bar']])
|
||||
retry(nil, 1000, function()
|
||||
eq({ 2, 'did_open', 1, 'did_close', 1, 'clients' }, test_messages())
|
||||
end)
|
||||
end)
|
||||
|
||||
it('validates config on attach', function()
|
||||
local tmp1 = t.tmpname(true)
|
||||
exec_lua(function()
|
||||
|
||||
Reference in New Issue
Block a user