mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.4123: complete function cannot be import.Name
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)
This commit is contained in:
parent
3f3597be3f
commit
15d1635e50
116
src/eval.c
116
src/eval.c
@ -625,6 +625,63 @@ eval_expr(char_u *arg, exarg_T *eap)
|
|||||||
return tv;
|
return tv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "*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".
|
* Call some Vim script function and return the result in "*rettv".
|
||||||
* Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc]
|
* Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc]
|
||||||
@ -640,15 +697,27 @@ call_vim_function(
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
funcexe_T funcexe;
|
funcexe_T funcexe;
|
||||||
|
char_u *arg;
|
||||||
|
char_u *name;
|
||||||
|
char_u *tofree = NULL;
|
||||||
|
|
||||||
rettv->v_type = VAR_UNKNOWN; // clear_tv() uses this
|
rettv->v_type = VAR_UNKNOWN; // clear_tv() uses this
|
||||||
CLEAR_FIELD(funcexe);
|
CLEAR_FIELD(funcexe);
|
||||||
funcexe.fe_firstline = curwin->w_cursor.lnum;
|
funcexe.fe_firstline = curwin->w_cursor.lnum;
|
||||||
funcexe.fe_lastline = curwin->w_cursor.lnum;
|
funcexe.fe_lastline = curwin->w_cursor.lnum;
|
||||||
funcexe.fe_evaluate = TRUE;
|
funcexe.fe_evaluate = TRUE;
|
||||||
ret = call_func(func, -1, rettv, argc, argv, &funcexe);
|
|
||||||
|
// 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)
|
if (ret == FAIL)
|
||||||
clear_tv(rettv);
|
clear_tv(rettv);
|
||||||
|
vim_free(tofree);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -3979,57 +4048,16 @@ eval_method(
|
|||||||
if (**arg != '(' && alias == NULL
|
if (**arg != '(' && alias == NULL
|
||||||
&& (paren = vim_strchr(*arg, '(')) != NULL)
|
&& (paren = vim_strchr(*arg, '(')) != NULL)
|
||||||
{
|
{
|
||||||
typval_T ref;
|
|
||||||
|
|
||||||
*arg = name;
|
*arg = name;
|
||||||
*paren = NUL;
|
*paren = NUL;
|
||||||
ref.v_type = VAR_UNKNOWN;
|
name = deref_function_name(arg, &tofree, evalarg, verbose);
|
||||||
if (eval7(arg, &ref, evalarg, FALSE) == FAIL)
|
if (name == NULL)
|
||||||
{
|
{
|
||||||
*arg = name + len;
|
*arg = name + len;
|
||||||
ret = FAIL;
|
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
|
else
|
||||||
len = STRLEN(name);
|
len = STRLEN(name);
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (verbose)
|
|
||||||
semsg(_(e_not_callable_type_str), name);
|
|
||||||
ret = FAIL;
|
|
||||||
}
|
|
||||||
clear_tv(&ref);
|
|
||||||
*paren = '(';
|
*paren = '(';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,6 +580,29 @@ def Test_use_import_in_mapping()
|
|||||||
nunmap <F3>
|
nunmap <F3>
|
||||||
enddef
|
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()
|
def Test_export_fails()
|
||||||
CheckScriptFailure(['export var some = 123'], 'E1042:')
|
CheckScriptFailure(['export var some = 123'], 'E1042:')
|
||||||
CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:')
|
CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:')
|
||||||
|
@ -3119,18 +3119,30 @@ free_all_functions(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Return TRUE if "name" looks like a builtin function name: starts with a
|
* Return TRUE if "name" looks like a builtin function name: starts with a
|
||||||
* lower case letter and doesn't contain AUTOLOAD_CHAR or ':'.
|
* lower case letter, doesn't contain AUTOLOAD_CHAR or ':', no "." after the
|
||||||
|
* name.
|
||||||
* "len" is the length of "name", or -1 for NUL terminated.
|
* "len" is the length of "name", or -1 for NUL terminated.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
builtin_function(char_u *name, int len)
|
builtin_function(char_u *name, int len)
|
||||||
{
|
{
|
||||||
char_u *p;
|
int i;
|
||||||
|
|
||||||
if (!ASCII_ISLOWER(name[0]) || name[1] == ':')
|
if (!ASCII_ISLOWER(name[0]) || name[1] == ':')
|
||||||
return FALSE;
|
return FALSE;
|
||||||
p = vim_strchr(name, AUTOLOAD_CHAR);
|
for (i = 0; name[i] != NUL && (len < 0 || i < len); ++i)
|
||||||
return p == NULL || (len > 0 && p > name + len);
|
{
|
||||||
|
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
|
int
|
||||||
|
@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
4123,
|
||||||
/**/
|
/**/
|
||||||
4122,
|
4122,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user