mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.2.3259 when 'indentexpr' causes an error did_throw may hang (#21240)
vim-patch:8.2.3259: when 'indentexpr' causes an error did_throw may hang
Problem: When 'indentexpr' causes an error the did_throw flag may remain
set.
Solution: Reset did_throw and show the error. (closes vim/vim#8677)
620c959c6c
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
parent
bfdddec8ba
commit
c0d17cec0b
@ -766,53 +766,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
|
||||
// of interrupts or errors to exceptions, and ensure that no more
|
||||
// commands are executed.
|
||||
if (did_throw) {
|
||||
assert(current_exception != NULL);
|
||||
char *p = NULL;
|
||||
msglist_T *messages = NULL;
|
||||
msglist_T *next;
|
||||
|
||||
// If the uncaught exception is a user exception, report it as an
|
||||
// error. If it is an error exception, display the saved error
|
||||
// message now. For an interrupt exception, do nothing; the
|
||||
// interrupt message is given elsewhere.
|
||||
switch (current_exception->type) {
|
||||
case ET_USER:
|
||||
vim_snprintf((char *)IObuff, IOSIZE,
|
||||
_("E605: Exception not caught: %s"),
|
||||
current_exception->value);
|
||||
p = xstrdup((char *)IObuff);
|
||||
break;
|
||||
case ET_ERROR:
|
||||
messages = current_exception->messages;
|
||||
current_exception->messages = NULL;
|
||||
break;
|
||||
case ET_INTERRUPT:
|
||||
break;
|
||||
}
|
||||
|
||||
estack_push(ETYPE_EXCEPT, current_exception->throw_name, current_exception->throw_lnum);
|
||||
current_exception->throw_name = NULL;
|
||||
|
||||
discard_current_exception(); // uses IObuff if 'verbose'
|
||||
suppress_errthrow = true;
|
||||
force_abort = true;
|
||||
msg_ext_set_kind("emsg"); // kind=emsg for :throw, exceptions. #9993
|
||||
|
||||
if (messages != NULL) {
|
||||
do {
|
||||
next = messages->next;
|
||||
emsg(messages->msg);
|
||||
xfree(messages->msg);
|
||||
xfree(messages->sfile);
|
||||
xfree(messages);
|
||||
messages = next;
|
||||
} while (messages != NULL);
|
||||
} else if (p != NULL) {
|
||||
emsg(p);
|
||||
xfree(p);
|
||||
}
|
||||
xfree(SOURCING_NAME);
|
||||
estack_pop();
|
||||
handle_did_throw();
|
||||
} else if (got_int || (did_emsg && force_abort)) {
|
||||
// On an interrupt or an aborting error not converted to an exception,
|
||||
// disable the conversion of errors to exceptions. (Interrupts are not
|
||||
@ -902,6 +856,57 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// Handle when "did_throw" is set after executing commands.
|
||||
void handle_did_throw(void)
|
||||
{
|
||||
assert(current_exception != NULL);
|
||||
char *p = NULL;
|
||||
msglist_T *messages = NULL;
|
||||
|
||||
// If the uncaught exception is a user exception, report it as an
|
||||
// error. If it is an error exception, display the saved error
|
||||
// message now. For an interrupt exception, do nothing; the
|
||||
// interrupt message is given elsewhere.
|
||||
switch (current_exception->type) {
|
||||
case ET_USER:
|
||||
vim_snprintf((char *)IObuff, IOSIZE,
|
||||
_("E605: Exception not caught: %s"),
|
||||
current_exception->value);
|
||||
p = xstrdup((char *)IObuff);
|
||||
break;
|
||||
case ET_ERROR:
|
||||
messages = current_exception->messages;
|
||||
current_exception->messages = NULL;
|
||||
break;
|
||||
case ET_INTERRUPT:
|
||||
break;
|
||||
}
|
||||
|
||||
estack_push(ETYPE_EXCEPT, current_exception->throw_name, current_exception->throw_lnum);
|
||||
current_exception->throw_name = NULL;
|
||||
|
||||
discard_current_exception(); // uses IObuff if 'verbose'
|
||||
suppress_errthrow = true;
|
||||
force_abort = true;
|
||||
msg_ext_set_kind("emsg"); // kind=emsg for :throw, exceptions. #9993
|
||||
|
||||
if (messages != NULL) {
|
||||
do {
|
||||
msglist_T *next = messages->next;
|
||||
emsg(messages->msg);
|
||||
xfree(messages->msg);
|
||||
xfree(messages->sfile);
|
||||
xfree(messages);
|
||||
messages = next;
|
||||
} while (messages != NULL);
|
||||
} else if (p != NULL) {
|
||||
emsg(p);
|
||||
xfree(p);
|
||||
}
|
||||
xfree(SOURCING_NAME);
|
||||
estack_pop();
|
||||
}
|
||||
|
||||
/// Obtain a line when inside a ":while" or ":for" loop.
|
||||
static char *get_loop_line(int c, void *cookie, int indent, bool do_concat)
|
||||
{
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "nvim/edit.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/typval_defs.h"
|
||||
#include "nvim/ex_docmd.h"
|
||||
#include "nvim/extmark.h"
|
||||
#include "nvim/gettext.h"
|
||||
#include "nvim/globals.h"
|
||||
@ -1153,6 +1154,12 @@ int get_expr_indent(void)
|
||||
check_cursor();
|
||||
State = save_State;
|
||||
|
||||
// Reset did_throw, unless 'debug' has "throw" and inside a try/catch.
|
||||
if (did_throw && (vim_strchr(p_debug, 't') == NULL || trylevel == 0)) {
|
||||
handle_did_throw();
|
||||
did_throw = false;
|
||||
}
|
||||
|
||||
// If there is an error, just keep the current indent.
|
||||
if (indent < 0) {
|
||||
indent = get_indent();
|
||||
|
Loading…
Reference in New Issue
Block a user