From 09eefbe92ce83e81b6e9c80681152a41ed011d56 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sun, 4 Jun 2017 22:19:43 -0400 Subject: vim-patch:8.0.0156 Problem: Several float functions are not covered by tests. Solution: Add float tests. (Dominique Pelle) https://github.com/vim/vim/commit/453b576ee5d32e9b8e6876712748ae01f9be68dd --- src/nvim/testdir/test_alot.vim | 1 + src/nvim/testdir/test_float_func.vim | 228 +++++++++++++++++++++++++++++++++++ 2 files changed, 229 insertions(+) create mode 100644 src/nvim/testdir/test_float_func.vim diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 5da9a8b0f4..a250ba7493 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -10,6 +10,7 @@ source test_expr_utf8.vim source test_feedkeys.vim source test_filter_cmd.vim source test_filter_map.vim +source test_float_func.vim source test_goto.vim source test_jumps.vim source test_lambda.vim diff --git a/src/nvim/testdir/test_float_func.vim b/src/nvim/testdir/test_float_func.vim new file mode 100644 index 0000000000..57ab9bac99 --- /dev/null +++ b/src/nvim/testdir/test_float_func.vim @@ -0,0 +1,228 @@ +" test float functions + +if !has('float') + finish +end + +func Test_abs() + call assert_equal(string(abs(1.23)), '1.23') + call assert_equal(string(abs(-1.23)), '1.23') + call assert_equal(string(abs(0.0)), '0.0') + call assert_equal(string(abs(1.0/(1.0/0.0))), '0.0') + call assert_equal(string(abs(-1.0/(1.0/0.0))), '0.0') + call assert_equal(string(abs(1.0/0.0)), "str2float('inf')") + call assert_equal(string(abs(-1.0/0.0)), "str2float('inf')") + call assert_equal(string(abs(0.0/0.0)), "str2float('nan')") +endfunc + +func Test_sqrt() + call assert_equal(string(sqrt(0.0)), '0.0') + call assert_equal(string(sqrt(2.0)), '1.414214') + call assert_equal(string(sqrt(1.0/0.0)), "str2float('inf')") + call assert_equal(string(sqrt(-1.0)), "str2float('nan')") + call assert_equal(string(sqrt(0.0/0.0)), "str2float('nan')") +endfunc + +func Test_log() + call assert_equal(string(log(1.0)), '0.0') + call assert_equal(string(log(0.5)), '-0.693147') + call assert_equal(string(log(0.0)), "-str2float('inf')") + call assert_equal(string(log(-1.0)), "str2float('nan')") + call assert_equal(string(log(1.0/0.0)), "str2float('inf')") + call assert_equal(string(log(0.0/0.0)), "str2float('nan')") +endfunc + +func Test_log10() + call assert_equal(string(log10(1.0)), '0.0') + call assert_equal(string(log10(100.0)), '2.0') + call assert_equal(string(log10(120.0)), '2.079181') + call assert_equal(string(log10(0.0)), "-str2float('inf')") + call assert_equal(string(log10(-1.0)), "str2float('nan')") + call assert_equal(string(log10(1.0/0.0)), "str2float('inf')") + call assert_equal(string(log10(0.0/0.0)), "str2float('nan')") +endfunc + +func Test_exp() + call assert_equal(string(exp(0.0)), '1.0') + call assert_equal(string(exp(2.0)), '7.389056') + call assert_equal(string(exp(-1.0)),'0.367879') + call assert_equal(string(exp(1.0/0.0)), "str2float('inf')") + call assert_equal(string(exp(-1.0/0.0)), '0.0') + call assert_equal(string(exp(0.0/0.0)), "str2float('nan')") +endfunc + +func Test_sin() + call assert_equal(string(sin(0.0)), '0.0') + call assert_equal(string(sin(1.0)), '0.841471') + call assert_equal(string(sin(-0.5)), '-0.479426') + call assert_equal(string(sin(0.0/0.0)), "str2float('nan')") + call assert_equal(string(sin(1.0/0.0)), "str2float('nan')") + call assert_equal(string(sin(1.0/(1.0/0.0))), '0.0') + call assert_equal(string(sin(-1.0/(1.0/0.0))), '-0.0') +endfunc + +func Test_asin() + call assert_equal(string(asin(0.0)), '0.0') + call assert_equal(string(asin(1.0)), '1.570796') + call assert_equal(string(asin(-0.5)), '-0.523599') + call assert_equal(string(asin(1.1)), "str2float('nan')") + call assert_equal(string(asin(1.0/0.0)), "str2float('nan')") + call assert_equal(string(asin(0.0/0.0)), "str2float('nan')") +endfunc + +func Test_sinh() + call assert_equal(string(sinh(0.0)), '0.0') + call assert_equal(string(sinh(0.5)), '0.521095') + call assert_equal(string(sinh(-0.9)), '-1.026517') + call assert_equal(string(sinh(1.0/0.0)), "str2float('inf')") + call assert_equal(string(sinh(-1.0/0.0)), "-str2float('inf')") + call assert_equal(string(sinh(0.0/0.0)), "str2float('nan')") +endfunc + +func Test_cos() + call assert_equal(string(cos(0.0)), '1.0') + call assert_equal(string(cos(1.0)), '0.540302') + call assert_equal(string(cos(-0.5)), '0.877583') + call assert_equal(string(cos(0.0/0.0)), "str2float('nan')") + call assert_equal(string(cos(1.0/0.0)), "str2float('nan')") +endfunc + +func Test_acos() + call assert_equal(string(acos(0.0)), '1.570796') + call assert_equal(string(acos(1.0)), '0.0') + call assert_equal(string(acos(-1.0)), '3.141593') + call assert_equal(string(acos(-0.5)), '2.094395') + call assert_equal(string(acos(1.1)), "str2float('nan')") + call assert_equal(string(acos(1.0/0.0)), "str2float('nan')") + call assert_equal(string(acos(0.0/0.0)), "str2float('nan')") +endfunc + +func Test_cosh() + call assert_equal(string(cosh(0.0)), '1.0') + call assert_equal(string(cosh(0.5)), '1.127626') + call assert_equal(string(cosh(1.0/0.0)), "str2float('inf')") + call assert_equal(string(cosh(-1.0/0.0)), "str2float('inf')") + call assert_equal(string(cosh(0.0/0.0)), "str2float('nan')") +endfunc + +func Test_tan() + call assert_equal(string(tan(0.0)), '0.0') + call assert_equal(string(tan(0.5)), '0.546302') + call assert_equal(string(tan(-0.5)), '-0.546302') + call assert_equal(string(tan(1.0/0.0)), "str2float('nan')") + call assert_equal(string(cos(0.0/0.0)), "str2float('nan')") + call assert_equal(string(tan(1.0/(1.0/0.0))), '0.0') + call assert_equal(string(tan(-1.0/(1.0/0.0))), '-0.0') +endfunc + +func Test_atan() + call assert_equal(string(atan(0.0)), '0.0') + call assert_equal(string(atan(0.5)), '0.463648') + call assert_equal(string(atan(-1.0)), '-0.785398') + call assert_equal(string(atan(1.0/0.0)), '1.570796') + call assert_equal(string(atan(-1.0/0.0)), '-1.570796') + call assert_equal(string(atan(0.0/0.0)), "str2float('nan')") +endfunc + +func Test_atan2() + call assert_equal(string(atan2(-1, -1)), '-2.356194') + call assert_equal(string(atan2(1, -1)), '2.356194') + call assert_equal(string(atan2(1.0, 1.0/0.0)), '0.0') + call assert_equal(string(atan2(1.0/0.0, 1.0)), '1.570796') + call assert_equal(string(atan2(0.0/0.0, 1.0)), "str2float('nan')") +endfunc + +func Test_tanh() + call assert_equal(string(tanh(0.0)), '0.0') + call assert_equal(string(tanh(0.5)), '0.462117') + call assert_equal(string(tanh(-1.0)), '-0.761594') + call assert_equal(string(tanh(1.0/0.0)), '1.0') + call assert_equal(string(tanh(-1.0/0.0)), '-1.0') + call assert_equal(string(tanh(0.0/0.0)), "str2float('nan')") +endfunc + +func Test_fmod() + call assert_equal(string(fmod(12.33, 1.22)), '0.13') + call assert_equal(string(fmod(-12.33, 1.22)), '-0.13') + call assert_equal(string(fmod(1.0/0.0, 1.0)), "str2float('nan')") + call assert_equal(string(fmod(1.0, 1.0/0.0)), '1.0') + call assert_equal(string(fmod(1.0, 0.0)), "str2float('nan')") +endfunc + +func Test_pow() + call assert_equal(string(pow(0.0, 0.0)), '1.0') + call assert_equal(string(pow(2.0, 3.0)), '8.0') + call assert_equal(string(pow(2.0, 0.0/0.0)), "str2float('nan')") + call assert_equal(string(pow(0.0/0.0, 3.0)), "str2float('nan')") + call assert_equal(string(pow(0.0/0.0, 3.0)), "str2float('nan')") + call assert_equal(string(pow(2.0, 1.0/0.0)), "str2float('inf')") + call assert_equal(string(pow(1.0/0.0, 3.0)), "str2float('inf')") +endfunc + +func Test_str2float() + call assert_equal(string(str2float('1')), '1.0') + call assert_equal(string(str2float('1.23')), '1.23') + call assert_equal(string(str2float('1.23abc')), '1.23') + call assert_equal(string(str2float('1e40')), '1.0e40') + call assert_equal(string(str2float('1e1000')), "str2float('inf')") + call assert_equal(string(str2float('inf')), "str2float('inf')") + call assert_equal(string(str2float('-inf')), "-str2float('inf')") + call assert_equal(string(str2float('Inf')), "str2float('inf')") + call assert_equal(string(str2float('nan')), "str2float('nan')") + call assert_equal(string(str2float('NaN')), "str2float('nan')") +endfunc + +func Test_floor() + call assert_equal(string(floor(2.0)), '2.0') + call assert_equal(string(floor(2.11)), '2.0') + call assert_equal(string(floor(2.99)), '2.0') + call assert_equal(string(floor(-2.11)), '-3.0') + call assert_equal(string(floor(-2.99)), '-3.0') + call assert_equal(string(floor(0.0/0.0)), "str2float('nan')") + call assert_equal(string(floor(1.0/0.0)), "str2float('inf')") + call assert_equal(string(floor(-1.0/0.0)), "-str2float('inf')") +endfunc + +func Test_ceil() + call assert_equal(string(ceil(2.0)), '2.0') + call assert_equal(string(ceil(2.11)), '3.0') + call assert_equal(string(ceil(2.99)), '3.0') + call assert_equal(string(ceil(-2.11)), '-2.0') + call assert_equal(string(ceil(-2.99)), '-2.0') + call assert_equal(string(ceil(0.0/0.0)), "str2float('nan')") + call assert_equal(string(ceil(1.0/0.0)), "str2float('inf')") + call assert_equal(string(ceil(-1.0/0.0)), "-str2float('inf')") +endfunc + +func Test_round() + call assert_equal(string(round(2.1)), '2.0') + call assert_equal(string(round(2.5)), '3.0') + call assert_equal(string(round(2.9)), '3.0') + call assert_equal(string(round(-2.1)), '-2.0') + call assert_equal(string(round(-2.5)), '-3.0') + call assert_equal(string(round(-2.9)), '-3.0') + call assert_equal(string(round(0.0/0.0)), "str2float('nan')") + call assert_equal(string(round(1.0/0.0)), "str2float('inf')") + call assert_equal(string(round(-1.0/0.0)), "-str2float('inf')") +endfunc + +func Test_trunc() + call assert_equal(string(trunc(2.1)), '2.0') + call assert_equal(string(trunc(2.5)), '2.0') + call assert_equal(string(trunc(2.9)), '2.0') + call assert_equal(string(trunc(-2.1)), '-2.0') + call assert_equal(string(trunc(-2.5)), '-2.0') + call assert_equal(string(trunc(-2.9)), '-2.0') + call assert_equal(string(trunc(0.0/0.0)), "str2float('nan')") + call assert_equal(string(trunc(1.0/0.0)), "str2float('inf')") + call assert_equal(string(trunc(-1.0/0.0)), "-str2float('inf')") +endfunc + +func Test_isnan() + throw 'skipped: Nvim does not support isnan()' + call assert_equal(isnan(1.0), 0) + call assert_equal(isnan(0.0/0.0), 1) + call assert_equal(isnan(1.0/0.0), 0) + call assert_equal(isnan('a'), 0) + call assert_equal(isnan([]), 0) +endfunc -- cgit From b1d4ef2b420b1fa9826a9e79344adaf71ad27e18 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 5 Jun 2017 21:58:33 -0400 Subject: vim-patch:8.0.0158 Problem: On MS-Windows some float functions return a different value when passed unusual values. strtod() doesn't work for "inf" and "nan". Solution: Accept both results. Fix str2float() for MS-Windows. Also reorder assert function arguments. https://github.com/vim/vim/commit/6247361101dcccc0c877e90ad67cd0cc83df7c68 --- src/nvim/eval.c | 13 ++ src/nvim/testdir/test_float_func.vim | 310 ++++++++++++++++++----------------- 2 files changed, 170 insertions(+), 153 deletions(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index c9da08acd0..612c3be368 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5898,6 +5898,19 @@ size_t string2float(const char *const text, float_T *const ret_value) { char *s = NULL; + // MS-Windows does not deal with "inf" and "nan" properly + if (STRNICMP(text, "inf", 3) == 0) { + *ret_value = INFINITY; + return 3; + } + if (STRNICMP(text, "-inf", 3) == 0) { + *ret_value = -INFINITY; + return 4; + } + if (STRNICMP(text, "nan", 3) == 0) { + *ret_value = NAN; + return 3; + } *ret_value = strtod(text, &s); return (size_t) (s - text); } diff --git a/src/nvim/testdir/test_float_func.vim b/src/nvim/testdir/test_float_func.vim index 57ab9bac99..8600ce5b60 100644 --- a/src/nvim/testdir/test_float_func.vim +++ b/src/nvim/testdir/test_float_func.vim @@ -5,224 +5,228 @@ if !has('float') end func Test_abs() - call assert_equal(string(abs(1.23)), '1.23') - call assert_equal(string(abs(-1.23)), '1.23') - call assert_equal(string(abs(0.0)), '0.0') - call assert_equal(string(abs(1.0/(1.0/0.0))), '0.0') - call assert_equal(string(abs(-1.0/(1.0/0.0))), '0.0') - call assert_equal(string(abs(1.0/0.0)), "str2float('inf')") - call assert_equal(string(abs(-1.0/0.0)), "str2float('inf')") - call assert_equal(string(abs(0.0/0.0)), "str2float('nan')") + call assert_equal('1.23', string(abs(1.23))) + call assert_equal('1.23', string(abs(-1.23))) + call assert_equal('0.0', string(abs(0.0))) + call assert_equal('0.0', string(abs(1.0/(1.0/0.0)))) + call assert_equal('0.0', string(abs(-1.0/(1.0/0.0)))) + call assert_equal("str2float('inf')", string(abs(1.0/0.0))) + call assert_equal("str2float('inf')", string(abs(-1.0/0.0))) + call assert_equal("str2float('nan')", string(abs(0.0/0.0))) endfunc func Test_sqrt() - call assert_equal(string(sqrt(0.0)), '0.0') - call assert_equal(string(sqrt(2.0)), '1.414214') - call assert_equal(string(sqrt(1.0/0.0)), "str2float('inf')") - call assert_equal(string(sqrt(-1.0)), "str2float('nan')") - call assert_equal(string(sqrt(0.0/0.0)), "str2float('nan')") + call assert_equal('0.0', string(sqrt(0.0))) + call assert_equal('1.414214', string(sqrt(2.0))) + call assert_equal("str2float('inf')", string(sqrt(1.0/0.0))) + call assert_equal("str2float('nan')", string(sqrt(-1.0))) + call assert_equal("str2float('nan')", string(sqrt(0.0/0.0))) endfunc func Test_log() - call assert_equal(string(log(1.0)), '0.0') - call assert_equal(string(log(0.5)), '-0.693147') - call assert_equal(string(log(0.0)), "-str2float('inf')") - call assert_equal(string(log(-1.0)), "str2float('nan')") - call assert_equal(string(log(1.0/0.0)), "str2float('inf')") - call assert_equal(string(log(0.0/0.0)), "str2float('nan')") + call assert_equal('0.0', string(log(1.0))) + call assert_equal('-0.693147', string(log(0.5))) + call assert_equal("-str2float('inf')", string(log(0.0))) + call assert_equal("str2float('nan')", string(log(-1.0))) + call assert_equal("str2float('inf')", string(log(1.0/0.0))) + call assert_equal("str2float('nan')", string(log(0.0/0.0))) endfunc func Test_log10() - call assert_equal(string(log10(1.0)), '0.0') - call assert_equal(string(log10(100.0)), '2.0') - call assert_equal(string(log10(120.0)), '2.079181') - call assert_equal(string(log10(0.0)), "-str2float('inf')") - call assert_equal(string(log10(-1.0)), "str2float('nan')") - call assert_equal(string(log10(1.0/0.0)), "str2float('inf')") - call assert_equal(string(log10(0.0/0.0)), "str2float('nan')") + call assert_equal('0.0', string(log10(1.0))) + call assert_equal('2.0', string(log10(100.0))) + call assert_equal('2.079181', string(log10(120.0))) + call assert_equal("-str2float('inf')", string(log10(0.0))) + call assert_equal("str2float('nan')", string(log10(-1.0))) + call assert_equal("str2float('inf')", string(log10(1.0/0.0))) + call assert_equal("str2float('nan')", string(log10(0.0/0.0))) endfunc func Test_exp() - call assert_equal(string(exp(0.0)), '1.0') - call assert_equal(string(exp(2.0)), '7.389056') - call assert_equal(string(exp(-1.0)),'0.367879') - call assert_equal(string(exp(1.0/0.0)), "str2float('inf')") - call assert_equal(string(exp(-1.0/0.0)), '0.0') - call assert_equal(string(exp(0.0/0.0)), "str2float('nan')") + call assert_equal('1.0', string(exp(0.0))) + call assert_equal('7.389056', string(exp(2.0))) + call assert_equal('0.367879', string(exp(-1.0))) + call assert_equal("str2float('inf')", string(exp(1.0/0.0))) + call assert_equal('0.0', string(exp(-1.0/0.0))) + call assert_equal("str2float('nan')", string(exp(0.0/0.0))) endfunc func Test_sin() - call assert_equal(string(sin(0.0)), '0.0') - call assert_equal(string(sin(1.0)), '0.841471') - call assert_equal(string(sin(-0.5)), '-0.479426') - call assert_equal(string(sin(0.0/0.0)), "str2float('nan')") - call assert_equal(string(sin(1.0/0.0)), "str2float('nan')") - call assert_equal(string(sin(1.0/(1.0/0.0))), '0.0') - call assert_equal(string(sin(-1.0/(1.0/0.0))), '-0.0') + call assert_equal('0.0', string(sin(0.0))) + call assert_equal('0.841471', string(sin(1.0))) + call assert_equal('-0.479426', string(sin(-0.5))) + call assert_equal("str2float('nan')", string(sin(0.0/0.0))) + call assert_equal("str2float('nan')", string(sin(1.0/0.0))) + call assert_equal('0.0', string(sin(1.0/(1.0/0.0)))) + call assert_equal('-0.0', string(sin(-1.0/(1.0/0.0)))) endfunc func Test_asin() - call assert_equal(string(asin(0.0)), '0.0') - call assert_equal(string(asin(1.0)), '1.570796') - call assert_equal(string(asin(-0.5)), '-0.523599') - call assert_equal(string(asin(1.1)), "str2float('nan')") - call assert_equal(string(asin(1.0/0.0)), "str2float('nan')") - call assert_equal(string(asin(0.0/0.0)), "str2float('nan')") + call assert_equal('0.0', string(asin(0.0))) + call assert_equal('1.570796', string(asin(1.0))) + call assert_equal('-0.523599', string(asin(-0.5))) + call assert_equal("str2float('nan')", string(asin(1.1))) + call assert_equal("str2float('nan')", string(asin(1.0/0.0))) + call assert_equal("str2float('nan')", string(asin(0.0/0.0))) endfunc func Test_sinh() - call assert_equal(string(sinh(0.0)), '0.0') - call assert_equal(string(sinh(0.5)), '0.521095') - call assert_equal(string(sinh(-0.9)), '-1.026517') - call assert_equal(string(sinh(1.0/0.0)), "str2float('inf')") - call assert_equal(string(sinh(-1.0/0.0)), "-str2float('inf')") - call assert_equal(string(sinh(0.0/0.0)), "str2float('nan')") + call assert_equal('0.0', string(sinh(0.0))) + call assert_equal('0.521095', string(sinh(0.5))) + call assert_equal('-1.026517', string(sinh(-0.9))) + call assert_equal("str2float('inf')", string(sinh(1.0/0.0))) + call assert_equal("-str2float('inf')", string(sinh(-1.0/0.0))) + call assert_equal("str2float('nan')", string(sinh(0.0/0.0))) endfunc func Test_cos() - call assert_equal(string(cos(0.0)), '1.0') - call assert_equal(string(cos(1.0)), '0.540302') - call assert_equal(string(cos(-0.5)), '0.877583') - call assert_equal(string(cos(0.0/0.0)), "str2float('nan')") - call assert_equal(string(cos(1.0/0.0)), "str2float('nan')") + call assert_equal('1.0', string(cos(0.0))) + call assert_equal('0.540302', string(cos(1.0))) + call assert_equal('0.877583', string(cos(-0.5))) + call assert_equal("str2float('nan')", string(cos(0.0/0.0))) + call assert_equal("str2float('nan')", string(cos(1.0/0.0))) endfunc func Test_acos() - call assert_equal(string(acos(0.0)), '1.570796') - call assert_equal(string(acos(1.0)), '0.0') - call assert_equal(string(acos(-1.0)), '3.141593') - call assert_equal(string(acos(-0.5)), '2.094395') - call assert_equal(string(acos(1.1)), "str2float('nan')") - call assert_equal(string(acos(1.0/0.0)), "str2float('nan')") - call assert_equal(string(acos(0.0/0.0)), "str2float('nan')") + call assert_equal('1.570796', string(acos(0.0))) + call assert_equal('0.0', string(acos(1.0))) + call assert_equal('3.141593', string(acos(-1.0))) + call assert_equal('2.094395', string(acos(-0.5))) + call assert_equal("str2float('nan')", string(acos(1.1))) + call assert_equal("str2float('nan')", string(acos(1.0/0.0))) + call assert_equal("str2float('nan')", string(acos(0.0/0.0))) endfunc func Test_cosh() - call assert_equal(string(cosh(0.0)), '1.0') - call assert_equal(string(cosh(0.5)), '1.127626') - call assert_equal(string(cosh(1.0/0.0)), "str2float('inf')") - call assert_equal(string(cosh(-1.0/0.0)), "str2float('inf')") - call assert_equal(string(cosh(0.0/0.0)), "str2float('nan')") + call assert_equal('1.0', string(cosh(0.0))) + call assert_equal('1.127626', string(cosh(0.5))) + call assert_equal("str2float('inf')", string(cosh(1.0/0.0))) + call assert_equal("str2float('inf')", string(cosh(-1.0/0.0))) + call assert_equal("str2float('nan')", string(cosh(0.0/0.0))) endfunc func Test_tan() - call assert_equal(string(tan(0.0)), '0.0') - call assert_equal(string(tan(0.5)), '0.546302') - call assert_equal(string(tan(-0.5)), '-0.546302') - call assert_equal(string(tan(1.0/0.0)), "str2float('nan')") - call assert_equal(string(cos(0.0/0.0)), "str2float('nan')") - call assert_equal(string(tan(1.0/(1.0/0.0))), '0.0') - call assert_equal(string(tan(-1.0/(1.0/0.0))), '-0.0') + call assert_equal('0.0', string(tan(0.0))) + call assert_equal('0.546302', string(tan(0.5))) + call assert_equal('-0.546302', string(tan(-0.5))) + call assert_equal("str2float('nan')", string(tan(1.0/0.0))) + call assert_equal("str2float('nan')", string(cos(0.0/0.0))) + call assert_equal('0.0', string(tan(1.0/(1.0/0.0)))) + call assert_equal('-0.0', string(tan(-1.0/(1.0/0.0)))) endfunc func Test_atan() - call assert_equal(string(atan(0.0)), '0.0') - call assert_equal(string(atan(0.5)), '0.463648') - call assert_equal(string(atan(-1.0)), '-0.785398') - call assert_equal(string(atan(1.0/0.0)), '1.570796') - call assert_equal(string(atan(-1.0/0.0)), '-1.570796') - call assert_equal(string(atan(0.0/0.0)), "str2float('nan')") + call assert_equal('0.0', string(atan(0.0))) + call assert_equal('0.463648', string(atan(0.5))) + call assert_equal('-0.785398', string(atan(-1.0))) + call assert_equal('1.570796', string(atan(1.0/0.0))) + call assert_equal('-1.570796', string(atan(-1.0/0.0))) + call assert_equal("str2float('nan')", string(atan(0.0/0.0))) endfunc func Test_atan2() - call assert_equal(string(atan2(-1, -1)), '-2.356194') - call assert_equal(string(atan2(1, -1)), '2.356194') - call assert_equal(string(atan2(1.0, 1.0/0.0)), '0.0') - call assert_equal(string(atan2(1.0/0.0, 1.0)), '1.570796') - call assert_equal(string(atan2(0.0/0.0, 1.0)), "str2float('nan')") + call assert_equal('-2.356194', string(atan2(-1, -1))) + call assert_equal('2.356194', string(atan2(1, -1))) + call assert_equal('0.0', string(atan2(1.0, 1.0/0.0))) + call assert_equal('1.570796', string(atan2(1.0/0.0, 1.0))) + call assert_equal("str2float('nan')", string(atan2(0.0/0.0, 1.0))) endfunc func Test_tanh() - call assert_equal(string(tanh(0.0)), '0.0') - call assert_equal(string(tanh(0.5)), '0.462117') - call assert_equal(string(tanh(-1.0)), '-0.761594') - call assert_equal(string(tanh(1.0/0.0)), '1.0') - call assert_equal(string(tanh(-1.0/0.0)), '-1.0') - call assert_equal(string(tanh(0.0/0.0)), "str2float('nan')") + call assert_equal('0.0', string(tanh(0.0))) + call assert_equal('0.462117', string(tanh(0.5))) + call assert_equal('-0.761594', string(tanh(-1.0))) + call assert_equal('1.0', string(tanh(1.0/0.0))) + call assert_equal('-1.0', string(tanh(-1.0/0.0))) + call assert_equal("str2float('nan')", string(tanh(0.0/0.0))) endfunc func Test_fmod() - call assert_equal(string(fmod(12.33, 1.22)), '0.13') - call assert_equal(string(fmod(-12.33, 1.22)), '-0.13') - call assert_equal(string(fmod(1.0/0.0, 1.0)), "str2float('nan')") - call assert_equal(string(fmod(1.0, 1.0/0.0)), '1.0') - call assert_equal(string(fmod(1.0, 0.0)), "str2float('nan')") + call assert_equal('0.13', string(fmod(12.33, 1.22))) + call assert_equal('-0.13', string(fmod(-12.33, 1.22))) + call assert_equal("str2float('nan')", string(fmod(1.0/0.0, 1.0))) + " On Windows we get "nan" instead of 1.0, accept both. + let res = string(fmod(1.0, 1.0/0.0)) + if res != "str2float('nan')" + call assert_equal('1.0', res) + endif + call assert_equal("str2float('nan')", string(fmod(1.0, 0.0))) endfunc func Test_pow() - call assert_equal(string(pow(0.0, 0.0)), '1.0') - call assert_equal(string(pow(2.0, 3.0)), '8.0') - call assert_equal(string(pow(2.0, 0.0/0.0)), "str2float('nan')") - call assert_equal(string(pow(0.0/0.0, 3.0)), "str2float('nan')") - call assert_equal(string(pow(0.0/0.0, 3.0)), "str2float('nan')") - call assert_equal(string(pow(2.0, 1.0/0.0)), "str2float('inf')") - call assert_equal(string(pow(1.0/0.0, 3.0)), "str2float('inf')") + call assert_equal('1.0', string(pow(0.0, 0.0))) + call assert_equal('8.0', string(pow(2.0, 3.0))) + call assert_equal("str2float('nan')", string(pow(2.0, 0.0/0.0))) + call assert_equal("str2float('nan')", string(pow(0.0/0.0, 3.0))) + call assert_equal("str2float('nan')", string(pow(0.0/0.0, 3.0))) + call assert_equal("str2float('inf')", string(pow(2.0, 1.0/0.0))) + call assert_equal("str2float('inf')", string(pow(1.0/0.0, 3.0))) endfunc func Test_str2float() - call assert_equal(string(str2float('1')), '1.0') - call assert_equal(string(str2float('1.23')), '1.23') - call assert_equal(string(str2float('1.23abc')), '1.23') - call assert_equal(string(str2float('1e40')), '1.0e40') - call assert_equal(string(str2float('1e1000')), "str2float('inf')") - call assert_equal(string(str2float('inf')), "str2float('inf')") - call assert_equal(string(str2float('-inf')), "-str2float('inf')") - call assert_equal(string(str2float('Inf')), "str2float('inf')") - call assert_equal(string(str2float('nan')), "str2float('nan')") - call assert_equal(string(str2float('NaN')), "str2float('nan')") + call assert_equal('1.0', string(str2float('1'))) + call assert_equal('1.23', string(str2float('1.23'))) + call assert_equal('1.23', string(str2float('1.23abc'))) + call assert_equal('1.0e40', string(str2float('1e40'))) + call assert_equal("str2float('inf')", string(str2float('1e1000'))) + call assert_equal("str2float('inf')", string(str2float('inf'))) + call assert_equal("-str2float('inf')", string(str2float('-inf'))) + call assert_equal("str2float('inf')", string(str2float('Inf'))) + call assert_equal("str2float('nan')", string(str2float('nan'))) + call assert_equal("str2float('nan')", string(str2float('NaN'))) endfunc func Test_floor() - call assert_equal(string(floor(2.0)), '2.0') - call assert_equal(string(floor(2.11)), '2.0') - call assert_equal(string(floor(2.99)), '2.0') - call assert_equal(string(floor(-2.11)), '-3.0') - call assert_equal(string(floor(-2.99)), '-3.0') - call assert_equal(string(floor(0.0/0.0)), "str2float('nan')") - call assert_equal(string(floor(1.0/0.0)), "str2float('inf')") - call assert_equal(string(floor(-1.0/0.0)), "-str2float('inf')") + call assert_equal('2.0', string(floor(2.0))) + call assert_equal('2.0', string(floor(2.11))) + call assert_equal('2.0', string(floor(2.99))) + call assert_equal('-3.0', string(floor(-2.11))) + call assert_equal('-3.0', string(floor(-2.99))) + call assert_equal("str2float('nan')", string(floor(0.0/0.0))) + call assert_equal("str2float('inf')", string(floor(1.0/0.0))) + call assert_equal("-str2float('inf')", string(floor(-1.0/0.0))) endfunc func Test_ceil() - call assert_equal(string(ceil(2.0)), '2.0') - call assert_equal(string(ceil(2.11)), '3.0') - call assert_equal(string(ceil(2.99)), '3.0') - call assert_equal(string(ceil(-2.11)), '-2.0') - call assert_equal(string(ceil(-2.99)), '-2.0') - call assert_equal(string(ceil(0.0/0.0)), "str2float('nan')") - call assert_equal(string(ceil(1.0/0.0)), "str2float('inf')") - call assert_equal(string(ceil(-1.0/0.0)), "-str2float('inf')") + call assert_equal('2.0', string(ceil(2.0))) + call assert_equal('3.0', string(ceil(2.11))) + call assert_equal('3.0', string(ceil(2.99))) + call assert_equal('-2.0', string(ceil(-2.11))) + call assert_equal('-2.0', string(ceil(-2.99))) + call assert_equal("str2float('nan')", string(ceil(0.0/0.0))) + call assert_equal("str2float('inf')", string(ceil(1.0/0.0))) + call assert_equal("-str2float('inf')", string(ceil(-1.0/0.0))) endfunc func Test_round() - call assert_equal(string(round(2.1)), '2.0') - call assert_equal(string(round(2.5)), '3.0') - call assert_equal(string(round(2.9)), '3.0') - call assert_equal(string(round(-2.1)), '-2.0') - call assert_equal(string(round(-2.5)), '-3.0') - call assert_equal(string(round(-2.9)), '-3.0') - call assert_equal(string(round(0.0/0.0)), "str2float('nan')") - call assert_equal(string(round(1.0/0.0)), "str2float('inf')") - call assert_equal(string(round(-1.0/0.0)), "-str2float('inf')") + call assert_equal('2.0', string(round(2.1))) + call assert_equal('3.0', string(round(2.5))) + call assert_equal('3.0', string(round(2.9))) + call assert_equal('-2.0', string(round(-2.1))) + call assert_equal('-3.0', string(round(-2.5))) + call assert_equal('-3.0', string(round(-2.9))) + call assert_equal("str2float('nan')", string(round(0.0/0.0))) + call assert_equal("str2float('inf')", string(round(1.0/0.0))) + call assert_equal("-str2float('inf')", string(round(-1.0/0.0))) endfunc func Test_trunc() - call assert_equal(string(trunc(2.1)), '2.0') - call assert_equal(string(trunc(2.5)), '2.0') - call assert_equal(string(trunc(2.9)), '2.0') - call assert_equal(string(trunc(-2.1)), '-2.0') - call assert_equal(string(trunc(-2.5)), '-2.0') - call assert_equal(string(trunc(-2.9)), '-2.0') - call assert_equal(string(trunc(0.0/0.0)), "str2float('nan')") - call assert_equal(string(trunc(1.0/0.0)), "str2float('inf')") - call assert_equal(string(trunc(-1.0/0.0)), "-str2float('inf')") + call assert_equal('2.0', string(trunc(2.1))) + call assert_equal('2.0', string(trunc(2.5))) + call assert_equal('2.0', string(trunc(2.9))) + call assert_equal('-2.0', string(trunc(-2.1))) + call assert_equal('-2.0', string(trunc(-2.5))) + call assert_equal('-2.0', string(trunc(-2.9))) + call assert_equal("str2float('nan')", string(trunc(0.0/0.0))) + call assert_equal("str2float('inf')", string(trunc(1.0/0.0))) + call assert_equal("-str2float('inf')", string(trunc(-1.0/0.0))) endfunc func Test_isnan() throw 'skipped: Nvim does not support isnan()' - call assert_equal(isnan(1.0), 0) - call assert_equal(isnan(0.0/0.0), 1) - call assert_equal(isnan(1.0/0.0), 0) - call assert_equal(isnan('a'), 0) - call assert_equal(isnan([]), 0) + call assert_equal(0, isnan(1.0)) + call assert_equal(1, isnan(0.0/0.0)) + call assert_equal(0, isnan(1.0/0.0)) + call assert_equal(0, isnan('a')) + call assert_equal(0, isnan([])) endfunc -- cgit From 17d616037d9312be6fb99ab559861175a1bc35e6 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 5 Jun 2017 22:39:09 -0400 Subject: vim-patch:8.0.0167 Problem: str2nr() and str2float() do not always work with negative values. Solution: Be more flexible about handling signs. (LemonBoy, closes vim/vim#1332) Add more tests. https://github.com/vim/vim/commit/08243d26d22ad44a857d02c90071578577b8a55d --- src/nvim/eval.c | 15 ++++++++++++--- src/nvim/testdir/test_alot.vim | 1 + src/nvim/testdir/test_float_func.vim | 13 +++++++++++++ src/nvim/testdir/test_functions.vim | 19 +++++++++++++++++++ 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 612c3be368..8cf505587d 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -15698,11 +15698,15 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *p = skipwhite((const char_u *)tv_get_string(&argvars[0])); + bool isneg = (*p == '-'); - if (*p == '+') { + if (*p == '+' || *p == '-') { p = skipwhite(p + 1); } (void)string2float((char *)p, &rettv->vval.v_float); + if (isneg) { + rettv->vval.v_float *= -1; + } rettv->v_type = VAR_FLOAT; } @@ -15722,7 +15726,8 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) } char_u *p = skipwhite((const char_u *)tv_get_string(&argvars[0])); - if (*p == '+') { + bool isneg = (*p == '-'); + if (*p == '+' || *p == '-') { p = skipwhite(p + 1); } switch (base) { @@ -15743,7 +15748,11 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } vim_str2nr(p, NULL, NULL, what, &n, NULL, 0); - rettv->vval.v_number = n; + if (isneg) { + rettv->vval.v_number = -n; + } else { + rettv->vval.v_number = n; + } } /* diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index a250ba7493..1103778107 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -11,6 +11,7 @@ source test_feedkeys.vim source test_filter_cmd.vim source test_filter_map.vim source test_float_func.vim +source test_functions.vim source test_goto.vim source test_jumps.vim source test_lambda.vim diff --git a/src/nvim/testdir/test_float_func.vim b/src/nvim/testdir/test_float_func.vim index 8600ce5b60..21a156e3d8 100644 --- a/src/nvim/testdir/test_float_func.vim +++ b/src/nvim/testdir/test_float_func.vim @@ -165,9 +165,22 @@ endfunc func Test_str2float() call assert_equal('1.0', string(str2float('1'))) + call assert_equal('1.0', string(str2float(' 1 '))) + call assert_equal('1.0', string(str2float(' 1.0 '))) call assert_equal('1.23', string(str2float('1.23'))) call assert_equal('1.23', string(str2float('1.23abc'))) call assert_equal('1.0e40', string(str2float('1e40'))) + + call assert_equal('1.0', string(str2float('+1'))) + call assert_equal('1.0', string(str2float('+1'))) + call assert_equal('1.0', string(str2float(' +1 '))) + call assert_equal('1.0', string(str2float(' + 1 '))) + + call assert_equal('-1.0', string(str2float('-1'))) + call assert_equal('-1.0', string(str2float('-1'))) + call assert_equal('-1.0', string(str2float(' -1 '))) + call assert_equal('-1.0', string(str2float(' - 1 '))) + call assert_equal("str2float('inf')", string(str2float('1e1000'))) call assert_equal("str2float('inf')", string(str2float('inf'))) call assert_equal("-str2float('inf')", string(str2float('-inf'))) diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 3c258299c1..237a2dc820 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -1,3 +1,22 @@ +" Tests for various functions. + +func Test_str2nr() + call assert_equal(0, str2nr('')) + call assert_equal(1, str2nr('1')) + call assert_equal(1, str2nr(' 1 ')) + + call assert_equal(1, str2nr('+1')) + call assert_equal(1, str2nr('+ 1')) + call assert_equal(1, str2nr(' + 1 ')) + + call assert_equal(-1, str2nr('-1')) + call assert_equal(-1, str2nr('- 1')) + call assert_equal(-1, str2nr(' - 1 ')) + + call assert_equal(123456789, str2nr('123456789')) + call assert_equal(-123456789, str2nr('-123456789')) +endfunc + func Test_setbufvar_options() " This tests that aucmd_prepbuf() and aucmd_restbuf() properly restore the " window layout. -- cgit From 0088ed0f1a73dcf85ce35733f2f6b2c1e84dcfef Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 5 Jun 2017 22:53:20 -0400 Subject: vim-patch:8.0.0168 Problem: Still some float functionality is not covered by tests. Solution: Add more tests. (Dominique Pelle, closes vim/vim#1364) https://github.com/vim/vim/commit/872004132f25cabe59352912889e042d6c7e6b4e --- src/nvim/testdir/test_float_func.vim | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/nvim/testdir/test_float_func.vim b/src/nvim/testdir/test_float_func.vim index 21a156e3d8..07ffe96129 100644 --- a/src/nvim/testdir/test_float_func.vim +++ b/src/nvim/testdir/test_float_func.vim @@ -13,6 +13,10 @@ func Test_abs() call assert_equal("str2float('inf')", string(abs(1.0/0.0))) call assert_equal("str2float('inf')", string(abs(-1.0/0.0))) call assert_equal("str2float('nan')", string(abs(0.0/0.0))) + call assert_equal('12', string(abs('-12abc'))) + call assert_fails("call abs([])", 'E745:') + call assert_fails("call abs({})", 'E728:') + call assert_fails("call abs(function('string'))", 'E703:') endfunc func Test_sqrt() @@ -21,6 +25,7 @@ func Test_sqrt() call assert_equal("str2float('inf')", string(sqrt(1.0/0.0))) call assert_equal("str2float('nan')", string(sqrt(-1.0))) call assert_equal("str2float('nan')", string(sqrt(0.0/0.0))) + call assert_fails('call sqrt("")', 'E808:') endfunc func Test_log() @@ -30,6 +35,7 @@ func Test_log() call assert_equal("str2float('nan')", string(log(-1.0))) call assert_equal("str2float('inf')", string(log(1.0/0.0))) call assert_equal("str2float('nan')", string(log(0.0/0.0))) + call assert_fails('call log("")', 'E808:') endfunc func Test_log10() @@ -40,6 +46,7 @@ func Test_log10() call assert_equal("str2float('nan')", string(log10(-1.0))) call assert_equal("str2float('inf')", string(log10(1.0/0.0))) call assert_equal("str2float('nan')", string(log10(0.0/0.0))) + call assert_fails('call log10("")', 'E808:') endfunc func Test_exp() @@ -49,6 +56,7 @@ func Test_exp() call assert_equal("str2float('inf')", string(exp(1.0/0.0))) call assert_equal('0.0', string(exp(-1.0/0.0))) call assert_equal("str2float('nan')", string(exp(0.0/0.0))) + call assert_fails('call exp("")', 'E808:') endfunc func Test_sin() @@ -59,6 +67,7 @@ func Test_sin() call assert_equal("str2float('nan')", string(sin(1.0/0.0))) call assert_equal('0.0', string(sin(1.0/(1.0/0.0)))) call assert_equal('-0.0', string(sin(-1.0/(1.0/0.0)))) + call assert_fails('call sin("")', 'E808:') endfunc func Test_asin() @@ -68,6 +77,7 @@ func Test_asin() call assert_equal("str2float('nan')", string(asin(1.1))) call assert_equal("str2float('nan')", string(asin(1.0/0.0))) call assert_equal("str2float('nan')", string(asin(0.0/0.0))) + call assert_fails('call asin("")', 'E808:') endfunc func Test_sinh() @@ -77,6 +87,7 @@ func Test_sinh() call assert_equal("str2float('inf')", string(sinh(1.0/0.0))) call assert_equal("-str2float('inf')", string(sinh(-1.0/0.0))) call assert_equal("str2float('nan')", string(sinh(0.0/0.0))) + call assert_fails('call sinh("")', 'E808:') endfunc func Test_cos() @@ -85,6 +96,7 @@ func Test_cos() call assert_equal('0.877583', string(cos(-0.5))) call assert_equal("str2float('nan')", string(cos(0.0/0.0))) call assert_equal("str2float('nan')", string(cos(1.0/0.0))) + call assert_fails('call cos("")', 'E808:') endfunc func Test_acos() @@ -95,6 +107,7 @@ func Test_acos() call assert_equal("str2float('nan')", string(acos(1.1))) call assert_equal("str2float('nan')", string(acos(1.0/0.0))) call assert_equal("str2float('nan')", string(acos(0.0/0.0))) + call assert_fails('call acos("")', 'E808:') endfunc func Test_cosh() @@ -103,6 +116,7 @@ func Test_cosh() call assert_equal("str2float('inf')", string(cosh(1.0/0.0))) call assert_equal("str2float('inf')", string(cosh(-1.0/0.0))) call assert_equal("str2float('nan')", string(cosh(0.0/0.0))) + call assert_fails('call cosh("")', 'E808:') endfunc func Test_tan() @@ -113,6 +127,7 @@ func Test_tan() call assert_equal("str2float('nan')", string(cos(0.0/0.0))) call assert_equal('0.0', string(tan(1.0/(1.0/0.0)))) call assert_equal('-0.0', string(tan(-1.0/(1.0/0.0)))) + call assert_fails('call tan("")', 'E808:') endfunc func Test_atan() @@ -122,6 +137,7 @@ func Test_atan() call assert_equal('1.570796', string(atan(1.0/0.0))) call assert_equal('-1.570796', string(atan(-1.0/0.0))) call assert_equal("str2float('nan')", string(atan(0.0/0.0))) + call assert_fails('call atan("")', 'E808:') endfunc func Test_atan2() @@ -130,6 +146,8 @@ func Test_atan2() call assert_equal('0.0', string(atan2(1.0, 1.0/0.0))) call assert_equal('1.570796', string(atan2(1.0/0.0, 1.0))) call assert_equal("str2float('nan')", string(atan2(0.0/0.0, 1.0))) + call assert_fails('call atan2("", -1)', 'E808:') + call assert_fails('call atan2(-1, "")', 'E808:') endfunc func Test_tanh() @@ -139,6 +157,7 @@ func Test_tanh() call assert_equal('1.0', string(tanh(1.0/0.0))) call assert_equal('-1.0', string(tanh(-1.0/0.0))) call assert_equal("str2float('nan')", string(tanh(0.0/0.0))) + call assert_fails('call tanh("")', 'E808:') endfunc func Test_fmod() @@ -151,6 +170,8 @@ func Test_fmod() call assert_equal('1.0', res) endif call assert_equal("str2float('nan')", string(fmod(1.0, 0.0))) + call assert_fails("call fmod('', 1.22)", 'E808:') + call assert_fails("call fmod(12.33, '')", 'E808:') endfunc func Test_pow() @@ -161,6 +182,8 @@ func Test_pow() call assert_equal("str2float('nan')", string(pow(0.0/0.0, 3.0))) call assert_equal("str2float('inf')", string(pow(2.0, 1.0/0.0))) call assert_equal("str2float('inf')", string(pow(1.0/0.0, 3.0))) + call assert_fails("call pow('', 2.0)", 'E808:') + call assert_fails("call pow(2.0, '')", 'E808:') endfunc func Test_str2float() @@ -170,6 +193,8 @@ func Test_str2float() call assert_equal('1.23', string(str2float('1.23'))) call assert_equal('1.23', string(str2float('1.23abc'))) call assert_equal('1.0e40', string(str2float('1e40'))) + call assert_equal('-1.23', string(str2float('-1.23'))) + call assert_equal('1.23', string(str2float(' + 1.23 '))) call assert_equal('1.0', string(str2float('+1'))) call assert_equal('1.0', string(str2float('+1'))) @@ -181,12 +206,22 @@ func Test_str2float() call assert_equal('-1.0', string(str2float(' -1 '))) call assert_equal('-1.0', string(str2float(' - 1 '))) + call assert_equal('0.0', string(str2float('+0.0'))) + call assert_equal('-0.0', string(str2float('-0.0'))) call assert_equal("str2float('inf')", string(str2float('1e1000'))) call assert_equal("str2float('inf')", string(str2float('inf'))) call assert_equal("-str2float('inf')", string(str2float('-inf'))) + call assert_equal("str2float('inf')", string(str2float('+inf'))) call assert_equal("str2float('inf')", string(str2float('Inf'))) + call assert_equal("str2float('inf')", string(str2float(' +inf '))) call assert_equal("str2float('nan')", string(str2float('nan'))) call assert_equal("str2float('nan')", string(str2float('NaN'))) + call assert_equal("str2float('nan')", string(str2float(' nan '))) + + call assert_fails("call str2float(1.2)", 'E806:') + call assert_fails("call str2float([])", 'E730:') + call assert_fails("call str2float({})", 'E731:') + call assert_fails("call str2float(function('string'))", 'E729:') endfunc func Test_floor() @@ -198,6 +233,7 @@ func Test_floor() call assert_equal("str2float('nan')", string(floor(0.0/0.0))) call assert_equal("str2float('inf')", string(floor(1.0/0.0))) call assert_equal("-str2float('inf')", string(floor(-1.0/0.0))) + call assert_fails("call floor('')", 'E808:') endfunc func Test_ceil() @@ -209,6 +245,7 @@ func Test_ceil() call assert_equal("str2float('nan')", string(ceil(0.0/0.0))) call assert_equal("str2float('inf')", string(ceil(1.0/0.0))) call assert_equal("-str2float('inf')", string(ceil(-1.0/0.0))) + call assert_fails("call ceil('')", 'E808:') endfunc func Test_round() @@ -221,6 +258,7 @@ func Test_round() call assert_equal("str2float('nan')", string(round(0.0/0.0))) call assert_equal("str2float('inf')", string(round(1.0/0.0))) call assert_equal("-str2float('inf')", string(round(-1.0/0.0))) + call assert_fails("call round('')", 'E808:') endfunc func Test_trunc() @@ -233,6 +271,7 @@ func Test_trunc() call assert_equal("str2float('nan')", string(trunc(0.0/0.0))) call assert_equal("str2float('inf')", string(trunc(1.0/0.0))) call assert_equal("-str2float('inf')", string(trunc(-1.0/0.0))) + call assert_fails("call trunc('')", 'E808:') endfunc func Test_isnan() @@ -242,4 +281,5 @@ func Test_isnan() call assert_equal(0, isnan(1.0/0.0)) call assert_equal(0, isnan('a')) call assert_equal(0, isnan([])) + call assert_equal(0, isnan({})) endfunc -- cgit From cb8efa4fefd845e6cf42c9d14384bd291327cfe8 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 5 Jun 2017 23:05:28 -0400 Subject: vim-patch:8.0.0360 Problem: Sometimes VimL is used, which is confusing. Solution: Consistently use "Vim script". (Hirohito Higashi) https://github.com/vim/vim/commit/b544f3c81f1e6a50322855681ac266ffaa8e313c --- runtime/doc/if_pyth.txt | 2 +- runtime/doc/syntax.txt | 4 +- runtime/doc/usr_02.txt | 8 +- src/nvim/eval.c | 8 +- src/nvim/ex_getln.c | 6 +- src/nvim/testdir/Makefile | 2 +- src/nvim/testdir/runtest.vim | 2 +- src/nvim/testdir/test49.vim | 2 +- src/nvim/testdir/test_viml.vim | 1071 ----------------------------------- src/nvim/testdir/test_vimscript.vim | 1071 +++++++++++++++++++++++++++++++++++ 10 files changed, 1087 insertions(+), 1089 deletions(-) delete mode 100644 src/nvim/testdir/test_viml.vim create mode 100644 src/nvim/testdir/test_vimscript.vim diff --git a/runtime/doc/if_pyth.txt b/runtime/doc/if_pyth.txt index 25da033190..8baa2d309b 100644 --- a/runtime/doc/if_pyth.txt +++ b/runtime/doc/if_pyth.txt @@ -679,7 +679,7 @@ vim.Function object *python-Function* 8. pyeval() and py3eval() Vim functions *python-pyeval* To facilitate bi-directional interface, you can use |pyeval()| and |py3eval()| -functions to evaluate Python expressions and pass their values to VimL. +functions to evaluate Python expressions and pass their values to Vim script. ============================================================================== 9. Python 3 *python3* diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index d711aa6a29..07af856e6b 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -3285,8 +3285,8 @@ Some folding is now supported with syntax/vim.vim: > g:vimsyn_folding =~ 'P' : fold python script < *g:vimsyn_noerror* -Not all error highlighting that syntax/vim.vim does may be correct; VimL is a -difficult language to highlight correctly. A way to suppress error +Not all error highlighting that syntax/vim.vim does may be correct; Vim script +is a difficult language to highlight correctly. A way to suppress error highlighting is to put the following line in your |vimrc|: > let g:vimsyn_noerror = 1 diff --git a/runtime/doc/usr_02.txt b/runtime/doc/usr_02.txt index b32d84080c..b738cdc48b 100644 --- a/runtime/doc/usr_02.txt +++ b/runtime/doc/usr_02.txt @@ -578,7 +578,7 @@ Summary: *help-summary* > register: > :help quote: -13) Vim Script (VimL) is available at > +13) Vim Script is available at > :help eval.txt < Certain aspects of the language are available at :h expr-X where "X" is a single letter. E.g. > @@ -588,10 +588,10 @@ Summary: *help-summary* > Also important is > :help function-list < to find a short description of all functions available. Help topics for - VimL functions always include the "()", so: > + Vim script functions always include the "()", so: > :help append() -< talks about the append VimL function rather than how to append text in the - current buffer. +< talks about the append Vim script function rather than how to append text + in the current buffer. 14) Mappings are talked about in the help page :h |map.txt|. Use > :help mapmode-i diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 8cf505587d..be08e6a238 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1189,7 +1189,7 @@ int get_spellword(list_T *list, const char **pp) } -// Call some vimL function and return the result in "*rettv". +// Call some vim script function and return the result in "*rettv". // Uses argv[argc] for the function arguments. Only Number and String // arguments are currently supported. // @@ -1257,7 +1257,7 @@ int call_vim_function( } /* - * Call vimL function "func" and return the result as a number. + * Call vim script function "func" and return the result as a number. * Returns -1 when calling the function fails. * Uses argv[argc] for the function arguments. */ @@ -1281,7 +1281,7 @@ call_func_retnr ( return retval; } -/// Call VimL function and return the result as a string +/// Call Vim script function and return the result as a string /// /// @param[in] func Function name. /// @param[in] argc Number of arguments. @@ -1308,7 +1308,7 @@ char *call_func_retstr(const char *const func, const int argc, } /* - * Call vimL function "func" and return the result as a List. + * Call Vim script function "func" and return the result as a List. * Uses argv[argc] for the function arguments. * Returns NULL when there is something wrong. */ diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 2b4997928e..36b6bac9c3 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4174,10 +4174,8 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, } } -/* - * Call "user_expand_func()" to invoke a user defined VimL function and return - * the result (either a string or a List). - */ +/// Call "user_expand_func()" to invoke a user defined Vim script function and +/// return the result (either a string or a List). static void * call_user_expand_func(user_expand_func_T user_expand_func, expand_T *xp, int *num_file, char_u ***file) { diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 70a9f2b8c4..5b0d826c75 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -67,7 +67,7 @@ NEW_TESTS ?= \ test_timers.res \ test_undo.res \ test_usercommands.res \ - test_viml.res \ + test_vimscript.res \ test_visual.res \ test_window_id.res \ test_writefile.res \ diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index d87c12147e..9ae53c500f 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -121,7 +121,7 @@ let s:fail = 0 let s:errors = [] let s:messages = [] let s:skipped = [] -if expand('%') =~ 'test_viml.vim' +if expand('%') =~ 'test_vimscript.vim' " this test has intentional s:errors, don't use try/catch. source % else diff --git a/src/nvim/testdir/test49.vim b/src/nvim/testdir/test49.vim index adbabd61b9..467abcd9b9 100644 --- a/src/nvim/testdir/test49.vim +++ b/src/nvim/testdir/test49.vim @@ -608,7 +608,7 @@ com! -nargs=1 -bar ExecAsScript call ExecAsScript() " END_OF_TEST_ENVIRONMENT - do not change or remove this line. -" Tests 1 to 15 were moved to test_viml.vim +" Tests 1 to 15 were moved to test_vimscript.vim let Xtest = 16 "------------------------------------------------------------------------------- diff --git a/src/nvim/testdir/test_viml.vim b/src/nvim/testdir/test_viml.vim deleted file mode 100644 index a2997b6d4d..0000000000 --- a/src/nvim/testdir/test_viml.vim +++ /dev/null @@ -1,1071 +0,0 @@ -" Test various aspects of the Vim language. -" Most of this was formerly in test49. - -"------------------------------------------------------------------------------- -" Test environment {{{1 -"------------------------------------------------------------------------------- - -com! XpathINIT let g:Xpath = '' -com! -nargs=1 -bar Xpath let g:Xpath = g:Xpath . - -" Append a message to the "messages" file -func! Xout(text) - split messages - $put =a:text - wq -endfunc - -com! -nargs=1 Xout call Xout() - -" MakeScript() - Make a script file from a function. {{{2 -" -" Create a script that consists of the body of the function a:funcname. -" Replace any ":return" by a ":finish", any argument variable by a global -" variable, and and every ":call" by a ":source" for the next following argument -" in the variable argument list. This function is useful if similar tests are -" to be made for a ":return" from a function call or a ":finish" in a script -" file. -function! MakeScript(funcname, ...) - let script = tempname() - execute "redir! >" . script - execute "function" a:funcname - redir END - execute "edit" script - " Delete the "function" and the "endfunction" lines. Do not include the - " word "function" in the pattern since it might be translated if LANG is - " set. When MakeScript() is being debugged, this deletes also the debugging - " output of its line 3 and 4. - exec '1,/.*' . a:funcname . '(.*)/d' - /^\d*\s*endfunction\>/,$d - %s/^\d*//e - %s/return/finish/e - %s/\ 0 - let cnt = cnt + 1 - s/\) - - -"------------------------------------------------------------------------------- -" Test 1: :endwhile in function {{{1 -" -" Detect if a broken loop is (incorrectly) reactivated by the -" :endwhile. Use a :return to prevent an endless loop, and make -" this test first to get a meaningful result on an error before other -" tests will hang. -"------------------------------------------------------------------------------- - -function! T1_F() - Xpath 'a' - let first = 1 - while 1 - Xpath 'b' - if first - Xpath 'c' - let first = 0 - break - else - Xpath 'd' - return - endif - endwhile -endfunction - -function! T1_G() - Xpath 'h' - let first = 1 - while 1 - Xpath 'i' - if first - Xpath 'j' - let first = 0 - break - else - Xpath 'k' - return - endif - if 1 " unmatched :if - endwhile -endfunction - -func Test_endwhile_function() - XpathINIT - call T1_F() - Xpath 'F' - - try - call T1_G() - catch - " Catch missing :endif - call assert_true(v:exception =~ 'E171') - Xpath 'x' - endtry - Xpath 'G' - - call assert_equal('abcFhijxG', g:Xpath) -endfunc - -"------------------------------------------------------------------------------- -" Test 2: :endwhile in script {{{1 -" -" Detect if a broken loop is (incorrectly) reactivated by the -" :endwhile. Use a :finish to prevent an endless loop, and place -" this test before others that might hang to get a meaningful result -" on an error. -" -" This test executes the bodies of the functions T1_F and T1_G from -" the previous test as script files (:return replaced by :finish). -"------------------------------------------------------------------------------- - -func Test_endwhile_script() - XpathINIT - ExecAsScript T1_F - Xpath 'F' - call DeleteTheScript() - - try - ExecAsScript T1_G - catch - " Catch missing :endif - call assert_true(v:exception =~ 'E171') - Xpath 'x' - endtry - Xpath 'G' - call DeleteTheScript() - - call assert_equal('abcFhijxG', g:Xpath) -endfunc - -"------------------------------------------------------------------------------- -" Test 3: :if, :elseif, :while, :continue, :break {{{1 -"------------------------------------------------------------------------------- - -function Test_if_while() - XpathINIT - if 1 - Xpath 'a' - let loops = 3 - while loops > -1 " main loop: loops == 3, 2, 1 (which breaks) - if loops <= 0 - let break_err = 1 - let loops = -1 - else - Xpath 'b' . loops - endif - if (loops == 2) - while loops == 2 " dummy loop - Xpath 'c' . loops - let loops = loops - 1 - continue " stop dummy loop - Xpath 'd' . loops - endwhile - continue " continue main loop - Xpath 'e' . loops - elseif (loops == 1) - let p = 1 - while p " dummy loop - Xpath 'f' . loops - let p = 0 - break " break dummy loop - Xpath 'g' . loops - endwhile - Xpath 'h' . loops - unlet p - break " break main loop - Xpath 'i' . loops - endif - if (loops > 0) - Xpath 'j' . loops - endif - while loops == 3 " dummy loop - let loops = loops - 1 - endwhile " end dummy loop - endwhile " end main loop - Xpath 'k' - else - Xpath 'l' - endif - Xpath 'm' - if exists("break_err") - Xpath 'm' - unlet break_err - endif - - unlet loops - - call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath) -endfunc - -"------------------------------------------------------------------------------- -" Test 4: :return {{{1 -"------------------------------------------------------------------------------- - -function! T4_F() - if 1 - Xpath 'a' - let loops = 3 - while loops > 0 " 3: 2: 1: - Xpath 'b' . loops - if (loops == 2) - Xpath 'c' . loops - return - Xpath 'd' . loops - endif - Xpath 'e' . loops - let loops = loops - 1 - endwhile - Xpath 'f' - else - Xpath 'g' - endif -endfunction - -function Test_return() - XpathINIT - call T4_F() - Xpath '4' - - call assert_equal('ab3e3b2c24', g:Xpath) -endfunction - - -"------------------------------------------------------------------------------- -" Test 5: :finish {{{1 -" -" This test executes the body of the function T4_F from the previous -" test as a script file (:return replaced by :finish). -"------------------------------------------------------------------------------- - -function Test_finish() - XpathINIT - ExecAsScript T4_F - Xpath '5' - call DeleteTheScript() - - call assert_equal('ab3e3b2c25', g:Xpath) -endfunction - - - -"------------------------------------------------------------------------------- -" Test 6: Defining functions in :while loops {{{1 -" -" Functions can be defined inside other functions. An inner function -" gets defined when the outer function is executed. Functions may -" also be defined inside while loops. Expressions in braces for -" defining the function name are allowed. -" -" The functions are defined when sourcing the script, only the -" resulting path is checked in the test function. -"------------------------------------------------------------------------------- - -XpathINIT - -" The command CALL collects the argument of all its invocations in "calls" -" when used from a function (that is, when the global variable "calls" needs -" the "g:" prefix). This is to check that the function code is skipped when -" the function is defined. For inner functions, do so only if the outer -" function is not being executed. -" -let calls = "" -com! -nargs=1 CALL - \ if !exists("calls") && !exists("outer") | - \ let g:calls = g:calls . | - \ endif - -let i = 0 -while i < 3 - let i = i + 1 - if i == 1 - Xpath 'a' - function! F1(arg) - CALL a:arg - let outer = 1 - - let j = 0 - while j < 1 - Xpath 'b' - let j = j + 1 - function! G1(arg) - CALL a:arg - endfunction - Xpath 'c' - endwhile - endfunction - Xpath 'd' - - continue - endif - - Xpath 'e' . i - function! F{i}(i, arg) - CALL a:arg - let outer = 1 - - if a:i == 3 - Xpath 'f' - endif - let k = 0 - while k < 3 - Xpath 'g' . k - let k = k + 1 - function! G{a:i}{k}(arg) - CALL a:arg - endfunction - Xpath 'h' . k - endwhile - endfunction - Xpath 'i' - -endwhile - -if exists("*G1") - Xpath 'j' -endif -if exists("*F1") - call F1("F1") - if exists("*G1") - call G1("G1") - endif -endif - -if exists("G21") || exists("G22") || exists("G23") - Xpath 'k' -endif -if exists("*F2") - call F2(2, "F2") - if exists("*G21") - call G21("G21") - endif - if exists("*G22") - call G22("G22") - endif - if exists("*G23") - call G23("G23") - endif -endif - -if exists("G31") || exists("G32") || exists("G33") - Xpath 'l' -endif -if exists("*F3") - call F3(3, "F3") - if exists("*G31") - call G31("G31") - endif - if exists("*G32") - call G32("G32") - endif - if exists("*G33") - call G33("G33") - endif -endif - -Xpath 'm' - -let g:test6_result = g:Xpath -let g:test6_calls = calls - -unlet calls -delfunction F1 -delfunction G1 -delfunction F2 -delfunction G21 -delfunction G22 -delfunction G23 -delfunction G31 -delfunction G32 -delfunction G33 - -function Test_defining_functions() - call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result) - call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls) -endfunc - -"------------------------------------------------------------------------------- -" Test 7: Continuing on errors outside functions {{{1 -" -" On an error outside a function, the script processing continues -" at the line following the outermost :endif or :endwhile. When not -" inside an :if or :while, the script processing continues at the next -" line. -"------------------------------------------------------------------------------- - -XpathINIT - -if 1 - Xpath 'a' - while 1 - Xpath 'b' - asdf - Xpath 'c' - break - endwhile | Xpath 'd' - Xpath 'e' -endif | Xpath 'f' -Xpath 'g' - -while 1 - Xpath 'h' - if 1 - Xpath 'i' - asdf - Xpath 'j' - endif | Xpath 'k' - Xpath 'l' - break -endwhile | Xpath 'm' -Xpath 'n' - -asdf -Xpath 'o' - -asdf | Xpath 'p' -Xpath 'q' - -let g:test7_result = g:Xpath - -func Test_error_in_script() - call assert_equal('abghinoq', g:test7_result) -endfunc - -"------------------------------------------------------------------------------- -" Test 8: Aborting and continuing on errors inside functions {{{1 -" -" On an error inside a function without the "abort" attribute, the -" script processing continues at the next line (unless the error was -" in a :return command). On an error inside a function with the -" "abort" attribute, the function is aborted and the script processing -" continues after the function call; the value -1 is returned then. -"------------------------------------------------------------------------------- - -XpathINIT - -function! T8_F() - if 1 - Xpath 'a' - while 1 - Xpath 'b' - asdf - Xpath 'c' - asdf | Xpath 'd' - Xpath 'e' - break - endwhile - Xpath 'f' - endif | Xpath 'g' - Xpath 'h' - - while 1 - Xpath 'i' - if 1 - Xpath 'j' - asdf - Xpath 'k' - asdf | Xpath 'l' - Xpath 'm' - endif - Xpath 'n' - break - endwhile | Xpath 'o' - Xpath 'p' - - return novar " returns (default return value 0) - Xpath 'q' - return 1 " not reached -endfunction - -function! T8_G() abort - if 1 - Xpath 'r' - while 1 - Xpath 's' - asdf " returns -1 - Xpath 't' - break - endwhile - Xpath 'v' - endif | Xpath 'w' - Xpath 'x' - - return -4 " not reached -endfunction - -function! T8_H() abort - while 1 - Xpath 'A' - if 1 - Xpath 'B' - asdf " returns -1 - Xpath 'C' - endif - Xpath 'D' - break - endwhile | Xpath 'E' - Xpath 'F' - - return -4 " not reached -endfunction - -" Aborted functions (T8_G and T8_H) return -1. -let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H() -Xpath 'X' -let g:test8_result = g:Xpath - -func Test_error_in_function() - call assert_equal(13, g:test8_sum) - call assert_equal('abcefghijkmnoprsABX', g:test8_result) - - delfunction T8_F - delfunction T8_G - delfunction T8_H -endfunc - - -"------------------------------------------------------------------------------- -" Test 9: Continuing after aborted functions {{{1 -" -" When a function with the "abort" attribute is aborted due to an -" error, the next function back in the call hierarchy without an -" "abort" attribute continues; the value -1 is returned then. -"------------------------------------------------------------------------------- - -XpathINIT - -function! F() abort - Xpath 'a' - let result = G() " not aborted - Xpath 'b' - if result != 2 - Xpath 'c' - endif - return 1 -endfunction - -function! G() " no abort attribute - Xpath 'd' - if H() != -1 " aborted - Xpath 'e' - endif - Xpath 'f' - return 2 -endfunction - -function! H() abort - Xpath 'g' - call I() " aborted - Xpath 'h' - return 4 -endfunction - -function! I() abort - Xpath 'i' - asdf " error - Xpath 'j' - return 8 -endfunction - -if F() != 1 - Xpath 'k' -endif - -let g:test9_result = g:Xpath - -delfunction F -delfunction G -delfunction H -delfunction I - -func Test_func_abort() - call assert_equal('adgifb', g:test9_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 10: :if, :elseif, :while argument parsing {{{1 -" -" A '"' or '|' in an argument expression must not be mixed up with -" a comment or a next command after a bar. Parsing errors should -" be recognized. -"------------------------------------------------------------------------------- - -XpathINIT - -function! MSG(enr, emsg) - let english = v:lang == "C" || v:lang =~ '^[Ee]n' - if a:enr == "" - Xout "TODO: Add message number for:" a:emsg - let v:errmsg = ":" . v:errmsg - endif - let match = 1 - if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) - let match = 0 - if v:errmsg == "" - Xout "Message missing." - else - let v:errmsg = escape(v:errmsg, '"') - Xout "Unexpected message:" v:errmsg - endif - endif - return match -endfunction - -if 1 || strlen("\"") | Xpath 'a' - Xpath 'b' -endif -Xpath 'c' - -if 0 -elseif 1 || strlen("\"") | Xpath 'd' - Xpath 'e' -endif -Xpath 'f' - -while 1 || strlen("\"") | Xpath 'g' - Xpath 'h' - break -endwhile -Xpath 'i' - -let v:errmsg = "" -if 1 ||| strlen("\"") | Xpath 'j' - Xpath 'k' -endif -Xpath 'l' -if !MSG('E15', "Invalid expression") - Xpath 'm' -endif - -let v:errmsg = "" -if 0 -elseif 1 ||| strlen("\"") | Xpath 'n' - Xpath 'o' -endif -Xpath 'p' -if !MSG('E15', "Invalid expression") - Xpath 'q' -endif - -let v:errmsg = "" -while 1 ||| strlen("\"") | Xpath 'r' - Xpath 's' - break -endwhile -Xpath 't' -if !MSG('E15', "Invalid expression") - Xpath 'u' -endif - -let g:test10_result = g:Xpath -delfunction MSG - -func Test_expr_parsing() - call assert_equal('abcdefghilpt', g:test10_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 11: :if, :elseif, :while argument evaluation after abort {{{1 -" -" When code is skipped over due to an error, the boolean argument to -" an :if, :elseif, or :while must not be evaluated. -"------------------------------------------------------------------------------- - -XpathINIT - -let calls = 0 - -function! P(num) - let g:calls = g:calls + a:num " side effect on call - return 0 -endfunction - -if 1 - Xpath 'a' - asdf " error - Xpath 'b' - if P(1) " should not be called - Xpath 'c' - elseif !P(2) " should not be called - Xpath 'd' - else - Xpath 'e' - endif - Xpath 'f' - while P(4) " should not be called - Xpath 'g' - endwhile - Xpath 'h' -endif -Xpath 'x' - -let g:test11_calls = calls -let g:test11_result = g:Xpath - -unlet calls -delfunction P - -func Test_arg_abort() - call assert_equal(0, g:test11_calls) - call assert_equal('ax', g:test11_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 12: Expressions in braces in skipped code {{{1 -" -" In code skipped over due to an error or inactive conditional, -" an expression in braces as part of a variable or function name -" should not be evaluated. -"------------------------------------------------------------------------------- - -XpathINIT - -function! NULL() - Xpath 'a' - return 0 -endfunction - -function! ZERO() - Xpath 'b' - return 0 -endfunction - -function! F0() - Xpath 'c' -endfunction - -function! F1(arg) - Xpath 'e' -endfunction - -let V0 = 1 - -Xpath 'f' -echo 0 ? F{NULL() + V{ZERO()}}() : 1 - -Xpath 'g' -if 0 - Xpath 'h' - call F{NULL() + V{ZERO()}}() -endif - -Xpath 'i' -if 1 - asdf " error - Xpath 'j' - call F1(F{NULL() + V{ZERO()}}()) -endif - -Xpath 'k' -if 1 - asdf " error - Xpath 'l' - call F{NULL() + V{ZERO()}}() -endif - -let g:test12_result = g:Xpath - -func Test_braces_skipped() - call assert_equal('fgik', g:test12_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 13: Failure in argument evaluation for :while {{{1 -" -" A failure in the expression evaluation for the condition of a :while -" causes the whole :while loop until the matching :endwhile being -" ignored. Continuation is at the next following line. -"------------------------------------------------------------------------------- - -XpathINIT - -Xpath 'a' -while asdf - Xpath 'b' - while 1 - Xpath 'c' - break - endwhile - Xpath 'd' - break -endwhile -Xpath 'e' - -while asdf | Xpath 'f' | endwhile | Xpath 'g' -Xpath 'h' -let g:test13_result = g:Xpath - -func Test_while_fail() - call assert_equal('aeh', g:test13_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 14: Failure in argument evaluation for :if {{{1 -" -" A failure in the expression evaluation for the condition of an :if -" does not cause the corresponding :else or :endif being matched to -" a previous :if/:elseif. Neither of both branches of the failed :if -" are executed. -"------------------------------------------------------------------------------- - -XpathINIT - -function! F() - Xpath 'a' - let x = 0 - if x " false - Xpath 'b' - elseif !x " always true - Xpath 'c' - let x = 1 - if g:boolvar " possibly undefined - Xpath 'd' - else - Xpath 'e' - endif - Xpath 'f' - elseif x " never executed - Xpath 'g' - endif - Xpath 'h' -endfunction - -let boolvar = 1 -call F() -Xpath '-' - -unlet boolvar -call F() -let g:test14_result = g:Xpath - -delfunction F - -func Test_if_fail() - call assert_equal('acdfh-acfh', g:test14_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 15: Failure in argument evaluation for :if (bar) {{{1 -" -" Like previous test, except that the failing :if ... | ... | :endif -" is in a single line. -"------------------------------------------------------------------------------- - -XpathINIT - -function! F() - Xpath 'a' - let x = 0 - if x " false - Xpath 'b' - elseif !x " always true - Xpath 'c' - let x = 1 - if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif - Xpath 'f' - elseif x " never executed - Xpath 'g' - endif - Xpath 'h' -endfunction - -let boolvar = 1 -call F() -Xpath '-' - -unlet boolvar -call F() -let g:test15_result = g:Xpath - -delfunction F - -func Test_if_bar_fail() - call assert_equal('acdfh-acfh', g:test15_result) -endfunc - - -"------------------------------------------------------------------------------- -" Test 16: Recognizing {} in variable name. {{{1 -"------------------------------------------------------------------------------- - -func Test_curlies() - let s:var = 66 - let ns = 's' - call assert_equal(66, {ns}:var) - - let g:a = {} - let g:b = 't' - let g:a[g:b] = 77 - call assert_equal(77, g:a['t']) -endfunc - -"------------------------------------------------------------------------------- -" Test 91: using type(). {{{1 -"------------------------------------------------------------------------------- - -func Test_type() - call assert_equal(0, type(0)) - call assert_equal(1, type("")) - call assert_equal(2, type(function("tr"))) - call assert_equal(2, type(function("tr", [8]))) - call assert_equal(3, type([])) - call assert_equal(4, type({})) - call assert_equal(5, type(0.0)) - call assert_equal(6, type(v:false)) - call assert_equal(6, type(v:true)) - call assert_equal(7, type(v:null)) - call assert_equal(v:t_number, type(0)) - call assert_equal(v:t_string, type("")) - call assert_equal(v:t_func, type(function("tr"))) - call assert_equal(v:t_list, type([])) - call assert_equal(v:t_dict, type({})) - call assert_equal(v:t_float, type(0.0)) - call assert_equal(v:t_bool, type(v:false)) - call assert_equal(v:t_bool, type(v:true)) -endfunc - -"------------------------------------------------------------------------------- -" Test 92: skipping code {{{1 -"------------------------------------------------------------------------------- - -func Test_skip() - let Fn = function('Test_type') - call assert_false(0 && Fn[1]) - call assert_false(0 && string(Fn)) - call assert_false(0 && len(Fn)) - let l = [] - call assert_false(0 && l[1]) - call assert_false(0 && string(l)) - call assert_false(0 && len(l)) - let f = 1.0 - call assert_false(0 && f[1]) - call assert_false(0 && string(f)) - call assert_false(0 && len(f)) - let sp = v:null - call assert_false(0 && sp[1]) - call assert_false(0 && string(sp)) - call assert_false(0 && len(sp)) - -endfunc - -"------------------------------------------------------------------------------- -" Test 93: :echo and string() {{{1 -"------------------------------------------------------------------------------- - -func Test_echo_and_string() - " String - let a = 'foo bar' - redir => result - echo a - echo string(a) - redir END - let l = split(result, "\n") - call assert_equal(["foo bar", - \ "'foo bar'"], l) - - " Float - if has('float') - let a = -1.2e0 - redir => result - echo a - echo string(a) - redir END - let l = split(result, "\n") - call assert_equal(["-1.2", - \ "-1.2"], l) - endif - - " Funcref - redir => result - echo function('string') - echo string(function('string')) - redir END - let l = split(result, "\n") - call assert_equal(["string", - \ "function('string')"], l) - - " Empty dictionaries in a list - let a = {} - redir => result - echo [a, a, a] - echo string([a, a, a]) - redir END - let l = split(result, "\n") - call assert_equal(["[{}, {}, {}]", - \ "[{}, {}, {}]"], l) - - " Empty dictionaries in a dictionary - let a = {} - let b = {"a": a, "b": a} - redir => result - echo b - echo string(b) - redir END - let l = split(result, "\n") - call assert_equal(["{'a': {}, 'b': {}}", - \ "{'a': {}, 'b': {}}"], l) - - " Empty lists in a list - let a = [] - redir => result - echo [a, a, a] - echo string([a, a, a]) - redir END - let l = split(result, "\n") - call assert_equal(["[[], [], []]", - \ "[[], [], []]"], l) - - " Empty lists in a dictionary - let a = [] - let b = {"a": a, "b": a} - redir => result - echo b - echo string(b) - redir END - let l = split(result, "\n") - call assert_equal(["{'a': [], 'b': []}", - \ "{'a': [], 'b': []}"], l) - -endfunc - -"------------------------------------------------------------------------------- -" Modelines {{{1 -" vim: ts=8 sw=4 tw=80 fdm=marker -" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "") -"------------------------------------------------------------------------------- diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim new file mode 100644 index 0000000000..a2997b6d4d --- /dev/null +++ b/src/nvim/testdir/test_vimscript.vim @@ -0,0 +1,1071 @@ +" Test various aspects of the Vim language. +" Most of this was formerly in test49. + +"------------------------------------------------------------------------------- +" Test environment {{{1 +"------------------------------------------------------------------------------- + +com! XpathINIT let g:Xpath = '' +com! -nargs=1 -bar Xpath let g:Xpath = g:Xpath . + +" Append a message to the "messages" file +func! Xout(text) + split messages + $put =a:text + wq +endfunc + +com! -nargs=1 Xout call Xout() + +" MakeScript() - Make a script file from a function. {{{2 +" +" Create a script that consists of the body of the function a:funcname. +" Replace any ":return" by a ":finish", any argument variable by a global +" variable, and and every ":call" by a ":source" for the next following argument +" in the variable argument list. This function is useful if similar tests are +" to be made for a ":return" from a function call or a ":finish" in a script +" file. +function! MakeScript(funcname, ...) + let script = tempname() + execute "redir! >" . script + execute "function" a:funcname + redir END + execute "edit" script + " Delete the "function" and the "endfunction" lines. Do not include the + " word "function" in the pattern since it might be translated if LANG is + " set. When MakeScript() is being debugged, this deletes also the debugging + " output of its line 3 and 4. + exec '1,/.*' . a:funcname . '(.*)/d' + /^\d*\s*endfunction\>/,$d + %s/^\d*//e + %s/return/finish/e + %s/\ 0 + let cnt = cnt + 1 + s/\) + + +"------------------------------------------------------------------------------- +" Test 1: :endwhile in function {{{1 +" +" Detect if a broken loop is (incorrectly) reactivated by the +" :endwhile. Use a :return to prevent an endless loop, and make +" this test first to get a meaningful result on an error before other +" tests will hang. +"------------------------------------------------------------------------------- + +function! T1_F() + Xpath 'a' + let first = 1 + while 1 + Xpath 'b' + if first + Xpath 'c' + let first = 0 + break + else + Xpath 'd' + return + endif + endwhile +endfunction + +function! T1_G() + Xpath 'h' + let first = 1 + while 1 + Xpath 'i' + if first + Xpath 'j' + let first = 0 + break + else + Xpath 'k' + return + endif + if 1 " unmatched :if + endwhile +endfunction + +func Test_endwhile_function() + XpathINIT + call T1_F() + Xpath 'F' + + try + call T1_G() + catch + " Catch missing :endif + call assert_true(v:exception =~ 'E171') + Xpath 'x' + endtry + Xpath 'G' + + call assert_equal('abcFhijxG', g:Xpath) +endfunc + +"------------------------------------------------------------------------------- +" Test 2: :endwhile in script {{{1 +" +" Detect if a broken loop is (incorrectly) reactivated by the +" :endwhile. Use a :finish to prevent an endless loop, and place +" this test before others that might hang to get a meaningful result +" on an error. +" +" This test executes the bodies of the functions T1_F and T1_G from +" the previous test as script files (:return replaced by :finish). +"------------------------------------------------------------------------------- + +func Test_endwhile_script() + XpathINIT + ExecAsScript T1_F + Xpath 'F' + call DeleteTheScript() + + try + ExecAsScript T1_G + catch + " Catch missing :endif + call assert_true(v:exception =~ 'E171') + Xpath 'x' + endtry + Xpath 'G' + call DeleteTheScript() + + call assert_equal('abcFhijxG', g:Xpath) +endfunc + +"------------------------------------------------------------------------------- +" Test 3: :if, :elseif, :while, :continue, :break {{{1 +"------------------------------------------------------------------------------- + +function Test_if_while() + XpathINIT + if 1 + Xpath 'a' + let loops = 3 + while loops > -1 " main loop: loops == 3, 2, 1 (which breaks) + if loops <= 0 + let break_err = 1 + let loops = -1 + else + Xpath 'b' . loops + endif + if (loops == 2) + while loops == 2 " dummy loop + Xpath 'c' . loops + let loops = loops - 1 + continue " stop dummy loop + Xpath 'd' . loops + endwhile + continue " continue main loop + Xpath 'e' . loops + elseif (loops == 1) + let p = 1 + while p " dummy loop + Xpath 'f' . loops + let p = 0 + break " break dummy loop + Xpath 'g' . loops + endwhile + Xpath 'h' . loops + unlet p + break " break main loop + Xpath 'i' . loops + endif + if (loops > 0) + Xpath 'j' . loops + endif + while loops == 3 " dummy loop + let loops = loops - 1 + endwhile " end dummy loop + endwhile " end main loop + Xpath 'k' + else + Xpath 'l' + endif + Xpath 'm' + if exists("break_err") + Xpath 'm' + unlet break_err + endif + + unlet loops + + call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath) +endfunc + +"------------------------------------------------------------------------------- +" Test 4: :return {{{1 +"------------------------------------------------------------------------------- + +function! T4_F() + if 1 + Xpath 'a' + let loops = 3 + while loops > 0 " 3: 2: 1: + Xpath 'b' . loops + if (loops == 2) + Xpath 'c' . loops + return + Xpath 'd' . loops + endif + Xpath 'e' . loops + let loops = loops - 1 + endwhile + Xpath 'f' + else + Xpath 'g' + endif +endfunction + +function Test_return() + XpathINIT + call T4_F() + Xpath '4' + + call assert_equal('ab3e3b2c24', g:Xpath) +endfunction + + +"------------------------------------------------------------------------------- +" Test 5: :finish {{{1 +" +" This test executes the body of the function T4_F from the previous +" test as a script file (:return replaced by :finish). +"------------------------------------------------------------------------------- + +function Test_finish() + XpathINIT + ExecAsScript T4_F + Xpath '5' + call DeleteTheScript() + + call assert_equal('ab3e3b2c25', g:Xpath) +endfunction + + + +"------------------------------------------------------------------------------- +" Test 6: Defining functions in :while loops {{{1 +" +" Functions can be defined inside other functions. An inner function +" gets defined when the outer function is executed. Functions may +" also be defined inside while loops. Expressions in braces for +" defining the function name are allowed. +" +" The functions are defined when sourcing the script, only the +" resulting path is checked in the test function. +"------------------------------------------------------------------------------- + +XpathINIT + +" The command CALL collects the argument of all its invocations in "calls" +" when used from a function (that is, when the global variable "calls" needs +" the "g:" prefix). This is to check that the function code is skipped when +" the function is defined. For inner functions, do so only if the outer +" function is not being executed. +" +let calls = "" +com! -nargs=1 CALL + \ if !exists("calls") && !exists("outer") | + \ let g:calls = g:calls . | + \ endif + +let i = 0 +while i < 3 + let i = i + 1 + if i == 1 + Xpath 'a' + function! F1(arg) + CALL a:arg + let outer = 1 + + let j = 0 + while j < 1 + Xpath 'b' + let j = j + 1 + function! G1(arg) + CALL a:arg + endfunction + Xpath 'c' + endwhile + endfunction + Xpath 'd' + + continue + endif + + Xpath 'e' . i + function! F{i}(i, arg) + CALL a:arg + let outer = 1 + + if a:i == 3 + Xpath 'f' + endif + let k = 0 + while k < 3 + Xpath 'g' . k + let k = k + 1 + function! G{a:i}{k}(arg) + CALL a:arg + endfunction + Xpath 'h' . k + endwhile + endfunction + Xpath 'i' + +endwhile + +if exists("*G1") + Xpath 'j' +endif +if exists("*F1") + call F1("F1") + if exists("*G1") + call G1("G1") + endif +endif + +if exists("G21") || exists("G22") || exists("G23") + Xpath 'k' +endif +if exists("*F2") + call F2(2, "F2") + if exists("*G21") + call G21("G21") + endif + if exists("*G22") + call G22("G22") + endif + if exists("*G23") + call G23("G23") + endif +endif + +if exists("G31") || exists("G32") || exists("G33") + Xpath 'l' +endif +if exists("*F3") + call F3(3, "F3") + if exists("*G31") + call G31("G31") + endif + if exists("*G32") + call G32("G32") + endif + if exists("*G33") + call G33("G33") + endif +endif + +Xpath 'm' + +let g:test6_result = g:Xpath +let g:test6_calls = calls + +unlet calls +delfunction F1 +delfunction G1 +delfunction F2 +delfunction G21 +delfunction G22 +delfunction G23 +delfunction G31 +delfunction G32 +delfunction G33 + +function Test_defining_functions() + call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result) + call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls) +endfunc + +"------------------------------------------------------------------------------- +" Test 7: Continuing on errors outside functions {{{1 +" +" On an error outside a function, the script processing continues +" at the line following the outermost :endif or :endwhile. When not +" inside an :if or :while, the script processing continues at the next +" line. +"------------------------------------------------------------------------------- + +XpathINIT + +if 1 + Xpath 'a' + while 1 + Xpath 'b' + asdf + Xpath 'c' + break + endwhile | Xpath 'd' + Xpath 'e' +endif | Xpath 'f' +Xpath 'g' + +while 1 + Xpath 'h' + if 1 + Xpath 'i' + asdf + Xpath 'j' + endif | Xpath 'k' + Xpath 'l' + break +endwhile | Xpath 'm' +Xpath 'n' + +asdf +Xpath 'o' + +asdf | Xpath 'p' +Xpath 'q' + +let g:test7_result = g:Xpath + +func Test_error_in_script() + call assert_equal('abghinoq', g:test7_result) +endfunc + +"------------------------------------------------------------------------------- +" Test 8: Aborting and continuing on errors inside functions {{{1 +" +" On an error inside a function without the "abort" attribute, the +" script processing continues at the next line (unless the error was +" in a :return command). On an error inside a function with the +" "abort" attribute, the function is aborted and the script processing +" continues after the function call; the value -1 is returned then. +"------------------------------------------------------------------------------- + +XpathINIT + +function! T8_F() + if 1 + Xpath 'a' + while 1 + Xpath 'b' + asdf + Xpath 'c' + asdf | Xpath 'd' + Xpath 'e' + break + endwhile + Xpath 'f' + endif | Xpath 'g' + Xpath 'h' + + while 1 + Xpath 'i' + if 1 + Xpath 'j' + asdf + Xpath 'k' + asdf | Xpath 'l' + Xpath 'm' + endif + Xpath 'n' + break + endwhile | Xpath 'o' + Xpath 'p' + + return novar " returns (default return value 0) + Xpath 'q' + return 1 " not reached +endfunction + +function! T8_G() abort + if 1 + Xpath 'r' + while 1 + Xpath 's' + asdf " returns -1 + Xpath 't' + break + endwhile + Xpath 'v' + endif | Xpath 'w' + Xpath 'x' + + return -4 " not reached +endfunction + +function! T8_H() abort + while 1 + Xpath 'A' + if 1 + Xpath 'B' + asdf " returns -1 + Xpath 'C' + endif + Xpath 'D' + break + endwhile | Xpath 'E' + Xpath 'F' + + return -4 " not reached +endfunction + +" Aborted functions (T8_G and T8_H) return -1. +let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H() +Xpath 'X' +let g:test8_result = g:Xpath + +func Test_error_in_function() + call assert_equal(13, g:test8_sum) + call assert_equal('abcefghijkmnoprsABX', g:test8_result) + + delfunction T8_F + delfunction T8_G + delfunction T8_H +endfunc + + +"------------------------------------------------------------------------------- +" Test 9: Continuing after aborted functions {{{1 +" +" When a function with the "abort" attribute is aborted due to an +" error, the next function back in the call hierarchy without an +" "abort" attribute continues; the value -1 is returned then. +"------------------------------------------------------------------------------- + +XpathINIT + +function! F() abort + Xpath 'a' + let result = G() " not aborted + Xpath 'b' + if result != 2 + Xpath 'c' + endif + return 1 +endfunction + +function! G() " no abort attribute + Xpath 'd' + if H() != -1 " aborted + Xpath 'e' + endif + Xpath 'f' + return 2 +endfunction + +function! H() abort + Xpath 'g' + call I() " aborted + Xpath 'h' + return 4 +endfunction + +function! I() abort + Xpath 'i' + asdf " error + Xpath 'j' + return 8 +endfunction + +if F() != 1 + Xpath 'k' +endif + +let g:test9_result = g:Xpath + +delfunction F +delfunction G +delfunction H +delfunction I + +func Test_func_abort() + call assert_equal('adgifb', g:test9_result) +endfunc + + +"------------------------------------------------------------------------------- +" Test 10: :if, :elseif, :while argument parsing {{{1 +" +" A '"' or '|' in an argument expression must not be mixed up with +" a comment or a next command after a bar. Parsing errors should +" be recognized. +"------------------------------------------------------------------------------- + +XpathINIT + +function! MSG(enr, emsg) + let english = v:lang == "C" || v:lang =~ '^[Ee]n' + if a:enr == "" + Xout "TODO: Add message number for:" a:emsg + let v:errmsg = ":" . v:errmsg + endif + let match = 1 + if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) + let match = 0 + if v:errmsg == "" + Xout "Message missing." + else + let v:errmsg = escape(v:errmsg, '"') + Xout "Unexpected message:" v:errmsg + endif + endif + return match +endfunction + +if 1 || strlen("\"") | Xpath 'a' + Xpath 'b' +endif +Xpath 'c' + +if 0 +elseif 1 || strlen("\"") | Xpath 'd' + Xpath 'e' +endif +Xpath 'f' + +while 1 || strlen("\"") | Xpath 'g' + Xpath 'h' + break +endwhile +Xpath 'i' + +let v:errmsg = "" +if 1 ||| strlen("\"") | Xpath 'j' + Xpath 'k' +endif +Xpath 'l' +if !MSG('E15', "Invalid expression") + Xpath 'm' +endif + +let v:errmsg = "" +if 0 +elseif 1 ||| strlen("\"") | Xpath 'n' + Xpath 'o' +endif +Xpath 'p' +if !MSG('E15', "Invalid expression") + Xpath 'q' +endif + +let v:errmsg = "" +while 1 ||| strlen("\"") | Xpath 'r' + Xpath 's' + break +endwhile +Xpath 't' +if !MSG('E15', "Invalid expression") + Xpath 'u' +endif + +let g:test10_result = g:Xpath +delfunction MSG + +func Test_expr_parsing() + call assert_equal('abcdefghilpt', g:test10_result) +endfunc + + +"------------------------------------------------------------------------------- +" Test 11: :if, :elseif, :while argument evaluation after abort {{{1 +" +" When code is skipped over due to an error, the boolean argument to +" an :if, :elseif, or :while must not be evaluated. +"------------------------------------------------------------------------------- + +XpathINIT + +let calls = 0 + +function! P(num) + let g:calls = g:calls + a:num " side effect on call + return 0 +endfunction + +if 1 + Xpath 'a' + asdf " error + Xpath 'b' + if P(1) " should not be called + Xpath 'c' + elseif !P(2) " should not be called + Xpath 'd' + else + Xpath 'e' + endif + Xpath 'f' + while P(4) " should not be called + Xpath 'g' + endwhile + Xpath 'h' +endif +Xpath 'x' + +let g:test11_calls = calls +let g:test11_result = g:Xpath + +unlet calls +delfunction P + +func Test_arg_abort() + call assert_equal(0, g:test11_calls) + call assert_equal('ax', g:test11_result) +endfunc + + +"------------------------------------------------------------------------------- +" Test 12: Expressions in braces in skipped code {{{1 +" +" In code skipped over due to an error or inactive conditional, +" an expression in braces as part of a variable or function name +" should not be evaluated. +"------------------------------------------------------------------------------- + +XpathINIT + +function! NULL() + Xpath 'a' + return 0 +endfunction + +function! ZERO() + Xpath 'b' + return 0 +endfunction + +function! F0() + Xpath 'c' +endfunction + +function! F1(arg) + Xpath 'e' +endfunction + +let V0 = 1 + +Xpath 'f' +echo 0 ? F{NULL() + V{ZERO()}}() : 1 + +Xpath 'g' +if 0 + Xpath 'h' + call F{NULL() + V{ZERO()}}() +endif + +Xpath 'i' +if 1 + asdf " error + Xpath 'j' + call F1(F{NULL() + V{ZERO()}}()) +endif + +Xpath 'k' +if 1 + asdf " error + Xpath 'l' + call F{NULL() + V{ZERO()}}() +endif + +let g:test12_result = g:Xpath + +func Test_braces_skipped() + call assert_equal('fgik', g:test12_result) +endfunc + + +"------------------------------------------------------------------------------- +" Test 13: Failure in argument evaluation for :while {{{1 +" +" A failure in the expression evaluation for the condition of a :while +" causes the whole :while loop until the matching :endwhile being +" ignored. Continuation is at the next following line. +"------------------------------------------------------------------------------- + +XpathINIT + +Xpath 'a' +while asdf + Xpath 'b' + while 1 + Xpath 'c' + break + endwhile + Xpath 'd' + break +endwhile +Xpath 'e' + +while asdf | Xpath 'f' | endwhile | Xpath 'g' +Xpath 'h' +let g:test13_result = g:Xpath + +func Test_while_fail() + call assert_equal('aeh', g:test13_result) +endfunc + + +"------------------------------------------------------------------------------- +" Test 14: Failure in argument evaluation for :if {{{1 +" +" A failure in the expression evaluation for the condition of an :if +" does not cause the corresponding :else or :endif being matched to +" a previous :if/:elseif. Neither of both branches of the failed :if +" are executed. +"------------------------------------------------------------------------------- + +XpathINIT + +function! F() + Xpath 'a' + let x = 0 + if x " false + Xpath 'b' + elseif !x " always true + Xpath 'c' + let x = 1 + if g:boolvar " possibly undefined + Xpath 'd' + else + Xpath 'e' + endif + Xpath 'f' + elseif x " never executed + Xpath 'g' + endif + Xpath 'h' +endfunction + +let boolvar = 1 +call F() +Xpath '-' + +unlet boolvar +call F() +let g:test14_result = g:Xpath + +delfunction F + +func Test_if_fail() + call assert_equal('acdfh-acfh', g:test14_result) +endfunc + + +"------------------------------------------------------------------------------- +" Test 15: Failure in argument evaluation for :if (bar) {{{1 +" +" Like previous test, except that the failing :if ... | ... | :endif +" is in a single line. +"------------------------------------------------------------------------------- + +XpathINIT + +function! F() + Xpath 'a' + let x = 0 + if x " false + Xpath 'b' + elseif !x " always true + Xpath 'c' + let x = 1 + if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif + Xpath 'f' + elseif x " never executed + Xpath 'g' + endif + Xpath 'h' +endfunction + +let boolvar = 1 +call F() +Xpath '-' + +unlet boolvar +call F() +let g:test15_result = g:Xpath + +delfunction F + +func Test_if_bar_fail() + call assert_equal('acdfh-acfh', g:test15_result) +endfunc + + +"------------------------------------------------------------------------------- +" Test 16: Recognizing {} in variable name. {{{1 +"------------------------------------------------------------------------------- + +func Test_curlies() + let s:var = 66 + let ns = 's' + call assert_equal(66, {ns}:var) + + let g:a = {} + let g:b = 't' + let g:a[g:b] = 77 + call assert_equal(77, g:a['t']) +endfunc + +"------------------------------------------------------------------------------- +" Test 91: using type(). {{{1 +"------------------------------------------------------------------------------- + +func Test_type() + call assert_equal(0, type(0)) + call assert_equal(1, type("")) + call assert_equal(2, type(function("tr"))) + call assert_equal(2, type(function("tr", [8]))) + call assert_equal(3, type([])) + call assert_equal(4, type({})) + call assert_equal(5, type(0.0)) + call assert_equal(6, type(v:false)) + call assert_equal(6, type(v:true)) + call assert_equal(7, type(v:null)) + call assert_equal(v:t_number, type(0)) + call assert_equal(v:t_string, type("")) + call assert_equal(v:t_func, type(function("tr"))) + call assert_equal(v:t_list, type([])) + call assert_equal(v:t_dict, type({})) + call assert_equal(v:t_float, type(0.0)) + call assert_equal(v:t_bool, type(v:false)) + call assert_equal(v:t_bool, type(v:true)) +endfunc + +"------------------------------------------------------------------------------- +" Test 92: skipping code {{{1 +"------------------------------------------------------------------------------- + +func Test_skip() + let Fn = function('Test_type') + call assert_false(0 && Fn[1]) + call assert_false(0 && string(Fn)) + call assert_false(0 && len(Fn)) + let l = [] + call assert_false(0 && l[1]) + call assert_false(0 && string(l)) + call assert_false(0 && len(l)) + let f = 1.0 + call assert_false(0 && f[1]) + call assert_false(0 && string(f)) + call assert_false(0 && len(f)) + let sp = v:null + call assert_false(0 && sp[1]) + call assert_false(0 && string(sp)) + call assert_false(0 && len(sp)) + +endfunc + +"------------------------------------------------------------------------------- +" Test 93: :echo and string() {{{1 +"------------------------------------------------------------------------------- + +func Test_echo_and_string() + " String + let a = 'foo bar' + redir => result + echo a + echo string(a) + redir END + let l = split(result, "\n") + call assert_equal(["foo bar", + \ "'foo bar'"], l) + + " Float + if has('float') + let a = -1.2e0 + redir => result + echo a + echo string(a) + redir END + let l = split(result, "\n") + call assert_equal(["-1.2", + \ "-1.2"], l) + endif + + " Funcref + redir => result + echo function('string') + echo string(function('string')) + redir END + let l = split(result, "\n") + call assert_equal(["string", + \ "function('string')"], l) + + " Empty dictionaries in a list + let a = {} + redir => result + echo [a, a, a] + echo string([a, a, a]) + redir END + let l = split(result, "\n") + call assert_equal(["[{}, {}, {}]", + \ "[{}, {}, {}]"], l) + + " Empty dictionaries in a dictionary + let a = {} + let b = {"a": a, "b": a} + redir => result + echo b + echo string(b) + redir END + let l = split(result, "\n") + call assert_equal(["{'a': {}, 'b': {}}", + \ "{'a': {}, 'b': {}}"], l) + + " Empty lists in a list + let a = [] + redir => result + echo [a, a, a] + echo string([a, a, a]) + redir END + let l = split(result, "\n") + call assert_equal(["[[], [], []]", + \ "[[], [], []]"], l) + + " Empty lists in a dictionary + let a = [] + let b = {"a": a, "b": a} + redir => result + echo b + echo string(b) + redir END + let l = split(result, "\n") + call assert_equal(["{'a': [], 'b': []}", + \ "{'a': [], 'b': []}"], l) + +endfunc + +"------------------------------------------------------------------------------- +" Modelines {{{1 +" vim: ts=8 sw=4 tw=80 fdm=marker +" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "") +"------------------------------------------------------------------------------- -- cgit From dafc14b9691dfa9af143c0372f84b9288163c30a Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 5 Jun 2017 23:17:54 -0400 Subject: vim-patch:8.0.0477 Problem: The client-server test may hang when failing. Solution: Set a timer. Add assert_report() https://github.com/vim/vim/commit/42205551b140bee8b419b24abe210f56bb80b35e --- runtime/doc/eval.txt | 39 ++++++++++------ src/nvim/eval.c | 11 +++++ src/nvim/eval.lua | 1 + src/nvim/testdir/runtest.vim | 108 ++++++++++++++++++++++++------------------- 4 files changed, 98 insertions(+), 61 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 11b42dd2e5..9a1f4a426f 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1936,16 +1936,23 @@ argidx() Number current index in the argument list arglistid([{winnr} [, {tabnr}]]) Number argument list id argv({nr}) String {nr} entry of the argument list argv() List the argument list -assert_equal({exp}, {act} [, {msg}]) none assert {exp} is equal to {act} -assert_exception( {error} [, {msg}]) none assert {error} is in v:exception -assert_fails( {cmd} [, {error}]) none assert {cmd} fails -assert_false({actual} [, {msg}]) none assert {actual} is false +assert_equal({exp}, {act} [, {msg}]) + none assert {exp} is equal to {act} +assert_exception({error} [, {msg}]) + none assert {error} is in v:exception +assert_fails({cmd} [, {error}]) none assert {cmd} fails +assert_false({actual} [, {msg}]) + none assert {actual} is false assert_inrange({lower}, {upper}, {actual} [, {msg}]) none assert {actual} is inside the range -assert_match( {pat}, {text} [, {msg}]) none assert {pat} matches {text} -assert_notequal( {exp}, {act} [, {msg}]) none assert {exp} is not equal {act} -assert_notmatch( {pat}, {text} [, {msg}]) none assert {pat} not matches {text} -assert_true({actual} [, {msg}]) none assert {actual} is true +assert_match({pat}, {text} [, {msg}]) + none assert {pat} matches {text} +assert_notequal({exp}, {act} [, {msg}]) + none assert {exp} is not equal {act} +assert_notmatch({pat}, {text} [, {msg}]) + none assert {pat} not matches {text} +assert_report({msg}) none report a test failure +assert_true({actual} [, {msg}]) none assert {actual} is true asin({expr}) Float arc sine of {expr} atan({expr}) Float arc tangent of {expr} atan2({expr}, {expr}) Float arc tangent of {expr1} / {expr2} @@ -2501,6 +2508,9 @@ assert_notmatch({pattern}, {actual} [, {msg}]) The opposite of `assert_match()`: add an error message to |v:errors| when {pattern} matches {actual}. +assert_report({msg}) *assert_report()* + Report a test failure directly, using {msg}. + assert_true({actual} [, {msg}]) *assert_true()* When {actual} is not true an error message is added to |v:errors|, like with |assert_equal()|. @@ -3632,11 +3642,14 @@ foldtext() Returns a String, to be displayed for a closed fold. This is |v:foldstart|, |v:foldend| and |v:folddashes| variables. The returned string looks like this: > +-- 45 lines: abcdef -< The number of dashes depends on the foldlevel. The "45" is - the number of lines in the fold. "abcdef" is the text in the - first non-blank line of the fold. Leading white space, "//" - or "/*" and the text from the 'foldmarker' and 'commentstring' - options is removed. +< The number of leading dashes depends on the foldlevel. The + "45" is the number of lines in the fold. "abcdef" is the text + in the first non-blank line of the fold. Leading white space, + "//" or "/*" and the text from the 'foldmarker' and + 'commentstring' options is removed. + When used to draw the actual foldtext, the rest of the line + will be filled with the fold char from the 'fillchars' + setting. {not available when compiled without the |+folding| feature} foldtextresult({lnum}) *foldtextresult()* diff --git a/src/nvim/eval.c b/src/nvim/eval.c index be08e6a238..072adb4ebb 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6807,6 +6807,17 @@ static void f_assert_notequal(typval_T *argvars, typval_T *rettv, FunPtr fptr) assert_equal_common(argvars, ASSERT_NOTEQUAL); } +/// "assert_report(msg) +static void f_assert_report(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + garray_T ga; + + prepare_assert_error(&ga); + ga_concat(&ga, (const char_u *)tv_get_string(&argvars[0])); + assert_error(&ga); + ga_clear(&ga); +} + /// "assert_exception(string[, msg])" function static void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr) { diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 334e10eb6c..30766a0734 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -33,6 +33,7 @@ return { assert_match={args={2, 3}}, assert_notequal={args={2, 3}}, assert_notmatch={args={2, 3}}, + assert_report={args=1}, assert_true={args={1, 2}}, atan={args=1, func="float_op_wrapper", data="&atan"}, atan2={args=2}, diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index 9ae53c500f..fa3c0a6ad0 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -76,7 +76,7 @@ set listchars=eol:$ " Prevent Nvim log from writing to stderr. let $NVIM_LOG_FILE='Xnvim.log' -function RunTheTest(test) +func RunTheTest(test) echo 'Executing ' . a:test if exists("*SetUp") call SetUp() @@ -113,6 +113,60 @@ function RunTheTest(test) set nomodified endfunc +func AfterTheTest() + if len(v:errors) > 0 + let s:fail += 1 + call add(s:errors, 'Found errors in ' . s:test . ':') + call extend(s:errors, v:errors) + let v:errors = [] + endif +endfunc + +" This function can be called by a test if it wants to abort testing. +func FinishTesting() + call AfterTheTest() + + " Don't write viminfo on exit. + set viminfo= + + if s:fail == 0 + " Success, create the .res file so that make knows it's done. + exe 'split ' . fnamemodify(g:testname, ':r') . '.res' + write + endif + + if len(s:errors) > 0 + " Append errors to test.log + split test.log + call append(line('$'), '') + call append(line('$'), 'From ' . g:testname . ':') + call append(line('$'), s:errors) + write + endif + + let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test') + echo message + call add(s:messages, message) + if s:fail > 0 + let message = s:fail . ' FAILED:' + echo message + call add(s:messages, message) + call extend(s:messages, s:errors) + endif + + " Add SKIPPED messages + call extend(s:messages, s:skipped) + + " Append messages to the file "messages" + split messages + call append(line('$'), '') + call append(line('$'), 'From ' . g:testname . ':') + call append(line('$'), s:messages) + write + + qall! +endfunc + " Source the test script. First grab the file name, in case the script " navigates away. g:testname can be used by the tests. let g:testname = expand('%') @@ -157,56 +211,14 @@ for s:test in sort(s:tests) call RunTheTest(s:test) if len(v:errors) > 0 && index(s:flaky, s:test) >= 0 - call add(s:messages, 'Flaky test failed, running it again') - let v:errors = [] - call RunTheTest(s:test) - endif - - if len(v:errors) > 0 - let s:fail += 1 - call add(s:errors, 'Found errors in ' . s:test . ':') - call extend(s:errors, v:errors) + call add(s:messages, 'Flaky test failed, running it again') let v:errors = [] + call RunTheTest(s:test) endif + call AfterTheTest() endfor -" Don't write viminfo on exit. -set viminfo= - -if s:fail == 0 - " Success, create the .res file so that make knows it's done. - exe 'split ' . fnamemodify(g:testname, ':r') . '.res' - write -endif - -if len(s:errors) > 0 - " Append errors to test.log - split test.log - call append(line('$'), '') - call append(line('$'), 'From ' . g:testname . ':') - call append(line('$'), s:errors) - write -endif - -let message = 'Executed ' . s:done . (s:done > 1 ? ' tests': ' test') -echo message -call add(s:messages, message) -if s:fail > 0 - let message = s:fail . ' FAILED' - echo message - call add(s:messages, message) - call extend(s:messages, s:errors) -endif - -" Add SKIPPED messages -call extend(s:messages, s:skipped) - -" Append messages to the file "messages" -split messages -call append(line('$'), '') -call append(line('$'), 'From ' . g:testname . ':') -call append(line('$'), s:messages) -write +call FinishTesting() -qall! +" vim: shiftwidth=2 sts=2 expandtab -- cgit From d707b2a1711a02307a02684904b12b74cfb2ea32 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 5 Jun 2017 23:41:46 -0400 Subject: vim-patch:8.0.0478 Problem: Tests use assert_true(0) and assert_false(1) to report errors. Solution: Use assert_report(). https://github.com/vim/vim/commit/37175409d766ce67f2548dffa6d73451379b5737 --- src/nvim/testdir/test_cscope.vim | 2 +- src/nvim/testdir/test_cursor_func.vim | 8 +------- src/nvim/testdir/test_expr.vim | 2 +- src/nvim/testdir/test_menu.vim | 2 +- src/nvim/testdir/test_popup.vim | 2 +- test/functional/legacy/assert_spec.lua | 10 ++++++++++ 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/nvim/testdir/test_cscope.vim b/src/nvim/testdir/test_cscope.vim index c8d2ebd7da..01a9a3f9ad 100644 --- a/src/nvim/testdir/test_cscope.vim +++ b/src/nvim/testdir/test_cscope.vim @@ -28,7 +28,7 @@ func Test_cscopeWithCscopeConnections() cscope add Xcscope.out set cscopeverbose catch - call assert_true(0) + call assert_report('exception thrown') endtry call assert_fails('cscope add', 'E560') call assert_fails('cscope add Xcscope.out', 'E568') diff --git a/src/nvim/testdir/test_cursor_func.vim b/src/nvim/testdir/test_cursor_func.vim index d819b7b092..e1b9651c84 100644 --- a/src/nvim/testdir/test_cursor_func.vim +++ b/src/nvim/testdir/test_cursor_func.vim @@ -1,13 +1,7 @@ " Tests for cursor(). func Test_wrong_arguments() - try - call cursor(1. 3) - " not reached - call assert_false(1) - catch - call assert_exception('E474:') - endtry + call assert_fails('call cursor(1. 3)', 'E474:') endfunc func Test_move_cursor() diff --git a/src/nvim/testdir/test_expr.vim b/src/nvim/testdir/test_expr.vim index 03a9155512..ce1523324e 100644 --- a/src/nvim/testdir/test_expr.vim +++ b/src/nvim/testdir/test_expr.vim @@ -78,7 +78,7 @@ endfunc func Test_loop_over_null_list() let null_list = submatch(1, 1) for i in null_list - call assert_true(0, 'should not get here') + call assert_report('should not get here') endfor endfunc diff --git a/src/nvim/testdir/test_menu.vim b/src/nvim/testdir/test_menu.vim index be559467c8..af18760065 100644 --- a/src/nvim/testdir/test_menu.vim +++ b/src/nvim/testdir/test_menu.vim @@ -4,6 +4,6 @@ func Test_load_menu() try source $VIMRUNTIME/menu.vim catch - call assert_false(1, 'error while loading menus: ' . v:exception) + call assert_report('error while loading menus: ' . v:exception) endtry endfunc diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim index fd0f3c0d2d..519d855cd8 100644 --- a/src/nvim/testdir/test_popup.vim +++ b/src/nvim/testdir/test_popup.vim @@ -533,7 +533,7 @@ func Test_completion_comment_formatting() %d try call feedkeys("o/*\\\\/\", 'tx') - call assert_false(1, 'completefunc not set, should have failed') + call assert_report('completefunc not set, should have failed') catch call assert_exception('E764:') endtry diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua index d6255d42e7..2f342ec9a3 100644 --- a/test/functional/legacy/assert_spec.lua +++ b/test/functional/legacy/assert_spec.lua @@ -255,6 +255,16 @@ describe('assert function:', function() end) end) + -- assert_report({msg}) + describe('assert_report()', function() + it('should add a message to v:errors', function() + command("call assert_report('something is wrong')") + command("call assert_match('something is wrong', v:errors[0])") + command('call remove(v:errors, 0)') + expected_empty() + end) + end) + -- assert_exception({cmd}, [, {error}]) describe('assert_exception()', function() it('should assert thrown exceptions properly', function() -- cgit From 5f8411b7bf706210a4ff0960032389d015b88b16 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Tue, 6 Jun 2017 05:19:28 -0400 Subject: vim-patch:8.0.0176 Problem: Using :change in between :function and :endfunction fails. Solution: Recognize :change inside a function. (ichizok, closes vim/vim#1374) https://github.com/vim/vim/commit/70bcd7336f9f19304f32c52a86ed5b4b3de852c2 --- src/nvim/eval.c | 8 ++++- src/nvim/testdir/test_vimscript.vim | 71 +++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 072adb4ebb..72c00ad10b 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -19872,9 +19872,15 @@ void ex_function(exarg_T *eap) } } - /* Check for ":append" or ":insert". */ + // Check for ":append", ":change", ":insert". p = skip_range(p, NULL); if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p')) + || (p[0] == 'c' + && (!ASCII_ISALPHA(p[1]) + || (p[1] == 'h' && (!ASCII_ISALPHA(p[2]) + || (p[2] == 'a' + && (STRNCMP(&p[3], "nge", 3) != 0 + || !ASCII_ISALPHA(p[6]))))))) || (p[0] == 'i' && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n' && (!ASCII_ISALPHA(p[2]) diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim index a2997b6d4d..b7d12d8c93 100644 --- a/src/nvim/testdir/test_vimscript.vim +++ b/src/nvim/testdir/test_vimscript.vim @@ -1064,6 +1064,77 @@ func Test_echo_and_string() endfunc +"------------------------------------------------------------------------------- +" Test 95: lines of :append, :change, :insert {{{1 +"------------------------------------------------------------------------------- + +function! DefineFunction(name, body) + let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n") + exec func +endfunction + +func Test_script_lines() + " :append + try + call DefineFunction('T_Append', [ + \ 'append', + \ 'py < Date: Tue, 6 Jun 2017 05:28:23 -0400 Subject: vim-patch:8.0.0561 Problem: Undefined behavior when using backslash after empty line. Solution: Check for an empty line. (Dominique Pelle, closes vim/vim#1631) https://github.com/vim/vim/commit/478af67dd6a9adc456464c3736bda328ae3a28cb --- src/nvim/testdir/test_vimscript.vim | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim index b7d12d8c93..da3adf5e2b 100644 --- a/src/nvim/testdir/test_vimscript.vim +++ b/src/nvim/testdir/test_vimscript.vim @@ -1135,6 +1135,17 @@ func Test_script_lines() endtry endfunc +"------------------------------------------------------------------------------- +" Test 96: line continuation {{{1 +" +" Undefined behavior was detected by ubsan with line continuation +" after an empty line. +"------------------------------------------------------------------------------- +func Test_script_emty_line_continuation() + + \ +endfunc + "------------------------------------------------------------------------------- " Modelines {{{1 " vim: ts=8 sw=4 tw=80 fdm=marker -- cgit From 75c32b549bb505890e657d760e10295cb58cb7fc Mon Sep 17 00:00:00 2001 From: James McCoy Date: Tue, 6 Jun 2017 05:38:34 -0400 Subject: lint --- src/nvim/eval.c | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 72c00ad10b..59d673fc00 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1256,18 +1256,16 @@ int call_vim_function( return ret; } -/* - * Call vim script function "func" and return the result as a number. - * Returns -1 when calling the function fails. - * Uses argv[argc] for the function arguments. - */ -long -call_func_retnr ( - char_u *func, - int argc, - const char_u *const *const argv, - int safe // use the sandbox -) +/// Call Vim script function and return the result as a number +/// +/// @param[in] func Function name. +/// @param[in] argc Number of arguments. +/// @param[in] argv Array with string arguments. +/// @param[in] safe Use with sandbox. +/// +/// @return -1 when calling function fails, result of function otherwise. +long call_func_retnr(char_u *func, int argc, const char_u *const *const argv, + int safe) { typval_T rettv; long retval; @@ -1288,7 +1286,7 @@ call_func_retnr ( /// @param[in] argv Array with string arguments. /// @param[in] safe Use the sandbox. /// -/// @return [allocated] NULL when calling function failes, allocated string +/// @return [allocated] NULL when calling function fails, allocated string /// otherwise. char *call_func_retstr(const char *const func, const int argc, const char_u *const *const argv, @@ -1307,18 +1305,17 @@ char *call_func_retstr(const char *const func, const int argc, return retval; } -/* - * Call Vim script function "func" and return the result as a List. - * Uses argv[argc] for the function arguments. - * Returns NULL when there is something wrong. - */ -void * -call_func_retlist ( - char_u *func, - int argc, - const char_u *const *const argv, - int safe // use the sandbox -) +/// Call Vim script function and return the result as a List +/// +/// @param[in] func Function name. +/// @param[in] argc Number of arguments. +/// @param[in] argv Array with string arguments. +/// @param[in] safe Use the sandbox. +/// +/// @return [allocated] NULL when calling function fails or return tv is not a +/// List, allocated List otherwise. +void *call_func_retlist(char_u *func, int argc, const char_u *const *const argv, + int safe) { typval_T rettv; -- cgit