diff options
author | Bram Moolenaar <Bram@vim.org> | 2022-01-18 17:43:04 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-01-18 17:43:04 +0000 |
commit | d02dce2bb572f0e6b4570442e9cdbed14ef41820 (patch) | |
tree | 8d45fb3ef354ba98df86fd26701570e2c2644680 | |
parent | fd218c8a36e7ed33f7a205163690c5b7d2f31f8a (diff) |
patch 8.2.4137: Vim9: calling import with and without method is inconsistentv8.2.4137
Problem: Vim9: calling import with and without method is inconsistent.
Solution: Set a flag that a parenthsis follows to compile_load_scriptvar().
Add some more tests. Improve error message.
-rw-r--r-- | src/testdir/test_vim9_import.vim | 130 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9execute.c | 30 | ||||
-rw-r--r-- | src/vim9expr.c | 13 | ||||
-rw-r--r-- | src/vim9script.c | 24 |
5 files changed, 170 insertions, 29 deletions
diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim index 3c55f43122..3f918f849e 100644 --- a/src/testdir/test_vim9_import.vim +++ b/src/testdir/test_vim9_import.vim @@ -1256,6 +1256,136 @@ def Test_vim9script_autoload() &rtp = save_rtp enddef +def Test_import_autoload_not_exported() + mkdir('Xdir/autoload', 'p') + var save_rtp = &rtp + exe 'set rtp^=' .. getcwd() .. '/Xdir' + + # error when using an item that is not exported from an autoload script + var exportLines =<< trim END + vim9script + var notExported = 123 + def NotExport() + echo 'nop' + enddef + END + writefile(exportLines, 'Xdir/autoload/notExport1.vim') + + var lines =<< trim END + vim9script + import autoload 'notExport1.vim' + echo notExport1.notFound + END + CheckScriptFailure(lines, 'E1048: Item not found in script: notFound') + + lines =<< trim END + vim9script + import autoload 'notExport1.vim' + echo notExport1.notExported + END + CheckScriptFailure(lines, 'E1049: Item not exported in script: notExported') + + lines =<< trim END + vim9script + import autoload 'notExport1.vim' + echo notExport1.NotFunc() + END + CheckScriptFailure(lines, 'E1048: Item not found in script: NotFunc') + + lines =<< trim END + vim9script + import autoload 'notExport1.vim' + echo notExport1.NotExport() + END + CheckScriptFailure(lines, 'E1049: Item not exported in script: NotExport') + + lines =<< trim END + vim9script + import autoload 'notExport1.vim' + echo 'text'->notExport1.NotFunc() + END + CheckScriptFailure(lines, 'E1048: Item not found in script: NotFunc') + + lines =<< trim END + vim9script + import autoload 'notExport1.vim' + echo 'text'->notExport1.NotExport() + END + CheckScriptFailure(lines, 'E1049: Item not exported in script: NotExport') + + # using a :def function we use a different autoload script every time so that + # the function is compiled without the script loaded + writefile(exportLines, 'Xdir/autoload/notExport2.vim') + lines =<< trim END + vim9script + import autoload 'notExport2.vim' + def Testit() + echo notExport2.notFound + enddef + Testit() + END + CheckScriptFailure(lines, 'E1048: Item not found in script: notExport2#notFound') + + writefile(exportLines, 'Xdir/autoload/notExport3.vim') + lines =<< trim END + vim9script + import autoload 'notExport3.vim' + def Testit() + echo notExport3.notExported + enddef + Testit() + END + # don't get E1049 because it is too complicated to figure out + CheckScriptFailure(lines, 'E1048: Item not found in script: notExport3#notExported') + + writefile(exportLines, 'Xdir/autoload/notExport4.vim') + lines =<< trim END + vim9script + import autoload 'notExport4.vim' + def Testit() + echo notExport4.NotFunc() + enddef + Testit() + END + CheckScriptFailure(lines, 'E117: Unknown function: notExport4#NotFunc') + + writefile(exportLines, 'Xdir/autoload/notExport5.vim') + lines =<< trim END + vim9script + import autoload 'notExport5.vim' + def Testit() + echo notExport5.NotExport() + enddef + Testit() + END + CheckScriptFailure(lines, 'E117: Unknown function: notExport5#NotExport') + + writefile(exportLines, 'Xdir/autoload/notExport6.vim') + lines =<< trim END + vim9script + import autoload 'notExport6.vim' + def Testit() + echo 'text'->notExport6.NotFunc() + enddef + Testit() + END + CheckScriptFailure(lines, 'E117: Unknown function: notExport6#NotFunc') + + writefile(exportLines, 'Xdir/autoload/notExport7.vim') + lines =<< trim END + vim9script + import autoload 'notExport7.vim' + def Testit() + echo 'text'->notExport7.NotExport() + enddef + Testit() + END + CheckScriptFailure(lines, 'E117: Unknown function: notExport7#NotExport') + + delete('Xdir', 'rf') + &rtp = save_rtp +enddef + def Test_vim9script_autoload_call() mkdir('Xdir/autoload', 'p') var save_rtp = &rtp diff --git a/src/version.c b/src/version.c index b2e7429d00..67e9ca5ff3 100644 --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4137, +/**/ 4136, /**/ 4135, diff --git a/src/vim9execute.c b/src/vim9execute.c index 0037f51af8..5ede04ca8b 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -2240,33 +2240,19 @@ exec_instructions(ectx_T *ectx) iptr->isn_arg.string, TRUE); if (did_emsg) goto on_error; - if (di == NULL) - { - isn_T *next = &ectx->ec_instr[ectx->ec_iidx]; - - // When compiling "script.Func()" when "script" is - // an autoload import then this results in - // "LOADG script#Func" because we don't know if it - // is a funcref variable or a function name. In - // that case a PCALL follows, push the function - // name instead. - if (next->isn_type == ISN_PCALL) - { - tv = STACK_TV_BOT(0); - tv->v_type = VAR_FUNC; - tv->v_lock = 0; - tv->vval.v_string = - vim_strsave(iptr->isn_arg.string); - ++ectx->ec_stack.ga_len; - break; - } - } } if (di == NULL) { SOURCING_LNUM = iptr->isn_lnum; - semsg(_(e_undefined_variable_char_str), + if (vim_strchr(iptr->isn_arg.string, + AUTOLOAD_CHAR) != NULL) + // no check if the item exists in the script but + // isn't exported, it is too complicated + semsg(_(e_item_not_found_in_script_str), + iptr->isn_arg.string); + else + semsg(_(e_undefined_variable_char_str), namespace, iptr->isn_arg.string); goto on_error; } diff --git a/src/vim9expr.c b/src/vim9expr.c index 922c7bab8a..72bfc01e51 100644 --- a/src/vim9expr.c +++ b/src/vim9expr.c @@ -21,6 +21,9 @@ # include "vim9.h" #endif +// flag passed from compile_subscript() to compile_load_scriptvar() +static int paren_follows_after_expr = 0; + /* * Generate code for any ppconst entries. */ @@ -277,7 +280,6 @@ compile_load_scriptvar( int done = FALSE; int res = OK; - // TODO: if this is an autoload import do something else. // Need to lookup the member. if (*p != '.') { @@ -306,7 +308,7 @@ compile_load_scriptvar( // autoload script must be loaded later, access by the autoload // name. - if (cc == '(') + if (cc == '(' || paren_follows_after_expr) res = generate_PUSHFUNC(cctx, auto_name, &t_func_any); else res = generate_LOAD(cctx, ISN_LOADG, 0, auto_name, &t_any); @@ -1736,12 +1738,19 @@ compile_subscript( int save_len = cctx->ctx_ufunc->uf_lines.ga_len; *paren = NUL; + + // instead of using LOADG for "import.Func" use PUSHFUNC + ++paren_follows_after_expr; + // do not look in the next line cctx->ctx_ufunc->uf_lines.ga_len = 1; + fail = compile_expr8(arg, cctx, ppconst) == FAIL || *skipwhite(*arg) != NUL; *paren = '('; + --paren_follows_after_expr; cctx->ctx_ufunc->uf_lines.ga_len = save_len; + if (fail) { semsg(_(e_invalid_expression_str), pstart); diff --git a/src/vim9script.c b/src/vim9script.c index 2f7f732ac4..e13ac4ac47 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -707,22 +707,36 @@ find_exported( sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name); } *ufunc = find_func(funcname, FALSE); - if (funcname != buffer) - vim_free(funcname); if (*ufunc == NULL) { if (verbose) - semsg(_(e_item_not_found_in_script_str), name); - return -1; + { + ufunc_T *alt_ufunc = NULL; + + if (script->sn_autoload_prefix != NULL) + { + // try find the function by the script-local name + funcname[0] = K_SPECIAL; + funcname[1] = KS_EXTRA; + funcname[2] = (int)KE_SNR; + sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name); + alt_ufunc = find_func(funcname, FALSE); + } + if (alt_ufunc != NULL) + semsg(_(e_item_not_exported_in_script_str), name); + else + semsg(_(e_item_not_found_in_script_str), name); + } } else if (((*ufunc)->uf_flags & FC_EXPORT) == 0) { if (verbose) semsg(_(e_item_not_exported_in_script_str), name); *ufunc = NULL; - return -1; } + if (funcname != buffer) + vim_free(funcname); } return idx; |