]> granicus.if.org Git - vim/commitdiff
patch 8.2.4137: Vim9: calling import with and without method is inconsistent v8.2.4137
authorBram Moolenaar <Bram@vim.org>
Tue, 18 Jan 2022 17:43:04 +0000 (17:43 +0000)
committerBram Moolenaar <Bram@vim.org>
Tue, 18 Jan 2022 17:43:04 +0000 (17:43 +0000)
Problem:    Vim9: calling import with and without method is inconsistent.
Solution:   Set a flag that a parenthsis follows to compile_load_scriptvar().
            Add some more tests.  Improve error message.

src/testdir/test_vim9_import.vim
src/version.c
src/vim9execute.c
src/vim9expr.c
src/vim9script.c

index 3c55f431220f91478eab705e74c487a72d471350..3f918f849eba1cf114a45c8917d68fc62136ba1e 100644 (file)
@@ -1256,6 +1256,136 @@ def Test_vim9script_autoload()
   &rtp = save_rtp
 enddef
 
+def Test_import_autoload_not_exported()
+  mkdir('Xdir/autoload', 'p')
+  var save_rtp = &rtp
+  exe 'set rtp^=' .. getcwd() .. '/Xdir'
+
+  # error when using an item that is not exported from an autoload script
+  var exportLines =<< trim END
+      vim9script
+      var notExported = 123
+      def NotExport()
+        echo 'nop'
+      enddef
+  END
+  writefile(exportLines, 'Xdir/autoload/notExport1.vim')
+
+  var lines =<< trim END
+      vim9script
+      import autoload 'notExport1.vim'
+      echo notExport1.notFound
+  END
+  CheckScriptFailure(lines, 'E1048: Item not found in script: notFound')
+
+  lines =<< trim END
+      vim9script
+      import autoload 'notExport1.vim'
+      echo notExport1.notExported
+  END
+  CheckScriptFailure(lines, 'E1049: Item not exported in script: notExported')
+
+  lines =<< trim END
+      vim9script
+      import autoload 'notExport1.vim'
+      echo notExport1.NotFunc()
+  END
+  CheckScriptFailure(lines, 'E1048: Item not found in script: NotFunc')
+
+  lines =<< trim END
+      vim9script
+      import autoload 'notExport1.vim'
+      echo notExport1.NotExport()
+  END
+  CheckScriptFailure(lines, 'E1049: Item not exported in script: NotExport')
+
+  lines =<< trim END
+      vim9script
+      import autoload 'notExport1.vim'
+      echo 'text'->notExport1.NotFunc()
+  END
+  CheckScriptFailure(lines, 'E1048: Item not found in script: NotFunc')
+
+  lines =<< trim END
+      vim9script
+      import autoload 'notExport1.vim'
+      echo 'text'->notExport1.NotExport()
+  END
+  CheckScriptFailure(lines, 'E1049: Item not exported in script: NotExport')
+
+  # using a :def function we use a different autoload script every time so that
+  # the function is compiled without the script loaded
+  writefile(exportLines, 'Xdir/autoload/notExport2.vim')
+  lines =<< trim END
+      vim9script
+      import autoload 'notExport2.vim'
+      def Testit()
+        echo notExport2.notFound
+      enddef
+      Testit()
+  END
+  CheckScriptFailure(lines, 'E1048: Item not found in script: notExport2#notFound')
+
+  writefile(exportLines, 'Xdir/autoload/notExport3.vim')
+  lines =<< trim END
+      vim9script
+      import autoload 'notExport3.vim'
+      def Testit()
+        echo notExport3.notExported
+      enddef
+      Testit()
+  END
+  # don't get E1049 because it is too complicated to figure out
+  CheckScriptFailure(lines, 'E1048: Item not found in script: notExport3#notExported')
+
+  writefile(exportLines, 'Xdir/autoload/notExport4.vim')
+  lines =<< trim END
+      vim9script
+      import autoload 'notExport4.vim'
+      def Testit()
+        echo notExport4.NotFunc()
+      enddef
+      Testit()
+  END
+  CheckScriptFailure(lines, 'E117: Unknown function: notExport4#NotFunc')
+
+  writefile(exportLines, 'Xdir/autoload/notExport5.vim')
+  lines =<< trim END
+      vim9script
+      import autoload 'notExport5.vim'
+      def Testit()
+        echo notExport5.NotExport()
+      enddef
+      Testit()
+  END
+  CheckScriptFailure(lines, 'E117: Unknown function: notExport5#NotExport')
+
+  writefile(exportLines, 'Xdir/autoload/notExport6.vim')
+  lines =<< trim END
+      vim9script
+      import autoload 'notExport6.vim'
+      def Testit()
+        echo 'text'->notExport6.NotFunc()
+      enddef
+      Testit()
+  END
+  CheckScriptFailure(lines, 'E117: Unknown function: notExport6#NotFunc')
+
+  writefile(exportLines, 'Xdir/autoload/notExport7.vim')
+  lines =<< trim END
+      vim9script
+      import autoload 'notExport7.vim'
+      def Testit()
+        echo 'text'->notExport7.NotExport()
+      enddef
+      Testit()
+  END
+  CheckScriptFailure(lines, 'E117: Unknown function: notExport7#NotExport')
+
+  delete('Xdir', 'rf')
+  &rtp = save_rtp
+enddef
+
 def Test_vim9script_autoload_call()
   mkdir('Xdir/autoload', 'p')
   var save_rtp = &rtp
index b2e7429d0008a4c362059aa6a252f23ca00e5cc2..67e9ca5ff318c91c287a07100e1fe9ba0c8aba47 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4137,
 /**/
     4136,
 /**/
index 0037f51af8546fc37b6894a97565b2061eae33b4..5ede04ca8b8314b7a3b8f9c37c88c096b77d511e 100644 (file)
@@ -2240,33 +2240,19 @@ exec_instructions(ectx_T *ectx)
                                                   iptr->isn_arg.string, TRUE);
                        if (did_emsg)
                            goto on_error;
-                       if (di == NULL)
-                       {
-                           isn_T   *next = &ectx->ec_instr[ectx->ec_iidx];
-
-                           // When compiling "script.Func()" when "script" is
-                           // an autoload import then this results in
-                           // "LOADG script#Func" because we don't know if it
-                           // is a funcref variable or a function name.  In
-                           // that case a PCALL follows, push the function
-                           // name instead.
-                           if (next->isn_type == ISN_PCALL)
-                           {
-                               tv = STACK_TV_BOT(0);
-                               tv->v_type = VAR_FUNC;
-                               tv->v_lock = 0;
-                               tv->vval.v_string =
-                                            vim_strsave(iptr->isn_arg.string);
-                               ++ectx->ec_stack.ga_len;
-                               break;
-                           }
-                       }
                    }
 
                    if (di == NULL)
                    {
                        SOURCING_LNUM = iptr->isn_lnum;
-                       semsg(_(e_undefined_variable_char_str),
+                       if (vim_strchr(iptr->isn_arg.string,
+                                                       AUTOLOAD_CHAR) != NULL)
+                           // no check if the item exists in the script but
+                           // isn't exported, it is too complicated
+                           semsg(_(e_item_not_found_in_script_str),
+                                                        iptr->isn_arg.string);
+                       else
+                           semsg(_(e_undefined_variable_char_str),
                                             namespace, iptr->isn_arg.string);
                        goto on_error;
                    }
index 922c7bab8a91722416830e8463307aeebe71bac9..72bfc01e516550e47ca0a351ca0b68a734ee49bd 100644 (file)
@@ -21,6 +21,9 @@
 # include "vim9.h"
 #endif
 
+// flag passed from compile_subscript() to compile_load_scriptvar()
+static int paren_follows_after_expr = 0;
+
 /*
  * Generate code for any ppconst entries.
  */
@@ -277,7 +280,6 @@ compile_load_scriptvar(
        int     done = FALSE;
        int     res = OK;
 
-       // TODO: if this is an autoload import do something else.
        // Need to lookup the member.
        if (*p != '.')
        {
@@ -306,7 +308,7 @@ compile_load_scriptvar(
 
            // autoload script must be loaded later, access by the autoload
            // name.
-           if (cc == '(')
+           if (cc == '(' || paren_follows_after_expr)
                res = generate_PUSHFUNC(cctx, auto_name, &t_func_any);
            else
                res = generate_LOAD(cctx, ISN_LOADG, 0, auto_name, &t_any);
@@ -1736,12 +1738,19 @@ compile_subscript(
                    int save_len = cctx->ctx_ufunc->uf_lines.ga_len;
 
                    *paren = NUL;
+
+                   // instead of using LOADG for "import.Func" use PUSHFUNC
+                   ++paren_follows_after_expr;
+
                    // do not look in the next line
                    cctx->ctx_ufunc->uf_lines.ga_len = 1;
+
                    fail = compile_expr8(arg, cctx, ppconst) == FAIL
                                                    || *skipwhite(*arg) != NUL;
                    *paren = '(';
+                   --paren_follows_after_expr;
                    cctx->ctx_ufunc->uf_lines.ga_len = save_len;
+
                    if (fail)
                    {
                        semsg(_(e_invalid_expression_str), pstart);
index 2f7f732ac42d11bfa4354fbe1391d9efef38be4b..e13ac4ac47e9e180c0d2eb4bde2eccc0452b7765 100644 (file)
@@ -707,22 +707,36 @@ find_exported(
            sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
        }
        *ufunc = find_func(funcname, FALSE);
-       if (funcname != buffer)
-           vim_free(funcname);
 
        if (*ufunc == NULL)
        {
            if (verbose)
-               semsg(_(e_item_not_found_in_script_str), name);
-           return -1;
+           {
+               ufunc_T *alt_ufunc = NULL;
+
+               if (script->sn_autoload_prefix != NULL)
+               {
+                   // try find the function by the script-local name
+                   funcname[0] = K_SPECIAL;
+                   funcname[1] = KS_EXTRA;
+                   funcname[2] = (int)KE_SNR;
+                   sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
+                   alt_ufunc = find_func(funcname, FALSE);
+               }
+               if (alt_ufunc != NULL)
+                   semsg(_(e_item_not_exported_in_script_str), name);
+               else
+                   semsg(_(e_item_not_found_in_script_str), name);
+           }
        }
        else if (((*ufunc)->uf_flags & FC_EXPORT) == 0)
        {
            if (verbose)
                semsg(_(e_item_not_exported_in_script_str), name);
            *ufunc = NULL;
-           return -1;
        }
+       if (funcname != buffer)
+           vim_free(funcname);
     }
 
     return idx;