# HG changeset patch # User Bram Moolenaar # Date 1583778604 -3600 # Node ID 2fee087c94cbe3d1cb18aefe9e110d4cdc7300f7 # Parent 684f747f05681dc07cb8935b27ff8db828f4cf82 patch 8.2.0368: Vim9: import that redefines local variable does not fail Commit: https://github.com/vim/vim/commit/5269bd2a724fdb8c16c9635ef744a670f1bc8bd5 Author: Bram Moolenaar Date: Mon Mar 9 19:25:27 2020 +0100 patch 8.2.0368: Vim9: import that redefines local variable does not fail Problem: Vim9: import that redefines local variable does not fail. Solution: Check for already defined symbols. diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro --- a/src/proto/vim9compile.pro +++ b/src/proto/vim9compile.pro @@ -1,4 +1,5 @@ /* vim9compile.c */ +int check_defined(char_u *p, int len, cctx_T *cctx); char_u *skip_type(char_u *start); type_T *parse_type(char_u **arg, garray_T *type_list); char *vartype_name(vartype_T type); diff --git a/src/proto/vim9script.pro b/src/proto/vim9script.pro --- a/src/proto/vim9script.pro +++ b/src/proto/vim9script.pro @@ -5,5 +5,5 @@ void ex_export(exarg_T *eap); void free_imports(int sid); void ex_import(exarg_T *eap); int find_exported(int sid, char_u **argp, int *name_len, ufunc_T **ufunc, type_T **type); -char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid); +char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid, void *cctx); /* vim: set ft=c : */ diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -362,7 +362,7 @@ let s:export_script_lines =<< trim END enddef END -def Test_vim9script() +def Test_vim9_import_export() let import_script_lines =<< trim END vim9script import {exported, Exported} from './Xexport.vim' @@ -449,6 +449,33 @@ def Test_vim9script() writefile(import_not_exported_lines, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1049:') + " try to import something that is already defined + let import_already_defined =<< trim END + vim9script + let exported = 'something' + import exported from './Xexport.vim' + END + writefile(import_already_defined, 'Ximport.vim') + assert_fails('source Ximport.vim', 'E1073:') + + " try to import something that is already defined + import_already_defined =<< trim END + vim9script + let exported = 'something' + import * as exported from './Xexport.vim' + END + writefile(import_already_defined, 'Ximport.vim') + assert_fails('source Ximport.vim', 'E1073:') + + " try to import something that is already defined + import_already_defined =<< trim END + vim9script + let exported = 'something' + import {exported} from './Xexport.vim' + END + writefile(import_already_defined, 'Ximport.vim') + assert_fails('source Ximport.vim', 'E1073:') + " import a very long name, requires making a copy let import_long_name_lines =<< trim END vim9script @@ -482,10 +509,11 @@ def Test_vim9script() vim9script import {exported name} from './Xexport.vim' END - writefile(import_missing_comma_lines, 'Ximport.vim') - assert_fails('source Ximport.vim', 'E1046:') + writefile(import_missing_comma_lines, 'Ximport3.vim') + assert_fails('source Ximport3.vim', 'E1046:') delete('Ximport.vim') + delete('Ximport3.vim') delete('Xexport.vim') " Check that in a Vim9 script 'cpo' is set to the Vim default. diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -739,6 +739,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 368, +/**/ 367, /**/ 366, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -203,6 +203,25 @@ lookup_script(char_u *name, size_t len) return di == NULL ? FAIL: OK; } +/* + * Check if "p[len]" is already defined, either in script "import_sid" or in + * compilation context "cctx". + * Return FAIL and give an error if it defined. + */ + int +check_defined(char_u *p, int len, cctx_T *cctx) +{ + if (lookup_script(p, len) == OK + || (cctx != NULL + && (lookup_local(p, len, cctx) >= 0 + || find_imported(p, len, cctx) != NULL))) + { + semsg("E1073: imported name already defined: %s", p); + return FAIL; + } + return OK; +} + static type_T * get_list_type(type_T *member_type, garray_T *type_list) { @@ -3812,7 +3831,7 @@ theend: static char_u * compile_import(char_u *arg, cctx_T *cctx) { - return handle_import(arg, &cctx->ctx_imports, 0); + return handle_import(arg, &cctx->ctx_imports, 0, cctx); } /* diff --git a/src/vim9script.c b/src/vim9script.c --- a/src/vim9script.c +++ b/src/vim9script.c @@ -143,7 +143,8 @@ ex_import(exarg_T *eap) emsg(_(e_needs_vim9)); else { - char_u *cmd_end = handle_import(eap->arg, NULL, current_sctx.sc_sid); + char_u *cmd_end = handle_import(eap->arg, NULL, + current_sctx.sc_sid, NULL); if (cmd_end != NULL) eap->nextcmd = check_nextcmd(cmd_end); @@ -238,7 +239,7 @@ find_exported( * Returns a pointer to after the command or NULL in case of failure */ char_u * -handle_import(char_u *arg_start, garray_T *gap, int import_sid) +handle_import(char_u *arg_start, garray_T *gap, int import_sid, void *cctx) { char_u *arg = arg_start; char_u *cmd_end; @@ -278,6 +279,8 @@ handle_import(char_u *arg_start, garray_ ++arg; as_len = (int)(arg - as_ptr); arg = skipwhite(arg); + if (check_defined(as_ptr, as_len, cctx) == FAIL) + return NULL; } else if (*arg_start == '*') { @@ -389,6 +392,9 @@ handle_import(char_u *arg_start, garray_ if (idx < 0 && ufunc == NULL) return NULL; + if (check_defined(name, name_len, cctx) == FAIL) + return NULL; + imported = new_imported(gap != NULL ? gap : &SCRIPT_ITEM(import_sid)->sn_imports); if (imported == NULL)