Patch 8.2.4123
Problem:    Complete function cannot be import.Name.
Solution:   Dereference the function name if needed.  Also: do not see
            "import.Name" as a builtin function. (closes #9541)
Files:      src/userfunc.c, src/eval.c, src/testdir/test_vim9_import.vim


*** ../vim-8.2.4122/src/userfunc.c      2022-01-16 18:06:17.723808427 +0000
--- src/userfunc.c      2022-01-17 19:23:22.299766567 +0000
***************
*** 3119,3136 ****
  
  /*
   * Return TRUE if "name" looks like a builtin function name: starts with a
!  * lower case letter and doesn't contain AUTOLOAD_CHAR or ':'.
   * "len" is the length of "name", or -1 for NUL terminated.
   */
      int
  builtin_function(char_u *name, int len)
  {
!     char_u *p;
  
      if (!ASCII_ISLOWER(name[0]) || name[1] == ':')
        return FALSE;
!     p = vim_strchr(name, AUTOLOAD_CHAR);
!     return p == NULL || (len > 0 && p > name + len);
  }
  
      int
--- 3119,3148 ----
  
  /*
   * Return TRUE if "name" looks like a builtin function name: starts with a
!  * lower case letter, doesn't contain AUTOLOAD_CHAR or ':', no "." after the
!  * name.
   * "len" is the length of "name", or -1 for NUL terminated.
   */
      int
  builtin_function(char_u *name, int len)
  {
!     int i;
  
      if (!ASCII_ISLOWER(name[0]) || name[1] == ':')
        return FALSE;
!     for (i = 0; name[i] != NUL && (len < 0 || i < len); ++i)
!     {
!       if (name[i] == AUTOLOAD_CHAR)
!           return FALSE;
!       if (!eval_isnamec(name[i]))
!       {
!           // "name.something" is not a builtin function
!           if (name[i] == '.')
!               return FALSE;
!           break;
!       }
!     }
!     return TRUE;
  }
  
      int
*** ../vim-8.2.4122/src/eval.c  2022-01-16 21:18:49.419329705 +0000
--- src/eval.c  2022-01-17 19:54:45.130914748 +0000
***************
*** 626,631 ****
--- 626,688 ----
  }
  
  /*
+  * "*arg" points to what can be a function name in the form of "import.Name" 
or
+  * "Funcref".  Return the name of the function.  Set "tofree" to something 
that
+  * was allocated.
+  * If "verbose" is FALSE no errors are given.
+  * Return NULL for any failure.
+  */
+     static char_u *
+ deref_function_name(
+           char_u **arg,
+           char_u **tofree,
+           evalarg_T *evalarg,
+           int verbose)
+ {
+     typval_T  ref;
+     char_u    *name = *arg;
+ 
+     ref.v_type = VAR_UNKNOWN;
+     if (eval7(arg, &ref, evalarg, FALSE) == FAIL)
+       return NULL;
+     if (*skipwhite(*arg) != NUL)
+     {
+       if (verbose)
+           semsg(_(e_trailing_characters_str), *arg);
+       name = NULL;
+     }
+     else if (ref.v_type == VAR_FUNC && ref.vval.v_string != NULL)
+     {
+       name = ref.vval.v_string;
+       ref.vval.v_string = NULL;
+       *tofree = name;
+     }
+     else if (ref.v_type == VAR_PARTIAL && ref.vval.v_partial != NULL)
+     {
+       if (ref.vval.v_partial->pt_argc > 0
+               || ref.vval.v_partial->pt_dict != NULL)
+       {
+           if (verbose)
+               emsg(_(e_cannot_use_partial_here));
+           name = NULL;
+       }
+       else
+       {
+           name = vim_strsave(partial_name(ref.vval.v_partial));
+           *tofree = name;
+       }
+     }
+     else
+     {
+       if (verbose)
+           semsg(_(e_not_callable_type_str), name);
+       name = NULL;
+     }
+     clear_tv(&ref);
+     return name;
+ }
+ 
+ /*
   * Call some Vim script function and return the result in "*rettv".
   * Uses argv[0] to argv[argc - 1] for the function arguments.  argv[argc]
   * should have type VAR_UNKNOWN.
***************
*** 640,654 ****
  {
      int               ret;
      funcexe_T funcexe;
  
      rettv->v_type = VAR_UNKNOWN;              // clear_tv() uses this
      CLEAR_FIELD(funcexe);
      funcexe.fe_firstline = curwin->w_cursor.lnum;
      funcexe.fe_lastline = curwin->w_cursor.lnum;
      funcexe.fe_evaluate = TRUE;
!     ret = call_func(func, -1, rettv, argc, argv, &funcexe);
      if (ret == FAIL)
        clear_tv(rettv);
  
      return ret;
  }
--- 697,723 ----
  {
      int               ret;
      funcexe_T funcexe;
+     char_u    *arg;
+     char_u    *name;
+     char_u    *tofree = NULL;
  
      rettv->v_type = VAR_UNKNOWN;              // clear_tv() uses this
      CLEAR_FIELD(funcexe);
      funcexe.fe_firstline = curwin->w_cursor.lnum;
      funcexe.fe_lastline = curwin->w_cursor.lnum;
      funcexe.fe_evaluate = TRUE;
! 
!     // The name might be "import.Func" or "Funcref".
!     arg = func;
!     name = deref_function_name(&arg, &tofree, &EVALARG_EVALUATE, FALSE);
!     if (name == NULL)
!       name = func;
! 
!     ret = call_func(name, -1, rettv, argc, argv, &funcexe);
! 
      if (ret == FAIL)
        clear_tv(rettv);
+     vim_free(tofree);
  
      return ret;
  }
***************
*** 3979,4035 ****
        if (**arg != '(' && alias == NULL
                                    && (paren = vim_strchr(*arg, '(')) != NULL)
        {
-           typval_T ref;
- 
            *arg = name;
            *paren = NUL;
!           ref.v_type = VAR_UNKNOWN;
!           if (eval7(arg, &ref, evalarg, FALSE) == FAIL)
            {
                *arg = name + len;
                ret = FAIL;
            }
-           else if (*skipwhite(*arg) != NUL)
-           {
-               if (verbose)
-                   semsg(_(e_trailing_characters_str), *arg);
-               ret = FAIL;
-           }
-           else if (ref.v_type == VAR_FUNC && ref.vval.v_string != NULL)
-           {
-               name = ref.vval.v_string;
-               ref.vval.v_string = NULL;
-               tofree = name;
-               len = STRLEN(name);
-           }
-           else if (ref.v_type == VAR_PARTIAL && ref.vval.v_partial != NULL)
-           {
-               if (ref.vval.v_partial->pt_argc > 0
-                                       || ref.vval.v_partial->pt_dict != NULL)
-               {
-                   emsg(_(e_cannot_use_partial_here));
-                   ret = FAIL;
-               }
-               else
-               {
-                   name = vim_strsave(partial_name(ref.vval.v_partial));
-                   tofree = name;
-                   if (name == NULL)
-                   {
-                       ret = FAIL;
-                       name = *arg;
-                   }
-                   else
-                       len = STRLEN(name);
-               }
-           }
            else
!           {
!               if (verbose)
!                   semsg(_(e_not_callable_type_str), name);
!               ret = FAIL;
!           }
!               clear_tv(&ref);
            *paren = '(';
        }
  
--- 4048,4063 ----
        if (**arg != '(' && alias == NULL
                                    && (paren = vim_strchr(*arg, '(')) != NULL)
        {
            *arg = name;
            *paren = NUL;
!           name = deref_function_name(arg, &tofree, evalarg, verbose);
!           if (name == NULL)
            {
                *arg = name + len;
                ret = FAIL;
            }
            else
!               len = STRLEN(name);
            *paren = '(';
        }
  
*** ../vim-8.2.4122/src/testdir/test_vim9_import.vim    2022-01-16 
21:18:49.419329705 +0000
--- src/testdir/test_vim9_import.vim    2022-01-17 20:03:56.425467411 +0000
***************
*** 580,585 ****
--- 580,608 ----
    nunmap <F3>
  enddef
  
+ def Test_use_import_in_completion()
+   var lines =<< trim END
+       vim9script
+       export def Complete(..._): list<string>
+         return ['abcd']
+       enddef
+   END
+   writefile(lines, 'Xscript.vim')
+ 
+   lines =<< trim END
+       vim9script
+       import './Xscript.vim'
+ 
+       command -nargs=1 -complete=customlist,Xscript.Complete Cmd echo 'ok'
+       feedkeys(":Cmd ab\<Tab>\<C-B>#\<CR>", 'xnt')
+       assert_equal('#Cmd abcd', @:)
+   END
+   CheckScriptSuccess(lines)
+ 
+   delcommand Cmd
+   delete('Xscript.vim')
+ enddef
+ 
  def Test_export_fails()
    CheckScriptFailure(['export var some = 123'], 'E1042:')
    CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:')
*** ../vim-8.2.4122/src/version.c       2022-01-17 19:06:52.458100460 +0000
--- src/version.c       2022-01-17 19:24:13.267788083 +0000
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     4123,
  /**/

-- 
WOMAN:   I didn't know we had a king. I thought we were an autonomous
         collective.
DENNIS:  You're fooling yourself.  We're living in a dictatorship.  A
         self-perpetuating autocracy in which the working classes--
WOMAN:   Oh there you go, bringing class into it again.
DENNIS:  That's what it's all about if only people would--
                                  The Quest for the Holy Grail (Monty Python)

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220117201001.60B421C044E%40moolenaar.net.

Raspunde prin e-mail lui