changeset 19623:2fee087c94cb v8.2.0368

patch 8.2.0368: Vim9: import that redefines local variable does not fail Commit: https://github.com/vim/vim/commit/5269bd2a724fdb8c16c9635ef744a670f1bc8bd5 Author: Bram Moolenaar <Bram@vim.org> 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.
author Bram Moolenaar <Bram@vim.org>
date Mon, 09 Mar 2020 19:30:04 +0100
parents 684f747f0568
children ce4838c19ca1
files src/proto/vim9compile.pro src/proto/vim9script.pro src/testdir/test_vim9_script.vim src/version.c src/vim9compile.c src/vim9script.c
diffstat 6 files changed, 63 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- 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);
--- 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 : */
--- 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.
--- 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,
--- 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);
 }
 
 /*
--- 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)