mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.4260: Vim9: can still use a global function without g:
Problem: Vim9: can still use a global function without g: at the script level. Solution: Also check for g: at the script level. (issue #9637)
This commit is contained in:
@@ -2779,17 +2779,20 @@ eval_variable(
|
|||||||
}
|
}
|
||||||
else if (in_vim9script() && (flags & EVAL_VAR_NO_FUNC) == 0)
|
else if (in_vim9script() && (flags & EVAL_VAR_NO_FUNC) == 0)
|
||||||
{
|
{
|
||||||
|
int has_g_prefix = STRNCMP(name, "g:", 2) == 0;
|
||||||
ufunc_T *ufunc = find_func(name, FALSE);
|
ufunc_T *ufunc = find_func(name, FALSE);
|
||||||
|
|
||||||
// In Vim9 script we can get a function reference by using the
|
// In Vim9 script we can get a function reference by using the
|
||||||
// function name.
|
// function name. For a global non-autoload function "g:" is
|
||||||
if (ufunc != NULL)
|
// required.
|
||||||
|
if (ufunc != NULL && (has_g_prefix
|
||||||
|
|| !func_requires_g_prefix(ufunc)))
|
||||||
{
|
{
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
if (rettv != NULL)
|
if (rettv != NULL)
|
||||||
{
|
{
|
||||||
rettv->v_type = VAR_FUNC;
|
rettv->v_type = VAR_FUNC;
|
||||||
if (STRNCMP(name, "g:", 2) == 0)
|
if (has_g_prefix)
|
||||||
// Keep the "g:", otherwise script-local may be
|
// Keep the "g:", otherwise script-local may be
|
||||||
// assumed.
|
// assumed.
|
||||||
rettv->vval.v_string = vim_strsave(name);
|
rettv->vval.v_string = vim_strsave(name);
|
||||||
|
@@ -11,6 +11,7 @@ char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *e
|
|||||||
ufunc_T *find_func_even_dead(char_u *name, int flags);
|
ufunc_T *find_func_even_dead(char_u *name, int flags);
|
||||||
ufunc_T *find_func(char_u *name, int is_global);
|
ufunc_T *find_func(char_u *name, int is_global);
|
||||||
int func_is_global(ufunc_T *ufunc);
|
int func_is_global(ufunc_T *ufunc);
|
||||||
|
int func_requires_g_prefix(ufunc_T *ufunc);
|
||||||
int func_name_refcount(char_u *name);
|
int func_name_refcount(char_u *name);
|
||||||
void func_clear_free(ufunc_T *fp, int force);
|
void func_clear_free(ufunc_T *fp, int force);
|
||||||
int copy_func(char_u *lambda, char_u *global, ectx_T *ectx);
|
int copy_func(char_u *lambda, char_u *global, ectx_T *ectx);
|
||||||
|
@@ -7,4 +7,4 @@
|
|||||||
|7| @20|4+0#0000001#ffd7ff255| @28| +0#0000000#a8a8a8255| +0&#ffffff0@21
|
|7| @20|4+0#0000001#ffd7ff255| @28| +0#0000000#a8a8a8255| +0&#ffffff0@21
|
||||||
|8| @73
|
|8| @73
|
||||||
|9| @73
|
|9| @73
|
||||||
|:|c|a|l@1| |P|o|p|u|p|S|c|r|o|l@1|(|)| @37|1|,|1| @10|T|o|p|
|
|:|c|a|l@1| |g|:|P|o|p|u|p|S|c|r|o|l@1|(|)| @35|1|,|1| @10|T|o|p|
|
||||||
|
@@ -7,4 +7,4 @@
|
|||||||
|7| @20|l+0#0000001#ffd7ff255|o|n|g| |l|i|n|e| |l|o|n|g| |l|i|n|e| |l|o|n|g| |l|i|n|e| | +0#0000000#a8a8a8255| +0&#ffffff0@21
|
|7| @20|l+0#0000001#ffd7ff255|o|n|g| |l|i|n|e| |l|o|n|g| |l|i|n|e| |l|o|n|g| |l|i|n|e| | +0#0000000#a8a8a8255| +0&#ffffff0@21
|
||||||
|8| @73
|
|8| @73
|
||||||
|9| @73
|
|9| @73
|
||||||
|:|c|a|l@1| |P|o|p|u|p|S|c|r|o|l@1|(|)| @37|1|,|1| @10|T|o|p|
|
|:|c|a|l@1| |g|:|P|o|p|u|p|S|c|r|o|l@1|(|)| @35|1|,|1| @10|T|o|p|
|
||||||
|
@@ -1422,7 +1422,7 @@ func Test_completefunc_callback()
|
|||||||
call assert_fails("set completefunc=funcref('abc')", "E700:")
|
call assert_fails("set completefunc=funcref('abc')", "E700:")
|
||||||
|
|
||||||
#" set 'completefunc' to a non-existing function
|
#" set 'completefunc' to a non-existing function
|
||||||
set completefunc=CompleteFunc2
|
set completefunc=g:CompleteFunc2
|
||||||
call setline(1, 'five')
|
call setline(1, 'five')
|
||||||
call assert_fails("set completefunc=function('NonExistingFunc')", 'E700:')
|
call assert_fails("set completefunc=function('NonExistingFunc')", 'E700:')
|
||||||
call assert_fails("LET &completefunc = function('NonExistingFunc')", 'E700:')
|
call assert_fails("LET &completefunc = function('NonExistingFunc')", 'E700:')
|
||||||
@@ -1679,7 +1679,7 @@ func Test_omnifunc_callback()
|
|||||||
call assert_fails("set omnifunc=funcref('abc')", "E700:")
|
call assert_fails("set omnifunc=funcref('abc')", "E700:")
|
||||||
|
|
||||||
#" set 'omnifunc' to a non-existing function
|
#" set 'omnifunc' to a non-existing function
|
||||||
set omnifunc=OmniFunc2
|
set omnifunc=g:OmniFunc2
|
||||||
call setline(1, 'nine')
|
call setline(1, 'nine')
|
||||||
call assert_fails("set omnifunc=function('NonExistingFunc')", 'E700:')
|
call assert_fails("set omnifunc=function('NonExistingFunc')", 'E700:')
|
||||||
call assert_fails("LET &omnifunc = function('NonExistingFunc')", 'E700:')
|
call assert_fails("LET &omnifunc = function('NonExistingFunc')", 'E700:')
|
||||||
@@ -1936,7 +1936,7 @@ func Test_thesaurusfunc_callback()
|
|||||||
call assert_fails("set thesaurusfunc=funcref('abc')", "E700:")
|
call assert_fails("set thesaurusfunc=funcref('abc')", "E700:")
|
||||||
|
|
||||||
#" set 'thesaurusfunc' to a non-existing function
|
#" set 'thesaurusfunc' to a non-existing function
|
||||||
set thesaurusfunc=TsrFunc2
|
set thesaurusfunc=g:TsrFunc2
|
||||||
call setline(1, 'ten')
|
call setline(1, 'ten')
|
||||||
call assert_fails("set thesaurusfunc=function('NonExistingFunc')", 'E700:')
|
call assert_fails("set thesaurusfunc=function('NonExistingFunc')", 'E700:')
|
||||||
call assert_fails("LET &thesaurusfunc = function('NonExistingFunc')", 'E700:')
|
call assert_fails("LET &thesaurusfunc = function('NonExistingFunc')", 'E700:')
|
||||||
|
@@ -2263,7 +2263,7 @@ func Test_popup_scrollbar()
|
|||||||
\ wrap: true,
|
\ wrap: true,
|
||||||
\ scrollbar: true,
|
\ scrollbar: true,
|
||||||
\ mapping: false,
|
\ mapping: false,
|
||||||
\ filter: Popup_filter,
|
\ filter: g:Popup_filter,
|
||||||
\ })
|
\ })
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
@@ -2328,7 +2328,7 @@ func Test_popup_scrollbar()
|
|||||||
call VerifyScreenDump(buf, 'Test_popupwin_scroll_10', {})
|
call VerifyScreenDump(buf, 'Test_popupwin_scroll_10', {})
|
||||||
|
|
||||||
" check size with non-wrapping lines
|
" check size with non-wrapping lines
|
||||||
call term_sendkeys(buf, ":call PopupScroll()\<CR>")
|
call term_sendkeys(buf, ":call g:PopupScroll()\<CR>")
|
||||||
call VerifyScreenDump(buf, 'Test_popupwin_scroll_11', {})
|
call VerifyScreenDump(buf, 'Test_popupwin_scroll_11', {})
|
||||||
|
|
||||||
" check size with wrapping lines
|
" check size with wrapping lines
|
||||||
|
@@ -75,7 +75,7 @@ def Test_assignment()
|
|||||||
|
|
||||||
# lower case name is OK for a list
|
# lower case name is OK for a list
|
||||||
var lambdaLines =<< trim END
|
var lambdaLines =<< trim END
|
||||||
var lambdaList: list<func> = [Test_syntax]
|
var lambdaList: list<func> = [g:Test_syntax]
|
||||||
lambdaList[0] = () => "lambda"
|
lambdaList[0] = () => "lambda"
|
||||||
END
|
END
|
||||||
v9.CheckDefAndScriptSuccess(lambdaLines)
|
v9.CheckDefAndScriptSuccess(lambdaLines)
|
||||||
@@ -890,7 +890,7 @@ enddef
|
|||||||
|
|
||||||
def Test_assignment_partial()
|
def Test_assignment_partial()
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
var Partial: func(): string = function(PartFuncBool, [true])
|
var Partial: func(): string = function(g:PartFuncBool, [true])
|
||||||
assert_equal('done', Partial())
|
assert_equal('done', Partial())
|
||||||
END
|
END
|
||||||
v9.CheckDefAndScriptSuccess(lines)
|
v9.CheckDefAndScriptSuccess(lines)
|
||||||
@@ -1393,7 +1393,7 @@ def Test_assignment_failure()
|
|||||||
v9.CheckDefFailure(['var name: dict <number>'], 'E1068:')
|
v9.CheckDefFailure(['var name: dict <number>'], 'E1068:')
|
||||||
v9.CheckDefFailure(['var name: dict<number'], 'E1009:')
|
v9.CheckDefFailure(['var name: dict<number'], 'E1009:')
|
||||||
|
|
||||||
assert_fails('s/^/\=Mess()/n', 'E794:')
|
assert_fails('s/^/\=g:Mess()/n', 'E794:')
|
||||||
v9.CheckDefFailure(['var name: dict<number'], 'E1009:')
|
v9.CheckDefFailure(['var name: dict<number'], 'E1009:')
|
||||||
|
|
||||||
v9.CheckDefFailure(['w:foo: number = 10'],
|
v9.CheckDefFailure(['w:foo: number = 10'],
|
||||||
|
@@ -1303,7 +1303,7 @@ def Test_filter()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_filter_wrong_dict_key_type()
|
def Test_filter_wrong_dict_key_type()
|
||||||
assert_fails('Wrong_dict_key_type([1, v:null, 3])', 'E1013:')
|
assert_fails('g:Wrong_dict_key_type([1, v:null, 3])', 'E1013:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_filter_return_type()
|
def Test_filter_return_type()
|
||||||
|
@@ -1324,7 +1324,7 @@ def Test_gdefault_not_used()
|
|||||||
bwipe!
|
bwipe!
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def g:SomeComplFunc(findstart: number, base: string): any
|
def s:SomeComplFunc(findstart: number, base: string): any
|
||||||
if findstart
|
if findstart
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
|
@@ -887,7 +887,7 @@ def Test_disassemble_call_default()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
|
||||||
def HasEval()
|
def s:HasEval()
|
||||||
if has("eval")
|
if has("eval")
|
||||||
echo "yes"
|
echo "yes"
|
||||||
else
|
else
|
||||||
@@ -895,7 +895,7 @@ def HasEval()
|
|||||||
endif
|
endif
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def HasNothing()
|
def s:HasNothing()
|
||||||
if has("nothing")
|
if has("nothing")
|
||||||
echo "yes"
|
echo "yes"
|
||||||
else
|
else
|
||||||
@@ -903,7 +903,7 @@ def HasNothing()
|
|||||||
endif
|
endif
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def HasSomething()
|
def s:HasSomething()
|
||||||
if has("nothing")
|
if has("nothing")
|
||||||
echo "nothing"
|
echo "nothing"
|
||||||
elseif has("something")
|
elseif has("something")
|
||||||
@@ -915,7 +915,7 @@ def HasSomething()
|
|||||||
endif
|
endif
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def HasGuiRunning()
|
def s:HasGuiRunning()
|
||||||
if has("gui_running")
|
if has("gui_running")
|
||||||
echo "yes"
|
echo "yes"
|
||||||
else
|
else
|
||||||
@@ -2487,7 +2487,7 @@ def Test_debug_for()
|
|||||||
res)
|
res)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
func Legacy() dict
|
func s:Legacy() dict
|
||||||
echo 'legacy'
|
echo 'legacy'
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@@ -2501,7 +2501,7 @@ def Test_disassemble_dict_stack()
|
|||||||
assert_match('<SNR>\d*_UseMember\_s*' ..
|
assert_match('<SNR>\d*_UseMember\_s*' ..
|
||||||
'var d = {func: Legacy}\_s*' ..
|
'var d = {func: Legacy}\_s*' ..
|
||||||
'\d PUSHS "func"\_s*' ..
|
'\d PUSHS "func"\_s*' ..
|
||||||
'\d PUSHFUNC "g:Legacy"\_s*' ..
|
'\d PUSHFUNC "<80><fd>R\d\+_Legacy"\_s*' ..
|
||||||
'\d NEWDICT size 1\_s*' ..
|
'\d NEWDICT size 1\_s*' ..
|
||||||
'\d STORE $0\_s*' ..
|
'\d STORE $0\_s*' ..
|
||||||
|
|
||||||
|
@@ -61,12 +61,17 @@ def Test_expr1_trinary()
|
|||||||
var RetThat: func = g:atrue ? RetOne : RetTwo
|
var RetThat: func = g:atrue ? RetOne : RetTwo
|
||||||
assert_equal(function('len'), RetThat)
|
assert_equal(function('len'), RetThat)
|
||||||
|
|
||||||
var X = FuncOne
|
var X = g:FuncOne
|
||||||
var Y = FuncTwo
|
var Y = g:FuncTwo
|
||||||
var Z = g:cond ? FuncOne : FuncTwo
|
var Z = g:cond ? g:FuncOne : g:FuncTwo
|
||||||
assert_equal(123, Z(3))
|
assert_equal(123, Z(3))
|
||||||
END
|
END
|
||||||
v9.CheckDefAndScriptSuccess(lines)
|
v9.CheckDefAndScriptSuccess(lines)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
var Z = g:cond ? FuncOne : FuncTwo
|
||||||
|
END
|
||||||
|
v9.CheckDefAndScriptFailure(lines, ['E1001: Variable not found: FuncOne', 'E121: Undefined variable: FuncTwo'])
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_expr1_trinary_vimscript()
|
def Test_expr1_trinary_vimscript()
|
||||||
@@ -209,9 +214,9 @@ func Test_expr1_trinary_fails()
|
|||||||
|
|
||||||
" missing argument detected even when common type is used
|
" missing argument detected even when common type is used
|
||||||
call v9.CheckDefAndScriptFailure([
|
call v9.CheckDefAndScriptFailure([
|
||||||
\ 'var X = FuncOne',
|
\ 'var X = g:FuncOne',
|
||||||
\ 'var Y = FuncTwo',
|
\ 'var Y = g:FuncTwo',
|
||||||
\ 'var Z = g:cond ? FuncOne : FuncTwo',
|
\ 'var Z = g:cond ? g:FuncOne : g:FuncTwo',
|
||||||
\ 'Z()'], 'E119:', 4)
|
\ 'Z()'], 'E119:', 4)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@@ -2334,7 +2339,7 @@ def Test_expr8_funcref()
|
|||||||
def Test()
|
def Test()
|
||||||
var Ref = g:GlobalFunc
|
var Ref = g:GlobalFunc
|
||||||
assert_equal('global', Ref())
|
assert_equal('global', Ref())
|
||||||
Ref = GlobalFunc
|
Ref = g:GlobalFunc
|
||||||
assert_equal('global', Ref())
|
assert_equal('global', Ref())
|
||||||
|
|
||||||
Ref = s:ScriptFunc
|
Ref = s:ScriptFunc
|
||||||
@@ -3083,12 +3088,12 @@ def Test_expr8_call()
|
|||||||
v9.CheckDefAndScriptFailure(["var Ref = function('len' [1, 2])"], ['E1123:', 'E116:'], 1)
|
v9.CheckDefAndScriptFailure(["var Ref = function('len' [1, 2])"], ['E1123:', 'E116:'], 1)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def g:ExistingGloba(): string
|
def g:ExistingGlobal(): string
|
||||||
return 'existing'
|
return 'existing'
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_expr8_call_global()
|
def Test_expr8_call_global()
|
||||||
assert_equal('existing', g:ExistingGloba())
|
assert_equal('existing', g:ExistingGlobal())
|
||||||
|
|
||||||
def g:DefinedLater(): string
|
def g:DefinedLater(): string
|
||||||
return 'later'
|
return 'later'
|
||||||
|
@@ -340,7 +340,7 @@ enddef
|
|||||||
def Test_return_something()
|
def Test_return_something()
|
||||||
g:ReturnString()->assert_equal('string')
|
g:ReturnString()->assert_equal('string')
|
||||||
g:ReturnNumber()->assert_equal(123)
|
g:ReturnNumber()->assert_equal(123)
|
||||||
assert_fails('ReturnGlobal()', 'E1012: Type mismatch; expected number but got string', '', 1, 'ReturnGlobal')
|
assert_fails('g:ReturnGlobal()', 'E1012: Type mismatch; expected number but got string', '', 1, 'ReturnGlobal')
|
||||||
|
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
@@ -943,7 +943,7 @@ def Test_local_function_shadows_global()
|
|||||||
def g:Func(): string
|
def g:Func(): string
|
||||||
return 'global'
|
return 'global'
|
||||||
enddef
|
enddef
|
||||||
assert_equal('global', Func())
|
assert_equal('global', g:Func())
|
||||||
delfunc g:Func
|
delfunc g:Func
|
||||||
END
|
END
|
||||||
v9.CheckScriptSuccess(lines)
|
v9.CheckScriptSuccess(lines)
|
||||||
@@ -1498,14 +1498,14 @@ enddef
|
|||||||
|
|
||||||
def Test_func_type_varargs()
|
def Test_func_type_varargs()
|
||||||
var RefDefArg: func(?string)
|
var RefDefArg: func(?string)
|
||||||
RefDefArg = FuncOneDefArg
|
RefDefArg = g:FuncOneDefArg
|
||||||
RefDefArg()
|
RefDefArg()
|
||||||
s:value->assert_equal('text')
|
s:value->assert_equal('text')
|
||||||
RefDefArg('some')
|
RefDefArg('some')
|
||||||
s:value->assert_equal('some')
|
s:value->assert_equal('some')
|
||||||
|
|
||||||
var RefDef2Arg: func(?number, ?string): string
|
var RefDef2Arg: func(?number, ?string): string
|
||||||
RefDef2Arg = FuncTwoDefArg
|
RefDef2Arg = g:FuncTwoDefArg
|
||||||
RefDef2Arg()->assert_equal('123text')
|
RefDef2Arg()->assert_equal('123text')
|
||||||
RefDef2Arg(99)->assert_equal('99text')
|
RefDef2Arg(99)->assert_equal('99text')
|
||||||
RefDef2Arg(77, 'some')->assert_equal('77some')
|
RefDef2Arg(77, 'some')->assert_equal('77some')
|
||||||
@@ -1514,7 +1514,7 @@ def Test_func_type_varargs()
|
|||||||
v9.CheckDefFailure(['var RefWrong: func(?string, string)'], 'E1007:')
|
v9.CheckDefFailure(['var RefWrong: func(?string, string)'], 'E1007:')
|
||||||
|
|
||||||
var RefVarargs: func(...list<string>): string
|
var RefVarargs: func(...list<string>): string
|
||||||
RefVarargs = FuncVarargs
|
RefVarargs = g:FuncVarargs
|
||||||
RefVarargs()->assert_equal('')
|
RefVarargs()->assert_equal('')
|
||||||
RefVarargs('one')->assert_equal('one')
|
RefVarargs('one')->assert_equal('one')
|
||||||
RefVarargs('one', 'two')->assert_equal('one,two')
|
RefVarargs('one', 'two')->assert_equal('one,two')
|
||||||
@@ -1721,7 +1721,7 @@ enddef
|
|||||||
|
|
||||||
def Test_error_in_nested_function()
|
def Test_error_in_nested_function()
|
||||||
# Error in called function requires unwinding the call stack.
|
# Error in called function requires unwinding the call stack.
|
||||||
assert_fails('FuncWithForwardCall()', 'E1096:', '', 1, 'FuncWithForwardCall')
|
assert_fails('g:FuncWithForwardCall()', 'E1096:', '', 1, 'FuncWithForwardCall')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_nested_function_with_nextcmd()
|
def Test_nested_function_with_nextcmd()
|
||||||
@@ -2199,7 +2199,7 @@ def Test_func_type()
|
|||||||
s:funcResult->assert_equal(22)
|
s:funcResult->assert_equal(22)
|
||||||
|
|
||||||
s:funcResult = 0
|
s:funcResult = 0
|
||||||
Ref2 = FuncOneArgRetNumber
|
Ref2 = g:FuncOneArgRetNumber
|
||||||
Ref2(13)->assert_equal(13)
|
Ref2(13)->assert_equal(13)
|
||||||
s:funcResult->assert_equal(13)
|
s:funcResult->assert_equal(13)
|
||||||
enddef
|
enddef
|
||||||
@@ -2232,11 +2232,11 @@ def Test_func_type_part()
|
|||||||
RefVoid = g:FuncNoArgNoRet
|
RefVoid = g:FuncNoArgNoRet
|
||||||
RefVoid = g:FuncOneArgNoRet
|
RefVoid = g:FuncOneArgNoRet
|
||||||
v9.CheckDefFailure(['var RefVoid: func: void', 'RefVoid = g:FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...) but got func(): number')
|
v9.CheckDefFailure(['var RefVoid: func: void', 'RefVoid = g:FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...) but got func(): number')
|
||||||
v9.CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...) but got func(): string')
|
v9.CheckDefFailure(['var RefVoid: func: void', 'RefVoid = g:FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...) but got func(): string')
|
||||||
|
|
||||||
var RefAny: func(): any
|
var RefAny: func(): any
|
||||||
RefAny = g:FuncNoArgRetNumber
|
RefAny = g:FuncNoArgRetNumber
|
||||||
RefAny = FuncNoArgRetString
|
RefAny = g:FuncNoArgRetString
|
||||||
v9.CheckDefFailure(['var RefAny: func(): any', 'RefAny = g:FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func()')
|
v9.CheckDefFailure(['var RefAny: func(): any', 'RefAny = g:FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func()')
|
||||||
v9.CheckDefFailure(['var RefAny: func(): any', 'RefAny = g:FuncOneArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func(number)')
|
v9.CheckDefFailure(['var RefAny: func(): any', 'RefAny = g:FuncOneArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func(number)')
|
||||||
|
|
||||||
@@ -2244,12 +2244,12 @@ def Test_func_type_part()
|
|||||||
|
|
||||||
var RefNr: func: number
|
var RefNr: func: number
|
||||||
RefNr = g:FuncNoArgRetNumber
|
RefNr = g:FuncNoArgRetNumber
|
||||||
RefNr = FuncOneArgRetNumber
|
RefNr = g:FuncOneArgRetNumber
|
||||||
v9.CheckDefFailure(['var RefNr: func: number', 'RefNr = g:FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): number but got func()')
|
v9.CheckDefFailure(['var RefNr: func: number', 'RefNr = g:FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): number but got func()')
|
||||||
v9.CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...): number but got func(): string')
|
v9.CheckDefFailure(['var RefNr: func: number', 'RefNr = g:FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...): number but got func(): string')
|
||||||
|
|
||||||
var RefStr: func: string
|
var RefStr: func: string
|
||||||
RefStr = FuncNoArgRetString
|
RefStr = g:FuncNoArgRetString
|
||||||
RefStr = FuncOneArgRetString
|
RefStr = FuncOneArgRetString
|
||||||
v9.CheckDefFailure(['var RefStr: func: string', 'RefStr = g:FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): string but got func()')
|
v9.CheckDefFailure(['var RefStr: func: string', 'RefStr = g:FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): string but got func()')
|
||||||
v9.CheckDefFailure(['var RefStr: func: string', 'RefStr = g:FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...): string but got func(): number')
|
v9.CheckDefFailure(['var RefStr: func: string', 'RefStr = g:FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...): string but got func(): number')
|
||||||
@@ -2260,7 +2260,7 @@ def Test_func_type_fails()
|
|||||||
|
|
||||||
v9.CheckDefFailure(['var Ref1: func()', 'Ref1 = g:FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(): number')
|
v9.CheckDefFailure(['var Ref1: func()', 'Ref1 = g:FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(): number')
|
||||||
v9.CheckDefFailure(['var Ref1: func()', 'Ref1 = g:FuncOneArgNoRet'], 'E1012: Type mismatch; expected func() but got func(number)')
|
v9.CheckDefFailure(['var Ref1: func()', 'Ref1 = g:FuncOneArgNoRet'], 'E1012: Type mismatch; expected func() but got func(number)')
|
||||||
v9.CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(number): number')
|
v9.CheckDefFailure(['var Ref1: func()', 'Ref1 = g:FuncOneArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(number): number')
|
||||||
v9.CheckDefFailure(['var Ref1: func(bool)', 'Ref1 = g:FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(bool) but got func(bool, number)')
|
v9.CheckDefFailure(['var Ref1: func(bool)', 'Ref1 = g:FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(bool) but got func(bool, number)')
|
||||||
v9.CheckDefFailure(['var Ref1: func(?bool)', 'Ref1 = g:FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(?bool) but got func(bool, number)')
|
v9.CheckDefFailure(['var Ref1: func(?bool)', 'Ref1 = g:FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(?bool) but got func(bool, number)')
|
||||||
v9.CheckDefFailure(['var Ref1: func(...bool)', 'Ref1 = g:FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(...bool) but got func(bool, number)')
|
v9.CheckDefFailure(['var Ref1: func(...bool)', 'Ref1 = g:FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(...bool) but got func(bool, number)')
|
||||||
@@ -3355,7 +3355,7 @@ def Test_skip_cmds_with_silent()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_opfunc()
|
def Test_opfunc()
|
||||||
nnoremap <F3> <cmd>set opfunc=Opfunc<cr>g@
|
nnoremap <F3> <cmd>set opfunc=g:Opfunc<cr>g@
|
||||||
def g:Opfunc(_: any): string
|
def g:Opfunc(_: any): string
|
||||||
setline(1, 'ASDF')
|
setline(1, 'ASDF')
|
||||||
return ''
|
return ''
|
||||||
|
@@ -2018,7 +2018,7 @@ def Test_autoload_missing_function_name()
|
|||||||
delete('Xdir', 'rf')
|
delete('Xdir', 'rf')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_autoload_name_wring()
|
def Test_autoload_name_wrong()
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
def Xscriptname#Func()
|
def Xscriptname#Func()
|
||||||
|
@@ -1902,7 +1902,7 @@ find_func_with_prefix(char_u *name, int sid)
|
|||||||
char_u buffer[200];
|
char_u buffer[200];
|
||||||
scriptitem_T *si;
|
scriptitem_T *si;
|
||||||
|
|
||||||
if (vim_strchr(name, AUTOLOAD_CHAR) != 0)
|
if (vim_strchr(name, AUTOLOAD_CHAR) != NULL)
|
||||||
return NULL; // already has the prefix
|
return NULL; // already has the prefix
|
||||||
if (!SCRIPT_ID_VALID(sid))
|
if (!SCRIPT_ID_VALID(sid))
|
||||||
return NULL; // not in a script
|
return NULL; // not in a script
|
||||||
@@ -2004,6 +2004,17 @@ func_is_global(ufunc_T *ufunc)
|
|||||||
return ufunc->uf_name[0] != K_SPECIAL;
|
return ufunc->uf_name[0] != K_SPECIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return TRUE if "ufunc" must be called with a g: prefix in Vim9 script.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
func_requires_g_prefix(ufunc_T *ufunc)
|
||||||
|
{
|
||||||
|
return ufunc->uf_name[0] != K_SPECIAL
|
||||||
|
&& (ufunc->uf_flags & FC_LAMBDA) == 0
|
||||||
|
&& vim_strchr(ufunc->uf_name, AUTOLOAD_CHAR) == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the function name of "fp" to buffer "buf".
|
* Copy the function name of "fp" to buffer "buf".
|
||||||
* "buf" must be able to hold the function name plus three bytes.
|
* "buf" must be able to hold the function name plus three bytes.
|
||||||
@@ -3442,7 +3453,14 @@ call_func(
|
|||||||
* User defined function.
|
* User defined function.
|
||||||
*/
|
*/
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
|
{
|
||||||
fp = find_func(rfname, is_global);
|
fp = find_func(rfname, is_global);
|
||||||
|
if (fp != NULL && !is_global && in_vim9script()
|
||||||
|
&& func_requires_g_prefix(fp))
|
||||||
|
// In Vim9 script g: is required to find a global
|
||||||
|
// non-autoload function.
|
||||||
|
fp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Trigger FuncUndefined event, may load the function.
|
// Trigger FuncUndefined event, may load the function.
|
||||||
if (fp == NULL
|
if (fp == NULL
|
||||||
@@ -3672,6 +3690,7 @@ trans_function_name(
|
|||||||
char_u sid_buf[20];
|
char_u sid_buf[20];
|
||||||
int len;
|
int len;
|
||||||
int extra = 0;
|
int extra = 0;
|
||||||
|
int prefix_g = FALSE;
|
||||||
lval_T lv;
|
lval_T lv;
|
||||||
int vim9script;
|
int vim9script;
|
||||||
|
|
||||||
@@ -3837,8 +3856,20 @@ trans_function_name(
|
|||||||
// skip over "s:" and "g:"
|
// skip over "s:" and "g:"
|
||||||
if (lead == 2 || (lv.ll_name[0] == 'g' && lv.ll_name[1] == ':'))
|
if (lead == 2 || (lv.ll_name[0] == 'g' && lv.ll_name[1] == ':'))
|
||||||
{
|
{
|
||||||
if (is_global != NULL && lv.ll_name[0] == 'g')
|
if (lv.ll_name[0] == 'g')
|
||||||
*is_global = TRUE;
|
{
|
||||||
|
if (is_global != NULL)
|
||||||
|
{
|
||||||
|
*is_global = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// dropping "g:" without setting "is_global" won't work in
|
||||||
|
// Vim9script, put it back later
|
||||||
|
prefix_g = TRUE;
|
||||||
|
extra = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
lv.ll_name += 2;
|
lv.ll_name += 2;
|
||||||
}
|
}
|
||||||
len = (int)(end - lv.ll_name);
|
len = (int)(end - lv.ll_name);
|
||||||
@@ -3919,6 +3950,11 @@ trans_function_name(
|
|||||||
if (vim9script || lead > 3) // If it's "<SID>"
|
if (vim9script || lead > 3) // If it's "<SID>"
|
||||||
STRCPY(name + 3, sid_buf);
|
STRCPY(name + 3, sid_buf);
|
||||||
}
|
}
|
||||||
|
else if (prefix_g)
|
||||||
|
{
|
||||||
|
name[0] = 'g';
|
||||||
|
name[1] = ':';
|
||||||
|
}
|
||||||
mch_memmove(name + lead + extra, lv.ll_name, (size_t)len);
|
mch_memmove(name + lead + extra, lv.ll_name, (size_t)len);
|
||||||
name[lead + extra + len] = NUL;
|
name[lead + extra + len] = NUL;
|
||||||
}
|
}
|
||||||
|
@@ -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 */
|
||||||
|
/**/
|
||||||
|
4260,
|
||||||
/**/
|
/**/
|
||||||
4259,
|
4259,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -349,11 +349,12 @@ compile_load_scriptvar(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
generate_funcref(cctx_T *cctx, char_u *name)
|
generate_funcref(cctx_T *cctx, char_u *name, int has_g_prefix)
|
||||||
{
|
{
|
||||||
ufunc_T *ufunc = find_func(name, FALSE);
|
ufunc_T *ufunc = find_func(name, FALSE);
|
||||||
|
|
||||||
if (ufunc == NULL)
|
// Reject a global non-autoload function found without the "g:" prefix.
|
||||||
|
if (ufunc == NULL || (!has_g_prefix && func_requires_g_prefix(ufunc)))
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
// Need to compile any default values to get the argument types.
|
// Need to compile any default values to get the argument types.
|
||||||
@@ -420,7 +421,7 @@ compile_load(
|
|||||||
break;
|
break;
|
||||||
case 's': if (is_expr && ASCII_ISUPPER(*name)
|
case 's': if (is_expr && ASCII_ISUPPER(*name)
|
||||||
&& find_func(name, FALSE) != NULL)
|
&& find_func(name, FALSE) != NULL)
|
||||||
res = generate_funcref(cctx, name);
|
res = generate_funcref(cctx, name, FALSE);
|
||||||
else
|
else
|
||||||
res = compile_load_scriptvar(cctx, name,
|
res = compile_load_scriptvar(cctx, name,
|
||||||
NULL, &end, error);
|
NULL, &end, error);
|
||||||
@@ -429,7 +430,7 @@ compile_load(
|
|||||||
{
|
{
|
||||||
if (is_expr && ASCII_ISUPPER(*name)
|
if (is_expr && ASCII_ISUPPER(*name)
|
||||||
&& find_func(name, FALSE) != NULL)
|
&& find_func(name, FALSE) != NULL)
|
||||||
res = generate_funcref(cctx, name);
|
res = generate_funcref(cctx, name, TRUE);
|
||||||
else
|
else
|
||||||
isn_type = ISN_LOADG;
|
isn_type = ISN_LOADG;
|
||||||
}
|
}
|
||||||
@@ -505,7 +506,7 @@ compile_load(
|
|||||||
// uppercase letter it can be a user defined function.
|
// uppercase letter it can be a user defined function.
|
||||||
// generate_funcref() will fail if the function can't be found.
|
// generate_funcref() will fail if the function can't be found.
|
||||||
if (res == FAIL && is_expr && ASCII_ISUPPER(*name))
|
if (res == FAIL && is_expr && ASCII_ISUPPER(*name))
|
||||||
res = generate_funcref(cctx, name);
|
res = generate_funcref(cctx, name, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gen_load)
|
if (gen_load)
|
||||||
@@ -812,7 +813,7 @@ compile_call(
|
|||||||
|
|
||||||
// If the name is a variable, load it and use PCALL.
|
// If the name is a variable, load it and use PCALL.
|
||||||
// Not for g:Func(), we don't know if it is a variable or not.
|
// Not for g:Func(), we don't know if it is a variable or not.
|
||||||
// Not for eome#Func(), it will be loaded later.
|
// Not for some#Func(), it will be loaded later.
|
||||||
p = namebuf;
|
p = namebuf;
|
||||||
if (!has_g_namespace && !is_autoload
|
if (!has_g_namespace && !is_autoload
|
||||||
&& compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK)
|
&& compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK)
|
||||||
|
Reference in New Issue
Block a user