]> granicus.if.org Git - vim/commitdiff
patch 8.2.2597: Vim9: "import * as" does not work at script level v8.2.2597
authorBram Moolenaar <Bram@vim.org>
Sat, 13 Mar 2021 19:57:19 +0000 (20:57 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 13 Mar 2021 19:57:19 +0000 (20:57 +0100)
Problem:    Vim9: "import * as" does not work at script level.
Solution:   Implement using an imported namespace.

src/errors.h
src/eval.c
src/evalvars.c
src/proto/evalvars.pro
src/proto/vim9script.pro
src/testdir/test_vim9_script.vim
src/version.c
src/vim.h
src/vim9execute.c
src/vim9script.c

index db958e05419a69b604af147c786bd38ec802f9d7..c1dc547fbe8195f81c8d1bf020c15298231125c3 100644 (file)
@@ -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"));
index 1ad633965927520981182f8e3e5e905f27280886..8e964de700b95a9612ba391170e1481aa5a3854b 100644 (file)
@@ -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))))
index eac66b2b9216c1ca8978ed7be42f3108fb443f54..eefd05f367c1cb3f69d888d1aabb63f59dfe4875 100644 (file)
@@ -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)
index bd2c6879ff6c5dd3059e15ad89ea21293db1bd35..1094d4563068abfdcba41e22ee8334398e6ea721 100644 (file)
@@ -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);
index c6493519cf5169b23ba228f31b7dc40886365754..c80618f750632f21c92fafbe6f0a2cff854a5aa8 100644 (file)
@@ -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);
index 95c6a5b10b2e33b7096c9505f21a6409f0a1af6d..d2f5febb97a9620fb5989d49fb045614302ec7e8 100644 (file)
@@ -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'
index fbcf57e3645a988f273d18fa3a839d68830eb454..f35f8b0b039e1b2da93baedb31ee49b347ab1198 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2597,
 /**/
     2596,
 /**/
index 5dd69f6ee7a084871e2a9222c635313f023f068e..7f4c99ad3698d1ee2efd1bd2283dc871b0fadbdf 100644 (file)
--- 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
index d4435c4c5f1af3e9e649ebca038065b9a334e677..f8470f5c7723742b7916d3721777ec3aa19b84f5 100644 (file)
@@ -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;
                }
index cd60b250f94cb5871e413993453e9e49e466165e..faee1316c4dc368867e32c691f6969b94da9af57 100644 (file)
@@ -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;