Compare commits

...

17 Commits

Author SHA1 Message Date
Bram Moolenaar
d0edaf9dc2 patch 8.2.2897: Vim9: can use reserved words at the script level
Problem:    Vim9: can use reserved words at the script level.
Solution:   Check variable names for reserved words. (closes #8253)
2021-05-28 21:06:08 +02:00
Dominique Pelle
dc3275a1ac patch 8.2.2896: spellfile functionality not fully tested
Problem:    Spellfile functionality not fully tested.
Solution:   Add tests for CHECKCOMPOUNDPATTERN and COMMON. (Dominique Pellé,
            closes #8270)
2021-05-28 18:32:12 +02:00
mityu
4ac198c61c patch 8.2.2895: Vim9: random characters appear in some error messages
Problem:    Vim9: random characters appear in some error messages.
Solution:   Pass the correct pointer. (closes #8277)
2021-05-28 17:52:40 +02:00
K.Takata
2c4a1d0a61 patch 8.2.2894: MS-Windows: using enc_locale() for strftime() might not work
Problem:    MS-Windows: using enc_locale() for strftime() might not work.
Solution:   Use wcsftime(). (Ken Takata, closes #8271)
2021-05-28 15:49:34 +02:00
Ralf Schandl
bc869874fe patch 8.2.2893: multi-byte text in popup title shows up wrong
Problem:    Multi-byte text in popup title shows up wrong.
Solution:   Use the character width instead of the byte length. (Ralf Schandl,
            closes #8267, closes #8264)
2021-05-28 14:12:14 +02:00
mityu
89dcb4dce3 patch 8.2.2892: error message contains random characters
Problem:    Error message contains random characters.
Solution:   Pass the right pointer to error_white_both(). (closes #8272,
            closes #8263)
2021-05-28 13:50:17 +02:00
ichizok
543467136f patch 8.2.2891: cannot build with Perl 5.34
Problem:    Cannot build with Perl 5.34.
Solution:   Add Perl_SvTRUE_common(). (Ozaki Kiichi, closes #8266,
            closes #8250)
2021-05-27 18:05:14 +02:00
Bram Moolenaar
840f91f110 patch 8.2.2890: text property duplicated when data block splits
Problem:    Text property duplicated when data block splits.
Solution:   Do not continue text prop from previous line. (closes #8261)
2021-05-26 22:32:10 +02:00
K.Takata
c512599b22 patch 8.2.2889: typo and verbose comment in Makefiles
Problem:    Typo and verbose comment in Makefiles.
Solution:   Fix typo. Use @#. (Ken Takata, closes #8252)
2021-05-26 21:49:18 +02:00
Bram Moolenaar
7d840e9ac7 patch 8.2.2888: Vim9: "k" command recognized in Vim9 script
Problem:    Vim9: "k" command recognized in Vim9 script.
Solution:   Do not recognize "k" or "s" and "d" with flags.
2021-05-26 21:10:11 +02:00
Bram Moolenaar
4c8e8c6e19 patch 8.2.2887: crash when passing null string to fullcommand()
Problem:    Crash when passing null string to fullcommand().
Solution:   Check for NULL pointer. (closes #8256)
2021-05-26 19:49:09 +02:00
Yegappan Lakshmanan
34fcb69724 patch 8.2.2886: various pieces of code not covered by tests
Problem:    Various pieces of code not covered by tests.
Solution:   Add a few more tests. (Yegappan Lakshmanan, closes #8255)
2021-05-25 20:14:00 +02:00
Bram Moolenaar
872bee557e patch 8.2.2885: searching for \%'> does not match linewise end of line
Problem:    searching for \%'> does not match linewise end of line. (Tim Chase)
Solution:   Match end of line if column is MAXCOL. (closes #8238)
2021-05-24 22:56:15 +02:00
Dominique Pelle
1e469c72ee patch 8.2.2884: not enough cscope code is covered by tests
Problem:    Not enough cscope code is covered by tests.
Solution:   Add a few test cases. (Dominique Pellé, closes #8246)
2021-05-24 19:37:26 +02:00
matveyt
e97c7c962c patch 8.2.2883: MS-Windows manifest file name is misleading
Problem:    MS-Windows manifest file name is misleading.
Solution:   Rename the file. (closes #8241)
2021-05-24 18:48:27 +02:00
Bram Moolenaar
15bbb8f4f3 patch 8.2.2882: Vim9: memory leak when lambda has an error
Problem:    Vim9: memory leak when lambda has an error.
Solution:   Free the list of argument types on failure.
2021-05-24 15:45:29 +02:00
Yegappan Lakshmanan
611728f806 patch 8.2.2881: various pieces of code not covered by tests
Problem:    Various pieces of code not covered by tests.
Solution:   Add a few more tests. (Yegappan Lakshmanan, closes #8245)
2021-05-24 15:15:47 +02:00
44 changed files with 589 additions and 89 deletions

1
.gitignore vendored
View File

@@ -25,7 +25,6 @@ src/auto/pathdef.c
# Windows
*.exe
*.idb
*.manifest
*.exp
*.map
*.obj

View File

@@ -26,7 +26,6 @@ src/auto/pathdef.c
# Windows
*.exe
*.idb
*.manifest
*.exp
*.map
*.obj

View File

@@ -567,7 +567,7 @@ SRC_DOS = \
src/uninstall.c \
src/vim.def \
src/vim.rc \
src/gvim.exe.mnf \
src/vim.manifest \
src/vimrun.c \
src/xpm_w32.c \
src/xpm_w32.h \

View File

@@ -94,7 +94,7 @@ MINOR = 2
# src/Makefile, README.txt, README.md, src/README.md, READMEdir/README*.txt,
# runtime/doc/*.txt and make nsis/gvim_version.nsh.
# For a minor/major version: src/GvimExt/GvimExt.reg, src/vim.def,
# src/gvim.exe.mnf.
# src/vim.manifest.
# - Compile Vim with GTK, Perl, Python, Python3, TCL, Ruby, Lua, Cscope and
# "huge" features. Add MZscheme if you can make it work.
# Use "make reconfig" after selecting the configure arguments.

View File

@@ -820,11 +820,11 @@ OBJ = \
$(OUTDIR)/window.o
ifeq ($(VIMDLL),yes)
OBJ += $(OUTDIR)/os_w32dll.o $(OUTDIR)/vimrcd.o
EXEOBJC = $(OUTDIR)/os_w32exec.o $(OUTDIR)/vimrcc.o
EXEOBJG = $(OUTDIR)/os_w32exeg.o $(OUTDIR)/vimrcg.o
OBJ += $(OUTDIR)/os_w32dll.o $(OUTDIR)/vimresd.o
EXEOBJC = $(OUTDIR)/os_w32exec.o $(OUTDIR)/vimresc.o
EXEOBJG = $(OUTDIR)/os_w32exeg.o $(OUTDIR)/vimresg.o
else
OBJ += $(OUTDIR)/os_w32exe.o $(OUTDIR)/vimrc.o
OBJ += $(OUTDIR)/os_w32exe.o $(OUTDIR)/vimres.o
endif
ifdef PERL
@@ -1145,21 +1145,21 @@ $(OUTDIR)/%.o : %.c $(INCL)
$(CC) -c $(CFLAGS) $< -o $@
ifeq ($(VIMDLL),yes)
$(OUTDIR)/vimrcc.o: vim.rc gvim.exe.mnf version.h gui_w32_rc.h vim.ico
$(OUTDIR)/vimresc.o: vim.rc vim.manifest version.h gui_w32_rc.h vim.ico
$(WINDRES) $(WINDRES_FLAGS) $(DEFINES) -UFEAT_GUI_MSWIN \
--input-format=rc --output-format=coff -i vim.rc -o $@
$(OUTDIR)/vimrcg.o: vim.rc gvim.exe.mnf version.h gui_w32_rc.h vim.ico
$(OUTDIR)/vimresg.o: vim.rc vim.manifest version.h gui_w32_rc.h vim.ico
$(WINDRES) $(WINDRES_FLAGS) $(DEFINES) \
--input-format=rc --output-format=coff -i vim.rc -o $@
$(OUTDIR)/vimrcd.o: vim.rc version.h gui_w32_rc.h \
$(OUTDIR)/vimresd.o: vim.rc version.h gui_w32_rc.h \
tools.bmp tearoff.bmp vim.ico vim_error.ico \
vim_alert.ico vim_info.ico vim_quest.ico
$(WINDRES) $(WINDRES_FLAGS) $(DEFINES) -DRCDLL -DVIMDLLBASE=\\\"$(VIMDLLBASE)\\\" \
--input-format=rc --output-format=coff -i vim.rc -o $@
else
$(OUTDIR)/vimrc.o: vim.rc gvim.exe.mnf version.h gui_w32_rc.h \
$(OUTDIR)/vimres.o: vim.rc vim.manifest version.h gui_w32_rc.h \
tools.bmp tearoff.bmp vim.ico vim_error.ico \
vim_alert.ico vim_info.ico vim_quest.ico
$(WINDRES) $(WINDRES_FLAGS) $(DEFINES) \

View File

@@ -1806,11 +1806,11 @@ $(OUTDIR)/xpm_w32.obj: $(OUTDIR) xpm_w32.c
$(CC) $(CFLAGS_OUTDIR) $(XPM_INC) xpm_w32.c
!if "$(VIMDLL)" == "yes"
$(OUTDIR)/vimc.res: $(OUTDIR) vim.rc gvim.exe.mnf version.h gui_w32_rc.h \
$(OUTDIR)/vimc.res: $(OUTDIR) vim.rc vim.manifest version.h gui_w32_rc.h \
vim.ico
$(RC) /nologo /l 0x409 /Fo$@ $(RCFLAGS:-DFEAT_GUI_MSWIN=) vim.rc
$(OUTDIR)/vimg.res: $(OUTDIR) vim.rc gvim.exe.mnf version.h gui_w32_rc.h \
$(OUTDIR)/vimg.res: $(OUTDIR) vim.rc vim.manifest version.h gui_w32_rc.h \
vim.ico
$(RC) /nologo /l 0x409 /Fo$@ $(RCFLAGS) vim.rc
@@ -1819,7 +1819,7 @@ $(OUTDIR)/vimd.res: $(OUTDIR) vim.rc version.h gui_w32_rc.h \
vim_alert.ico vim_info.ico vim_quest.ico
$(RC) /nologo /l 0x409 /Fo$@ $(RCFLAGS) -DRCDLL -DVIMDLLBASE=\"$(VIMDLLBASE)\" vim.rc
!else
$(OUTDIR)/vim.res: $(OUTDIR) vim.rc gvim.exe.mnf version.h gui_w32_rc.h \
$(OUTDIR)/vim.res: $(OUTDIR) vim.rc vim.manifest version.h gui_w32_rc.h \
tools.bmp tearoff.bmp vim.ico vim_error.ico \
vim_alert.ico vim_info.ico vim_quest.ico
$(RC) /nologo /l 0x409 /Fo$@ $(RCFLAGS) vim.rc

View File

@@ -1309,6 +1309,9 @@ set_var_lval(
{
cc = *endp;
*endp = NUL;
if (in_vim9script() && check_reserved_name(lp->ll_name) == FAIL)
return;
if (lp->ll_blob != NULL)
{
int error = FALSE, val;
@@ -2358,7 +2361,7 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
++*arg;
if (evaluate && vim9script && !IS_WHITE_OR_NUL((*arg)[1]))
{
error_white_both(p, op_falsy ? 2 : 1);
error_white_both(*arg - (op_falsy ? 1 : 0), op_falsy ? 2 : 1);
clear_tv(rettv);
return FAIL;
}
@@ -2406,7 +2409,7 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
*/
if (evaluate && vim9script && !IS_WHITE_OR_NUL((*arg)[1]))
{
error_white_both(p, 1);
error_white_both(*arg, 1);
clear_tv(rettv);
evalarg_used->eval_flags = orig_flags;
return FAIL;
@@ -2511,7 +2514,7 @@ eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
*/
if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[2]))
{
error_white_both(p, 2);
error_white_both(*arg, 2);
clear_tv(rettv);
return FAIL;
}
@@ -2637,7 +2640,7 @@ eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
*/
if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[2]))
{
error_white_both(p, 2);
error_white_both(*arg, 2);
clear_tv(rettv);
return FAIL;
}
@@ -2735,10 +2738,13 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
if (getnext)
{
*arg = eval_next_line(evalarg);
p = *arg;
}
else if (evaluate && vim9script && !VIM_ISWHITE(**arg))
{
error_white_both(p, len);
error_white_both(*arg, len);
clear_tv(rettv);
return FAIL;
}
@@ -2898,7 +2904,7 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
{
if (evaluate && vim9script && !VIM_ISWHITE(**arg))
{
error_white_both(p, oplen);
error_white_both(*arg, oplen);
clear_tv(rettv);
return FAIL;
}
@@ -2934,7 +2940,7 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
*/
if (evaluate && vim9script && !IS_WHITE_OR_NUL((*arg)[oplen]))
{
error_white_both(p, oplen);
error_white_both(*arg, oplen);
clear_tv(rettv);
return FAIL;
}
@@ -3130,7 +3136,7 @@ eval6(
{
if (evaluate && in_vim9script() && !VIM_ISWHITE(**arg))
{
error_white_both(p, 1);
error_white_both(*arg, 1);
clear_tv(rettv);
return FAIL;
}

View File

@@ -3392,8 +3392,11 @@ find_ex_command(
int len;
char_u *p;
int i;
#ifndef FEAT_EVAL
int vim9 = FALSE;
#else
int vim9 = in_vim9script();
#ifdef FEAT_EVAL
/*
* Recognize a Vim9 script function/method call and assignment:
* "lvar = value", "lvar(arg)", "[1, 2 3]->Func()"
@@ -3556,12 +3559,13 @@ find_ex_command(
* - the "d" command can directly be followed by 'l' or 'p' flag.
*/
p = eap->cmd;
if (*p == 'k')
if (!vim9 && *p == 'k')
{
eap->cmdidx = CMD_k;
++p;
}
else if (p[0] == 's'
else if (!vim9
&& p[0] == 's'
&& ((p[1] == 'c' && (p[2] == NUL || (p[2] != 's' && p[2] != 'r'
&& (p[3] == NUL || (p[3] != 'i' && p[4] != 'p')))))
|| p[1] == 'g'
@@ -3594,7 +3598,7 @@ find_ex_command(
if (p == eap->cmd && vim_strchr((char_u *)"@*!=><&~#}", *p) != NULL)
++p;
len = (int)(p - eap->cmd);
if (*eap->cmd == 'd' && (p[-1] == 'l' || p[-1] == 'p'))
if (!vim9 && *eap->cmd == 'd' && (p[-1] == 'l' || p[-1] == 'p'))
{
// Check for ":dl", ":dell", etc. to ":deletel": that's
// :delete with the 'l' flag. Same for 'p'.
@@ -3671,7 +3675,7 @@ find_ex_command(
#ifdef FEAT_EVAL
if (eap->cmdidx < CMD_SIZE
&& in_vim9script()
&& vim9
&& !IS_WHITE_OR_NUL(*p) && *p != '\n' && *p != '!'
&& (eap->cmdidx < 0 ||
(cmdnames[eap->cmdidx].cmd_argt & EX_NONWHITE_OK) == 0))
@@ -3791,17 +3795,32 @@ f_fullcommand(typval_T *argvars, typval_T *rettv)
char_u *name = argvars[0].vval.v_string;
char_u *p;
while (name[0] != NUL && name[0] == ':')
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
if (name == NULL)
return;
while (*name != NUL && *name == ':')
name++;
name = skip_range(name, TRUE, NULL);
rettv->v_type = VAR_STRING;
ea.cmd = (*name == '2' || *name == '3') ? name + 1 : name;
ea.cmdidx = (cmdidx_T)0;
ea.addr_count = 0;
p = find_ex_command(&ea, NULL, NULL, NULL);
if (p == NULL || ea.cmdidx == CMD_SIZE)
return;
if (in_vim9script())
{
int res;
++emsg_silent;
res = not_in_vim9(&ea);
--emsg_silent;
if (res == FAIL)
return;
}
rettv->vval.v_string = vim_strsave(IS_USER_CMDIDX(ea.cmdidx)
? get_user_commands(NULL, ea.useridx)

View File

@@ -700,12 +700,41 @@ S_POPMARK(pTHX)
/* perl-5.32 needs Perl_POPMARK */
# if (PERL_REVISION == 5) && (PERL_VERSION >= 32)
# define Perl_POPMARK S_POPMARK
# endif
/* perl-5.34 needs Perl_SvTRUE_common; used in SvTRUE_nomg_NN */
# if (PERL_REVISION == 5) && (PERL_VERSION >= 34)
PERL_STATIC_INLINE bool
Perl_SvTRUE_common(pTHX_ SV * sv, const bool sv_2bool_is_fallback)
{
if (UNLIKELY(SvIMMORTAL_INTERP(sv)))
return SvIMMORTAL_TRUE(sv);
if (! SvOK(sv))
return FALSE;
if (SvPOK(sv))
return SvPVXtrue(sv);
if (SvIOK(sv))
return SvIVX(sv) != 0; /* casts to bool */
if (SvROK(sv) && !(SvOBJECT(SvRV(sv)) && HvAMAGIC(SvSTASH(SvRV(sv)))))
return TRUE;
if (sv_2bool_is_fallback)
return sv_2bool_nomg(sv);
return isGV_with_GP(sv);
}
# endif
/* perl-5.32 needs Perl_SvTRUE */
# if (PERL_REVISION == 5) && (PERL_VERSION >= 32)
PERL_STATIC_INLINE bool
Perl_SvTRUE(pTHX_ SV *sv) {
if (!LIKELY(sv))
return FALSE;
return FALSE;
SvGETMAGIC(sv);
return SvTRUE_nomg_NN(sv);
}

View File

@@ -2772,7 +2772,8 @@ ml_append_int(
len = (colnr_T)STRLEN(line) + 1; // space needed for the text
#ifdef FEAT_PROP_POPUP
if (curbuf->b_has_textprop && lnum > 0 && !(flags & ML_APPEND_UNDO))
if (curbuf->b_has_textprop && lnum > 0
&& !(flags & (ML_APPEND_UNDO | ML_APPEND_NOPROP)))
// Add text properties that continue from the previous line.
add_text_props_for_append(buf, lnum, &line, &len, &tofree);
#endif
@@ -3992,7 +3993,11 @@ ml_flush_line(buf_T *buf)
*/
// How about handling errors???
(void)ml_append_int(buf, lnum, new_line, new_len,
(dp->db_index[idx] & DB_MARKED) ? ML_APPEND_MARK : 0);
((dp->db_index[idx] & DB_MARKED) ? ML_APPEND_MARK : 0)
#ifdef FEAT_PROP_POPUP
| ML_APPEND_NOPROP
#endif
);
(void)ml_delete_int(buf, lnum, 0);
}
}

View File

@@ -120,6 +120,37 @@ test_trunc_string(void)
vim_free(s);
}
/*
* Test trunc_string() with mbyte chars.
*/
static void
test_trunc_string_mbyte(void)
{
char_u *buf; // allocated every time to find uninit errors
char_u *s;
buf = alloc(40);
s = vim_strsave((char_u *)"Ä text tha just fits");
trunc_string(s, buf, 20, 40);
assert(STRCMP(buf, "Ä text tha just fits") == 0);
vim_free(buf);
vim_free(s);
buf = alloc(40);
s = vim_strsave((char_u *)"a text ÄÖÜä nott fits");
trunc_string(s, buf, 20, 40);
assert(STRCMP(buf, "a text Ä...nott fits") == 0);
vim_free(buf);
vim_free(s);
buf = alloc(40);
s = vim_strsave((char_u *)"a text that not fitsÄ");
trunc_string(s, buf, 20, 40);
assert(STRCMP(buf, "a text t...not fitsÄ") == 0);
vim_free(buf);
vim_free(s);
}
/*
* Test vim_snprintf() with a focus on checking that truncation is
* correct when buffer is small, since it cannot be tested from
@@ -286,6 +317,7 @@ main(int argc, char **argv)
set_option_value((char_u *)"encoding", 0, (char_u *)"utf-8", 0);
init_chartab();
test_trunc_string();
test_trunc_string_mbyte();
test_vim_snprintf();
set_option_value((char_u *)"encoding", 0, (char_u *)"latin1", 0);

View File

@@ -3822,17 +3822,29 @@ update_popups(void (*win_update)(win_T *wp))
title_wincol = wp->w_wincol + 1;
if (wp->w_popup_title != NULL)
{
char_u *title_text;
title_len = (int)MB_CHARLEN(wp->w_popup_title);
title_len = (int)STRLEN(wp->w_popup_title);
title_text = alloc(title_len + 1);
trunc_string(wp->w_popup_title, title_text,
total_width - 2, title_len + 1);
screen_puts(title_text, wp->w_winrow, title_wincol,
wp->w_popup_border[0] > 0 ? border_attr[0] : popup_attr);
vim_free(title_text);
// truncate the title if too long
if (title_len > total_width - 2)
{
int title_byte_len = (int)STRLEN(wp->w_popup_title);
char_u *title_text = alloc(title_byte_len + 1);
if (title_text != NULL)
{
trunc_string(wp->w_popup_title, title_text,
total_width - 2, title_byte_len + 1);
screen_puts(title_text, wp->w_winrow, title_wincol,
wp->w_popup_border[0] > 0
? border_attr[0] : popup_attr);
vim_free(title_text);
}
title_len = total_width - 2;
}
else
screen_puts(wp->w_popup_title, wp->w_winrow, title_wincol,
wp->w_popup_border[0] > 0 ? border_attr[0] : popup_attr);
}
wincol = wp->w_wincol - wp->w_popup_leftoff;

View File

@@ -18,4 +18,5 @@ void hide_script_var(scriptitem_T *si, int idx, int func_defined);
void free_all_script_vars(scriptitem_T *si);
svar_T *find_typval_in_script(typval_T *dest);
int check_script_var_type(typval_T *dest, typval_T *value, char_u *name, where_T where);
int check_reserved_name(char_u *name);
/* vim: set ft=c : */

View File

@@ -3357,17 +3357,29 @@ regmatch(
pos = getmark_buf(rex.reg_buf, mark, FALSE);
if (pos == NULL // mark doesn't exist
|| pos->lnum <= 0 // mark isn't set in reg_buf
|| (pos->lnum == rex.lnum + rex.reg_firstlnum
? (pos->col == (colnr_T)(rex.input - rex.line)
|| pos->lnum <= 0) // mark isn't set in reg_buf
{
status = RA_NOMATCH;
}
else
{
colnr_T pos_col = pos->lnum == rex.lnum + rex.reg_firstlnum
&& pos->col == MAXCOL
? (colnr_T)STRLEN(reg_getline(
pos->lnum - rex.reg_firstlnum))
: pos->col;
if ((pos->lnum == rex.lnum + rex.reg_firstlnum
? (pos_col == (colnr_T)(rex.input - rex.line)
? (cmp == '<' || cmp == '>')
: (pos->col < (colnr_T)(rex.input - rex.line)
: (pos_col < (colnr_T)(rex.input - rex.line)
? cmp != '>'
: cmp != '<'))
: (pos->lnum < rex.lnum + rex.reg_firstlnum
? cmp != '>'
: cmp != '<')))
status = RA_NOMATCH;
}
}
break;

View File

@@ -6806,22 +6806,30 @@ nfa_regmatch(
{
pos_T *pos = getmark_buf(rex.reg_buf, t->state->val, FALSE);
// Compare the mark position to the match position.
result = (pos != NULL // mark doesn't exist
&& pos->lnum > 0 // mark isn't set in reg_buf
&& (pos->lnum == rex.lnum + rex.reg_firstlnum
? (pos->col == (colnr_T)(rex.input - rex.line)
// Compare the mark position to the match position, if the mark
// exists and mark is set in reg_buf.
if (pos != NULL && pos->lnum > 0)
{
colnr_T pos_col = pos->lnum == rex.lnum + rex.reg_firstlnum
&& pos->col == MAXCOL
? (colnr_T)STRLEN(reg_getline(
pos->lnum - rex.reg_firstlnum))
: pos->col;
result = (pos->lnum == rex.lnum + rex.reg_firstlnum
? (pos_col == (colnr_T)(rex.input - rex.line)
? t->state->c == NFA_MARK
: (pos->col < (colnr_T)(rex.input - rex.line)
: (pos_col < (colnr_T)(rex.input - rex.line)
? t->state->c == NFA_MARK_GT
: t->state->c == NFA_MARK_LT))
: (pos->lnum < rex.lnum + rex.reg_firstlnum
? t->state->c == NFA_MARK_GT
: t->state->c == NFA_MARK_LT)));
if (result)
{
add_here = TRUE;
add_state = t->state->out;
: t->state->c == NFA_MARK_LT));
if (result)
{
add_here = TRUE;
add_state = t->state->out;
}
}
break;
}

View File

@@ -774,6 +774,7 @@ typedef struct memline
#define ML_APPEND_NEW 1 // starting to edit a new file
#define ML_APPEND_MARK 2 // mark the new line
#define ML_APPEND_UNDO 4 // called from undo
#define ML_APPEND_NOPROP 8 // do not continue textprop from previous line
/*

View File

@@ -40,7 +40,7 @@ tiny: nolog tinytests report
benchmark: $(SCRIPTS_BENCH)
report:
# without the +eval feature test_result.log is a copy of test.log
@# without the +eval feature test_result.log is a copy of test.log
@/bin/sh -c "if test -f test.log; \
then cp test.log test_result.log; \
else echo No failures reported > test_result.log; \

View File

@@ -0,0 +1,10 @@
>1+0&#ffffff0| @73
|2| @73
|3| @73
|4| @25|╔+0#0000001#ffd7ff255|▶|Ä|Ö|Ü|◀|═@12|╗| +0#0000000#ffffff0@27
|5| @25|║+0#0000001#ffd7ff255| |T+0&#e0e0e08|h|i|s| |i|s| |a| |l|i|n|e| @1| +0&#ffd7ff255|║| +0#0000000#ffffff0@27
|6| @25|║+0#0000001#ffd7ff255| |a|n|d| |a|n|o|t|h|e|r| |l|i|n|e| |║| +0#0000000#ffffff0@27
|7| @25|╚+0#0000001#ffd7ff255|═@17|╝| +0#0000000#ffffff0@27
|8| @73
|9| @73
@57|1|,|1| @10|T|o|p|

View File

@@ -475,6 +475,7 @@ func Test_fullcommand()
for [in, want] in items(tests)
call assert_equal(want, fullcommand(in))
endfor
call assert_equal('', fullcommand(test_null_string()))
call assert_equal('syntax', 'syn'->fullcommand())
endfunc

View File

@@ -223,8 +223,28 @@ func Test_lockvar()
call add(val, 4)
call assert_equal([9, 2, 3, 4], val)
call assert_fails('let val = [4, 5, 6]', 'E1122:')
endfunc
let l =<< trim END
let d = {}
lockvar d
func d.fn()
return 1
endfunc
END
let @a = l->join("\n")
call assert_fails('exe @a', 'E741:')
let l =<< trim END
let d = {}
let d.fn = function("min")
lockvar d.fn
func! d.fn()
return 1
endfunc
END
let @a = l->join("\n")
call assert_fails('exe @a', 'E741:')
endfunc
func Test_const_with_index_access()
let l = [1, 2, 3]

View File

@@ -119,6 +119,7 @@ func Test_cscopeWithCscopeConnections()
endfor
" Test: Invalid find command
call assert_fails('cs find', 'E560:')
call assert_fails('cs find x', 'E560:')
if has('float')
@@ -180,12 +181,19 @@ func Test_cscopeWithCscopeConnections()
let a = execute('cstag TEST_COUNT')
call assert_match('(1 of 1): <<TEST_COUNT>> #define TEST_COUNT 50000', a)
call assert_equal('#define TEST_COUNT 50000', getline('.'))
call assert_fails('cstag DOES_NOT_EXIST', 'E257:')
set csto=1
let a = execute('cstag index_to_key')
call assert_match('(1 of 1): <<index_to_key>> #define index_to_key(i) ((i) ^ 15167)', a)
call assert_equal('#define index_to_key(i) ((i) ^ 15167)', getline('.'))
call assert_fails('cstag xxx', 'E257:')
call assert_fails('cstag DOES_NOT_EXIST', 'E257:')
call assert_fails('cstag', 'E562:')
let save_tags = &tags
set tags=
call assert_fails('cstag DOES_NOT_EXIST', 'E257:')
let a = execute('cstag index_to_key')
call assert_match('(1 of 1): <<index_to_key>> #define index_to_key(i) ((i) ^ 15167)', a)
let &tags = save_tags
" Test: 'cst' option
set nocst
@@ -209,12 +217,16 @@ func Test_cscopeWithCscopeConnections()
cd ..
call delete('Xcscoperelative', 'd')
" Test: E259: no match found
call assert_fails('cscope find g DOES_NOT_EXIST', 'E259:')
" Test: this should trigger call to cs_print_tags()
" Unclear how to check result though, we just exercise the code.
set cst cscopequickfix=s0
call feedkeys(":cs find s main\<CR>", 't')
" Test: cscope kill
call assert_fails('cscope kill', 'E560:')
call assert_fails('cscope kill 2', 'E261:')
call assert_fails('cscope kill xxx', 'E261:')

View File

@@ -127,6 +127,7 @@ func Test_getreg_empty_list()
let y = x
call add(x, 'foo')
call assert_equal(['foo'], y)
call assert_fails('call getreg([])', 'E730:')
endfunc
func Test_loop_over_null_list()

View File

@@ -141,6 +141,7 @@ func Test_min()
call assert_fails('call min(1)', 'E712:')
call assert_fails('call min(v:none)', 'E712:')
call assert_fails('call min([1, {}])', 'E728:')
" check we only get one error
call assert_fails('call min([[1], #{}])', ['E745:', 'E745:'])
@@ -715,6 +716,7 @@ func Test_tr()
call assert_fails("let s=tr('abcd', 'abcd', 'def')", 'E475:')
call assert_equal('hEllO', tr('hello', 'eo', 'EO'))
call assert_equal('hello', tr('hello', 'xy', 'ab'))
call assert_fails('call tr("abc", "123", "₁₂")', 'E475:')
set encoding=utf8
endfunc
@@ -1843,6 +1845,10 @@ func Test_func_exists_on_reload()
call writefile(['func ExistingFunction()', 'echo "yes"', 'endfunc'], 'Xfuncexists2')
call assert_fails('source Xfuncexists2', 'E122:')
" Defining a new function from the cmdline should fail if the function is
" already defined
call assert_fails('call feedkeys(":func ExistingFunction()\<CR>", "xt")', 'E122:')
delfunc ExistingFunction
call assert_equal(0, exists('*ExistingFunction'))
call writefile([
@@ -2670,4 +2676,9 @@ func Test_default_arg_value()
call assert_equal('msg', HasDefault())
endfunc
" Test for gettext()
func Test_gettext()
call assert_fails('call gettext(1)', 'E475:')
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -513,6 +513,11 @@ func Test_list_locked_var_unlet()
call assert_equal(expected[depth][u][1], ps)
endfor
endfor
" Deleting a list range should fail if the range is locked
let l = [1, 2, 3, 4]
lockvar l[1:2]
call assert_fails('unlet l[1:2]', 'E741:')
unlet l
endfunc
" Locked variables and :unlet or list / dict functions

View File

@@ -1799,6 +1799,11 @@ func Test_popup_title()
call term_sendkeys(buf, ":\<CR>")
call VerifyScreenDump(buf, 'Test_popupwin_longtitle_4', {})
call term_sendkeys(buf, ":call popup_clear()\<CR>")
call term_sendkeys(buf, ":call popup_menu(['This is a line', 'and another line'], #{title: '▶ÄÖÜ◀', })\<CR>")
call VerifyScreenDump(buf, 'Test_popupwin_multibytetitle', {})
call term_sendkeys(buf, "x")
" clean up
call StopVimInTerminal(buf)
call delete('XtestPopupTitle')

View File

@@ -314,6 +314,8 @@ func Test_python_window()
10new
py vim.current.window.height = 5
call assert_equal(5, winheight(0))
py vim.current.window.height = 3.2
call assert_equal(3, winheight(0))
" Test for setting the window width
10vnew

View File

@@ -511,6 +511,8 @@ func Test_python3_window()
10new
py3 vim.current.window.height = 5
call assert_equal(5, winheight(0))
py3 vim.current.window.height = 3.2
call assert_equal(3, winheight(0))
" Test for setting the window width
10vnew

View File

@@ -281,6 +281,7 @@ endfunc
func Test_set_register()
call assert_fails("call setreg('#', 200)", 'E86:')
call assert_fails("call setreg('a', test_unknown())", 'E908:')
edit Xfile_alt_1
let b1 = bufnr('')
@@ -470,6 +471,14 @@ func Test_get_reginfo()
let info = getreginfo('"')
call assert_equal('z', info.points_to)
let @a="a1b2"
nnoremap <F2> <Cmd>let g:RegInfo = getreginfo()<CR>
exe "normal \"a\<F2>"
call assert_equal({'regcontents': ['a1b2'], 'isunnamed': v:false,
\ 'regtype': 'v'}, g:RegInfo)
nunmap <F2>
unlet g:RegInfo
bwipe!
endfunc

View File

@@ -1332,13 +1332,28 @@ func Test_look_behind()
bwipe!
endfunc
func Test_search_visual_area_linewise()
new
call setline(1, ['aa', 'bb', 'cc'])
exe "normal 2GV\<Esc>"
for engine in [1, 2]
exe 'set regexpengine=' .. engine
exe "normal gg/\\%'<\<CR>>"
call assert_equal([0, 2, 1, 0, 1], getcurpos(), 'engine ' .. engine)
exe "normal gg/\\%'>\<CR>"
call assert_equal([0, 2, 2, 0, 2], getcurpos(), 'engine ' .. engine)
endfor
bwipe!
set regexpengine&
endfunc
func Test_search_sentence()
new
" this used to cause a crash
call assert_fails("/\\%')", 'E486:')
call assert_fails("/", 'E486:')
/\%'(
/
bwipe
endfunc
" Test that there is no crash when there is a last search pattern but no last

View File

@@ -842,6 +842,72 @@ func Test_spell_add_word()
%bw!
endfunc
" Test CHECKCOMPOUNDPATTERN (see :help spell-CHECKCOMPOUNDPATTERN)
func Test_spellfile_CHECKCOMPOUNDPATTERN()
call writefile(['4',
\ 'one/c',
\ 'two/c',
\ 'three/c',
\ 'four'], 'XtestCHECKCOMPOUNDPATTERN.dic')
" Forbid compound words where first word ends with 'wo' and second starts with 'on'.
call writefile(['CHECKCOMPOUNDPATTERN 1',
\ 'CHECKCOMPOUNDPATTERN wo on',
\ 'COMPOUNDFLAG c'], 'XtestCHECKCOMPOUNDPATTERN.aff')
let output = execute('mkspell! XtestCHECKCOMPOUNDPATTERN-utf8.spl XtestCHECKCOMPOUNDPATTERN')
set spell spelllang=XtestCHECKCOMPOUNDPATTERN-utf8.spl
" Check valid words with and without valid compounds.
for goodword in ['one', 'two', 'three', 'four',
\ 'oneone', 'onetwo', 'onethree',
\ 'twotwo', 'twothree',
\ 'threeone', 'threetwo', 'threethree',
\ 'onetwothree', 'onethreetwo', 'twothreeone', 'oneoneone']
call assert_equal(['', ''], spellbadword(goodword), goodword)
endfor
" Compounds 'twoone' or 'threetwoone' should be forbidden by CHECKCOMPOUNPATTERN.
" 'four' does not have the 'c' flag in *.aff file so no compound.
" 'five' is not in the *.dic file.
for badword in ['five', 'onetwox',
\ 'twoone', 'threetwoone',
\ 'fourone', 'onefour']
call assert_equal([badword, 'bad'], spellbadword(badword))
endfor
set spell& spelllang&
call delete('XtestCHECKCOMPOUNDPATTERN.dic')
call delete('XtestCHECKCOMPOUNDPATTERN.aff')
call delete('XtestCHECKCOMPOUNDPATTERN-utf8.spl')
endfunc
" Test COMMON (better suggestions with common words, see :help spell-COMMON)
func Test_spellfile_COMMON()
call writefile(['7',
\ 'and',
\ 'ant',
\ 'end',
\ 'any',
\ 'tee',
\ 'the',
\ 'ted'], 'XtestCOMMON.dic')
call writefile(['COMMON the and'], 'XtestCOMMON.aff')
let output = execute('mkspell! XtestCOMMON-utf8.spl XtestCOMMON')
set spell spelllang=XtestCOMMON-utf8.spl
" COMMON words 'and' and 'the' should be the top suggestions.
call assert_equal(['and', 'ant'], spellsuggest('anr', 2))
call assert_equal(['and', 'end'], spellsuggest('ond', 2))
call assert_equal(['the', 'ted'], spellsuggest('tha', 2))
call assert_equal(['the', 'tee'], spellsuggest('dhe', 2))
set spell& spelllang&
call delete('XtestCOMMON.dic')
call delete('XtestCOMMON.aff')
call delete('XtestCOMMON-utf8.spl')
endfunc
" When 'spellfile' is not set, adding a new good word will automatically set
" the 'spellfile'
func Test_init_spellfile()

View File

@@ -1469,5 +1469,24 @@ func Test_prop_one_line_window()
bwipe!
endfunc
" This was calling ml_append_int() and copy a text property from a previous
" line at the wrong moment. Exact text length matters.
def Test_prop_splits_data_block()
new
var lines: list<string> = [repeat('x', 35)]->repeat(41)
+ [repeat('!', 35)]
+ [repeat('x', 35)]->repeat(56)
lines->setline(1)
prop_type_add('someprop', {highlight: 'ErrorMsg'})
prop_add(1, 27, {end_lnum: 1, end_col: 70, type: 'someprop'})
prop_remove({type: 'someprop'}, 1)
prop_add(35, 22, {end_lnum: 43, end_col: 43, type: 'someprop'})
prop_remove({type: 'someprop'}, 35, 43)
assert_equal([], prop_list(42))
bwipe!
prop_type_delete('someprop')
enddef
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -160,6 +160,16 @@ func Test_default_arg()
\ .. "1 return deepcopy(a:)\n"
\ .. " endfunction",
\ execute('func Args2'))
" Error in default argument expression
let l =<< trim END
func F1(x = y)
return a:x * 2
endfunc
echo F1()
END
let @a = l->join("\n")
call assert_fails("exe @a", 'E121:')
endfunc
func s:addFoo(lead)
@@ -405,6 +415,7 @@ func Test_func_def_error()
let l = join(lines, "\n") . "\n"
exe l
call assert_fails('exe l', 'E717:')
call assert_fails('call feedkeys(":func d.F1()\<CR>", "xt")', 'E717:')
" Define an autoload function with an incorrect file name
call writefile(['func foo#Bar()', 'return 1', 'endfunc'], 'Xscript')
@@ -420,6 +431,11 @@ func Test_del_func()
call assert_fails('delfunction Xabc', 'E130:')
let d = {'a' : 10}
call assert_fails('delfunc d.a', 'E718:')
func d.fn()
return 1
endfunc
delfunc d.fn
call assert_equal({'a' : 10}, d)
endfunc
" Test for calling return outside of a function
@@ -451,11 +467,12 @@ func Test_func_dict()
return len(self)
endfunc
call assert_equal("{'a': 'b', 'somefunc': function('2')}", string(mydict))
call assert_equal("{'a': 'b', 'somefunc': function('3')}", string(mydict))
call assert_equal(2, mydict.somefunc())
call assert_match("^\n function \\d\\\+() dict"
\ .. "\n1 return len(self)"
\ .. "\n endfunction$", execute('func mydict.somefunc'))
call assert_fails('call mydict.nonexist()', 'E716:')
endfunc
func Test_func_range()

View File

@@ -249,6 +249,13 @@ def Test_assignment()
END
enddef
def Test_reserved_name()
for name in ['true', 'false', 'null']
CheckDefExecAndScriptFailure(['var ' .. name .. ' = 0'], 'E1034:')
CheckDefExecAndScriptFailure(['var ' .. name .. ': bool'], 'E1034:')
endfor
enddef
def Test_skipped_assignment()
var lines =<< trim END
for x in []

View File

@@ -363,6 +363,7 @@ def Test_extend_arg_types()
END
CheckDefAndScriptSuccess(lines)
CheckDefFailure(['extend("a", 1)'], 'E1013: Argument 1: type mismatch, expected list<any> but got string')
CheckDefFailure(['extend([1, 2], 3)'], 'E1013: Argument 2: type mismatch, expected list<number> but got number')
CheckDefFailure(['extend([1, 2], ["x"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>')
CheckDefFailure(['extend([1, 2], [3], "x")'], 'E1013: Argument 3: type mismatch, expected number but got string')
@@ -553,6 +554,29 @@ def Test_filter_missing_argument()
res->assert_equal({aa: [1], ac: [3]})
enddef
def Test_fullcommand()
assert_equal('next', fullcommand('n'))
assert_equal('noremap', fullcommand('no'))
assert_equal('noremap', fullcommand('nor'))
assert_equal('normal', fullcommand('norm'))
assert_equal('', fullcommand('k'))
assert_equal('keepmarks', fullcommand('ke'))
assert_equal('keepmarks', fullcommand('kee'))
assert_equal('keepmarks', fullcommand('keep'))
assert_equal('keepjumps', fullcommand('keepj'))
assert_equal('dlist', fullcommand('dl'))
assert_equal('', fullcommand('dp'))
assert_equal('delete', fullcommand('del'))
assert_equal('', fullcommand('dell'))
assert_equal('', fullcommand('delp'))
assert_equal('srewind', fullcommand('sre'))
assert_equal('scriptnames', fullcommand('scr'))
assert_equal('', fullcommand('scg'))
enddef
def Test_garbagecollect()
garbagecollect(true)
enddef
@@ -726,6 +750,12 @@ def Test_insert()
endfor
res->assert_equal(6)
var m: any = []
insert(m, 4)
call assert_equal([4], m)
extend(m, [6], 0)
call assert_equal([6, 4], m)
var lines =<< trim END
insert(test_null_list(), 123)
END
@@ -743,6 +773,7 @@ def Test_insert()
assert_equal(['a', 'b', 'c'], insert(['b', 'c'], 'a'))
assert_equal(0z1234, insert(0z34, 0x12))
CheckDefFailure(['insert("a", 1)'], 'E1013: Argument 1: type mismatch, expected list<any> but got string', 1)
CheckDefFailure(['insert([2, 3], "a")'], 'E1013: Argument 2: type mismatch, expected number but got string', 1)
CheckDefFailure(['insert([2, 3], 1, "x")'], 'E1013: Argument 3: type mismatch, expected number but got string', 1)
enddef

View File

@@ -172,11 +172,23 @@ func Test_expr1_trinary_fails()
call CheckDefAndScriptFailure(["var x = 1? 'one' : 'two'"], msg, 1)
call CheckDefAndScriptFailure(["var x = 1 ?'one' : 'two'"], msg, 1)
call CheckDefAndScriptFailure(["var x = 1?'one' : 'two'"], msg, 1)
let lines =<< trim END
var x = 1
?'one' : 'two'
# comment
END
call CheckDefAndScriptFailure(lines, 'E1004: White space required before and after ''?'' at "?''one'' : ''two''"', 2)
let msg = "White space required before and after ':'"
call CheckDefAndScriptFailure(["var x = 1 ? 'one': 'two'"], msg, 1)
call CheckDefAndScriptFailure(["var x = 1 ? 'one' :'two'"], msg, 1)
call CheckDefAndScriptFailure(["var x = 1 ? 'one':'two'"], msg, 1)
let lines =<< trim END
var x = 1 ? 'one'
:'two'
# Comment
END
call CheckDefAndScriptFailure(lines, 'E1004: White space required before and after '':'' at ":''two''"', 2)
call CheckDefAndScriptFailure(["var x = 'x' ? 'one' : 'two'"], 'E1135:', 1)
call CheckDefAndScriptFailure(["var x = 0z1234 ? 'one' : 'two'"], 'E974:', 1)
@@ -229,6 +241,12 @@ def Test_expr1_falsy()
call CheckDefAndScriptFailure(["var x = 1?? 'one' : 'two'"], msg, 1)
call CheckDefAndScriptFailure(["var x = 1 ??'one' : 'two'"], msg, 1)
call CheckDefAndScriptFailure(["var x = 1??'one' : 'two'"], msg, 1)
lines =<< trim END
var x = 1
??'one' : 'two'
#comment
END
CheckDefAndScriptFailure(lines, 'E1004: White space required before and after ''??'' at "??''one'' : ''two''"', 2)
enddef
def Record(val: any): any
@@ -376,6 +394,13 @@ def Test_expr2_fails()
call CheckDefAndScriptFailure2(["var x = [] || false"], 'E1012: Type mismatch; expected bool but got list<unknown>', 'E745:', 1)
var lines =<< trim END
vim9script
echo false
||true
# comment
END
CheckScriptFailure(lines, 'E1004: White space required before and after ''||'' at "||true"', 3)
enddef
" test &&
@@ -476,13 +501,19 @@ def Test_expr3_fails()
CheckDefAndScriptFailure(["var x = 1&&2"], msg, 1)
CheckDefAndScriptFailure(["var x = 1 &&2"], msg, 1)
CheckDefAndScriptFailure(["var x = 1&& 2"], msg, 1)
var lines =<< trim END
var x = 1
&&2
# comment
END
CheckDefAndScriptFailure(lines, 'E1004: White space required before and after ''&&'' at "&&2"', 2)
g:vals = []
CheckDefAndScriptFailure2(["if 'yes' && 0", 'echo 0', 'endif'], 'E1012: Type mismatch; expected bool but got string', 'E1135: Using a String as a Bool', 1)
CheckDefExecAndScriptFailure(['assert_equal(false, Record(1) && Record(4) && Record(0))'], 'E1023: Using a Number as a Bool: 4', 1)
var lines =<< trim END
lines =<< trim END
if 3
&& true
endif
@@ -976,6 +1007,12 @@ def Test_expr4_vim9script()
END
CheckDefAndScriptFailure(lines, 'E1004:', 1)
for op in ['==', '>', '>=', '<', '<=', '=~', '!~', 'is', 'isnot']
lines = ["echo 'aaa'", op .. "'bbb'", '# comment']
var msg = printf("E1004: White space required before and after '%s'", op)
CheckDefAndScriptFailure(lines, msg, 2)
endfor
lines =<< trim END
echo len('xxx') == 3
END
@@ -1220,7 +1257,14 @@ def Test_expr5_vim9script()
lines =<< trim END
echo 'a'.. 'b'
END
CheckDefAndScriptFailure(lines, 'E1004:', 1)
CheckDefAndScriptFailure(lines, 'E1004: White space required before and after ''..'' at ".. ''b''"', 1)
lines =<< trim END
echo 'a'
..'b'
# comment
END
CheckDefAndScriptFailure(lines, 'E1004: White space required before and after ''..'' at "..''b''"', 2)
# check invalid string concatenation
lines =<< trim END
@@ -1257,6 +1301,12 @@ def Test_expr5_vim9script()
bwipe!
END
CheckDefAndScriptFailure(lines, "E1004: White space required before and after '/' at \"/pattern", 3)
for op in ['+', '-']
lines = ['var x = 1', op .. '2', '# comment']
var msg = printf("E1004: White space required before and after '%s' at \"%s2\"", op, op)
CheckDefAndScriptFailure(lines, msg, 2)
endfor
enddef
def Test_expr5_vim9script_channel()
@@ -1538,6 +1588,12 @@ func Test_expr6_fails()
if has('float')
call CheckDefAndScriptFailure2(["var x = 0.7[1]"], 'E1107:', 'E806:', 1)
endif
for op in ['*', '/', '%']
let lines = ['var x = 1', op .. '2', '# comment']
let msg = printf("E1004: White space required before and after '%s' at \"%s2\"", op, op)
call CheckDefAndScriptFailure(lines, msg, 2)
endfor
endfunc
func Test_expr6_float_fails()
@@ -1580,6 +1636,8 @@ def Test_expr7t()
var ln: list<number> = [<number>g:anint, <number>g:thefour]
var nr = <number>234
assert_equal(234, nr)
var b: bool = <bool>1
assert_equal(true, b)
var text =
<string>
'text'
@@ -1591,6 +1649,7 @@ def Test_expr7t()
CheckDefAndScriptFailure(["var x = <nr>123"], 'E1010:', 1)
CheckDefFailure(["var x = <number>"], 'E1097:', 3)
CheckDefFailure(["var x = <number>string(1)"], 'E1012:', 1)
CheckScriptFailure(['vim9script', "var x = <number>"], 'E15:', 2)
CheckDefAndScriptFailure(["var x = <number >123"], 'E1068:', 1)
CheckDefAndScriptFailure(["var x = <number 123"], 'E1104:', 1)
@@ -1941,6 +2000,9 @@ def Test_expr7_lambda()
CheckDefAndScriptFailure(["var Ref = (a)=>a + 1"], 'E1004:')
CheckDefAndScriptFailure(["var Ref = (a)=> a + 1"], 'E1004: White space required before and after ''=>'' at "=> a + 1"')
CheckDefAndScriptFailure(["var Ref = (a) =>a + 1"], 'E1004:')
CheckDefAndScriptFailure2(["var Ref = (a) =< a + 1"], 'E1001:', 'E121:')
CheckDefAndScriptFailure(["var Ref = (a: int) => a + 1"], 'E1010:')
CheckDefAndScriptFailure(["var Ref = (a): int => a + 1"], 'E1010:')
CheckDefAndScriptFailure(["filter([1, 2], (k,v) => 1)"], 'E1069:', 1)
# error is in first line of the lambda

View File

@@ -397,6 +397,7 @@ def Test_call_default_args()
delfunc g:Func
CheckScriptFailure(['def Func(arg: number = "text")', 'enddef', 'defcompile'], 'E1013: Argument 1: type mismatch, expected number but got string')
delfunc g:Func
CheckDefFailure(['def Func(x: number = )', 'enddef'], 'E15:')
lines =<< trim END
vim9script
@@ -887,6 +888,12 @@ def Test_lambda_return_type()
END
CheckDefAndScriptFailure(lines, 'E1157:', 1)
# no space before the return type
lines =<< trim END
var Ref = (x):number => x + 1
END
CheckDefAndScriptFailure(lines, 'E1069:', 1)
# this works
for x in ['foo', 'boo']
echo FilterWithCond(x, (v) => v =~ '^b')
@@ -1309,6 +1316,8 @@ def Test_arg_type_wrong()
CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...')
CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:')
CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:')
CheckScriptFailure(['def Func6(...x:list<number>)', 'echo "a"', 'enddef'], 'E1069:')
CheckScriptFailure(['def Func7(...x: int)', 'echo "a"', 'enddef'], 'E1010:')
enddef
def Test_white_space_before_comma()
@@ -1318,6 +1327,7 @@ def Test_white_space_before_comma()
enddef
END
CheckScriptFailure(lines, 'E1068:')
call assert_fails('vim9cmd echo stridx("a" .. "b" , "a")', 'E1068:')
enddef
def Test_white_space_after_comma()
@@ -2710,6 +2720,11 @@ def Test_ignored_argument()
var _ = 1
END
CheckDefAndScriptFailure(lines, 'E1181:', 1)
lines =<< trim END
var x = _
END
CheckDefAndScriptFailure(lines, 'E1181:', 1)
enddef
def Test_too_many_arguments()

View File

@@ -3844,12 +3844,14 @@ def Test_unsupported_commands()
var lines =<< trim END
ka
END
CheckDefAndScriptFailure(lines, 'E1100:')
CheckDefFailure(lines, 'E476:')
CheckScriptFailure(['vim9script'] + lines, 'E492:')
lines =<< trim END
:1ka
END
CheckDefAndScriptFailure(lines, 'E481:')
CheckDefFailure(lines, 'E476:')
CheckScriptFailure(['vim9script'] + lines, 'E492:')
lines =<< trim END
t

View File

@@ -252,7 +252,6 @@ f_reltimestr(typval_T *argvars UNUSED, typval_T *rettv)
void
f_strftime(typval_T *argvars, typval_T *rettv)
{
char_u result_buf[256];
struct tm tmval;
struct tm *curtime;
time_t seconds;
@@ -271,6 +270,20 @@ f_strftime(typval_T *argvars, typval_T *rettv)
rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
else
{
# ifdef MSWIN
WCHAR result_buf[256];
WCHAR *wp;
wp = enc_to_utf16(p, NULL);
if (wp != NULL)
(void)wcsftime(result_buf, sizeof(result_buf) / sizeof(WCHAR),
wp, curtime);
else
result_buf[0] = NUL;
rettv->vval.v_string = utf16_to_enc(result_buf, NULL);
vim_free(wp);
# else
char_u result_buf[256];
vimconv_T conv;
char_u *enc;
@@ -296,6 +309,7 @@ f_strftime(typval_T *argvars, typval_T *rettv)
// Release conversion descriptors
convert_setup(&conv, NULL, NULL);
vim_free(enc);
# endif
}
}
# endif

View File

@@ -1394,7 +1394,11 @@ errret:
ga_clear_strings(&newlines);
ga_clear_strings(&default_args);
if (types_optional)
{
ga_clear_strings(&argtypes);
if (fp != NULL)
vim_free(fp->uf_arg_types);
}
vim_free(fp);
vim_free(pt);
if (evalarg != NULL && evalarg->eval_tofree == NULL)

View File

@@ -750,6 +750,40 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2897,
/**/
2896,
/**/
2895,
/**/
2894,
/**/
2893,
/**/
2892,
/**/
2891,
/**/
2890,
/**/
2889,
/**/
2888,
/**/
2887,
/**/
2886,
/**/
2885,
/**/
2884,
/**/
2883,
/**/
2882,
/**/
2881,
/**/
2880,
/**/

View File

@@ -1,4 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
VIM - Vi IMproved by Bram Moolenaar et al.
MS-Windows WinSxS (aka Side-by-side assembly) manifest file
Do ":help uganda" in Vim to read copying and usage conditions.
Do ":help credits" in Vim to see a list of people who contributed.
-->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
<assemblyIdentity
processorArchitecture="*"

View File

@@ -46,7 +46,7 @@ IDR_TOOLBAR1 BITMAP DISCARDABLE "tools.bmp"
# define RT_MANIFEST 24
#endif
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "gvim.exe.mnf"
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "vim.manifest"
#endif // RCDLL
//

View File

@@ -5187,7 +5187,7 @@ compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1 + op_falsy]))
{
semsg(_(e_white_space_required_before_and_after_str_at_str),
op_falsy ? "??" : "?", *arg);
op_falsy ? "??" : "?", p);
return FAIL;
}
@@ -5594,14 +5594,6 @@ assignment_len(char_u *p, int *heredoc)
return 0;
}
// words that cannot be used as a variable
static char *reserved[] = {
"true",
"false",
"null",
NULL
};
/*
* Generate the load instruction for "name".
*/
@@ -5995,16 +5987,9 @@ compile_lhs(
}
else
{
int idx;
// No specific kind of variable recognized, just a name.
for (idx = 0; reserved[idx] != NULL; ++idx)
if (STRCMP(reserved[idx], lhs->lhs_name) == 0)
{
semsg(_(e_cannot_use_reserved_name), lhs->lhs_name);
return FAIL;
}
if (check_reserved_name(lhs->lhs_name) == FAIL)
return FAIL;
if (lookup_local(var_start, lhs->lhs_varlen,
&lhs->lhs_local_lvar, cctx) == OK)

View File

@@ -709,10 +709,10 @@ vim9_declare_scriptvar(exarg_T *eap, char_u *arg)
}
name = vim_strnsave(arg, p - arg);
// parse type
// parse type, check for reserved name
p = skipwhite(p + 1);
type = parse_type(&p, &si->sn_type_list, TRUE);
if (type == NULL)
if (type == NULL || check_reserved_name(name) == FAIL)
{
vim_free(name);
return p;
@@ -974,4 +974,26 @@ check_script_var_type(
return OK; // not really
}
// words that cannot be used as a variable
static char *reserved[] = {
"true",
"false",
"null",
NULL
};
int
check_reserved_name(char_u *name)
{
int idx;
for (idx = 0; reserved[idx] != NULL; ++idx)
if (STRCMP(reserved[idx], name) == 0)
{
semsg(_(e_cannot_use_reserved_name), name);
return FAIL;
}
return OK;
}
#endif // FEAT_EVAL