mirror of
https://github.com/vim/vim.git
synced 2026-05-28 00:21:37 +02:00
patch 9.1.2106: Vim9: class, enum and type alias can be used as value
Problem: Vim9: class, enum and type alias can be used as value in an
expression (kennypete)
Solution: Abort expression evaluation if class, enum or type alias is
used in an expression (Yegappan Lakshmanan)
related: #19173
closes: #19238
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
2b6bdbc697
commit
7d22f84f0b
+16
@@ -3646,7 +3646,15 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
int error = FALSE;
|
||||
|
||||
if (op_falsy)
|
||||
{
|
||||
// Is this typeval supported with the falsy operator?
|
||||
if (check_typval_is_value(rettv) == FAIL)
|
||||
{
|
||||
clear_tv(rettv);
|
||||
return FAIL;
|
||||
}
|
||||
result = tv2bool(rettv);
|
||||
}
|
||||
else if (vim9script)
|
||||
result = tv_get_bool_chk(rettv, &error);
|
||||
else if (tv_get_number_chk(rettv, &error) != 0)
|
||||
@@ -5376,7 +5384,15 @@ eval9_leader(
|
||||
while (VIM_ISWHITE(end_leader[-1]))
|
||||
--end_leader;
|
||||
if (vim9script && end_leader[-1] == '!')
|
||||
{
|
||||
// Is this typeval supported with the ! operator?
|
||||
if (check_typval_is_value(rettv) == FAIL)
|
||||
{
|
||||
clear_tv(rettv);
|
||||
return FAIL;
|
||||
}
|
||||
val = tv2bool(rettv);
|
||||
}
|
||||
else
|
||||
val = tv_get_number_chk(rettv, &error);
|
||||
}
|
||||
|
||||
@@ -280,6 +280,69 @@ def Test_expr1_falsy()
|
||||
END
|
||||
v9.CheckSourceScriptFailure(lines, 'E1405: Class "B" cannot be used as a value')
|
||||
|
||||
# Expression evaluation should stop after using a class with the falsy
|
||||
# operator
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
var output: string = 'pass'
|
||||
try
|
||||
echo C ?? 'falsy' !! execute("output = 'fail'")
|
||||
catch /E1405:/
|
||||
endtry
|
||||
assert_equal('pass', output)
|
||||
END
|
||||
v9.CheckSourceScriptSuccess(lines)
|
||||
|
||||
# When using a class with the falsy operator, expression evaluation should
|
||||
# be aborted in a function
|
||||
g:falsy_output = 'pass'
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
g:falsy_output = 'pass'
|
||||
def Fn()
|
||||
echo C ?? 'falsy' !! execute('g:falsy_output = "fail"')
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value', 1)
|
||||
assert_equal('pass', g:falsy_output)
|
||||
unlet g:falsy_output
|
||||
|
||||
# When using a class with the "!" operator, expression evaluation should be
|
||||
# aborted
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
var output: string = 'pass'
|
||||
try
|
||||
echo !C !! execute("output = 'fail'")
|
||||
catch /E1405:/
|
||||
endtry
|
||||
assert_equal('pass', output)
|
||||
END
|
||||
v9.CheckSourceScriptSuccess(lines)
|
||||
|
||||
# When using a class with the "!" operator, expression evaluation should be
|
||||
# aborted in a function
|
||||
g:falsy_output = 'pass'
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
def Fn()
|
||||
echo !C !! execute('g:falsy_output = "fail"')
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value', 1)
|
||||
assert_equal('pass', g:falsy_output)
|
||||
unlet g:falsy_output
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
echo null_class ?? 'falsy'
|
||||
@@ -309,6 +372,68 @@ def Test_expr1_falsy()
|
||||
END
|
||||
v9.CheckSourceScriptFailure(lines, 'E1421: Enum "E2" cannot be used as a value')
|
||||
|
||||
# Expression evaluation should stop after using an enum with the falsy
|
||||
# operator
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
enum E
|
||||
endenum
|
||||
var output: string = 'pass'
|
||||
try
|
||||
echo E ?? 'falsy' !! execute("output = 'fail'")
|
||||
catch /E1421:/
|
||||
endtry
|
||||
assert_equal('pass', output)
|
||||
END
|
||||
v9.CheckSourceScriptSuccess(lines)
|
||||
|
||||
# When using a enum with the falsy operator, expression evaluation should
|
||||
# be aborted in a function
|
||||
g:falsy_output = 'pass'
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
enum E3
|
||||
endenum
|
||||
g:falsy_output = 'pass'
|
||||
def Fn()
|
||||
echo E3 ?? 'falsy' !! execute('g:falsy_output = "fail"')
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceScriptFailure(lines, 'E1421: Enum "E3" cannot be used as a value', 1)
|
||||
assert_equal('pass', g:falsy_output)
|
||||
unlet g:falsy_output
|
||||
|
||||
# Expression evaluation should stop after using an enum with the ! operator
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
enum E
|
||||
endenum
|
||||
var output: string = 'pass'
|
||||
try
|
||||
echo !E !! execute("output = 'fail'")
|
||||
catch /E1421:/
|
||||
endtry
|
||||
assert_equal('pass', output)
|
||||
END
|
||||
v9.CheckSourceScriptSuccess(lines)
|
||||
|
||||
# When using a enum with the "!" operator, expression evaluation should be
|
||||
# aborted in a function
|
||||
g:falsy_output = 'pass'
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
enum E4
|
||||
endenum
|
||||
def Fn()
|
||||
echo !E4 !! execute('g:falsy_output = "fail"')
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceScriptFailure(lines, 'E1421: Enum "E4" cannot be used as a value', 1)
|
||||
assert_equal('pass', g:falsy_output)
|
||||
unlet g:falsy_output
|
||||
|
||||
# typealias cannot be used with the falsy operator
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
@@ -324,6 +449,65 @@ def Test_expr1_falsy()
|
||||
END
|
||||
v9.CheckSourceScriptFailure(lines, 'E1403: Type alias "T2" cannot be used as a value')
|
||||
|
||||
# Expression evaluation should stop after using a typealias with the falsy
|
||||
# operator
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T3 = dict<string>
|
||||
var output: string = 'pass'
|
||||
try
|
||||
echo T3 ?? 'falsy' !! execute("output = 'fail'")
|
||||
catch /E1403:/
|
||||
endtry
|
||||
assert_equal('pass', output)
|
||||
END
|
||||
v9.CheckSourceScriptSuccess(lines)
|
||||
|
||||
# When using a typealias with the falsy operator, expression evaluation
|
||||
# should be aborted in a function
|
||||
g:falsy_output = 'pass'
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T3 = dict<job>
|
||||
g:falsy_output = 'pass'
|
||||
def Fn()
|
||||
echo T3 ?? 'falsy' !! execute('g:falsy_output = "fail"')
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value', 1)
|
||||
assert_equal('pass', g:falsy_output)
|
||||
unlet g:falsy_output
|
||||
|
||||
# Expression evaluation should stop after using a typealias with the !
|
||||
# operator
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T3 = dict<string>
|
||||
var output: string = 'pass'
|
||||
try
|
||||
echo !T3 !! execute("output = 'fail'")
|
||||
catch /E1403:/
|
||||
endtry
|
||||
assert_equal('pass', output)
|
||||
END
|
||||
v9.CheckSourceScriptSuccess(lines)
|
||||
|
||||
# When using a typealias with the "!" operator, expression evaluation should
|
||||
# be aborted in a function
|
||||
g:falsy_output = 'pass'
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T4 = list<number>
|
||||
def Fn()
|
||||
echo !T4 !! execute('g:falsy_output = "fail"')
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value', 1)
|
||||
assert_equal('pass', g:falsy_output)
|
||||
unlet g:falsy_output
|
||||
|
||||
var msg = "White space required before and after '??'"
|
||||
call v9.CheckDefAndScriptFailure(["var x = 1?? 'one' : 'two'"], msg, 1)
|
||||
call v9.CheckDefAndScriptFailure(["var x = 1 ??'one' : 'two'"], msg, 1)
|
||||
|
||||
@@ -734,6 +734,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2106,
|
||||
/**/
|
||||
2105,
|
||||
/**/
|
||||
|
||||
@@ -2430,6 +2430,8 @@ compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end)
|
||||
invert = !invert;
|
||||
--p;
|
||||
}
|
||||
if (check_type_is_value(get_type_on_stack(cctx, 0)) == FAIL)
|
||||
return FAIL;
|
||||
if (generate_2BOOL(cctx, invert, -1) == FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
@@ -3948,7 +3950,11 @@ compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
generate_JUMP(cctx, op_falsy
|
||||
? JUMP_AND_KEEP_IF_TRUE : JUMP_IF_FALSE, 0);
|
||||
if (op_falsy)
|
||||
{
|
||||
type1 = get_type_on_stack(cctx, -1);
|
||||
if (check_type_is_value(type1) == FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate the second expression; any type is accepted
|
||||
|
||||
Reference in New Issue
Block a user