summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-10-07 17:26:22 +0100
committerBram Moolenaar <Bram@vim.org>2022-10-07 17:26:22 +0100
commit5ab300195b0831cbdba3ce349416a0e6a218e4ef (patch)
tree58fe616911cb9e06e84d83220daf5b5dd5e036d1
parent8d8b9758ced52b6303af95ad7e28ae9c5636cdf8 (diff)
downloadvim-git-9.0.0687.tar.gz
patch 9.0.0687: "export def" does not work in a nested blockv9.0.0687
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)
-rw-r--r--src/ex_cmds.h17
-rw-r--r--src/ex_docmd.c32
-rw-r--r--src/testdir/test_vim9_import.vim17
-rw-r--r--src/version.c2
-rw-r--r--src/vim9script.c44
5 files changed, 59 insertions, 53 deletions
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index ca7f292c9..ed954efc0 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -59,6 +59,7 @@
#define EX_KEEPSCRIPT 0x4000000 // keep sctx of where command was invoked
#define EX_EXPR_ARG 0x8000000 // argument is an expression
#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_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,
ADDR_UNSIGNED),
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),
EXCMD(CMD_close, "close", ex_close,
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,
ADDR_NONE),
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),
EXCMD(CMD_copen, "copen", ex_copen,
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,
ADDR_OTHER),
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),
EXCMD(CMD_defcompile, "defcompile", ex_defcompile,
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,
ADDR_NONE),
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),
EXCMD(CMD_eval, "eval", ex_eval,
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,
ADDR_OTHER),
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),
EXCMD(CMD_finally, "finally", ex_finally,
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,
ADDR_NONE),
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),
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,
@@ -1665,7 +1666,7 @@ EXCMD(CMD_tunmap, "tunmap", ex_unmap,
EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK,
ADDR_NONE),
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),
EXCMD(CMD_undo, "undo", ex_undo,
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,
ADDR_LINES),
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),
EXCMD(CMD_version, "version", ex_version,
EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index a7047d49c..3ffbf2b90 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -1820,6 +1820,15 @@ do_one_cmd(
if (may_have_range)
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 (ea.cmd == cmd + 1 && *cmd == '$')
@@ -2496,11 +2505,17 @@ do_one_cmd(
}
#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)
- goto doend;
+ emsg(_(e_invalid_command_after_export));
+ goto doend;
}
+#endif
/*
* 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.
*/
- ea.errmsg = NULL;
(cmdnames[ea.cmdidx].cmd_func)(&ea);
if (ea.errmsg != NULL)
errormsg = ea.errmsg;
}
#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().
// Not if this was a command that wasn't executed or :endif.
if (sourcing_a_script(&ea)
@@ -2620,6 +2643,7 @@ doend:
if (did_set_expr_line)
set_expr_line(NULL, NULL);
+ is_export = FALSE;
#endif
undo_cmdmod(&cmdmod);
diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim
index e844d4a08..d509007d5 100644
--- a/src/testdir/test_vim9_import.vim
+++ b/src/testdir/test_vim9_import.vim
@@ -452,6 +452,21 @@ def Test_import_funcref()
delete('Xlib.vim')
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()
# Function Hover() exists in both scripts, partial should refer to the right
# one.
@@ -1513,7 +1528,7 @@ def Test_export_fails()
v9.CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
v9.CheckScriptFailure(['vim9script', 'export function /a1b2c3'], 'E1044:')
- assert_fails('export something', 'E1043:')
+ assert_fails('export echo 1', 'E1043:')
enddef
func Test_import_fails_without_script()
diff --git a/src/version.c b/src/version.c
index c6c01976c..7330eebcf 100644
--- a/src/version.c
+++ b/src/version.c
@@ -700,6 +700,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 687,
+/**/
686,
/**/
685,
diff --git a/src/vim9script.c b/src/vim9script.c
index f6c8c49a2..557892cf8 100644
--- a/src/vim9script.c
+++ b/src/vim9script.c
@@ -246,49 +246,13 @@ ex_incdec(exarg_T *eap)
}
/*
- * ":export let Name: type"
- * ":export const Name: type"
- * ":export def Name(..."
- * ":export class Name ..."
+ * ":export cmd"
*/
void
-ex_export(exarg_T *eap)
+ex_export(exarg_T *eap UNUSED)
{
- int prev_did_emsg = did_emsg;
-
- 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;
- }
+ // can only get here when "export" wasn't caught in do_cmdline()
+ emsg(_(e_export_can_only_be_used_in_vim9script));
}
/*