Merge pull request #27485 from zeertzjq/vim-9.1.0112

vim-patch:9.1.{0112,0113}
This commit is contained in:
zeertzjq 2024-02-16 07:34:02 +08:00 committed by GitHub
commit 04dfa2eea9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 104 additions and 18 deletions

View File

@ -843,8 +843,9 @@ void buf_freeall(buf_T *buf, int flags)
ml_close(buf, true); // close and delete the memline/memfile ml_close(buf, true); // close and delete the memline/memfile
buf->b_ml.ml_line_count = 0; // no lines in buffer buf->b_ml.ml_line_count = 0; // no lines in buffer
if ((flags & BFA_KEEP_UNDO) == 0) { if ((flags & BFA_KEEP_UNDO) == 0) {
u_blockfree(buf); // free the memory allocated for undo // free the memory allocated for undo
u_clearall(buf); // reset all undo information // and reset all undo information
u_clearallandblockfree(buf);
} }
syntax_clear(&buf->b_s); // reset syntax info syntax_clear(&buf->b_s); // reset syntax info
buf->b_flags &= ~BF_READERR; // a read error is no longer relevant buf->b_flags &= ~BF_READERR; // a read error is no longer relevant

View File

@ -3171,8 +3171,7 @@ void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
// Mark the buffer as unmodified and free undo info. // Mark the buffer as unmodified and free undo info.
unchanged(buf, true, true); unchanged(buf, true, true);
if ((flags & READ_KEEP_UNDO) == 0) { if ((flags & READ_KEEP_UNDO) == 0) {
u_blockfree(buf); u_clearallandblockfree(buf);
u_clearall(buf);
} else { } else {
// Mark all undo states as changed. // Mark all undo states as changed.
u_unchanged(curbuf); u_unchanged(curbuf);

View File

@ -68,6 +68,7 @@
#include "nvim/strings.h" #include "nvim/strings.h"
#include "nvim/types_defs.h" #include "nvim/types_defs.h"
#include "nvim/ui.h" #include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/vim_defs.h" #include "nvim/vim_defs.h"
#include "nvim/window.h" #include "nvim/window.h"
@ -4142,6 +4143,12 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q
} }
// delete all existing lines // delete all existing lines
//
// Note: we cannot store undo information, because
// qf buffer is usually not allowed to be modified.
//
// So we need to clean up undo information
// otherwise autocommands may invalidate the undo stack
while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0) { while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0) {
// If deletion fails, this loop may run forever, so // If deletion fails, this loop may run forever, so
// signal error and return. // signal error and return.
@ -4150,6 +4157,9 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q
return; return;
} }
} }
// Remove all undo information
u_clearallandblockfree(curbuf);
} }
// Check if there is anything to display // Check if there is anything to display

View File

@ -2988,6 +2988,28 @@ void u_clearall(buf_T *buf)
buf->b_u_line_lnum = 0; buf->b_u_line_lnum = 0;
} }
/// Free all allocated memory blocks for the buffer 'buf'.
void u_blockfree(buf_T *buf)
{
while (buf->b_u_oldhead != NULL) {
#ifndef NDEBUG
u_header_T *previous_oldhead = buf->b_u_oldhead;
#endif
u_freeheader(buf, buf->b_u_oldhead, NULL);
assert(buf->b_u_oldhead != previous_oldhead);
}
xfree(buf->b_u_line_ptr);
}
/// Free all allocated memory blocks for the buffer 'buf'.
/// and invalidate the undo buffer
void u_clearallandblockfree(buf_T *buf)
{
u_blockfree(buf);
u_clearall(buf);
}
/// Save the line "lnum" for the "U" command. /// Save the line "lnum" for the "U" command.
void u_saveline(buf_T *buf, linenr_T lnum) void u_saveline(buf_T *buf, linenr_T lnum)
{ {
@ -3054,20 +3076,6 @@ void u_undoline(void)
check_cursor_col(); check_cursor_col();
} }
/// Free all allocated memory blocks for the buffer 'buf'.
void u_blockfree(buf_T *buf)
{
while (buf->b_u_oldhead != NULL) {
#ifndef NDEBUG
u_header_T *previous_oldhead = buf->b_u_oldhead;
#endif
u_freeheader(buf, buf->b_u_oldhead, NULL);
assert(buf->b_u_oldhead != previous_oldhead);
}
xfree(buf->b_u_line_ptr);
}
/// Allocate memory and copy curbuf line into it. /// Allocate memory and copy curbuf line into it.
/// ///
/// @param lnum the line to copy /// @param lnum the line to copy

View File

@ -0,0 +1,40 @@
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local write_file = helpers.write_file
local command = helpers.command
local feed = helpers.feed
local api = helpers.api
local eq = helpers.eq
before_each(clear)
-- oldtest: Test_autocmd_invalidates_undo_on_textchanged()
it('no E440 in quickfix window when autocommand invalidates undo', function()
write_file(
'XTest_autocmd_invalidates_undo_on_textchanged',
[[
set hidden
" create quickfix list (at least 2 lines to move line)
vimgrep /u/j %
" enter quickfix window
cwindow
" set modifiable
setlocal modifiable
" set autocmd to clear quickfix list
autocmd! TextChanged <buffer> call setqflist([])
" move line
move+1
]]
)
finally(function()
os.remove('XTest_autocmd_invalidates_undo_on_textchanged')
end)
command('edit XTest_autocmd_invalidates_undo_on_textchanged')
command('so %')
feed('G')
eq('', api.nvim_get_vvar('errmsg'))
end)

View File

@ -3840,4 +3840,32 @@ func Test_autocmd_shortmess()
delfunc SetupVimTest_shm delfunc SetupVimTest_shm
endfunc endfunc
func Test_autocmd_invalidates_undo_on_textchanged()
CheckRunVimInTerminal
let script =<< trim END
set hidden
" create quickfix list (at least 2 lines to move line)
vimgrep /u/j %
" enter quickfix window
cwindow
" set modifiable
setlocal modifiable
" set autocmd to clear quickfix list
autocmd! TextChanged <buffer> call setqflist([])
" move line
move+1
END
call writefile(script, 'XTest_autocmd_invalidates_undo_on_textchanged', 'D')
let buf = RunVimInTerminal('XTest_autocmd_invalidates_undo_on_textchanged', {'rows': 20})
call term_sendkeys(buf, ":so %\<cr>")
call term_sendkeys(buf, "G")
call WaitForAssert({-> assert_match('^XTest_autocmd_invalidates_undo_on_textchanged\s*$', term_getline(buf, 20))}, 1000)
call StopVimInTerminal(buf)
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab