Compare commits

...

7 Commits

Author SHA1 Message Date
Bram Moolenaar
859cc21c6b patch 8.2.4642: Vim9: in :def function script var cannot be null
Problem:    Vim9: in :def function script var cannot be null.
Solution:   Only initialize a script variable when not set to a null value.
            (closes #10034)
2022-03-28 15:22:35 +01:00
Bram Moolenaar
471b3aed3e patch 8.2.4641: may mark the wrong window for redrawing
Problem:    May mark the wrong window for redrawing.
Solution:   Use redraw_win_later(). (closes #10032)
2022-03-28 12:41:19 +01:00
James McCoy
8be423b7ac patch 8.2.4640: some boolean options use "long" instead of "int"
Problem:    Some boolean options use "long" instead of "int".
Solution:   Adjust the type. (James McCoy, closes #10033)
2022-03-28 11:55:12 +01:00
kylo252
9dac9b1751 patch 8.2.4639: not sufficient parenthesis in preprocessor macros
Problem:    Not sufficient parenthesis in preprocessor macros.
Solution:   Add more parenthesis. (closes #10031)
2022-03-27 20:05:17 +01:00
zeertzjq
3e559cd884 patch 8.2.4638: superfluous check if a redraw is needed for 'cursorline'
Problem:    Superfluous check if a redraw is needed for 'cursorline'.
Solution:   Remove check_redraw_cursorline(). (closes #10030, closes #10029)
2022-03-27 19:26:55 +01:00
Bram Moolenaar
565d1278cb patch 8.2.4637: warning for using uninitialized variable
Problem:    Warning for using uninitialized variable. (Tony Mechelynck)
Solution:   Initialize it.
2022-03-27 18:11:05 +01:00
Bram Moolenaar
1501b63f8d patch 8.2.4636: not using Visual range
Problem:    Not using Visual range.
Solution:   Put the command pointer back to the range.
2022-03-27 16:56:21 +01:00
27 changed files with 298 additions and 117 deletions

View File

@@ -3032,23 +3032,6 @@ redraw_asap(int type)
}
#endif
#if defined(FEAT_SYN_HL) || defined(PROTO)
/*
* Check if the cursor moved and 'cursorline' is set. Mark for a VALID redraw
* if needed.
*/
void
check_redraw_cursorline(void)
{
// When 'cursorlineopt' is "screenline" need to redraw always.
if (curwin->w_p_cul
&& (curwin->w_last_cursorline != curwin->w_cursor.lnum
|| (curwin->w_p_culopt_flags & CULOPT_SCRLINE))
&& !char_avail())
redraw_later(VALID);
}
#endif
/*
* Invoked after an asynchronous callback is called.
* If an echo command was used the cursor needs to be put back where
@@ -3093,10 +3076,9 @@ redraw_after_callback(int call_update_screen, int do_message)
}
else if (State & (NORMAL | INSERT | TERMINAL))
{
#ifdef FEAT_SYN_HL
// might need to update for 'cursorline'
check_redraw_cursorline();
#endif
update_topline();
validate_cursor();
// keep the command line if possible
update_screen(VALID_NO_UPDATE);
setcursor();

View File

@@ -1058,10 +1058,6 @@ doESCkey:
case K_COMMAND: // <Cmd>command<CR>
case K_SCRIPT_COMMAND: // <ScriptCmd>command<CR>
do_cmdkey_command(c, 0);
#ifdef FEAT_SYN_HL
// Might need to update for 'cursorline'.
check_redraw_cursorline();
#endif
#ifdef FEAT_TERMINAL
if (term_use_loop())
// Started a terminal that gets the input, exit Insert mode.

View File

@@ -2823,7 +2823,7 @@ eval_variable(
{
if (tv->v_type == VAR_DICT && tv->vval.v_dict == NULL
&& ((type != NULL && type != &t_dict_empty)
|| !in_vim9script()))
|| !in_vim9script()))
{
tv->vval.v_dict = dict_alloc();
if (tv->vval.v_dict != NULL)
@@ -2843,6 +2843,14 @@ eval_variable(
tv->vval.v_list->lv_type = alloc_type(type);
}
}
else if (tv->v_type == VAR_BLOB && tv->vval.v_blob == NULL
&& ((type != NULL && type != &t_blob_null)
|| !in_vim9script()))
{
tv->vval.v_blob = blob_alloc();
if (tv->vval.v_blob != NULL)
++tv->vval.v_blob->bv_refcount;
}
}
copy_tv(tv, rettv);
}

View File

@@ -2782,7 +2782,7 @@ parse_command_modifiers(
cmdmod_T *cmod,
int skip_only)
{
char_u *cmd_start;
char_u *cmd_start = NULL;
char_u *p;
int starts_with_colon = FALSE;
int vim9script = in_vim9script();
@@ -3092,15 +3092,21 @@ parse_command_modifiers(
break;
}
if (has_visual_range && eap->cmd > cmd_start)
if (has_visual_range)
{
// Move the '<,'> range to after the modifiers and insert a colon.
// Since the modifiers have been parsed put the colon on top of the
// space: "'<,'>mod cmd" -> "mod:'<,'>cmd
// Put eap->cmd after the colon.
mch_memmove(cmd_start - 5, cmd_start, eap->cmd - cmd_start);
eap->cmd -= 5;
mch_memmove(eap->cmd - 1, ":'<,'>", 6);
if (eap->cmd > cmd_start)
{
// Move the '<,'> range to after the modifiers and insert a colon.
// Since the modifiers have been parsed put the colon on top of the
// space: "'<,'>mod cmd" -> "mod:'<,'>cmd
// Put eap->cmd after the colon.
mch_memmove(cmd_start - 5, cmd_start, eap->cmd - cmd_start);
eap->cmd -= 5;
mch_memmove(eap->cmd - 1, ":'<,'>", 6);
}
else
// no modifiers, move the pointer back
eap->cmd -= 5;
}
return OK;

View File

@@ -405,6 +405,7 @@ EXTERN type_T t_number_bool INIT6(VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_BOOL_OK
EXTERN type_T t_float INIT6(VAR_FLOAT, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_string INIT6(VAR_STRING, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_blob INIT6(VAR_BLOB, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_blob_null INIT6(VAR_BLOB, 0, 0, TTFLAG_STATIC, &t_void, NULL);
EXTERN type_T t_job INIT6(VAR_JOB, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_channel INIT6(VAR_CHANNEL, 0, 0, TTFLAG_STATIC, NULL, NULL);
@@ -702,10 +703,10 @@ EXTERN win_T *lastwin; // last window
EXTERN win_T *prevwin INIT(= NULL); // previous window
#define ONE_WINDOW (firstwin == lastwin)
#define W_NEXT(wp) ((wp)->w_next)
#define FOR_ALL_WINDOWS(wp) for (wp = firstwin; wp != NULL; wp = wp->w_next)
#define FOR_ALL_WINDOWS(wp) for ((wp) = firstwin; (wp) != NULL; (wp) = (wp)->w_next)
#define FOR_ALL_FRAMES(frp, first_frame) \
for (frp = first_frame; frp != NULL; frp = frp->fr_next)
#define FOR_ALL_TABPAGES(tp) for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
for ((frp) = first_frame; (frp) != NULL; (frp) = (frp)->fr_next)
#define FOR_ALL_TABPAGES(tp) for ((tp) = first_tabpage; (tp) != NULL; (tp) = (tp)->tp_next)
#define FOR_ALL_WINDOWS_IN_TAB(tp, wp) \
for ((wp) = ((tp) == NULL || (tp) == curtab) \
? firstwin : (tp)->tp_firstwin; (wp); (wp) = (wp)->w_next)
@@ -778,7 +779,7 @@ EXTERN buf_T *curbuf INIT(= NULL); // currently active buffer
// Iterate through all the signs placed in a buffer
#define FOR_ALL_SIGNS_IN_BUF(buf, sign) \
for (sign = buf->b_signlist; sign != NULL; sign = sign->se_next)
for ((sign) = (buf)->b_signlist; (sign) != NULL; (sign) = (sign)->se_next)
// Flag that is set when switching off 'swapfile'. It means that all blocks
// are to be loaded into memory. Shouldn't be global...
@@ -1000,7 +1001,7 @@ EXTERN JMP_BUF x_jump_env;
#define DBCS_CHT 950 // taiwan
#define DBCS_CHTU 9950 // euc-tw
#define DBCS_2BYTE 1 // 2byte-
#define DBCS_DEBUG -1
#define DBCS_DEBUG (-1)
EXTERN int enc_dbcs INIT(= 0); // One of DBCS_xxx values if
// DBCS encoding

View File

@@ -100,7 +100,7 @@
#endif
// Indices for arrays of scrollbars
#define SBAR_NONE -1
#define SBAR_NONE (-1)
#define SBAR_LEFT 0
#define SBAR_RIGHT 1
#define SBAR_BOTTOM 2
@@ -198,10 +198,10 @@ typedef struct GuiScrollbar
typedef long guicolor_T; // handle for a GUI color; for X11 this should
// be "Pixel", but that's an unsigned and we
// need a signed value
#define INVALCOLOR (guicolor_T)-11111 // number for invalid color; on 32 bit
#define INVALCOLOR ((guicolor_T)-11111) // number for invalid color; on 32 bit
// displays there is a tiny chance this is an
// actual color
#define CTERMCOLOR (guicolor_T)-11110 // only used for cterm.bg_rgb and
#define CTERMCOLOR ((guicolor_T)-11110) // only used for cterm.bg_rgb and
// cterm.fg_rgb: use cterm color
#ifdef FEAT_GUI_GTK

View File

@@ -30,9 +30,9 @@ static const char *vim_special_path = "_vim_path_";
#define PyErr_FORMAT2(exc, str, arg1, arg2) PyErr_Format(exc, _(str), arg1,arg2)
#define PyErr_VIM_FORMAT(str, arg) PyErr_FORMAT(VimError, str, arg)
#define Py_TYPE_NAME(obj) (obj->ob_type->tp_name == NULL \
#define Py_TYPE_NAME(obj) ((obj)->ob_type->tp_name == NULL \
? "(NULL)" \
: obj->ob_type->tp_name)
: (obj)->ob_type->tp_name)
#define RAISE_NO_EMPTY_KEYS PyErr_SET_STRING(PyExc_ValueError, \
N_("empty keys are not allowed"))
@@ -6686,7 +6686,7 @@ init_structs(void)
}
#define PYTYPE_READY(type) \
if (PyType_Ready(&type)) \
if (PyType_Ready(&(type))) \
return -1;
static int

View File

@@ -232,11 +232,11 @@
// Advance multi-byte pointer, do not skip over composing chars.
#define MB_CPTR_ADV(p) p += enc_utf8 ? utf_ptr2len(p) : (*mb_ptr2len)(p)
// Backup multi-byte pointer. Only use with "p" > "s" !
#define MB_PTR_BACK(s, p) p -= has_mbyte ? ((*mb_head_off)(s, p - 1) + 1) : 1
#define MB_PTR_BACK(s, p) p -= has_mbyte ? ((*mb_head_off)(s, (p) - 1) + 1) : 1
// get length of multi-byte char, not including composing chars
#define MB_CPTR2LEN(p) (enc_utf8 ? utf_ptr2len(p) : (*mb_ptr2len)(p))
#define MB_COPY_CHAR(f, t) do { if (has_mbyte) mb_copy_char(&f, &t); else *t++ = *f++; } while (0)
#define MB_COPY_CHAR(f, t) do { if (has_mbyte) mb_copy_char(&(f), &(t)); else *(t)++ = *(f)++; } while (0)
#define MB_CHARLEN(p) (has_mbyte ? mb_charlen(p) : (int)STRLEN(p))
#define MB_CHAR2LEN(c) (has_mbyte ? mb_char2len(c) : 1)
#define PTR2CHAR(p) (has_mbyte ? mb_ptr2char(p) : (int)*(p))
@@ -313,7 +313,7 @@
* HI2DI() converts a hashitem pointer to a dictitem pointer.
*/
#define DI2HIKEY(di) ((di)->di_key)
#define HIKEY2DI(p) ((dictitem_T *)(p - offsetof(dictitem_T, di_key)))
#define HIKEY2DI(p) ((dictitem_T *)((p) - offsetof(dictitem_T, di_key)))
#define HI2DI(hi) HIKEY2DI((hi)->hi_key)
/*
@@ -376,9 +376,9 @@
#define CHECK_LIST_MATERIALIZE(l) if ((l)->lv_first == &range_list_item) range_list_materialize(l)
// Inlined version of ga_grow() with optimized condition that it fails.
#define GA_GROW_FAILS(gap, n) unlikely((((gap)->ga_maxlen - (gap)->ga_len < n) ? ga_grow_inner((gap), (n)) : OK) == FAIL)
#define GA_GROW_FAILS(gap, n) unlikely((((gap)->ga_maxlen - (gap)->ga_len < (n)) ? ga_grow_inner((gap), (n)) : OK) == FAIL)
// Inlined version of ga_grow() with optimized condition that it succeeds.
#define GA_GROW_OK(gap, n) likely((((gap)->ga_maxlen - (gap)->ga_len < n) ? ga_grow_inner((gap), (n)) : OK) == OK)
#define GA_GROW_OK(gap, n) likely((((gap)->ga_maxlen - (gap)->ga_len < (n)) ? ga_grow_inner((gap), (n)) : OK) == OK)
#ifndef MIN
# define MIN(a, b) ((a) < (b) ? (a) : (b))

View File

@@ -1384,10 +1384,6 @@ main_loop(
update_topline();
validate_cursor();
#ifdef FEAT_SYN_HL
// Might need to update for 'cursorline'.
check_redraw_cursorline();
#endif
if (VIsual_active)
update_curbuf(INVERTED); // update inverted part
else if (must_redraw)

View File

@@ -135,6 +135,26 @@ redraw_for_cursorline(win_T *wp)
}
}
#ifdef FEAT_SYN_HL
/*
* Redraw when w_virtcol changes and 'cursorcolumn' is set or 'cursorlineopt'
* contains "screenline".
*/
static void
redraw_for_cursorcolumn(win_T *wp)
{
if ((wp->w_valid & VALID_VIRTCOL) == 0 && !pum_visible())
{
// When 'cursorcolumn' is set need to redraw with SOME_VALID.
if (wp->w_p_cuc)
redraw_win_later(wp, SOME_VALID);
// When 'cursorlineopt' contains "screenline" need to redraw with VALID.
else if (wp->w_p_cul && (wp->w_p_culopt_flags & CULOPT_SCRLINE))
redraw_win_later(wp, VALID);
}
}
#endif
/*
* Update curwin->w_topline and redraw if necessary.
* Used to update the screen before printing a message.
@@ -798,11 +818,10 @@ validate_virtcol_win(win_T *wp)
if (!(wp->w_valid & VALID_VIRTCOL))
{
getvvcol(wp, &wp->w_cursor, NULL, &(wp->w_virtcol), NULL);
wp->w_valid |= VALID_VIRTCOL;
#ifdef FEAT_SYN_HL
if (wp->w_p_cuc && !pum_visible())
redraw_win_later(wp, SOME_VALID);
redraw_for_cursorcolumn(wp);
#endif
wp->w_valid |= VALID_VIRTCOL;
}
}
@@ -1169,10 +1188,7 @@ curs_columns(
redraw_later(NOT_VALID);
#ifdef FEAT_SYN_HL
// Redraw when w_virtcol changes and 'cursorcolumn' is set
if (curwin->w_p_cuc && (curwin->w_valid & VALID_VIRTCOL) == 0
&& !pum_visible())
redraw_later(SOME_VALID);
redraw_for_cursorcolumn(curwin);
#endif
#if defined(FEAT_PROP_POPUP) && defined(FEAT_TERMINAL)
if (popup_is_popup(curwin) && curbuf->b_term != NULL)

View File

@@ -6971,10 +6971,6 @@ nv_edit(cmdarg_T *cap)
coladvance(getviscol());
State = save_State;
}
#ifdef FEAT_SYN_HL
// Might need to update for 'cursorline'.
check_redraw_cursorline();
#endif
invoke_edit(cap, FALSE, cap->cmdchar, FALSE);
}

View File

@@ -131,7 +131,7 @@ typedef enum {
#endif
// end-of-line style
#define EOL_UNKNOWN -1 // not defined yet
#define EOL_UNKNOWN (-1) // not defined yet
#define EOL_UNIX 0 // NL
#define EOL_DOS 1 // CR NL
#define EOL_MAC 2 // CR
@@ -570,7 +570,7 @@ EXTERN char_u *p_fenc; // 'fileencoding'
EXTERN char_u *p_fencs; // 'fileencodings'
EXTERN char_u *p_ff; // 'fileformat'
EXTERN char_u *p_ffs; // 'fileformats'
EXTERN long p_fic; // 'fileignorecase'
EXTERN int p_fic; // 'fileignorecase'
EXTERN char_u *p_ft; // 'filetype'
EXTERN char_u *p_fcs; // 'fillchar'
EXTERN int p_fixeol; // 'fixendofline'
@@ -750,7 +750,7 @@ EXTERN long p_mis; // 'menuitems'
EXTERN char_u *p_msm; // 'mkspellmem'
#endif
EXTERN int p_ml; // 'modeline'
EXTERN long p_mle; // 'modelineexpr'
EXTERN int p_mle; // 'modelineexpr'
EXTERN long p_mls; // 'modelines'
EXTERN int p_ma; // 'modifiable'
EXTERN int p_mod; // 'modified'
@@ -1078,7 +1078,7 @@ EXTERN int p_wiv; // 'weirdinvert'
EXTERN char_u *p_ww; // 'whichwrap'
EXTERN long p_wc; // 'wildchar'
EXTERN long p_wcm; // 'wildcharm'
EXTERN long p_wic; // 'wildignorecase'
EXTERN int p_wic; // 'wildignorecase'
EXTERN char_u *p_wim; // 'wildmode'
#ifdef FEAT_WILDMENU
EXTERN int p_wmnu; // 'wildmenu'
@@ -1328,6 +1328,6 @@ enum
};
// Value for b_p_ul indicating the global value must be used.
#define NO_LOCAL_UNDOLEVEL -123456
#define NO_LOCAL_UNDOLEVEL (-123456)
#endif // _OPTION_H_

View File

@@ -8,7 +8,6 @@ void update_curbuf(int type);
void update_debug_sign(buf_T *buf, linenr_T lnum);
void updateWindow(win_T *wp);
int redraw_asap(int type);
void check_redraw_cursorline(void);
void redraw_after_callback(int call_update_screen, int do_message);
void redraw_later(int type);
void redraw_win_later(win_T *wp, int type);

View File

@@ -31,7 +31,7 @@
* In the NFA engine: how many states are allowed
*/
#define NFA_MAX_STATES 100000
#define NFA_TOO_EXPENSIVE -1
#define NFA_TOO_EXPENSIVE (-1)
// Which regexp engine to use? Needed for vim_regcomp().
// Must match with 'regexpengine'.

View File

@@ -211,9 +211,9 @@ typedef struct salitem_S
// Values for SP_*ERROR are negative, positive values are used by
// read_cnt_string().
#define SP_TRUNCERROR -1 // spell file truncated error
#define SP_FORMERROR -2 // format error in spell file
#define SP_OTHERERROR -3 // other error while reading spell file
#define SP_TRUNCERROR (-1) // spell file truncated error
#define SP_FORMERROR (-2) // format error in spell file
#define SP_OTHERERROR (-3) // other error while reading spell file
/*
* Structure used in "b_langp", filled from 'spelllang'.

View File

@@ -2830,7 +2830,7 @@ struct file_buffer
// flags for use of ":lmap" and IM control
long b_p_iminsert; // input mode for insert
long b_p_imsearch; // input mode for search
#define B_IMODE_USE_INSERT -1 // Use b_p_iminsert value for search
#define B_IMODE_USE_INSERT (-1) // Use b_p_iminsert value for search
#define B_IMODE_NONE 0 // Input via none
#define B_IMODE_LMAP 1 // Input via langmap
#define B_IMODE_IM 2 // Input via input method
@@ -3698,7 +3698,7 @@ struct window_S
winopt_T w_onebuf_opt;
winopt_T w_allbuf_opt;
// transform a pointer to a "onebuf" option into a "allbuf" option
#define GLOBAL_WO(p) ((char *)p + sizeof(winopt_T))
#define GLOBAL_WO(p) ((char *)(p) + sizeof(winopt_T))
// A few options have local flags for P_INSECURE.
#ifdef FEAT_STL_OPT
@@ -4462,7 +4462,7 @@ typedef struct {
#define FIO_ENCRYPTED 0x1000 // encrypt written bytes
#define FIO_NOCONVERT 0x2000 // skip encoding conversion
#define FIO_UCSBOM 0x4000 // check for BOM at start of file
#define FIO_ALL -1 // allow all formats
#define FIO_ALL (-1) // allow all formats
// When converting, a read() or write() may leave some bytes to be converted
// for the next call. The value is guessed...

View File

@@ -0,0 +1,8 @@
>a+0&#ffffff0@4| @69
|b+0&#e0e0e08|b+0&#ffffff0@3| @69
|c+0&#e0e0e08|c+0&#ffffff0@3| @69
|d+0&#e0e0e08|d+0&#ffffff0@3| @69
|~+0#4040ff13&| @73
|~| @73
|~| @73
| +0#0000000&@56|4|,|5| @10|A|l@1|

View File

@@ -0,0 +1,8 @@
| +0#af5f00255#ffffff0@1|0| >a+0#0000000&@4| @65
| +0#af5f00255&@1|1| |b+0#0000000&@4| @65
| +0#af5f00255&@1|2| |c+0#0000000&@4| @65
| +0#af5f00255&@1|3| |d+0#0000000&@4| @65
|~+0#4040ff13&| @73
|~| @73
|~| @73
| +0#0000000&@56|4|,|1| @10|A|l@1|

View File

@@ -592,6 +592,31 @@ func Test_cursorline_with_visualmode()
call delete('Xtest_cursorline_with_visualmode')
endfunc
func Test_cursorcolumn_callback()
CheckScreendump
CheckFeature timers
let lines =<< trim END
call setline(1, ['aaaaa', 'bbbbb', 'ccccc', 'ddddd'])
set cursorcolumn
call cursor(4, 5)
func Func(timer)
call cursor(1, 1)
endfunc
call timer_start(300, 'Func')
END
call writefile(lines, 'Xcuc_timer')
let buf = RunVimInTerminal('-S Xcuc_timer', #{rows: 8})
call TermWait(buf, 310)
call VerifyScreenDump(buf, 'Test_cursorcolumn_callback_1', {})
call StopVimInTerminal(buf)
call delete('Xcuc_timer')
endfunc
func Test_wincolor()
CheckScreendump
" make sure the width is enough for the test

View File

@@ -298,6 +298,31 @@ func Test_relativenumber_colors()
call delete('XTest_relnr')
endfunc
func Test_relativenumber_callback()
CheckScreendump
CheckFeature timers
let lines =<< trim END
call setline(1, ['aaaaa', 'bbbbb', 'ccccc', 'ddddd'])
set relativenumber
call cursor(4, 1)
func Func(timer)
call cursor(1, 1)
endfunc
call timer_start(300, 'Func')
END
call writefile(lines, 'Xrnu_timer')
let buf = RunVimInTerminal('-S Xrnu_timer', #{rows: 8})
call TermWait(buf, 310)
call VerifyScreenDump(buf, 'Test_relativenumber_callback_1', {})
call StopVimInTerminal(buf)
call delete('Xrnu_timer')
endfunc
" Test for displaying line numbers with 'rightleft'
func Test_number_rightleft()
CheckFeature rightleft

View File

@@ -890,6 +890,93 @@ def Test_expr4_compare_null()
unlet g:null_dict
unlet g:not_null_list
# variables declared at script level used in a :def function
lines =<< trim END
vim9script
var l_decl: list<number>
var l_empty = []
var l_null = null_list
def TestList()
assert_false(l_decl == null)
assert_false(l_decl is null_list)
assert_false(l_empty == null)
assert_false(l_empty is null_list)
assert_true(l_null == null)
assert_true(l_null is null_list)
assert_true(l_null == null_list)
add(l_decl, 6)
assert_equal([6], l_decl)
add(l_empty, 7)
assert_equal([7], l_empty)
var caught = false
try
add(l_null, 9)
catch /E1130:/
caught = true
endtry
assert_true(caught)
enddef
TestList()
var b_decl: blob
var b_empty = 0z
var b_null = null_blob
def TestBlob()
assert_false(b_decl == null)
assert_false(b_decl is null_blob)
assert_false(b_empty == null)
assert_false(b_empty is null_blob)
assert_true(b_null == null)
assert_true(b_null is null_blob)
assert_true(b_null == null_blob)
add(b_decl, 6)
assert_equal(0z06, b_decl)
add(b_empty, 7)
assert_equal(0z07, b_empty)
var caught = false
try
add(b_null, 9)
catch /E1131:/
caught = true
endtry
assert_true(caught)
enddef
TestBlob()
var d_decl: dict<number>
var d_empty = {}
var d_null = null_dict
def TestDict()
assert_false(d_decl == null)
assert_false(d_decl is null_dict)
assert_false(d_empty == null)
assert_false(d_empty is null_dict)
assert_true(d_null == null)
assert_true(d_null is null_dict)
assert_true(d_null == null_dict)
d_decl['a'] = 6
assert_equal({a: 6}, d_decl)
d_empty['b'] = 7
assert_equal({b: 7}, d_empty)
var caught = false
try
d_null['c'] = 9
catch /E1103:/
caught = true
endtry
assert_true(caught)
enddef
TestDict()
END
v9.CheckScriptSuccess(lines)
lines =<< trim END
var d: dict<func> = {f: null_function}
assert_equal(null_function, d.f)

View File

@@ -750,6 +750,20 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
4642,
/**/
4641,
/**/
4640,
/**/
4639,
/**/
4638,
/**/
4637,
/**/
4636,
/**/
4635,
/**/

View File

@@ -864,9 +864,9 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
#define FINDFILE_DIR 1 // only directories
#define FINDFILE_BOTH 2 // files and directories
#define W_ENDCOL(wp) (wp->w_wincol + wp->w_width)
#define W_ENDCOL(wp) ((wp)->w_wincol + (wp)->w_width)
#ifdef FEAT_MENU
# define W_WINROW(wp) (wp->w_winrow + wp->w_winbar_height)
# define W_WINROW(wp) ((wp)->w_winrow + (wp)->w_winbar_height)
#else
# define W_WINROW(wp) (wp->w_winrow)
#endif
@@ -887,7 +887,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
# define SST_MAX_ENTRIES 1000 // maximal size for state stack array
# define SST_FIX_STATES 7 // size of sst_stack[].
# define SST_DIST 16 // normal distance between entries
# define SST_INVALID (synstate_T *)-1 // invalid syn_state pointer
# define SST_INVALID ((synstate_T *)-1) // invalid syn_state pointer
# define HL_CONTAINED 0x01 // not used on toplevel
# define HL_TRANSP 0x02 // has no highlighting
@@ -949,7 +949,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
#define GETFILE_ERROR 1 // normal error
#define GETFILE_NOT_WRITTEN 2 // "not written" error
#define GETFILE_SAME_FILE 0 // success, same file
#define GETFILE_OPEN_OTHER -1 // success, opened another file
#define GETFILE_OPEN_OTHER (-1) // success, opened another file
#define GETFILE_UNUSED 8
#define GETFILE_SUCCESS(x) ((x) <= 0)
@@ -971,9 +971,9 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
// Values for "noremap" argument of ins_typebuf(). Also used for
// map->m_noremap and menu->noremap[].
#define REMAP_YES 0 // allow remapping
#define REMAP_NONE -1 // no remapping
#define REMAP_SCRIPT -2 // remap script-local mappings only
#define REMAP_SKIP -3 // no remapping for first char
#define REMAP_NONE (-1) // no remapping
#define REMAP_SCRIPT (-2) // remap script-local mappings only
#define REMAP_SKIP (-3) // no remapping for first char
// Values for mch_call_shell() second argument
#define SHELL_FILTER 1 // filtering text
@@ -1069,7 +1069,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
// for lnum argument in do_ecmd()
#define ECMD_LASTL (linenr_T)0 // use last position in loaded file
#define ECMD_LAST (linenr_T)-1 // use last position in all files
#define ECMD_LAST ((linenr_T)-1) // use last position in all files
#define ECMD_ONE (linenr_T)1 // use first line
// flags for do_cmdline()
@@ -1265,13 +1265,13 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
#define MAX_SWAP_PAGE_SIZE 50000
// Special values for current_sctx.sc_sid.
#define SID_MODELINE -1 // when using a modeline
#define SID_CMDARG -2 // for "--cmd" argument
#define SID_CARG -3 // for "-c" argument
#define SID_ENV -4 // for sourcing environment variable
#define SID_ERROR -5 // option was reset because of an error
#define SID_NONE -6 // don't set scriptID
#define SID_WINLAYOUT -7 // changing window size
#define SID_MODELINE (-1) // when using a modeline
#define SID_CMDARG (-2) // for "--cmd" argument
#define SID_CARG (-3) // for "-c" argument
#define SID_ENV (-4) // for sourcing environment variable
#define SID_ERROR (-5) // option was reset because of an error
#define SID_NONE (-6) // don't set scriptID
#define SID_WINLAYOUT (-7) // changing window size
/*
* Events for autocommands.
@@ -1723,7 +1723,7 @@ void *vim_memset(void *, int, size_t);
// Prefer using emsgf(), because perror() may send the output to the wrong
// destination and mess up the screen.
#ifdef HAVE_STRERROR
# define PERROR(msg) (void)semsg("%s: %s", (char *)msg, strerror(errno))
# define PERROR(msg) (void)semsg("%s: %s", (char *)(msg), strerror(errno))
#else
# define PERROR(msg) do_perror(msg)
#endif
@@ -1921,7 +1921,7 @@ typedef int sock_T;
(((unsigned)((code) & 0xC0) >> 6) + 1)
#define SET_NUM_MOUSE_CLICKS(code, num) \
(code) = ((code) & 0x3f) | ((((num) - 1) & 3) << 6)
((code) = ((code) & 0x3f) | ((((num) - 1) & 3) << 6))
// Added to mouse column for GUI when 'mousefocus' wants to give focus to a
// window by simulating a click on its status line. We could use up to 128 *
@@ -2229,6 +2229,7 @@ typedef enum {
#define ASSIGN_UNPACK 0x10 // using [a, b] = list
#define ASSIGN_NO_MEMBER_TYPE 0x20 // use "any" for list and dict member type
#define ASSIGN_FOR_LOOP 0x40 // assigning to loop variable
#define ASSIGN_INIT 0x80 // not assigning a value, just a declaration
#include "ex_cmds.h" // Ex command defines
#include "spell.h" // spell checking stuff
@@ -2515,8 +2516,8 @@ typedef enum {
#endif
// values for vim_handle_signal() that are not a signal
#define SIGNAL_BLOCK -1
#define SIGNAL_UNBLOCK -2
#define SIGNAL_BLOCK (-1)
#define SIGNAL_UNBLOCK (-2)
#if !defined(UNIX) && !defined(VMS)
# define vim_handle_signal(x) 0
#endif
@@ -2528,8 +2529,8 @@ typedef enum {
// behavior for bad character, "++bad=" argument
#define BAD_REPLACE '?' // replace it with '?' (default)
#define BAD_KEEP -1 // leave it
#define BAD_DROP -2 // erase it
#define BAD_KEEP (-1) // leave it
#define BAD_DROP (-2) // erase it
// last argument for do_source()
#define DOSO_NONE 0
@@ -2552,11 +2553,11 @@ typedef enum {
// direction for nv_mousescroll() and ins_mousescroll()
#define MSCR_DOWN 0 // DOWN must be FALSE
#define MSCR_UP 1
#define MSCR_LEFT -1
#define MSCR_RIGHT -2
#define MSCR_LEFT (-1)
#define MSCR_RIGHT (-2)
#define KEYLEN_PART_KEY -1 // keylen value for incomplete key-code
#define KEYLEN_PART_MAP -2 // keylen value for incomplete mapping
#define KEYLEN_PART_KEY (-1) // keylen value for incomplete key-code
#define KEYLEN_PART_MAP (-2) // keylen value for incomplete mapping
#define KEYLEN_REMOVED 9999 // keylen value for removed sequence
// Return values from win32_fileinfo().
@@ -2716,8 +2717,8 @@ typedef enum {
#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
# define ELAPSED_TIMEVAL
# define ELAPSED_INIT(v) gettimeofday(&v, NULL)
# define ELAPSED_FUNC(v) elapsed(&v)
# define ELAPSED_INIT(v) gettimeofday(&(v), NULL)
# define ELAPSED_FUNC(v) elapsed(&(v))
typedef struct timeval elapsed_T;
long elapsed(struct timeval *start_tv);
#elif defined(MSWIN)
@@ -2734,8 +2735,8 @@ long elapsed(DWORD start_tick);
#endif
// Replacement for nchar used by nv_replace().
#define REPLACE_CR_NCHAR -1
#define REPLACE_NL_NCHAR -2
#define REPLACE_CR_NCHAR (-1)
#define REPLACE_NL_NCHAR (-2)
// flags for term_start()
#define TERM_START_NOJOB 1

View File

@@ -515,10 +515,10 @@ struct dfunc_S {
extern garray_T def_functions;
// Used for "lnum" when a range is to be taken from the stack.
#define LNUM_VARIABLE_RANGE -999
#define LNUM_VARIABLE_RANGE (-999)
// Used for "lnum" when a range is to be taken from the stack and "!" is used.
#define LNUM_VARIABLE_RANGE_ABOVE -888
#define LNUM_VARIABLE_RANGE_ABOVE (-888)
// Keep in sync with get_compile_type()
#ifdef FEAT_PROFILE
@@ -530,7 +530,7 @@ extern garray_T def_functions;
: (dfunc)->df_instr))
#else
# define INSTRUCTIONS(dfunc) \
(debug_break_level > 0 || may_break_in_function(dfunc->df_ufunc) \
(debug_break_level > 0 || may_break_in_function((dfunc)->df_ufunc) \
? (dfunc)->df_instr_debug \
: (dfunc)->df_instr)
#endif

View File

@@ -1336,20 +1336,22 @@ do_2string(typval_T *tv, int is_2string_any, int tolerant)
* When the value of "sv" is a null list of dict, allocate it.
*/
static void
allocate_if_null(typval_T *tv)
allocate_if_null(svar_T *sv)
{
typval_T *tv = sv->sv_tv;
switch (tv->v_type)
{
case VAR_LIST:
if (tv->vval.v_list == NULL)
if (tv->vval.v_list == NULL && sv->sv_type != &t_list_empty)
(void)rettv_list_alloc(tv);
break;
case VAR_DICT:
if (tv->vval.v_dict == NULL)
if (tv->vval.v_dict == NULL && sv->sv_type != &t_dict_empty)
(void)rettv_dict_alloc(tv);
break;
case VAR_BLOB:
if (tv->vval.v_blob == NULL)
if (tv->vval.v_blob == NULL && sv->sv_type != &t_blob_null)
(void)rettv_blob_alloc(tv);
break;
default:
@@ -2891,7 +2893,7 @@ exec_instructions(ectx_T *ectx)
sv = get_script_svar(sref, ectx->ec_dfunc_idx);
if (sv == NULL)
goto theend;
allocate_if_null(sv->sv_tv);
allocate_if_null(sv);
if (GA_GROW_FAILS(&ectx->ec_stack, 1))
goto theend;
copy_tv(sv->sv_tv, STACK_TV_BOT(0));

View File

@@ -822,7 +822,7 @@ vim9_declare_scriptvar(exarg_T *eap, char_u *arg)
init_tv.v_type = VAR_NUMBER;
else
init_tv.v_type = type->tt_type;
set_var_const(name, 0, type, &init_tv, FALSE, 0, 0);
set_var_const(name, 0, type, &init_tv, FALSE, ASSIGN_INIT, 0);
vim_free(name);
return p;
@@ -925,6 +925,13 @@ update_vim9_script_var(
if (*type == NULL)
*type = typval2type(tv, get_copyID(), &si->sn_type_list,
do_member ? TVTT_DO_MEMBER : 0);
else if ((flags & ASSIGN_INIT) == 0
&& (*type)->tt_type == VAR_BLOB && tv->v_type == VAR_BLOB
&& tv->vval.v_blob == NULL)
{
// "var b: blob = null_blob" has a different type.
*type = &t_blob_null;
}
if (sv->sv_type_allocated)
free_type(sv->sv_type);
if (*type != NULL && ((*type)->tt_type == VAR_FUNC

View File

@@ -337,7 +337,11 @@ typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int flags)
if (tv->v_type == VAR_STRING)
return &t_string;
if (tv->v_type == VAR_BLOB)
{
if (tv->vval.v_blob == NULL)
return &t_blob_null;
return &t_blob;
}
if (tv->v_type == VAR_LIST)
{