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 -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///