patch 9.0.0687: "export def" does not work in a nested block
Problem: "export def" does not work in a nested block.
Solution: Do not handle "export" with a separate function but in the same
command stack. (closes #11304)
This commit is contained in:
@ -59,6 +59,7 @@
|
|||||||
#define EX_KEEPSCRIPT 0x4000000 // keep sctx of where command was invoked
|
#define EX_KEEPSCRIPT 0x4000000 // keep sctx of where command was invoked
|
||||||
#define EX_EXPR_ARG 0x8000000 // argument is an expression
|
#define EX_EXPR_ARG 0x8000000 // argument is an expression
|
||||||
#define EX_WHOLE 0x10000000 // command name cannot be shortened in Vim9
|
#define EX_WHOLE 0x10000000 // command name cannot be shortened in Vim9
|
||||||
|
#define EX_EXPORT 0x20000000 // command can be used after :export
|
||||||
|
|
||||||
#define EX_FILES (EX_XFILE | EX_EXTRA) // multiple extra files allowed
|
#define EX_FILES (EX_XFILE | EX_EXTRA) // multiple extra files allowed
|
||||||
#define EX_FILE1 (EX_FILES | EX_NOSPC) // 1 file, defaults to current file
|
#define EX_FILE1 (EX_FILES | EX_NOSPC) // 1 file, defaults to current file
|
||||||
@ -354,7 +355,7 @@ EXCMD(CMD_clast, "clast", ex_cc,
|
|||||||
EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG,
|
EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG,
|
||||||
ADDR_UNSIGNED),
|
ADDR_UNSIGNED),
|
||||||
EXCMD(CMD_class, "class", ex_ni,
|
EXCMD(CMD_class, "class", ex_ni,
|
||||||
EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
|
EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_EXPORT,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
EXCMD(CMD_close, "close", ex_close,
|
EXCMD(CMD_close, "close", ex_close,
|
||||||
EX_BANG|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
|
EX_BANG|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
|
||||||
@ -414,7 +415,7 @@ EXCMD(CMD_confirm, "confirm", ex_wrongmodifier,
|
|||||||
EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN|EX_LOCK_OK,
|
EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN|EX_LOCK_OK,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
EXCMD(CMD_const, "const", ex_let,
|
EXCMD(CMD_const, "const", ex_let,
|
||||||
EX_EXTRA|EX_BANG|EX_NOTRLCOM|EX_EXPR_ARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE,
|
EX_EXTRA|EX_BANG|EX_NOTRLCOM|EX_EXPR_ARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE|EX_EXPORT,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
EXCMD(CMD_copen, "copen", ex_copen,
|
EXCMD(CMD_copen, "copen", ex_copen,
|
||||||
EX_RANGE|EX_COUNT|EX_TRLBAR,
|
EX_RANGE|EX_COUNT|EX_TRLBAR,
|
||||||
@ -462,7 +463,7 @@ EXCMD(CMD_debuggreedy, "debuggreedy", ex_debuggreedy,
|
|||||||
EX_RANGE|EX_ZEROR|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
|
EX_RANGE|EX_ZEROR|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
|
||||||
ADDR_OTHER),
|
ADDR_OTHER),
|
||||||
EXCMD(CMD_def, "def", ex_function,
|
EXCMD(CMD_def, "def", ex_function,
|
||||||
EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
|
EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_EXPORT,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
EXCMD(CMD_defcompile, "defcompile", ex_defcompile,
|
EXCMD(CMD_defcompile, "defcompile", ex_defcompile,
|
||||||
EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_TRLBAR|EX_EXTRA,
|
EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_TRLBAR|EX_EXTRA,
|
||||||
@ -594,7 +595,7 @@ EXCMD(CMD_enew, "enew", ex_edit,
|
|||||||
EX_BANG|EX_TRLBAR,
|
EX_BANG|EX_TRLBAR,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
EXCMD(CMD_enum, "enum", ex_ni,
|
EXCMD(CMD_enum, "enum", ex_ni,
|
||||||
EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
|
EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_EXPORT,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
EXCMD(CMD_eval, "eval", ex_eval,
|
EXCMD(CMD_eval, "eval", ex_eval,
|
||||||
EX_EXTRA|EX_NOTRLCOM|EX_EXPR_ARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
|
EX_EXTRA|EX_NOTRLCOM|EX_EXPR_ARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
|
||||||
@ -630,7 +631,7 @@ EXCMD(CMD_find, "find", ex_find,
|
|||||||
EX_RANGE|EX_BANG|EX_FILE1|EX_CMDARG|EX_ARGOPT|EX_TRLBAR|EX_NEEDARG,
|
EX_RANGE|EX_BANG|EX_FILE1|EX_CMDARG|EX_ARGOPT|EX_TRLBAR|EX_NEEDARG,
|
||||||
ADDR_OTHER),
|
ADDR_OTHER),
|
||||||
EXCMD(CMD_final, "final", ex_let,
|
EXCMD(CMD_final, "final", ex_let,
|
||||||
EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE,
|
EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE|EX_EXPORT,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
EXCMD(CMD_finally, "finally", ex_finally,
|
EXCMD(CMD_finally, "finally", ex_finally,
|
||||||
EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE,
|
EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE,
|
||||||
@ -663,7 +664,7 @@ EXCMD(CMD_for, "for", ex_while,
|
|||||||
EX_EXTRA|EX_NOTRLCOM|EX_EXPR_ARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
|
EX_EXTRA|EX_NOTRLCOM|EX_EXPR_ARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
EXCMD(CMD_function, "function", ex_function,
|
EXCMD(CMD_function, "function", ex_function,
|
||||||
EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
|
EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_EXPORT,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
EXCMD(CMD_global, "global", ex_global,
|
EXCMD(CMD_global, "global", ex_global,
|
||||||
EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_EXTRA|EX_DFLALL|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_NONWHITE_OK,
|
EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_EXTRA|EX_DFLALL|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_NONWHITE_OK,
|
||||||
@ -1665,7 +1666,7 @@ EXCMD(CMD_tunmap, "tunmap", ex_unmap,
|
|||||||
EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK,
|
EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
EXCMD(CMD_type, "type", ex_ni,
|
EXCMD(CMD_type, "type", ex_ni,
|
||||||
EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
|
EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_EXPORT,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
EXCMD(CMD_undo, "undo", ex_undo,
|
EXCMD(CMD_undo, "undo", ex_undo,
|
||||||
EX_RANGE|EX_COUNT|EX_ZEROR|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
|
EX_RANGE|EX_COUNT|EX_ZEROR|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
|
||||||
@ -1704,7 +1705,7 @@ EXCMD(CMD_vglobal, "vglobal", ex_global,
|
|||||||
EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_DFLALL|EX_CMDWIN|EX_LOCK_OK|EX_NONWHITE_OK,
|
EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_DFLALL|EX_CMDWIN|EX_LOCK_OK|EX_NONWHITE_OK,
|
||||||
ADDR_LINES),
|
ADDR_LINES),
|
||||||
EXCMD(CMD_var, "var", ex_var,
|
EXCMD(CMD_var, "var", ex_var,
|
||||||
EX_EXTRA|EX_NOTRLCOM|EX_EXPR_ARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE,
|
EX_EXTRA|EX_NOTRLCOM|EX_EXPR_ARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE|EX_EXPORT,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
EXCMD(CMD_version, "version", ex_version,
|
EXCMD(CMD_version, "version", ex_version,
|
||||||
EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
|
EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
|
||||||
|
|||||||
@ -1820,6 +1820,15 @@ do_one_cmd(
|
|||||||
if (may_have_range)
|
if (may_have_range)
|
||||||
ea.cmd = skip_range(ea.cmd, TRUE, NULL);
|
ea.cmd = skip_range(ea.cmd, TRUE, NULL);
|
||||||
|
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
// Handle ":export" - it functions almost like a command modifier.
|
||||||
|
// ":export var Name: type"
|
||||||
|
// ":export def Name(..."
|
||||||
|
// etc.
|
||||||
|
if (vim9script && checkforcmd_noparen(&ea.cmd, "export", 6))
|
||||||
|
is_export = TRUE;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (vim9script && !may_have_range)
|
if (vim9script && !may_have_range)
|
||||||
{
|
{
|
||||||
if (ea.cmd == cmd + 1 && *cmd == '$')
|
if (ea.cmd == cmd + 1 && *cmd == '$')
|
||||||
@ -2496,11 +2505,17 @@ do_one_cmd(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ea.argt & EX_XFILE)
|
if ((ea.argt & EX_XFILE)
|
||||||
|
&& expand_filename(&ea, cmdlinep, &errormsg) == FAIL)
|
||||||
|
goto doend;
|
||||||
|
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
if (is_export && (ea.argt & EX_EXPORT) == 0)
|
||||||
{
|
{
|
||||||
if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL)
|
emsg(_(e_invalid_command_after_export));
|
||||||
goto doend;
|
goto doend;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Accept buffer name. Cannot be used at the same time with a buffer
|
* Accept buffer name. Cannot be used at the same time with a buffer
|
||||||
@ -2557,13 +2572,21 @@ do_one_cmd(
|
|||||||
/*
|
/*
|
||||||
* Call the function to execute the builtin command.
|
* Call the function to execute the builtin command.
|
||||||
*/
|
*/
|
||||||
ea.errmsg = NULL;
|
|
||||||
(cmdnames[ea.cmdidx].cmd_func)(&ea);
|
(cmdnames[ea.cmdidx].cmd_func)(&ea);
|
||||||
if (ea.errmsg != NULL)
|
if (ea.errmsg != NULL)
|
||||||
errormsg = ea.errmsg;
|
errormsg = ea.errmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
|
// A command will reset "is_export" when exporting an item. If it is still
|
||||||
|
// set something went wrong.
|
||||||
|
if (is_export)
|
||||||
|
{
|
||||||
|
if (errormsg == NULL)
|
||||||
|
errormsg = _(e_export_with_invalid_argument);
|
||||||
|
is_export = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
// Set flag that any command was executed, used by ex_vim9script().
|
// Set flag that any command was executed, used by ex_vim9script().
|
||||||
// Not if this was a command that wasn't executed or :endif.
|
// Not if this was a command that wasn't executed or :endif.
|
||||||
if (sourcing_a_script(&ea)
|
if (sourcing_a_script(&ea)
|
||||||
@ -2620,6 +2643,7 @@ doend:
|
|||||||
|
|
||||||
if (did_set_expr_line)
|
if (did_set_expr_line)
|
||||||
set_expr_line(NULL, NULL);
|
set_expr_line(NULL, NULL);
|
||||||
|
is_export = FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
undo_cmdmod(&cmdmod);
|
undo_cmdmod(&cmdmod);
|
||||||
|
|||||||
@ -452,6 +452,21 @@ def Test_import_funcref()
|
|||||||
delete('Xlib.vim')
|
delete('Xlib.vim')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_export_closure()
|
||||||
|
# tests that the closure in block can be compiled, not the import part
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
{
|
||||||
|
var foo = 42
|
||||||
|
export def Bar(): number
|
||||||
|
return foo
|
||||||
|
enddef
|
||||||
|
}
|
||||||
|
assert_equal(42, Bar())
|
||||||
|
END
|
||||||
|
v9.CheckScriptSuccess(lines)
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_import_duplicate_function()
|
def Test_import_duplicate_function()
|
||||||
# Function Hover() exists in both scripts, partial should refer to the right
|
# Function Hover() exists in both scripts, partial should refer to the right
|
||||||
# one.
|
# one.
|
||||||
@ -1513,7 +1528,7 @@ def Test_export_fails()
|
|||||||
v9.CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
|
v9.CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
|
||||||
v9.CheckScriptFailure(['vim9script', 'export function /a1b2c3'], 'E1044:')
|
v9.CheckScriptFailure(['vim9script', 'export function /a1b2c3'], 'E1044:')
|
||||||
|
|
||||||
assert_fails('export something', 'E1043:')
|
assert_fails('export echo 1', 'E1043:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
func Test_import_fails_without_script()
|
func Test_import_fails_without_script()
|
||||||
|
|||||||
@ -699,6 +699,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
687,
|
||||||
/**/
|
/**/
|
||||||
686,
|
686,
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
@ -246,49 +246,13 @@ ex_incdec(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ":export let Name: type"
|
* ":export cmd"
|
||||||
* ":export const Name: type"
|
|
||||||
* ":export def Name(..."
|
|
||||||
* ":export class Name ..."
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ex_export(exarg_T *eap)
|
ex_export(exarg_T *eap UNUSED)
|
||||||
{
|
{
|
||||||
int prev_did_emsg = did_emsg;
|
// can only get here when "export" wasn't caught in do_cmdline()
|
||||||
|
emsg(_(e_export_can_only_be_used_in_vim9script));
|
||||||
if (!in_vim9script())
|
|
||||||
{
|
|
||||||
emsg(_(e_export_can_only_be_used_in_vim9script));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
eap->cmd = eap->arg;
|
|
||||||
(void)find_ex_command(eap, NULL, lookup_scriptitem, NULL);
|
|
||||||
switch (eap->cmdidx)
|
|
||||||
{
|
|
||||||
case CMD_var:
|
|
||||||
case CMD_final:
|
|
||||||
case CMD_const:
|
|
||||||
case CMD_def:
|
|
||||||
case CMD_function:
|
|
||||||
// case CMD_class:
|
|
||||||
is_export = TRUE;
|
|
||||||
do_cmdline(eap->cmd, eap->getline, eap->cookie,
|
|
||||||
DOCMD_VERBOSE + DOCMD_NOWAIT);
|
|
||||||
|
|
||||||
// The command will reset "is_export" when exporting an item.
|
|
||||||
if (is_export)
|
|
||||||
{
|
|
||||||
if (did_emsg == prev_did_emsg)
|
|
||||||
emsg(_(e_export_with_invalid_argument));
|
|
||||||
is_export = FALSE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (did_emsg == prev_did_emsg)
|
|
||||||
emsg(_(e_invalid_command_after_export));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user