changeset 25282:9bce044c7643 v8.2.3178

patch 8.2.3178: Vim9: the file name of an :import cannot be an expression Commit: https://github.com/vim/vim/commit/4db572eeb2b42819268e934e76c67163316d873f Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jul 18 18:21:38 2021 +0200 patch 8.2.3178: Vim9: the file name of an :import cannot be an expression Problem: Vim9: the file name of an :import cannot be an expression. Solution: Accept an expression that results in a string. Do not support :import in a function.
author Bram Moolenaar <Bram@vim.org>
date Sun, 18 Jul 2021 18:30:04 +0200
parents 1ec4ac687d85
children dbf77501fe00
files runtime/doc/vim9.txt src/testdir/test_vim9_script.vim src/version.c src/vim9compile.c src/vim9script.c
diffstat 5 files changed, 25 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/vim9.txt
+++ b/runtime/doc/vim9.txt
@@ -1354,6 +1354,9 @@ script file to avoid confusion.
 `:import` can also be used in legacy Vim script.  The imported items still
 become script-local, even when the "s:" prefix is not given.
 
+`:import` can not be used in a function.  Imported items are intended to exist
+at the script level and only imported once.
+
 The script name after `import` can be:
 - A relative path, starting "." or "..".  This finds a file relative to the
   location of the script file itself.  This is useful to split up a large
@@ -1363,6 +1366,7 @@ The script name after `import` can be:
 - A path not being relative or absolute.  This will be found in the
   "import" subdirectories of 'runtimepath' entries.  The name will usually be
   longer and unique, to avoid loading the wrong file.
+  Note that "after/import" is not used.
 
 Once a vim9 script file has been imported, the result is cached and used the
 next time the same script is imported.  It will not be read again.
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -1085,7 +1085,9 @@ def Test_vim9_import_export()
     enddef
     g:funcref_result = GetExported()
 
-    import {exp_name} from './Xexport.vim'
+    var dir = './'
+    var ext = ".vim"
+    import {exp_name} from dir .. 'Xexport' .. ext
     g:imported_name = exp_name
     exp_name ..= ' Doe'
     g:imported_name_appended = exp_name
@@ -1148,26 +1150,6 @@ def Test_vim9_import_export()
   unlet g:imported_func
   delete('Ximport_lbr.vim')
 
-  # import inside :def function
-  var import_in_def_lines =<< trim END
-    vim9script
-    def ImportInDef()
-      import exported from './Xexport.vim'
-      g:imported = exported
-      exported += 7
-      g:imported_added = exported
-    enddef
-    ImportInDef()
-  END
-  writefile(import_in_def_lines, 'Ximport2.vim')
-  source Ximport2.vim
-  # TODO: this should be 9879
-  assert_equal(9876, g:imported)
-  assert_equal(9883, g:imported_added)
-  unlet g:imported
-  unlet g:imported_added
-  delete('Ximport2.vim')
-
   var import_star_as_lines =<< trim END
     vim9script
     import * as Export from './Xexport.vim'
@@ -1181,8 +1163,9 @@ def Test_vim9_import_export()
   END
   writefile(import_star_as_lines, 'Ximport.vim')
   source Ximport.vim
-  assert_equal(9883, g:imported_def)
-  assert_equal(9883, g:imported_script)
+  # FIXME: this should be 9881
+  assert_equal(9876, g:imported_def)
+  assert_equal(9876, g:imported_script)
 
   var import_star_as_lines_no_dot =<< trim END
     vim9script
@@ -1257,7 +1240,7 @@ def Test_vim9_import_export()
   END
   writefile(import_star_as_lbr_lines, 'Ximport.vim')
   source Ximport.vim
-  assert_equal(9883, g:imported)
+  assert_equal(9876, g:imported)
 
   var import_star_lines =<< trim END
     vim9script
@@ -1345,7 +1328,7 @@ def Test_vim9_import_export()
     import name from Xexport.vim
   END
   writefile(import_invalid_string_lines, 'Ximport.vim')
-  assert_fails('source Ximport.vim', 'E1071:', '', 2, 'Ximport.vim')
+  assert_fails('source Ximport.vim', 'E121:', '', 2, 'Ximport.vim')
 
   var import_wrong_name_lines =<< trim END
     vim9script
@@ -1659,22 +1642,6 @@ def Test_vim9script_reload_import()
   source Xreload.vim
   source Xreload.vim
 
-  var testlines =<< trim END
-    vim9script
-    def TheFunc()
-      import GetValtwo from './Xreload.vim'
-      assert_equal(222, GetValtwo())
-    enddef
-    TheFunc()
-  END
-  writefile(testlines, 'Ximport.vim')
-  source Ximport.vim
-
-  # Test that when not using "morelines" GetValtwo() and valtwo are still
-  # defined, because import doesn't reload a script.
-  writefile(lines, 'Xreload.vim')
-  source Ximport.vim
-
   # cannot declare a var twice
   lines =<< trim END
     vim9script
--- a/src/version.c
+++ b/src/version.c
@@ -756,6 +756,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    3178,
+/**/
     3177,
 /**/
     3176,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -4335,7 +4335,6 @@ compile_subscript(
 		    semsg(_(e_missing_paren), *arg);
 		    return FAIL;
 		}
-		// TODO: base value may not be the first argument
 		if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
 		    return FAIL;
 	    }
@@ -7294,15 +7293,6 @@ compile_unletlock(char_u *arg, exarg_T *
 }
 
 /*
- * Compile an :import command.
- */
-    static char_u *
-compile_import(char_u *arg, cctx_T *cctx)
-{
-    return handle_import(arg, &cctx->ctx_imports, 0, NULL, cctx);
-}
-
-/*
  * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
  */
     static int
@@ -9638,7 +9628,8 @@ compile_def_function(
 		    break;
 
 	    case CMD_import:
-		    line = compile_import(p, &cctx);
+		    emsg(_(e_import_can_only_be_used_in_script));
+		    line = NULL;
 		    break;
 
 	    case CMD_if:
--- a/src/vim9script.c
+++ b/src/vim9script.c
@@ -412,6 +412,7 @@ handle_import(
     garray_T	names;
     garray_T	as_names;
 
+    tv.v_type = VAR_UNKNOWN;
     ga_init2(&names, sizeof(char_u *), 10);
     ga_init2(&as_names, sizeof(char_u *), 10);
     if (*arg == '{')
@@ -496,14 +497,14 @@ handle_import(
 	goto erret;
     }
 
+    // The name of the file can be an expression, which must evaluate to a
+    // string.
     arg = skipwhite_and_linebreak(arg + 4, evalarg);
-    tv.v_type = VAR_UNKNOWN;
-    // TODO: should we accept any expression?
-    if (*arg == '\'')
-	ret = eval_lit_string(&arg, &tv, TRUE);
-    else if (*arg == '"')
-	ret = eval_string(&arg, &tv, TRUE);
-    if (ret == FAIL || tv.vval.v_string == NULL || *tv.vval.v_string == NUL)
+    ret = eval0(arg, &tv, NULL, evalarg);
+    if (ret == FAIL)
+	goto erret;
+    if (tv.v_type != VAR_STRING
+		       || tv.vval.v_string == NULL || *tv.vval.v_string == NUL)
     {
 	emsg(_(e_invalid_string_after_from));
 	goto erret;
@@ -524,10 +525,7 @@ handle_import(
 	len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2;
 	from_name = alloc((int)len);
 	if (from_name == NULL)
-	{
-	    clear_tv(&tv);
 	    goto erret;
-	}
 	vim_strncpy(from_name, si->sn_name, tail - si->sn_name);
 	add_pathsep(from_name);
 	STRCAT(from_name, tv.vval.v_string);
@@ -550,7 +548,6 @@ handle_import(
 	from_name = alloc((int)len);
 	if (from_name == NULL)
 	{
-	    clear_tv(&tv);
 	    goto erret;
 	}
 	vim_snprintf((char *)from_name, len, "import/%s", tv.vval.v_string);
@@ -561,10 +558,8 @@ handle_import(
     if (res == FAIL || sid <= 0)
     {
 	semsg(_(e_could_not_import_str), tv.vval.v_string);
-	clear_tv(&tv);
 	goto erret;
     }
-    clear_tv(&tv);
 
     if (*arg_start == '*')
     {
@@ -669,6 +664,7 @@ handle_import(
 	}
     }
 erret:
+    clear_tv(&tv);
     ga_clear_strings(&names);
     ga_clear_strings(&as_names);
     return cmd_end;