Patch 9.0.1505
Problem:    Error when heredoc content looks like heredoc.
Solution:   Handle curly expressions. (closes #12325)
Files:      src/eval.c, src/userfunc.c, src/vim.h, src/testdir/test_let.vim,
            src/testdir/test_vim9_assign.vim


*** ../vim-9.0.1504/src/eval.c  2023-04-13 22:12:46.300718943 +0100
--- src/eval.c  2023-05-02 16:19:44.051000651 +0100
***************
*** 6581,6587 ****
      int               br_nest = 0;
      char_u    *p;
      int               len;
!     int               vim9script = in_vim9script();
  
      if (expr_start != NULL)
      {
--- 6581,6587 ----
      int               br_nest = 0;
      char_u    *p;
      int               len;
!     int               allow_curly = (flags & FNE_ALLOW_CURLY) || 
!in_vim9script();
  
      if (expr_start != NULL)
      {
***************
*** 6591,6602 ****
  
      // Quick check for valid starting character.
      if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg)
!                                               && (*arg != '{' || vim9script))
        return arg;
  
      for (p = arg; *p != NUL
                    && (eval_isnamec(*p)
!                       || (*p == '{' && !vim9script)
                        || ((flags & FNE_INCL_BR) && (*p == '['
                                         || (*p == '.' && eval_isdictc(p[1]))))
                        || mb_nest != 0
--- 6591,6602 ----
  
      // Quick check for valid starting character.
      if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg)
!                                             && (*arg != '{' || !allow_curly))
        return arg;
  
      for (p = arg; *p != NUL
                    && (eval_isnamec(*p)
!                       || (*p == '{' && allow_curly)
                        || ((flags & FNE_INCL_BR) && (*p == '['
                                         || (*p == '.' && eval_isdictc(p[1]))))
                        || mb_nest != 0
***************
*** 6637,6643 ****
                --br_nest;
        }
  
!       if (br_nest == 0 && !vim9script)
        {
            if (*p == '{')
            {
--- 6637,6643 ----
                --br_nest;
        }
  
!       if (br_nest == 0 && allow_curly)
        {
            if (*p == '{')
            {
*** ../vim-9.0.1504/src/userfunc.c      2023-04-19 14:21:19.078048657 +0100
--- src/userfunc.c      2023-05-02 16:18:35.495061306 +0100
***************
*** 1143,1149 ****
                    skip_until = vim_strnsave(p, skiptowhite(p) - p);
                getline_options = GETLINE_NONE;
                is_heredoc = TRUE;
!               if (eap->cmdidx == CMD_def && nesting == 0)
                    heredoc_concat_len = newlines->ga_len + 1;
            }
  
--- 1143,1149 ----
                    skip_until = vim_strnsave(p, skiptowhite(p) - p);
                getline_options = GETLINE_NONE;
                is_heredoc = TRUE;
!               if (vim9_function && nesting == 0)
                    heredoc_concat_len = newlines->ga_len + 1;
            }
  
***************
*** 1153,1175 ****
                //       and ":cmd [a, b] =<< [trim] EOF"
                //       and "lines =<< [trim] EOF" for Vim9
                // Where "cmd" can be "let", "var", "final" or "const".
!               arg = skipwhite(skiptowhite(p));
!               if (*arg == '[')
!                   arg = vim_strchr(arg, ']');
!               if (arg != NULL)
                {
!                   int found = (eap->cmdidx == CMD_def && arg[0] == '='
!                                            && arg[1] == '<' && arg[2] =='<');
! 
!                   if (!found)
!                       // skip over the argument after "cmd"
!                       arg = skipwhite(skiptowhite(arg));
!                   if (found || (arg[0] == '=' && arg[1] == '<'
!                                                               && arg[2] =='<'
!                           && (checkforcmd(&p, "let", 2)
!                               || checkforcmd(&p, "var", 3)
!                               || checkforcmd(&p, "final", 5)
!                               || checkforcmd(&p, "const", 5))))
                    {
                        p = skipwhite(arg + 3);
                        while (TRUE)
--- 1153,1172 ----
                //       and ":cmd [a, b] =<< [trim] EOF"
                //       and "lines =<< [trim] EOF" for Vim9
                // Where "cmd" can be "let", "var", "final" or "const".
!               arg = p;
!               if (checkforcmd(&arg, "let", 2)
!                       || checkforcmd(&arg, "var", 3)
!                       || checkforcmd(&arg, "final", 5)
!                       || checkforcmd(&arg, "const", 5)
!                       || vim9_function)
                {
!                   while (vim_strchr((char_u *)"$@&", *arg) != NULL)
!                       ++arg;
!                   arg = skipwhite(find_name_end(arg, NULL, NULL,
!                                              FNE_INCL_BR | FNE_ALLOW_CURLY));
!                   if (vim9_function && *arg == ':')
!                       arg = skipwhite(skip_type(skipwhite(arg + 1), FALSE));
!                   if (arg[0] == '=' && arg[1] == '<' && arg[2] =='<')
                    {
                        p = skipwhite(arg + 3);
                        while (TRUE)
*** ../vim-9.0.1504/src/vim.h   2023-04-13 19:15:50.023391985 +0100
--- src/vim.h   2023-05-02 16:18:35.495061306 +0100
***************
*** 2758,2763 ****
--- 2758,2764 ----
  // flags for find_name_end()
  #define FNE_INCL_BR   1       // include [] in name
  #define FNE_CHECK_START       2       // check name starts with valid 
character
+ #define FNE_ALLOW_CURLY       4       // always allow curly braces name
  
  // BSD is supposed to cover FreeBSD and similar systems.
  #if (defined(SUN_SYSTEM) || defined(BSD) || defined(__FreeBSD_kernel__)) \
*** ../vim-9.0.1504/src/testdir/test_let.vim    2022-11-05 20:21:50.601151478 
+0000
--- src/testdir/test_let.vim    2023-05-02 16:18:35.491061310 +0100
***************
*** 337,343 ****
      call assert_report('No exception thrown')
    catch /E488:/
    catch
!     call assert_report("Caught exception: " .. v:exception)
    endtry
  
    let text =<< trim END
--- 337,379 ----
      call assert_report('No exception thrown')
    catch /E488:/
    catch
!     call assert_report('Caught exception: ' .. v:exception)
!   endtry
! 
!   try
!     let &commentstring =<< trim TEXT
!       change
!       insert
!       append
!     TEXT
!     call assert_report('No exception thrown')
!   catch /E730:/
!   catch
!     call assert_report('Caught exception: ' .. v:exception)
!   endtry
! 
!   try
!     let $SOME_ENV_VAR =<< trim TEXT
!       change
!       insert
!       append
!     TEXT
!     call assert_report('No exception thrown')
!   catch /E730:/
!   catch
!     call assert_report('Caught exception: ' .. v:exception)
!   endtry
! 
!   try
!     let @r =<< trim TEXT
!       change
!       insert
!       append
!     TEXT
!     call assert_report('No exception thrown')
!   catch /E730:/
!   catch
!     call assert_report('Caught exception: ' .. v:exception)
    endtry
  
    let text =<< trim END
***************
*** 506,511 ****
--- 542,573 ----
       z
  END
    call assert_equal(['     x', '     \y', '     z'], [a, b, c])
+ 
+   " unpack assignment without whitespace
+   let[a,b,c]=<<END
+ change
+ insert
+ append
+ END
+   call assert_equal(['change', 'insert', 'append'], [a, b, c])
+ 
+   " curly braces name and list slice assignment
+   let foo_3_bar = ['', '', '']
+   let foo_{1 + 2}_bar[ : ] =<< END
+ change
+ insert
+ append
+ END
+   call assert_equal(['change', 'insert', 'append'], foo_3_bar)
+ 
+   " dictionary key containing brackets and spaces
+   let d = {'abc] 123': 'baz'}
+   let d[d['abc] 123'] .. '{'] =<< END
+ change
+ insert
+ append
+ END
+   call assert_equal(['change', 'insert', 'append'], d['baz{'])
  endfunc
  
  " Test for evaluating Vim expressions in a heredoc using {expr}
*** ../vim-9.0.1504/src/testdir/test_vim9_assign.vim    2023-01-30 
21:12:30.547422897 +0000
--- src/testdir/test_vim9_assign.vim    2023-05-02 16:18:35.491061310 +0100
***************
*** 1848,1877 ****
  def Test_heredoc()
    # simple heredoc
    var lines =<< trim END
!     var text =<< trim TEXT # comment
!       abc
!     TEXT
!     assert_equal(['abc'], text)
    END
    v9.CheckDefAndScriptSuccess(lines)
  
    # empty heredoc
    lines =<< trim END
!      var text =<< trim TEXT
!      TEXT
!      assert_equal([], text)
    END
    v9.CheckDefAndScriptSuccess(lines)
  
    # heredoc with a single empty line
    lines =<< trim END
!      var text =<< trim TEXT
  
!      TEXT
!      assert_equal([''], text)
    END
    v9.CheckDefAndScriptSuccess(lines)
  
    v9.CheckDefFailure(['var lines =<< trim END X', 'END'], 'E488:')
    v9.CheckDefFailure(['var lines =<< trim END " comment', 'END'], 'E488:')
  
--- 1848,1928 ----
  def Test_heredoc()
    # simple heredoc
    var lines =<< trim END
!       var text =<< trim TEXT # comment
!         abc
!       TEXT
!       assert_equal(['abc'], text)
    END
    v9.CheckDefAndScriptSuccess(lines)
  
    # empty heredoc
    lines =<< trim END
!        var text =<< trim TEXT
!        TEXT
!        assert_equal([], text)
    END
    v9.CheckDefAndScriptSuccess(lines)
  
    # heredoc with a single empty line
    lines =<< trim END
!       var text =<< trim TEXT
  
!       TEXT
!       assert_equal([''], text)
    END
    v9.CheckDefAndScriptSuccess(lines)
  
+   # assign heredoc to variable with type
+   lines =<< trim END
+       var text: list<string> =<< trim TEXT
+         var foo =<< trim FOO
+       TEXT
+       assert_equal(['var foo =<< trim FOO'], text)
+   END
+   v9.CheckDefAndScriptSuccess(lines)
+ 
+   # extra whitespace before type is allowed
+   lines =<< trim END
+       var text:   list<string> =<< trim TEXT
+         var foo =<< trim FOO
+       TEXT
+       assert_equal(['var foo =<< trim FOO'], text)
+   END
+   v9.CheckDefAndScriptSuccess(lines)
+ 
+   # missing whitespace before type is an error
+   lines =<< trim END
+       var text:list<string> =<< trim TEXT
+         var foo =<< trim FOO
+       TEXT
+       assert_equal(['var foo =<< trim FOO'], text)
+   END
+   v9.CheckDefAndScriptFailure(lines, 'E1069:')
+ 
+   # assign heredoc to list slice
+   lines =<< trim END
+       var text = ['']
+       text[ : ] =<< trim TEXT
+         var foo =<< trim FOO
+       TEXT
+       assert_equal(['var foo =<< trim FOO'], text)
+   END
+   v9.CheckDefAndScriptSuccess(lines)
+ 
+   # assign heredoc to curly braces name in legacy function in Vim9 script
+   lines =<< trim END
+       vim9script
+       func Func()
+         let foo_3_bar = ['']
+         let foo_{1 + 2}_bar[ : ] =<< trim TEXT
+           var foo =<< trim FOO
+         TEXT
+         call assert_equal(['var foo =<< trim FOO'], foo_3_bar)
+       endfunc
+       Func()
+   END
+   v9.CheckScriptSuccess(lines)
+ 
    v9.CheckDefFailure(['var lines =<< trim END X', 'END'], 'E488:')
    v9.CheckDefFailure(['var lines =<< trim END " comment', 'END'], 'E488:')
  
*** ../vim-9.0.1504/src/version.c       2023-05-01 22:36:52.870894672 +0100
--- src/version.c       2023-05-02 16:20:42.170957010 +0100
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1505,
  /**/

-- 
Are leaders born or made?  And if they're made, can we return them under
warranty?
                                (Scott Adams - The Dilbert principle)

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20230502152616.38F211C0916%40moolenaar.net.

Raspunde prin e-mail lui