changeset 20059:de756b3f4dee v8.2.0585

patch 8.2.0585: Vim9: # comment not recognized after :vim9script Commit: https://github.com/vim/vim/commit/7a09224583b2ad0d9d0648b53cc2d989d45ae96e Author: Bram Moolenaar <Bram@vim.org> Date: Thu Apr 16 22:10:49 2020 +0200 patch 8.2.0585: Vim9: # comment not recognized after :vim9script Problem: Vim9: # comment not recognized after :vim9script. Solution: Check script type. Make comment after ":echo" work. And in several other places.
author Bram Moolenaar <Bram@vim.org>
date Thu, 16 Apr 2020 22:15:04 +0200
parents bc03e6cae236
children 324f7433a2c4
files src/eval.c src/ex_docmd.c src/proto/ex_docmd.pro src/testdir/test_vim9_script.vim src/version.c src/vim9compile.c
diffstat 6 files changed, 105 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -6061,7 +6061,7 @@ ex_echo(exarg_T *eap)
 
     if (eap->skip)
 	++emsg_skip;
-    while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
+    while ((!ends_excmd2(eap->cmd, arg) || *arg == '"') && !got_int)
     {
 	// If eval1() causes an error message the text from the command may
 	// still need to be cleared. E.g., "echo 22,44".
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -1835,7 +1835,10 @@ do_one_cmd(
      * If we find a '|' or '\n' we set ea.nextcmd.
      */
     if (*ea.cmd == NUL || *ea.cmd == '"'
-			      || (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL)
+#ifdef FEAT_EVAL
+		|| (*ea.cmd == '#' && !starts_with_colon && in_vim9script())
+#endif
+		|| (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL)
     {
 	/*
 	 * strange vi behaviour:
@@ -4761,12 +4764,31 @@ ex_blast(exarg_T *eap)
 	do_cmdline_cmd(eap->do_ecmd_cmd);
 }
 
+/*
+ * Check if "c" ends an Ex command.
+ * In Vim9 script does not check for white space before #.
+ */
     int
 ends_excmd(int c)
 {
 #ifdef FEAT_EVAL
     if (c == '#')
-	// TODO: should check for preceding white space
+	return in_vim9script();
+#endif
+    return (c == NUL || c == '|' || c == '"' || c == '\n');
+}
+
+/*
+ * Like ends_excmd() but checks that a # in Vim9 script either has "cmd" equal
+ * to "cmd_start" or has a white space character before it.
+ */
+    int
+ends_excmd2(char_u *cmd_start, char_u *cmd)
+{
+    int c = *cmd;
+
+#ifdef FEAT_EVAL
+    if (c == '#' && (cmd == cmd_start || VIM_ISWHITE(cmd[-1])))
 	return in_vim9script();
 #endif
     return (c == NUL || c == '|' || c == '"' || c == '\n');
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -19,6 +19,7 @@ void separate_nextcmd(exarg_T *eap);
 char_u *skip_cmd_arg(char_u *p, int rembs);
 int get_bad_opt(char_u *p, exarg_T *eap);
 int ends_excmd(int c);
+int ends_excmd2(char_u *before, char_u *cmd);
 char_u *find_nextcmd(char_u *p);
 char_u *check_nextcmd(char_u *p);
 char_u *get_command_name(expand_T *xp, int idx);
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -10,11 +10,17 @@ func CheckDefFailure(lines, error)
   call delete('Xdef')
 endfunc
 
-func CheckScriptFailure(lines, error)
-  call writefile(a:lines, 'Xdef')
-  call assert_fails('so Xdef', a:error, a:lines)
-  call delete('Xdef')
-endfunc
+def CheckScriptFailure(lines: list<string>, error: string)
+  writefile(lines, 'Xdef')
+  assert_fails('so Xdef', error, lines)
+  delete('Xdef')
+enddef
+
+def CheckScriptSuccess(lines: list<string>)
+  writefile(lines, 'Xdef')
+  so Xdef
+  delete('Xdef')
+enddef
 
 def Test_syntax()
   let var = 234
@@ -269,15 +275,15 @@ enddef
 
 def Test_try_catch()
   let l = []
-  try
+  try # comment
     add(l, '1')
     throw 'wrong'
     add(l, '2')
-  catch
+  catch # comment
     add(l, v:exception)
-  finally
+  finally # comment
     add(l, '3')
-  endtry
+  endtry # comment
   assert_equal(['1', 'wrong', '3'], l)
 enddef
 
@@ -1003,6 +1009,58 @@ def Test_automatic_line_continuation()
         )
 enddef
 
+def Test_vim9_comment()
+  CheckScriptSuccess([
+      'vim9script',
+      '# something',
+      ])
+  CheckScriptFailure([
+      'vim9script',
+      ':# something',
+      ], 'E488:')
+  CheckScriptFailure([
+      '# something',
+      ], 'E488:')
+  CheckScriptFailure([
+      ':# something',
+      ], 'E488:')
+
+  CheckScriptSuccess([
+      'vim9script',
+      'echo "yes" # something',
+      ])
+  CheckScriptFailure([
+      'vim9script',
+      'echo "yes"# something',
+      ], 'E121:')
+  CheckScriptFailure([
+      'vim9script',
+      'echo# something',
+      ], 'E121:')
+  CheckScriptFailure([
+      'echo "yes" # something',
+      ], 'E121:')
+
+  CheckDefFailure([
+      'try# comment',
+      'echo "yes"',
+      'catch',
+      'endtry',
+      ], 'E488:')
+  CheckDefFailure([
+      'try',
+      'echo "yes"',
+      'catch# comment',
+      'endtry',
+      ], 'E488:')
+  CheckDefFailure([
+      'try',
+      'echo "yes"',
+      'catch',
+      'endtry# comment',
+      ], 'E488:')
+enddef
+
 " Keep this last, it messes up highlighting.
 def Test_substitute_cmd()
   new
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    585,
+/**/
     584,
 /**/
     583,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -108,6 +108,7 @@ typedef struct {
 struct cctx_S {
     ufunc_T	*ctx_ufunc;	    // current function
     int		ctx_lnum;	    // line number in current function
+    char_u	*ctx_line_start;    // start of current line or NULL
     garray_T	ctx_instr;	    // generated instructions
 
     garray_T	ctx_locals;	    // currently visible local variables
@@ -2055,14 +2056,18 @@ free_imported(cctx_T *cctx)
     static char_u *
 next_line_from_context(cctx_T *cctx)
 {
-    char_u	*line = NULL;
+    char_u	*line;
 
     do
     {
 	++cctx->ctx_lnum;
 	if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
+	{
+	    line = NULL;
 	    break;
+	}
 	line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
+	cctx->ctx_line_start = line;
 	SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum
 							  + cctx->ctx_lnum + 1;
     } while (line == NULL || *skipwhite(line) == NUL);
@@ -5448,7 +5453,7 @@ compile_catch(char_u *arg, cctx_T *cctx 
     }
 
     p = skipwhite(arg);
-    if (ends_excmd(*p))
+    if (ends_excmd2(arg, p))
     {
 	scope->se_u.se_try.ts_caught_all = TRUE;
 	scope->se_u.se_try.ts_catch_label = 0;
@@ -5782,7 +5787,9 @@ compile_def_function(ufunc_T *ufunc, int
 	if (line != NULL && *line == '|')
 	    // the line continues after a '|'
 	    ++line;
-	else if (line != NULL && *line != NUL)
+	else if (line != NULL && *line != NUL
+		&& !(*line == '#' && (line == cctx.ctx_line_start
+						    || VIM_ISWHITE(line[-1]))))
 	{
 	    semsg(_("E488: Trailing characters: %s"), line);
 	    goto erret;