To: vim_dev@googlegroups.com Subject: Patch 9.0.0687 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.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) Files: src/ex_docmd.c, src/vim9script.c, src/ex_cmds.h, src/testdir/test_vim9_import.vim *** ../vim-9.0.0686/src/ex_docmd.c 2022-10-04 16:23:39.014042183 +0100 --- src/ex_docmd.c 2022-10-07 17:18:20.354476923 +0100 *************** *** 1820,1825 **** --- 1820,1834 ---- 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,2506 **** } #endif ! if (ea.argt & EX_XFILE) { ! if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL) ! goto doend; } /* * Accept buffer name. Cannot be used at the same time with a buffer --- 2505,2521 ---- } #endif ! if ((ea.argt & EX_XFILE) ! && expand_filename(&ea, cmdlinep, &errormsg) == FAIL) ! goto doend; ! ! #ifdef FEAT_EVAL ! if (is_export && (ea.argt & EX_EXPORT) == 0) { ! emsg(_(e_invalid_command_after_export)); ! goto doend; } + #endif /* * Accept buffer name. Cannot be used at the same time with a buffer *************** *** 2557,2569 **** /* * 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 // 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) --- 2572,2592 ---- /* * Call the function to execute the builtin command. */ (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,2625 **** --- 2643,2649 ---- if (did_set_expr_line) set_expr_line(NULL, NULL); + is_export = FALSE; #endif undo_cmdmod(&cmdmod); *** ../vim-9.0.0686/src/vim9script.c 2022-10-07 16:00:00.757126668 +0100 --- src/vim9script.c 2022-10-07 17:10:12.814159416 +0100 *************** *** 246,294 **** } /* ! * ":export let Name: type" ! * ":export const Name: type" ! * ":export def Name(..." ! * ":export class Name ..." */ void ! ex_export(exarg_T *eap) { ! 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; ! } } /* --- 246,258 ---- } /* ! * ":export cmd" */ void ! ex_export(exarg_T *eap UNUSED) { ! // can only get here when "export" wasn't caught in do_cmdline() ! emsg(_(e_export_can_only_be_used_in_vim9script)); } /* *** ../vim-9.0.0686/src/ex_cmds.h 2022-10-07 14:31:04.320852668 +0100 --- src/ex_cmds.h 2022-10-07 17:05:00.691039541 +0100 *************** *** 59,64 **** --- 59,65 ---- #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,360 **** 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, ADDR_NONE), EXCMD(CMD_close, "close", ex_close, EX_BANG|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, --- 355,361 ---- 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_EXPORT, ADDR_NONE), EXCMD(CMD_close, "close", ex_close, EX_BANG|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, *************** *** 414,420 **** 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, ADDR_NONE), EXCMD(CMD_copen, "copen", ex_copen, EX_RANGE|EX_COUNT|EX_TRLBAR, --- 415,421 ---- 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_EXPORT, ADDR_NONE), EXCMD(CMD_copen, "copen", ex_copen, EX_RANGE|EX_COUNT|EX_TRLBAR, *************** *** 462,468 **** 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, ADDR_NONE), EXCMD(CMD_defcompile, "defcompile", ex_defcompile, EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_TRLBAR|EX_EXTRA, --- 463,469 ---- 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_EXPORT, ADDR_NONE), EXCMD(CMD_defcompile, "defcompile", ex_defcompile, EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_TRLBAR|EX_EXTRA, *************** *** 594,600 **** EX_BANG|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_enum, "enum", ex_ni, ! EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_eval, "eval", ex_eval, EX_EXTRA|EX_NOTRLCOM|EX_EXPR_ARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, --- 595,601 ---- EX_BANG|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_enum, "enum", ex_ni, ! 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,636 **** 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, ADDR_NONE), EXCMD(CMD_finally, "finally", ex_finally, EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE, --- 631,637 ---- 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_EXPORT, ADDR_NONE), EXCMD(CMD_finally, "finally", ex_finally, EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE, *************** *** 663,669 **** 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, 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, --- 664,670 ---- 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_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,1671 **** 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, ADDR_NONE), EXCMD(CMD_undo, "undo", ex_undo, EX_RANGE|EX_COUNT|EX_ZEROR|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, --- 1666,1672 ---- 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_EXPORT, ADDR_NONE), EXCMD(CMD_undo, "undo", ex_undo, EX_RANGE|EX_COUNT|EX_ZEROR|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, *************** *** 1704,1710 **** 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, ADDR_NONE), EXCMD(CMD_version, "version", ex_version, EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, --- 1705,1711 ---- 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_EXPORT, ADDR_NONE), EXCMD(CMD_version, "version", ex_version, EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, *** ../vim-9.0.0686/src/testdir/test_vim9_import.vim 2022-09-03 12:09:02.530363340 +0100 --- src/testdir/test_vim9_import.vim 2022-10-07 17:23:11.563142366 +0100 *************** *** 452,457 **** --- 452,472 ---- 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,1519 **** v9.CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:') v9.CheckScriptFailure(['vim9script', 'export function /a1b2c3'], 'E1044:') ! assert_fails('export something', 'E1043:') enddef func Test_import_fails_without_script() --- 1528,1534 ---- v9.CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:') v9.CheckScriptFailure(['vim9script', 'export function /a1b2c3'], 'E1044:') ! assert_fails('export echo 1', 'E1043:') enddef func Test_import_fails_without_script() *** ../vim-9.0.0686/src/version.c 2022-10-07 16:28:43.522256458 +0100 --- src/version.c 2022-10-07 17:25:09.351256660 +0100 *************** *** 701,702 **** --- 701,704 ---- { /* Add new patch number below this line */ + /**/ + 687, /**/ -- ARTHUR: Who are you? TALL KNIGHT: We are the Knights Who Say "Ni"! BEDEVERE: No! Not the Knights Who Say "Ni"! "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///