mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge #30237 validate --listen address
This commit is contained in:
commit
ae9674704a
@ -53,12 +53,6 @@ EDITOR
|
|||||||
documented and skips help buffers if run from a non-help buffer, otherwise
|
documented and skips help buffers if run from a non-help buffer, otherwise
|
||||||
it moves to another help buffer.
|
it moves to another help buffer.
|
||||||
|
|
||||||
VIM SCRIPT
|
|
||||||
|
|
||||||
• |v:msgpack_types| has the type "binary" removed. |msgpackparse()| no longer
|
|
||||||
treats BIN, STR and FIXSTR as separate types. Any of these is returned as a
|
|
||||||
string if possible, or a |blob| if the value contained embedded NUL:s.
|
|
||||||
|
|
||||||
EVENTS
|
EVENTS
|
||||||
|
|
||||||
• TODO
|
• TODO
|
||||||
@ -98,6 +92,12 @@ TUI
|
|||||||
|
|
||||||
• TODO
|
• TODO
|
||||||
|
|
||||||
|
VIMSCRIPT
|
||||||
|
|
||||||
|
• |v:msgpack_types| has the type "binary" removed. |msgpackparse()| no longer
|
||||||
|
treats BIN, STR and FIXSTR as separate types. Any of these is returned as a
|
||||||
|
string if possible, or a |blob| if the value contained embedded NUL:s.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
NEW FEATURES *news-features*
|
NEW FEATURES *news-features*
|
||||||
|
|
||||||
@ -162,7 +162,8 @@ PLUGINS
|
|||||||
|
|
||||||
STARTUP
|
STARTUP
|
||||||
|
|
||||||
• TODO
|
• Nvim will fail if the |--listen| or |$NVIM_LISTEN_ADDRESS| address is
|
||||||
|
invalid, instead of silently skipping an invalid address.
|
||||||
|
|
||||||
TERMINAL
|
TERMINAL
|
||||||
|
|
||||||
|
@ -93,15 +93,15 @@ void remote_ui_free_all_mem(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Wait until ui has connected on stdio channel if only_stdio
|
/// Wait until UI has connected.
|
||||||
/// is true, otherwise any channel.
|
///
|
||||||
|
/// @param only_stdio UI is expected to connect on stdio.
|
||||||
void remote_ui_wait_for_attach(bool only_stdio)
|
void remote_ui_wait_for_attach(bool only_stdio)
|
||||||
{
|
{
|
||||||
if (only_stdio) {
|
if (only_stdio) {
|
||||||
Channel *channel = find_channel(CHAN_STDIO);
|
Channel *channel = find_channel(CHAN_STDIO);
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
// this function should only be called in --embed mode, stdio channel
|
// `only_stdio` implies --embed mode, thus stdio channel can be assumed.
|
||||||
// can be assumed.
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,12 +332,6 @@ int main(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
bool use_builtin_ui = (has_term && !headless_mode && !embedded_mode && !silent_mode);
|
bool use_builtin_ui = (has_term && !headless_mode && !embedded_mode && !silent_mode);
|
||||||
|
|
||||||
// don't bind the server yet, if we are using builtin ui.
|
|
||||||
// This will be done when nvim server has been forked from the ui process
|
|
||||||
if (!use_builtin_ui) {
|
|
||||||
server_init(params.listen_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.remote) {
|
if (params.remote) {
|
||||||
remote_request(¶ms, params.remote, params.server_addr, argc, argv,
|
remote_request(¶ms, params.remote, params.server_addr, argc, argv,
|
||||||
use_builtin_ui);
|
use_builtin_ui);
|
||||||
@ -355,11 +349,19 @@ int main(int argc, char **argv)
|
|||||||
ui_client_channel_id = rv;
|
ui_client_channel_id = rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NORETURN: Start builtin UI client.
|
||||||
if (ui_client_channel_id) {
|
if (ui_client_channel_id) {
|
||||||
time_finish();
|
time_finish();
|
||||||
ui_client_run(remote_ui); // NORETURN
|
ui_client_run(remote_ui); // NORETURN
|
||||||
}
|
}
|
||||||
assert(!ui_client_channel_id && !use_builtin_ui);
|
assert(!ui_client_channel_id && !use_builtin_ui);
|
||||||
|
// Nvim server...
|
||||||
|
|
||||||
|
int listen_rv = server_init(params.listen_addr);
|
||||||
|
if (listen_rv != 0) {
|
||||||
|
mainerr("Failed to --listen", listen_rv < 0
|
||||||
|
? os_strerror(listen_rv) : (listen_rv == 1 ? "empty address" : NULL));
|
||||||
|
}
|
||||||
|
|
||||||
TIME_MSG("expanding arguments");
|
TIME_MSG("expanding arguments");
|
||||||
|
|
||||||
|
@ -28,27 +28,32 @@ static garray_T watchers = GA_EMPTY_INIT_VALUE;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Initializes the module
|
/// Initializes the module
|
||||||
bool server_init(const char *listen_addr)
|
///
|
||||||
|
/// @returns 0: success, 1: validation error, 2: already listening, -errno: failed to bind/listen.
|
||||||
|
int server_init(const char *listen_addr)
|
||||||
{
|
{
|
||||||
|
bool must_free = false;
|
||||||
ga_init(&watchers, sizeof(SocketWatcher *), 1);
|
ga_init(&watchers, sizeof(SocketWatcher *), 1);
|
||||||
|
|
||||||
// $NVIM_LISTEN_ADDRESS (deprecated)
|
// $NVIM_LISTEN_ADDRESS (deprecated)
|
||||||
if (!listen_addr && os_env_exists(ENV_LISTEN)) {
|
if ((!listen_addr || listen_addr[0] == '\0') && os_env_exists(ENV_LISTEN)) {
|
||||||
listen_addr = os_getenv(ENV_LISTEN);
|
listen_addr = os_getenv(ENV_LISTEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rv = listen_addr ? server_start(listen_addr) : 1;
|
if (!listen_addr || listen_addr[0] == '\0') {
|
||||||
if (0 != rv) {
|
|
||||||
listen_addr = server_address_new(NULL);
|
listen_addr = server_address_new(NULL);
|
||||||
if (!listen_addr) {
|
must_free = true;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
rv = server_start(listen_addr);
|
|
||||||
xfree((char *)listen_addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!listen_addr) {
|
||||||
|
abort(); // Cannot happen.
|
||||||
|
}
|
||||||
|
|
||||||
|
int rv = server_start(listen_addr);
|
||||||
|
|
||||||
if (os_env_exists(ENV_LISTEN)) {
|
if (os_env_exists(ENV_LISTEN)) {
|
||||||
// Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter.
|
// Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter. It is "input only", it must not be
|
||||||
|
// leaked to child jobs or :terminal.
|
||||||
os_unsetenv(ENV_LISTEN);
|
os_unsetenv(ENV_LISTEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +62,11 @@ bool server_init(const char *listen_addr)
|
|||||||
ELOG("test log message");
|
ELOG("test log message");
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv == 0;
|
if (must_free) {
|
||||||
|
xfree((char *)listen_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Teardown a single server
|
/// Teardown a single server
|
||||||
|
@ -6,17 +6,11 @@ require('os')
|
|||||||
local eval = n.eval
|
local eval = n.eval
|
||||||
local command = n.command
|
local command = n.command
|
||||||
local eq, neq = t.eq, t.neq
|
local eq, neq = t.eq, t.neq
|
||||||
local tempfile = t.tmpname()
|
local tempfile = t.tmpname(false)
|
||||||
local source = n.source
|
local source = n.source
|
||||||
local matches = t.matches
|
local matches = t.matches
|
||||||
local read_file = t.read_file
|
local read_file = t.read_file
|
||||||
|
|
||||||
-- tmpname() also creates the file on POSIX systems. Remove it again.
|
|
||||||
-- We just need the name, ignoring any race conditions.
|
|
||||||
if uv.fs_stat(tempfile).uid then
|
|
||||||
os.remove(tempfile)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function assert_file_exists(filepath)
|
local function assert_file_exists(filepath)
|
||||||
neq(nil, uv.fs_stat(filepath).uid)
|
neq(nil, uv.fs_stat(filepath).uid)
|
||||||
end
|
end
|
||||||
@ -31,6 +25,7 @@ describe(':profile', function()
|
|||||||
after_each(function()
|
after_each(function()
|
||||||
n.expect_exit(command, 'qall!')
|
n.expect_exit(command, 'qall!')
|
||||||
if uv.fs_stat(tempfile).uid ~= nil then
|
if uv.fs_stat(tempfile).uid ~= nil then
|
||||||
|
-- Delete the tempfile. We just need the name, ignoring any race conditions.
|
||||||
os.remove(tempfile)
|
os.remove(tempfile)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
@ -74,8 +74,7 @@ describe('vim.loader', function()
|
|||||||
vim.loader.enable()
|
vim.loader.enable()
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local tmp = t.tmpname()
|
local tmp = t.tmpname(false)
|
||||||
assert(os.remove(tmp))
|
|
||||||
assert(t.mkdir(tmp))
|
assert(t.mkdir(tmp))
|
||||||
assert(t.mkdir(tmp .. '/%'))
|
assert(t.mkdir(tmp .. '/%'))
|
||||||
local tmp1 = tmp .. '/%/x'
|
local tmp1 = tmp .. '/%/x'
|
||||||
|
@ -247,6 +247,7 @@ describe('startup defaults', function()
|
|||||||
} })
|
} })
|
||||||
eq('Xtest-logpath', eval('$NVIM_LOG_FILE'))
|
eq('Xtest-logpath', eval('$NVIM_LOG_FILE'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('defaults to stdpath("log")/log if empty', function()
|
it('defaults to stdpath("log")/log if empty', function()
|
||||||
eq(true, mkdir(xdgdir) and mkdir(xdgstatedir))
|
eq(true, mkdir(xdgdir) and mkdir(xdgstatedir))
|
||||||
clear({
|
clear({
|
||||||
@ -257,6 +258,7 @@ describe('startup defaults', function()
|
|||||||
})
|
})
|
||||||
eq(xdgstatedir .. '/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
|
eq(xdgstatedir .. '/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('defaults to stdpath("log")/log if invalid', function()
|
it('defaults to stdpath("log")/log if invalid', function()
|
||||||
eq(true, mkdir(xdgdir) and mkdir(xdgstatedir))
|
eq(true, mkdir(xdgdir) and mkdir(xdgstatedir))
|
||||||
clear({
|
clear({
|
||||||
@ -266,6 +268,8 @@ describe('startup defaults', function()
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
eq(xdgstatedir .. '/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
|
eq(xdgstatedir .. '/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
|
||||||
|
-- Avoid "failed to open $NVIM_LOG_FILE" noise in test output.
|
||||||
|
expect_exit(command, 'qall!')
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
@ -339,9 +343,11 @@ describe('XDG defaults', function()
|
|||||||
local state_dir = is_os('win') and 'nvim-data' or 'nvim'
|
local state_dir = is_os('win') and 'nvim-data' or 'nvim'
|
||||||
local root_path = is_os('win') and 'C:' or ''
|
local root_path = is_os('win') and 'C:' or ''
|
||||||
|
|
||||||
describe('with too long XDG variables', function()
|
describe('with too long XDG vars', function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
clear({
|
clear({
|
||||||
|
-- Ensure valid --listen address despite broken XDG vars (else Nvim won't start).
|
||||||
|
args = { '--listen', is_os('win') and '' or t.tmpname(false) },
|
||||||
args_rm = { 'runtimepath' },
|
args_rm = { 'runtimepath' },
|
||||||
env = {
|
env = {
|
||||||
NVIM_LOG_FILE = testlog,
|
NVIM_LOG_FILE = testlog,
|
||||||
@ -361,6 +367,9 @@ describe('XDG defaults', function()
|
|||||||
|
|
||||||
it('are correctly set', function()
|
it('are correctly set', function()
|
||||||
if not is_os('win') then
|
if not is_os('win') then
|
||||||
|
-- Broken XDG vars cause serverstart() to fail (except on Windows, where servernames are not
|
||||||
|
-- informed by $XDG_STATE_HOME).
|
||||||
|
t.matches('Failed to start server: no such file or directory', t.pcall_err(fn.serverstart))
|
||||||
assert_log('Failed to start server: no such file or directory: /X/X/X', testlog, 10)
|
assert_log('Failed to start server: no such file or directory: /X/X/X', testlog, 10)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -522,9 +531,11 @@ describe('XDG defaults', function()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with XDG variables that can be expanded', function()
|
describe('with expandable XDG vars', function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
clear({
|
clear({
|
||||||
|
-- Ensure valid --listen address despite broken XDG vars (else Nvim won't start).
|
||||||
|
args = { '--listen', is_os('win') and '' or t.tmpname(false) },
|
||||||
args_rm = { 'runtimepath' },
|
args_rm = { 'runtimepath' },
|
||||||
env = {
|
env = {
|
||||||
NVIM_LOG_FILE = testlog,
|
NVIM_LOG_FILE = testlog,
|
||||||
@ -544,6 +555,9 @@ describe('XDG defaults', function()
|
|||||||
|
|
||||||
it('are not expanded', function()
|
it('are not expanded', function()
|
||||||
if not is_os('win') then
|
if not is_os('win') then
|
||||||
|
-- Broken XDG vars cause serverstart() to fail (except on Windows, where servernames are not
|
||||||
|
-- informed by $XDG_STATE_HOME).
|
||||||
|
t.matches('Failed to start server: no such file or directory', t.pcall_err(fn.serverstart))
|
||||||
assert_log(
|
assert_log(
|
||||||
'Failed to start server: no such file or directory: %$XDG_RUNTIME_DIR%/',
|
'Failed to start server: no such file or directory: %$XDG_RUNTIME_DIR%/',
|
||||||
testlog,
|
testlog,
|
||||||
@ -895,7 +909,7 @@ describe('stdpath()', function()
|
|||||||
assert_alive() -- Check for crash. #8393
|
assert_alive() -- Check for crash. #8393
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('reacts to $NVIM_APPNAME', function()
|
it('supports $NVIM_APPNAME', function()
|
||||||
local appname = 'NVIM_APPNAME_TEST' .. ('_'):rep(106)
|
local appname = 'NVIM_APPNAME_TEST' .. ('_'):rep(106)
|
||||||
clear({ env = { NVIM_APPNAME = appname, NVIM_LOG_FILE = testlog } })
|
clear({ env = { NVIM_APPNAME = appname, NVIM_LOG_FILE = testlog } })
|
||||||
eq(appname, fn.fnamemodify(fn.stdpath('config'), ':t'))
|
eq(appname, fn.fnamemodify(fn.stdpath('config'), ':t'))
|
||||||
@ -916,7 +930,7 @@ describe('stdpath()', function()
|
|||||||
local function test_appname(testAppname, expected_exitcode)
|
local function test_appname(testAppname, expected_exitcode)
|
||||||
local lua_code = string.format(
|
local lua_code = string.format(
|
||||||
[[
|
[[
|
||||||
local child = vim.fn.jobstart({ vim.v.progpath, '--clean', '--headless', '+qall!' }, { env = { NVIM_APPNAME = %q } })
|
local child = vim.fn.jobstart({ vim.v.progpath, '--clean', '--headless', '--listen', 'x', '+qall!' }, { env = { NVIM_APPNAME = %q } })
|
||||||
return vim.fn.jobwait({ child }, %d)[1]
|
return vim.fn.jobwait({ child }, %d)[1]
|
||||||
]],
|
]],
|
||||||
alter_slashes(testAppname),
|
alter_slashes(testAppname),
|
||||||
@ -935,9 +949,6 @@ describe('stdpath()', function()
|
|||||||
-- Valid appnames:
|
-- Valid appnames:
|
||||||
test_appname('a/b', 0)
|
test_appname('a/b', 0)
|
||||||
test_appname('a/b\\c', 0)
|
test_appname('a/b\\c', 0)
|
||||||
if not is_os('win') then
|
|
||||||
assert_log('Failed to start server: no such file or directory:', testlog)
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('returns a String', function()
|
describe('returns a String', function()
|
||||||
|
@ -800,8 +800,7 @@ describe('LSP', function()
|
|||||||
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
||||||
if ctx.method == 'start' then
|
if ctx.method == 'start' then
|
||||||
local tmpfile_old = tmpname()
|
local tmpfile_old = tmpname()
|
||||||
local tmpfile_new = tmpname()
|
local tmpfile_new = tmpname(false)
|
||||||
os.remove(tmpfile_new)
|
|
||||||
exec_lua(function(oldname, newname)
|
exec_lua(function(oldname, newname)
|
||||||
_G.BUFFER = vim.api.nvim_get_current_buf()
|
_G.BUFFER = vim.api.nvim_get_current_buf()
|
||||||
vim.api.nvim_buf_set_name(_G.BUFFER, oldname)
|
vim.api.nvim_buf_set_name(_G.BUFFER, oldname)
|
||||||
@ -2370,8 +2369,7 @@ describe('LSP', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it('Supports file creation with CreateFile payload', function()
|
it('Supports file creation with CreateFile payload', function()
|
||||||
local tmpfile = tmpname()
|
local tmpfile = tmpname(false)
|
||||||
os.remove(tmpfile) -- Should not exist, only interested in a tmpname
|
|
||||||
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
|
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
|
||||||
local edit = {
|
local edit = {
|
||||||
documentChanges = {
|
documentChanges = {
|
||||||
@ -2388,9 +2386,7 @@ describe('LSP', function()
|
|||||||
it(
|
it(
|
||||||
'Supports file creation in folder that needs to be created with CreateFile payload',
|
'Supports file creation in folder that needs to be created with CreateFile payload',
|
||||||
function()
|
function()
|
||||||
local tmpfile = tmpname()
|
local tmpfile = tmpname(false) .. '/dummy/x/'
|
||||||
os.remove(tmpfile) -- Should not exist, only interested in a tmpname
|
|
||||||
tmpfile = tmpfile .. '/dummy/x/'
|
|
||||||
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
|
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
|
||||||
local edit = {
|
local edit = {
|
||||||
documentChanges = {
|
documentChanges = {
|
||||||
@ -2468,8 +2464,7 @@ describe('LSP', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it('DeleteFile fails if file does not exist and ignoreIfNotExists is false', function()
|
it('DeleteFile fails if file does not exist and ignoreIfNotExists is false', function()
|
||||||
local tmpfile = tmpname()
|
local tmpfile = tmpname(false)
|
||||||
os.remove(tmpfile)
|
|
||||||
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
|
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
|
||||||
local edit = {
|
local edit = {
|
||||||
documentChanges = {
|
documentChanges = {
|
||||||
@ -2493,8 +2488,7 @@ describe('LSP', function()
|
|||||||
it('Can rename an existing file', function()
|
it('Can rename an existing file', function()
|
||||||
local old = tmpname()
|
local old = tmpname()
|
||||||
write_file(old, 'Test content')
|
write_file(old, 'Test content')
|
||||||
local new = tmpname()
|
local new = tmpname(false)
|
||||||
os.remove(new) -- only reserve the name, file must not exist for the test scenario
|
|
||||||
local lines = exec_lua(function(old0, new0)
|
local lines = exec_lua(function(old0, new0)
|
||||||
local old_bufnr = vim.fn.bufadd(old0)
|
local old_bufnr = vim.fn.bufadd(old0)
|
||||||
vim.fn.bufload(old_bufnr)
|
vim.fn.bufload(old_bufnr)
|
||||||
@ -2514,10 +2508,8 @@ describe('LSP', function()
|
|||||||
|
|
||||||
it('Can rename a directory', function()
|
it('Can rename a directory', function()
|
||||||
-- only reserve the name, file must not exist for the test scenario
|
-- only reserve the name, file must not exist for the test scenario
|
||||||
local old_dir = tmpname()
|
local old_dir = tmpname(false)
|
||||||
local new_dir = tmpname()
|
local new_dir = tmpname(false)
|
||||||
os.remove(old_dir)
|
|
||||||
os.remove(new_dir)
|
|
||||||
|
|
||||||
n.mkdir_p(old_dir)
|
n.mkdir_p(old_dir)
|
||||||
|
|
||||||
@ -2542,10 +2534,8 @@ describe('LSP', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it('Does not touch buffers that do not match path prefix', function()
|
it('Does not touch buffers that do not match path prefix', function()
|
||||||
local old = tmpname()
|
local old = tmpname(false)
|
||||||
local new = tmpname()
|
local new = tmpname(false)
|
||||||
os.remove(old)
|
|
||||||
os.remove(new)
|
|
||||||
n.mkdir_p(old)
|
n.mkdir_p(old)
|
||||||
|
|
||||||
eq(
|
eq(
|
||||||
@ -2604,8 +2594,7 @@ describe('LSP', function()
|
|||||||
it('Maintains undo information for loaded buffer', function()
|
it('Maintains undo information for loaded buffer', function()
|
||||||
local old = tmpname()
|
local old = tmpname()
|
||||||
write_file(old, 'line')
|
write_file(old, 'line')
|
||||||
local new = tmpname()
|
local new = tmpname(false)
|
||||||
os.remove(new)
|
|
||||||
|
|
||||||
local undo_kept = exec_lua(function(old0, new0)
|
local undo_kept = exec_lua(function(old0, new0)
|
||||||
vim.opt.undofile = true
|
vim.opt.undofile = true
|
||||||
@ -2629,8 +2618,7 @@ describe('LSP', function()
|
|||||||
it('Maintains undo information for unloaded buffer', function()
|
it('Maintains undo information for unloaded buffer', function()
|
||||||
local old = tmpname()
|
local old = tmpname()
|
||||||
write_file(old, 'line')
|
write_file(old, 'line')
|
||||||
local new = tmpname()
|
local new = tmpname(false)
|
||||||
os.remove(new)
|
|
||||||
|
|
||||||
local undo_kept = exec_lua(function(old0, new0)
|
local undo_kept = exec_lua(function(old0, new0)
|
||||||
vim.opt.undofile = true
|
vim.opt.undofile = true
|
||||||
@ -2651,8 +2639,7 @@ describe('LSP', function()
|
|||||||
it('Does not rename file when it conflicts with a buffer without file', function()
|
it('Does not rename file when it conflicts with a buffer without file', function()
|
||||||
local old = tmpname()
|
local old = tmpname()
|
||||||
write_file(old, 'Old File')
|
write_file(old, 'Old File')
|
||||||
local new = tmpname()
|
local new = tmpname(false)
|
||||||
os.remove(new)
|
|
||||||
|
|
||||||
local lines = exec_lua(function(old0, new0)
|
local lines = exec_lua(function(old0, new0)
|
||||||
local old_buf = vim.fn.bufadd(old0)
|
local old_buf = vim.fn.bufadd(old0)
|
||||||
@ -5023,13 +5010,7 @@ describe('LSP', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it('can connect to lsp server via pipe or domain_socket', function()
|
it('can connect to lsp server via pipe or domain_socket', function()
|
||||||
local tmpfile --- @type string
|
local tmpfile = is_os('win') and '\\\\.\\\\pipe\\pipe.test' or tmpname(false)
|
||||||
if is_os('win') then
|
|
||||||
tmpfile = '\\\\.\\\\pipe\\pipe.test'
|
|
||||||
else
|
|
||||||
tmpfile = tmpname()
|
|
||||||
os.remove(tmpfile)
|
|
||||||
end
|
|
||||||
local result = exec_lua(function(SOCK)
|
local result = exec_lua(function(SOCK)
|
||||||
local uv = vim.uv
|
local uv = vim.uv
|
||||||
local server = assert(uv.new_pipe(false))
|
local server = assert(uv.new_pipe(false))
|
||||||
@ -5135,9 +5116,7 @@ describe('LSP', function()
|
|||||||
|
|
||||||
describe('#dynamic vim.lsp._dynamic', function()
|
describe('#dynamic vim.lsp._dynamic', function()
|
||||||
it('supports dynamic registration', function()
|
it('supports dynamic registration', function()
|
||||||
---@type string
|
local root_dir = tmpname(false)
|
||||||
local root_dir = tmpname()
|
|
||||||
os.remove(root_dir)
|
|
||||||
mkdir(root_dir)
|
mkdir(root_dir)
|
||||||
local tmpfile = root_dir .. '/dynamic.foo'
|
local tmpfile = root_dir .. '/dynamic.foo'
|
||||||
local file = io.open(tmpfile, 'w')
|
local file = io.open(tmpfile, 'w')
|
||||||
@ -5264,8 +5243,7 @@ describe('LSP', function()
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
local root_dir = tmpname()
|
local root_dir = tmpname(false)
|
||||||
os.remove(root_dir)
|
|
||||||
mkdir(root_dir)
|
mkdir(root_dir)
|
||||||
|
|
||||||
exec_lua(create_server_definition)
|
exec_lua(create_server_definition)
|
||||||
|
@ -4,7 +4,6 @@ local n = require('test.functional.testnvim')()
|
|||||||
local assert_log = t.assert_log
|
local assert_log = t.assert_log
|
||||||
local eq, neq, eval = t.eq, t.neq, n.eval
|
local eq, neq, eval = t.eq, t.neq, n.eval
|
||||||
local clear, fn, api = n.clear, n.fn, n.api
|
local clear, fn, api = n.clear, n.fn, n.api
|
||||||
local ok = t.ok
|
|
||||||
local matches = t.matches
|
local matches = t.matches
|
||||||
local pcall_err = t.pcall_err
|
local pcall_err = t.pcall_err
|
||||||
local check_close = n.check_close
|
local check_close = n.check_close
|
||||||
@ -49,15 +48,6 @@ describe('server', function()
|
|||||||
eq('', eval('$NVIM_LISTEN_ADDRESS'))
|
eq('', eval('$NVIM_LISTEN_ADDRESS'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('sets new v:servername if $NVIM_LISTEN_ADDRESS is invalid', function()
|
|
||||||
clear({ env = { NVIM_LISTEN_ADDRESS = '.' } })
|
|
||||||
-- Cleared on startup.
|
|
||||||
eq('', eval('$NVIM_LISTEN_ADDRESS'))
|
|
||||||
local servers = fn.serverlist()
|
|
||||||
eq(1, #servers)
|
|
||||||
ok(string.len(servers[1]) > 4) -- "~/.local/state/nvim…/…" or "\\.\pipe\…"
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('sets v:servername at startup or if all servers were stopped', function()
|
it('sets v:servername at startup or if all servers were stopped', function()
|
||||||
clear()
|
clear()
|
||||||
local initial_server = api.nvim_get_vvar('servername')
|
local initial_server = api.nvim_get_vvar('servername')
|
||||||
@ -89,20 +79,26 @@ describe('server', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it('serverstop() returns false for invalid input', function()
|
it('serverstop() returns false for invalid input', function()
|
||||||
clear { env = {
|
clear {
|
||||||
NVIM_LOG_FILE = testlog,
|
args_rm = { '--listen' },
|
||||||
NVIM_LISTEN_ADDRESS = '.',
|
env = {
|
||||||
} }
|
NVIM_LOG_FILE = testlog,
|
||||||
|
NVIM_LISTEN_ADDRESS = '',
|
||||||
|
},
|
||||||
|
}
|
||||||
eq(0, eval("serverstop('')"))
|
eq(0, eval("serverstop('')"))
|
||||||
eq(0, eval("serverstop('bogus-socket-name')"))
|
eq(0, eval("serverstop('bogus-socket-name')"))
|
||||||
assert_log('Not listening on bogus%-socket%-name', testlog, 10)
|
assert_log('Not listening on bogus%-socket%-name', testlog, 10)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('parses endpoints', function()
|
it('parses endpoints', function()
|
||||||
clear { env = {
|
clear {
|
||||||
NVIM_LOG_FILE = testlog,
|
args_rm = { '--listen' },
|
||||||
NVIM_LISTEN_ADDRESS = '.',
|
env = {
|
||||||
} }
|
NVIM_LOG_FILE = testlog,
|
||||||
|
NVIM_LISTEN_ADDRESS = '',
|
||||||
|
},
|
||||||
|
}
|
||||||
clear_serverlist()
|
clear_serverlist()
|
||||||
eq({}, fn.serverlist())
|
eq({}, fn.serverlist())
|
||||||
|
|
||||||
@ -178,18 +174,41 @@ end)
|
|||||||
describe('startup --listen', function()
|
describe('startup --listen', function()
|
||||||
it('validates', function()
|
it('validates', function()
|
||||||
clear()
|
clear()
|
||||||
local cmd = { unpack(n.nvim_argv) }
|
|
||||||
table.insert(cmd, '--listen')
|
|
||||||
matches('nvim.*: Argument missing after: "%-%-listen"', fn.system(cmd))
|
|
||||||
|
|
||||||
cmd = { unpack(n.nvim_argv) }
|
-- Tests args with and without "--headless".
|
||||||
table.insert(cmd, '--listen2')
|
local function _test(args, expected)
|
||||||
matches('nvim.*: Garbage after option argument: "%-%-listen2"', fn.system(cmd))
|
-- XXX: clear v:shell_error, sigh...
|
||||||
|
fn.system({ n.nvim_prog, '-es', '+qall!' })
|
||||||
|
assert(0 == eval('v:shell_error'))
|
||||||
|
local cmd = vim.list_extend({ unpack(n.nvim_argv) }, vim.list_extend({ '--headless' }, args))
|
||||||
|
local output = fn.system(cmd)
|
||||||
|
assert(0 ~= eval('v:shell_error'))
|
||||||
|
-- TODO(justinmk): output not properly captured on Windows?
|
||||||
|
if is_os('win') then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
matches(expected, output)
|
||||||
|
cmd = vim.list_extend({ unpack(n.nvim_argv) }, args)
|
||||||
|
matches(expected, fn.system(cmd))
|
||||||
|
end
|
||||||
|
|
||||||
|
_test({ '--listen' }, 'nvim.*: Argument missing after: "%-%-listen"')
|
||||||
|
_test({ '--listen2' }, 'nvim.*: Garbage after option argument: "%-%-listen2"')
|
||||||
|
_test({ '--listen', n.eval('v:servername') }, 'nvim.*: Failed to %-%-listen: ".* already .*"')
|
||||||
|
_test({ '--listen', '/' }, 'nvim.*: Failed to %-%-listen: ".*"')
|
||||||
|
_test(
|
||||||
|
{ '--listen', 'https://example.com' },
|
||||||
|
('nvim.*: Failed to %%-%%-listen: "%s"'):format(
|
||||||
|
(is_os('mac') or is_os('win')) and 'unknown node or service'
|
||||||
|
or 'service not available for socket type'
|
||||||
|
)
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('sets v:servername, overrides $NVIM_LISTEN_ADDRESS', function()
|
it('sets v:servername, overrides $NVIM_LISTEN_ADDRESS', function()
|
||||||
local addr = (is_os('win') and [[\\.\pipe\Xtest-listen-pipe]] or './Xtest-listen-pipe')
|
local addr = (is_os('win') and [[\\.\pipe\Xtest-listen-pipe]] or './Xtest-listen-pipe')
|
||||||
clear({ env = { NVIM_LISTEN_ADDRESS = './Xtest-env-pipe' }, args = { '--listen', addr } })
|
clear({ env = { NVIM_LISTEN_ADDRESS = './Xtest-env-pipe' }, args = { '--listen', addr } })
|
||||||
|
eq('', eval('$NVIM_LISTEN_ADDRESS')) -- Cleared on startup.
|
||||||
eq(addr, api.nvim_get_vvar('servername'))
|
eq(addr, api.nvim_get_vvar('servername'))
|
||||||
|
|
||||||
-- Address without slashes is a "name" which is appended to a generated path. #8519
|
-- Address without slashes is a "name" which is appended to a generated path. #8519
|
||||||
|
@ -402,14 +402,18 @@ end
|
|||||||
local tmpname_id = 0
|
local tmpname_id = 0
|
||||||
local tmpdir = tmpdir_get()
|
local tmpdir = tmpdir_get()
|
||||||
|
|
||||||
--- Creates a new temporary file for use by tests.
|
--- Generates a unique file path for use by tests, and writes the file unless `create=false`.
|
||||||
function M.tmpname()
|
---
|
||||||
|
---@param create? boolean (default true) Write the file.
|
||||||
|
function M.tmpname(create)
|
||||||
if tmpdir_is_local(tmpdir) then
|
if tmpdir_is_local(tmpdir) then
|
||||||
-- Cannot control os.tmpname() dir, so hack our own tmpname() impl.
|
-- Cannot control os.tmpname() dir, so hack our own tmpname() impl.
|
||||||
tmpname_id = tmpname_id + 1
|
tmpname_id = tmpname_id + 1
|
||||||
-- "…/Xtest_tmpdir/T42.7"
|
-- "…/Xtest_tmpdir/T42.7"
|
||||||
local fname = ('%s/%s.%d'):format(tmpdir, (_G._nvim_test_id or 'nvim-test'), tmpname_id)
|
local fname = ('%s/%s.%d'):format(tmpdir, (_G._nvim_test_id or 'nvim-test'), tmpname_id)
|
||||||
io.open(fname, 'w'):close()
|
if create ~= false then
|
||||||
|
io.open(fname, 'w'):close()
|
||||||
|
end
|
||||||
return fname
|
return fname
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user