summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-02-23 21:25:54 +0100
committerBram Moolenaar <Bram@vim.org>2020-02-23 21:25:54 +0100
commitf2d5c240a56853c0bbbc7979e9bff095de6c73ec (patch)
tree1244a029c4c623cd9e48743af1e7d442f9562402
parent750802b55c6edda4d3bc78c41ad0a25a3450a557 (diff)
downloadvim-git-f2d5c240a56853c0bbbc7979e9bff095de6c73ec.tar.gz
patch 8.2.0312: Vim9: insufficient script testsv8.2.0312
Problem: Vim9: insufficient script tests. Solution: Add more tests. Make "import * as Name" work.
-rw-r--r--src/proto/vim9script.pro3
-rw-r--r--src/testdir/test_vim9_script.vim23
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c54
-rw-r--r--src/vim9script.c149
5 files changed, 159 insertions, 72 deletions
diff --git a/src/proto/vim9script.pro b/src/proto/vim9script.pro
index 29fa269db..18edb8698 100644
--- a/src/proto/vim9script.pro
+++ b/src/proto/vim9script.pro
@@ -4,5 +4,6 @@ void ex_vim9script(exarg_T *eap);
void ex_export(exarg_T *eap);
void free_imports(int sid);
void ex_import(exarg_T *eap);
-char_u *handle_import(char_u *arg_start, garray_T *gap, int sid);
+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);
/* vim: set ft=c : */
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 1af897e06..ef06ecbbe 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -331,6 +331,28 @@ def Test_vim9script()
unlet g:imported_func
unlet g:imported_name g:imported_name_appended
delete('Ximport.vim')
+
+ let import_star_as_lines =<< trim END
+ vim9script
+ import * as Export from './Xexport.vim'
+ def UseExport()
+ g:imported = Export.exported
+ enddef
+ UseExport()
+ END
+ writefile(import_star_as_lines, 'Ximport.vim')
+ source Ximport.vim
+ assert_equal(9876, g:imported)
+
+ let import_star_lines =<< trim END
+ vim9script
+ import * from './Xexport.vim'
+ g:imported = exported
+ END
+ writefile(import_star_lines, 'Ximport.vim')
+ assert_fails('source Ximport.vim', 'E1045:')
+
+ delete('Ximport.vim')
delete('Xexport.vim')
" Check that in a Vim9 script 'cpo' is set to the Vim default.
@@ -352,6 +374,7 @@ def Test_vim9script_fails()
CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
CheckScriptFailure(['export let some = 123'], 'E1042:')
+ CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1042:')
CheckScriptFailure(['vim9script', 'export let g:some'], 'E1044:')
CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
diff --git a/src/version.c b/src/version.c
index ab8cb0ea7..05c0edca9 100644
--- 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 */
/**/
+ 312,
+/**/
311,
/**/
310,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 6408b67bf..e21f5cbe7 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1522,7 +1522,11 @@ find_imported(char_u *name, size_t len, cctx_T *cctx)
* Generate an instruction to load script-local variable "name".
*/
static int
-compile_load_scriptvar(cctx_T *cctx, char_u *name)
+compile_load_scriptvar(
+ cctx_T *cctx,
+ char_u *name, // variable NUL terminated
+ char_u *start, // start of variable
+ char_u **end) // end of variable
{
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
@@ -1546,11 +1550,40 @@ compile_load_scriptvar(cctx_T *cctx, char_u *name)
import = find_imported(name, 0, cctx);
if (import != NULL)
{
- // TODO: check this is a variable, not a function
- generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
- import->imp_sid,
- import->imp_var_vals_idx,
- import->imp_type);
+ if (import->imp_all)
+ {
+ char_u *p = skipwhite(*end);
+ int name_len;
+ ufunc_T *ufunc;
+ type_T *type;
+
+ // Used "import * as Name", need to lookup the member.
+ if (*p != '.')
+ {
+ semsg(_("E1060: expected dot after name: %s"), start);
+ return FAIL;
+ }
+ ++p;
+
+ idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
+ // TODO: what if it is a function?
+ if (idx < 0)
+ return FAIL;
+ *end = p;
+
+ generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
+ import->imp_sid,
+ idx,
+ type);
+ }
+ else
+ {
+ // TODO: check this is a variable, not a function
+ generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
+ import->imp_sid,
+ import->imp_var_vals_idx,
+ import->imp_type);
+ }
return OK;
}
@@ -1564,10 +1597,11 @@ compile_load_scriptvar(cctx_T *cctx, char_u *name)
* When "error" is FALSE do not give an error when not found.
*/
static int
-compile_load(char_u **arg, char_u *end, cctx_T *cctx, int error)
+compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
{
type_T *type;
char_u *name;
+ char_u *end = end_arg;
int res = FAIL;
if (*(*arg + 1) == ':')
@@ -1589,7 +1623,7 @@ compile_load(char_u **arg, char_u *end, cctx_T *cctx, int error)
}
else if (**arg == 's')
{
- res = compile_load_scriptvar(cctx, name);
+ res = compile_load_scriptvar(cctx, name, NULL, NULL);
}
else
{
@@ -1645,7 +1679,7 @@ compile_load(char_u **arg, char_u *end, cctx_T *cctx, int error)
else if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
== SCRIPT_VERSION_VIM9)
// in Vim9 script "var" can be script-local.
- res = compile_load_scriptvar(cctx, name);
+ res = compile_load_scriptvar(cctx, name, *arg, &end);
}
}
if (gen_load)
@@ -3412,7 +3446,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
break;
case dest_script:
- compile_load_scriptvar(cctx, name + (name[1] == ':' ? 2 : 0));
+ compile_load_scriptvar(cctx, name + (name[1] == ':' ? 2 : 0), NULL, NULL);
break;
case dest_env:
// Include $ in the name here
diff --git a/src/vim9script.c b/src/vim9script.c
index b73b592a2..97b714985 100644
--- a/src/vim9script.c
+++ b/src/vim9script.c
@@ -151,6 +151,88 @@ ex_import(exarg_T *eap)
}
/*
+ * Find an exported item in "sid" matching the name at "*argp".
+ * When it is a variable return the index.
+ * When it is a user function return "*ufunc".
+ * When not found returns -1 and "*ufunc" is NULL.
+ */
+ int
+find_exported(
+ int sid,
+ char_u **argp,
+ int *name_len,
+ ufunc_T **ufunc,
+ type_T **type)
+{
+ char_u *name = *argp;
+ char_u *arg = *argp;
+ int cc;
+ int idx = -1;
+ svar_T *sv;
+ scriptitem_T *script = SCRIPT_ITEM(sid);
+
+ // isolate one name
+ while (eval_isnamec1(*arg))
+ ++arg;
+ *name_len = (int)(arg - name);
+
+ // find name in "script"
+ // TODO: also find script-local user function
+ cc = *arg;
+ *arg = NUL;
+ idx = get_script_item_idx(sid, name, FALSE);
+ if (idx >= 0)
+ {
+ sv = ((svar_T *)script->sn_var_vals.ga_data) + idx;
+ if (!sv->sv_export)
+ {
+ semsg(_("E1049: Item not exported in script: %s"), name);
+ *arg = cc;
+ return -1;
+ }
+ *type = sv->sv_type;
+ *ufunc = NULL;
+ }
+ else
+ {
+ char_u buffer[200];
+ char_u *funcname;
+
+ // it could be a user function.
+ if (STRLEN(name) < sizeof(buffer) - 10)
+ funcname = buffer;
+ else
+ {
+ funcname = alloc(STRLEN(name) + 10);
+ if (funcname == NULL)
+ {
+ *arg = cc;
+ return -1;
+ }
+ }
+ funcname[0] = K_SPECIAL;
+ funcname[1] = KS_EXTRA;
+ funcname[2] = (int)KE_SNR;
+ sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
+ *ufunc = find_func(funcname, NULL);
+ if (funcname != buffer)
+ vim_free(funcname);
+
+ if (*ufunc == NULL)
+ {
+ semsg(_("E1048: Item not found in script: %s"), name);
+ *arg = cc;
+ return -1;
+ }
+ }
+ *arg = cc;
+ arg = skipwhite(arg);
+ *argp = arg;
+
+ return idx;
+}
+
+/*
* Handle an ":import" command and add the resulting imported_T to "gap", when
* not NULL, or script "import_sid" sn_imports.
* Returns a pointer to after the command or NULL in case of failure
@@ -289,8 +371,6 @@ handle_import(char_u *arg_start, garray_T *gap, int import_sid)
}
else
{
- scriptitem_T *script = SCRIPT_ITEM(sid);
-
arg = arg_start;
if (*arg == '{')
arg = skipwhite(arg + 1);
@@ -298,68 +378,15 @@ handle_import(char_u *arg_start, garray_T *gap, int import_sid)
{
char_u *name = arg;
int name_len;
- int cc;
int idx;
- svar_T *sv;
imported_T *imported;
- ufunc_T *ufunc;
+ ufunc_T *ufunc = NULL;
+ type_T *type;
- // isolate one name
- while (eval_isnamec1(*arg))
- ++arg;
- name_len = (int)(arg - name);
+ idx = find_exported(sid, &arg, &name_len, &ufunc, &type);
- // find name in "script"
- // TODO: also find script-local user function
- cc = *arg;
- *arg = NUL;
- idx = get_script_item_idx(sid, name, FALSE);
- if (idx >= 0)
- {
- sv = ((svar_T *)script->sn_var_vals.ga_data) + idx;
- if (!sv->sv_export)
- {
- semsg(_("E1049: Item not exported in script: %s"), name);
- *arg = cc;
- return NULL;
- }
- ufunc = NULL;
- }
- else
- {
- char_u buffer[200];
- char_u *funcname;
-
- // it could be a user function.
- if (STRLEN(name) < sizeof(buffer) - 10)
- funcname = buffer;
- else
- {
- funcname = alloc(STRLEN(name) + 10);
- if (funcname == NULL)
- {
- *arg = cc;
- return NULL;
- }
- }
- funcname[0] = K_SPECIAL;
- funcname[1] = KS_EXTRA;
- funcname[2] = (int)KE_SNR;
- sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
- ufunc = find_func(funcname, NULL);
- if (funcname != buffer)
- vim_free(funcname);
-
- if (ufunc == NULL)
- {
- semsg(_("E1048: Item not found in script: %s"), name);
- *arg = cc;
- return NULL;
- }
- sv = NULL;
- }
- *arg = cc;
- arg = skipwhite(arg);
+ if (idx < 0 && ufunc == NULL)
+ return NULL;
imported = new_imported(gap != NULL ? gap
: &SCRIPT_ITEM(import_sid)->sn_imports);
@@ -372,7 +399,7 @@ handle_import(char_u *arg_start, garray_T *gap, int import_sid)
imported->imp_sid = sid;
if (idx >= 0)
{
- imported->imp_type = sv->sv_type;
+ imported->imp_type = type;
imported->imp_var_vals_idx = idx;
}
else