summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-03-13 20:57:19 +0100
committerBram Moolenaar <Bram@vim.org>2021-03-13 20:57:19 +0100
commitcb4e80fab9b1ee67249bde4f784526f900cda70c (patch)
treef2d80bc69d80259f4ae2b8bb2ac501fac2ea00b0
parent41cd80335cf318c15c8b0139f53ab5e8a02561ef (diff)
downloadvim-git-cb4e80fab9b1ee67249bde4f784526f900cda70c.tar.gz
patch 8.2.2597: Vim9: "import * as" does not work at script levelv8.2.2597
Problem: Vim9: "import * as" does not work at script level. Solution: Implement using an imported namespace.
-rw-r--r--src/errors.h2
-rw-r--r--src/eval.c62
-rw-r--r--src/evalvars.c40
-rw-r--r--src/proto/evalvars.pro2
-rw-r--r--src/proto/vim9script.pro2
-rw-r--r--src/testdir/test_vim9_script.vim24
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h5
-rw-r--r--src/vim9execute.c2
-rw-r--r--src/vim9script.c11
10 files changed, 129 insertions, 23 deletions
diff --git a/src/errors.h b/src/errors.h
index db958e054..c1dc547fb 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -373,3 +373,5 @@ EXTERN char e_argument_name_shadows_existing_variable_str[]
INIT(= N_("E1167: Argument name shadows existing variable: %s"));
EXTERN char e_argument_already_declared_in_script_str[]
INIT(= N_("E1168: Argument already declared in the script: %s"));
+EXTERN char e_import_as_name_not_supported_here[]
+ INIT(= N_("E1169: 'import * as {name}' not supported here"));
diff --git a/src/eval.c b/src/eval.c
index 1ad633965..8e964de70 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1370,7 +1370,7 @@ set_var_lval(
// handle +=, -=, *=, /=, %= and .=
di = NULL;
if (eval_variable(lp->ll_name, (int)STRLEN(lp->ll_name),
- &tv, &di, TRUE, FALSE) == OK)
+ &tv, &di, EVAL_VAR_VERBOSE) == OK)
{
if ((di == NULL
|| (!var_check_ro(di->di_flags, lp->ll_name, FALSE)
@@ -3500,7 +3500,8 @@ eval7(
ret = OK;
}
else
- ret = eval_variable(s, len, rettv, NULL, TRUE, FALSE);
+ ret = eval_variable(s, len, rettv, NULL,
+ EVAL_VAR_VERBOSE + EVAL_VAR_IMPORT);
}
else
{
@@ -5760,6 +5761,63 @@ handle_subscript(
check_white = FALSE;
}
+ if (rettv->v_type == VAR_ANY)
+ {
+ char_u *exp_name;
+ int cc;
+ int idx;
+ ufunc_T *ufunc;
+ type_T *type;
+
+ // Found script from "import * as {name}", script item name must
+ // follow.
+ if (**arg != '.')
+ {
+ if (verbose)
+ semsg(_(e_expected_str_but_got_str), "'.'", *arg);
+ ret = FAIL;
+ break;
+ }
+ ++*arg;
+ if (IS_WHITE_OR_NUL(**arg))
+ {
+ if (verbose)
+ emsg(_(e_no_white_space_allowed_after_dot));
+ ret = FAIL;
+ break;
+ }
+
+ // isolate the name
+ exp_name = *arg;
+ while (eval_isnamec(**arg))
+ ++*arg;
+ cc = **arg;
+ **arg = NUL;
+
+ idx = find_exported(rettv->vval.v_number, exp_name, &ufunc, &type,
+ evalarg->eval_cctx, verbose);
+ **arg = cc;
+ *arg = skipwhite(*arg);
+
+ if (idx < 0 && ufunc == NULL)
+ {
+ ret = FAIL;
+ break;
+ }
+ if (idx >= 0)
+ {
+ scriptitem_T *si = SCRIPT_ITEM(rettv->vval.v_number);
+ svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
+
+ copy_tv(sv->sv_tv, rettv);
+ }
+ else
+ {
+ rettv->v_type = VAR_FUNC;
+ rettv->vval.v_string = vim_strsave(ufunc->uf_name);
+ }
+ }
+
if ((**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC
|| rettv->v_type == VAR_PARTIAL))
&& (!check_white || !VIM_ISWHITE(*(*arg - 1))))
diff --git a/src/evalvars.c b/src/evalvars.c
index eac66b2b9..eefd05f36 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -1219,7 +1219,8 @@ list_arg_vars(exarg_T *eap, char_u *arg, int *first)
arg = skipwhite(arg);
if (tofree != NULL)
name = tofree;
- if (eval_variable(name, len, &tv, NULL, TRUE, FALSE) == FAIL)
+ if (eval_variable(name, len, &tv, NULL,
+ EVAL_VAR_VERBOSE) == FAIL)
error = TRUE;
else
{
@@ -2539,6 +2540,8 @@ set_cmdarg(exarg_T *eap, char_u *oldarg)
/*
* Get the value of internal variable "name".
+ * If "flags" has EVAL_VAR_IMPORT may return a VAR_ANY with v_number set to the
+ * imported script ID.
* Return OK or FAIL. If OK is returned "rettv" must be cleared.
*/
int
@@ -2547,12 +2550,11 @@ eval_variable(
int len, // length of "name"
typval_T *rettv, // NULL when only checking existence
dictitem_T **dip, // non-NULL when typval's dict item is needed
- int verbose, // may give error message
- int no_autoload) // do not use script autoloading
+ int flags) // EVAL_VAR_ flags
{
int ret = OK;
typval_T *tv = NULL;
- int foundFunc = FALSE;
+ int found = FALSE;
dictitem_T *v;
int cc;
@@ -2561,7 +2563,7 @@ eval_variable(
name[len] = NUL;
// Check for user-defined variables.
- v = find_var(name, NULL, no_autoload);
+ v = find_var(name, NULL, flags & EVAL_VAR_NOAUTOLOAD);
if (v != NULL)
{
tv = &v->di_tv;
@@ -2581,7 +2583,7 @@ eval_variable(
{
if (import->imp_funcname != NULL)
{
- foundFunc = TRUE;
+ found = TRUE;
if (rettv != NULL)
{
rettv->v_type = VAR_FUNC;
@@ -2590,8 +2592,21 @@ eval_variable(
}
else if (import->imp_flags & IMP_FLAGS_STAR)
{
- emsg("Sorry, 'import * as X' not implemented yet");
- ret = FAIL;
+ if ((flags & EVAL_VAR_IMPORT) == 0)
+ {
+ if (flags & EVAL_VAR_VERBOSE)
+ emsg(_(e_import_as_name_not_supported_here));
+ ret = FAIL;
+ }
+ else
+ {
+ if (rettv != NULL)
+ {
+ rettv->v_type = VAR_ANY;
+ rettv->vval.v_number = import->imp_sid;
+ }
+ found = TRUE;
+ }
}
else
{
@@ -2607,7 +2622,7 @@ eval_variable(
if (ufunc != NULL)
{
- foundFunc = TRUE;
+ found = TRUE;
if (rettv != NULL)
{
rettv->v_type = VAR_FUNC;
@@ -2617,11 +2632,11 @@ eval_variable(
}
}
- if (!foundFunc)
+ if (!found)
{
if (tv == NULL)
{
- if (rettv != NULL && verbose)
+ if (rettv != NULL && (flags & EVAL_VAR_VERBOSE))
semsg(_(e_undefined_variable_str), name);
ret = FAIL;
}
@@ -3695,7 +3710,8 @@ var_exists(char_u *var)
{
if (tofree != NULL)
name = tofree;
- n = (eval_variable(name, len, &tv, NULL, FALSE, TRUE) == OK);
+ n = (eval_variable(name, len, &tv, NULL,
+ EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT) == OK);
if (n)
{
// handle d.key, l[idx], f(expr)
diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro
index bd2c6879f..1094d4563 100644
--- a/src/proto/evalvars.pro
+++ b/src/proto/evalvars.pro
@@ -56,7 +56,7 @@ void set_reg_var(int c);
char_u *v_exception(char_u *oldval);
char_u *v_throwpoint(char_u *oldval);
char_u *set_cmdarg(exarg_T *eap, char_u *oldarg);
-int eval_variable(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int verbose, int no_autoload);
+int eval_variable(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int flags);
void check_vars(char_u *name, int len);
dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload);
dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload);
diff --git a/src/proto/vim9script.pro b/src/proto/vim9script.pro
index c6493519c..c80618f75 100644
--- a/src/proto/vim9script.pro
+++ b/src/proto/vim9script.pro
@@ -7,7 +7,7 @@ void ex_export(exarg_T *eap);
void free_imports_and_script_vars(int sid);
void mark_imports_for_reload(int sid);
void ex_import(exarg_T *eap);
-int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx);
+int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx, int verbose);
char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid, evalarg_T *evalarg, void *cctx);
char_u *vim9_declare_scriptvar(exarg_T *eap, char_u *arg);
void update_vim9_script_var(int create, dictitem_T *di, int flags, typval_T *tv, type_T **type);
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 95c6a5b10..d2f5febb9 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -1031,13 +1031,17 @@ def Test_vim9_import_export()
vim9script
import * as Export from './Xexport.vim'
def UseExport()
- g:imported = Export.exported
+ g:imported_def = Export.exported
enddef
+ g:imported_script = Export.exported
+ assert_equal(1, exists('Export.exported'))
+ assert_equal(0, exists('Export.notexported'))
UseExport()
END
writefile(import_star_as_lines, 'Ximport.vim')
source Ximport.vim
- assert_equal(9883, g:imported)
+ assert_equal(9883, g:imported_def)
+ assert_equal(9883, g:imported_script)
var import_star_as_lines_no_dot =<< trim END
vim9script
@@ -1072,6 +1076,22 @@ def Test_vim9_import_export()
writefile(import_star_as_duplicated, 'Ximport.vim')
assert_fails('source Ximport.vim', 'E1073:', '', 4, 'Ximport.vim')
+ var import_star_as_lines_script_no_dot =<< trim END
+ vim9script
+ import * as Export from './Xexport.vim'
+ g:imported_script = Export exported
+ END
+ writefile(import_star_as_lines_script_no_dot, 'Ximport.vim')
+ assert_fails('source Ximport.vim', 'E1029:')
+
+ var import_star_as_lines_script_space_after_dot =<< trim END
+ vim9script
+ import * as Export from './Xexport.vim'
+ g:imported_script = Export. exported
+ END
+ writefile(import_star_as_lines_script_space_after_dot, 'Ximport.vim')
+ assert_fails('source Ximport.vim', 'E1074:')
+
var import_star_as_lines_missing_name =<< trim END
vim9script
import * as Export from './Xexport.vim'
diff --git a/src/version.c b/src/version.c
index fbcf57e36..f35f8b0b0 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 */
/**/
+ 2597,
+/**/
2596,
/**/
2595,
diff --git a/src/vim.h b/src/vim.h
index 5dd69f6ee..7f4c99ad3 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -2702,4 +2702,9 @@ long elapsed(DWORD start_tick);
#define MCH_DELAY_IGNOREINPUT 1
#define MCH_DELAY_SETTMODE 2
+// Flags for eval_variable().
+#define EVAL_VAR_VERBOSE 1 // may give error message
+#define EVAL_VAR_NOAUTOLOAD 2 // do not use script autoloading
+#define EVAL_VAR_IMPORT 4 // may return special variable for import
+
#endif // VIM__H
diff --git a/src/vim9execute.c b/src/vim9execute.c
index d4435c4c5..f8470f5c7 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1765,7 +1765,7 @@ call_def_function(
goto failed;
SOURCING_LNUM = iptr->isn_lnum;
if (eval_variable(name, (int)STRLEN(name),
- STACK_TV_BOT(0), NULL, TRUE, FALSE) == FAIL)
+ STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL)
goto on_error;
++ectx.ec_stack.ga_len;
}
diff --git a/src/vim9script.c b/src/vim9script.c
index cd60b250f..faee1316c 100644
--- a/src/vim9script.c
+++ b/src/vim9script.c
@@ -257,7 +257,8 @@ find_exported(
char_u *name,
ufunc_T **ufunc,
type_T **type,
- cctx_T *cctx)
+ cctx_T *cctx,
+ int verbose)
{
int idx = -1;
svar_T *sv;
@@ -271,7 +272,8 @@ find_exported(
sv = ((svar_T *)script->sn_var_vals.ga_data) + idx;
if (!sv->sv_export)
{
- semsg(_(e_item_not_exported_in_script_str), name);
+ if (verbose)
+ semsg(_(e_item_not_exported_in_script_str), name);
return -1;
}
*type = sv->sv_type;
@@ -301,7 +303,8 @@ find_exported(
if (*ufunc == NULL)
{
- semsg(_(e_item_not_found_in_script_str), name);
+ if (verbose)
+ semsg(_(e_item_not_found_in_script_str), name);
return -1;
}
}
@@ -532,7 +535,7 @@ handle_import(
ufunc_T *ufunc = NULL;
type_T *type;
- idx = find_exported(sid, name, &ufunc, &type, cctx);
+ idx = find_exported(sid, name, &ufunc, &type, cctx, TRUE);
if (idx < 0 && ufunc == NULL)
goto erret;