Mercurial > vim
comparison src/userfunc.c @ 25265:1d6ff96306fc v8.2.3169
patch 8.2.3169: Vim9: cannot handle nested inline function
Commit: https://github.com/vim/vim/commit/5245beb37cb52991a745644c20d7ca1b0138ef2c
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Jul 15 22:03:50 2021 +0200
patch 8.2.3169: Vim9: cannot handle nested inline function
Problem: Vim9: cannot handle nested inline function.
Solution: Check for nested inline function. (closes https://github.com/vim/vim/issues/8575)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Thu, 15 Jul 2021 22:15:03 +0200 |
parents | 0a3b1c66d3f2 |
children | c69ebc71bd85 |
comparison
equal
deleted
inserted
replaced
25264:19bc0f4c9379 | 25265:1d6ff96306fc |
---|---|
632 char_u *line_arg = line_arg_in; | 632 char_u *line_arg = line_arg_in; |
633 int vim9_function = eap->cmdidx == CMD_def | 633 int vim9_function = eap->cmdidx == CMD_def |
634 || eap->cmdidx == CMD_block; | 634 || eap->cmdidx == CMD_block; |
635 #define MAX_FUNC_NESTING 50 | 635 #define MAX_FUNC_NESTING 50 |
636 char nesting_def[MAX_FUNC_NESTING]; | 636 char nesting_def[MAX_FUNC_NESTING]; |
637 char nesting_inline[MAX_FUNC_NESTING]; | |
637 int nesting = 0; | 638 int nesting = 0; |
638 getline_opt_T getline_options; | 639 getline_opt_T getline_options; |
639 int indent = 2; | 640 int indent = 2; |
640 char_u *skip_until = NULL; | 641 char_u *skip_until = NULL; |
641 int ret = FAIL; | 642 int ret = FAIL; |
656 goto theend; | 657 goto theend; |
657 while (sourcing_lnum_off-- > 0) | 658 while (sourcing_lnum_off-- > 0) |
658 ((char_u **)(newlines->ga_data))[newlines->ga_len++] = NULL; | 659 ((char_u **)(newlines->ga_data))[newlines->ga_len++] = NULL; |
659 } | 660 } |
660 | 661 |
661 nesting_def[nesting] = vim9_function; | 662 nesting_def[0] = vim9_function; |
663 nesting_inline[0] = eap->cmdidx == CMD_block; | |
662 getline_options = vim9_function | 664 getline_options = vim9_function |
663 ? GETLINE_CONCAT_CONTBAR : GETLINE_CONCAT_CONT; | 665 ? GETLINE_CONCAT_CONTBAR : GETLINE_CONCAT_CONT; |
664 for (;;) | 666 for (;;) |
665 { | 667 { |
666 char_u *theline; | 668 char_u *theline; |
703 { | 705 { |
704 // Use the start of the function for the line number. | 706 // Use the start of the function for the line number. |
705 SOURCING_LNUM = sourcing_lnum_top; | 707 SOURCING_LNUM = sourcing_lnum_top; |
706 if (skip_until != NULL) | 708 if (skip_until != NULL) |
707 semsg(_(e_missing_heredoc_end_marker_str), skip_until); | 709 semsg(_(e_missing_heredoc_end_marker_str), skip_until); |
710 else if (nesting_inline[nesting]) | |
711 emsg(_(e_missing_end_block)); | |
708 else if (eap->cmdidx == CMD_def) | 712 else if (eap->cmdidx == CMD_def) |
709 emsg(_(e_missing_enddef)); | 713 emsg(_(e_missing_enddef)); |
710 else if (eap->cmdidx == CMD_block) | |
711 emsg(_(e_missing_end_block)); | |
712 else | 714 else |
713 emsg(_("E126: Missing :endfunction")); | 715 emsg(_("E126: Missing :endfunction")); |
714 goto theend; | 716 goto theend; |
715 } | 717 } |
716 | 718 |
763 } | 765 } |
764 } | 766 } |
765 } | 767 } |
766 else | 768 else |
767 { | 769 { |
768 int c; | 770 int c; |
771 char_u *end; | |
769 | 772 |
770 // skip ':' and blanks | 773 // skip ':' and blanks |
771 for (p = theline; VIM_ISWHITE(*p) || *p == ':'; ++p) | 774 for (p = theline; VIM_ISWHITE(*p) || *p == ':'; ++p) |
772 ; | 775 ; |
773 | 776 |
774 // Check for "endfunction", "enddef" or "}". | 777 // Check for "endfunction", "enddef" or "}". |
775 // When a ":" follows it must be a dict key; "enddef: value," | 778 // When a ":" follows it must be a dict key; "enddef: value," |
776 if ((nesting == 0 && eap->cmdidx == CMD_block) | 779 if (nesting_inline[nesting] |
777 ? *p == '}' | 780 ? *p == '}' |
778 : (checkforcmd(&p, nesting_def[nesting] | 781 : (checkforcmd(&p, nesting_def[nesting] |
779 ? "enddef" : "endfunction", 4) | 782 ? "enddef" : "endfunction", 4) |
780 && *p != ':')) | 783 && *p != ':')) |
781 { | 784 { |
855 emsg(_(e_function_nesting_too_deep)); | 858 emsg(_(e_function_nesting_too_deep)); |
856 else | 859 else |
857 { | 860 { |
858 ++nesting; | 861 ++nesting; |
859 nesting_def[nesting] = (c == 'd'); | 862 nesting_def[nesting] = (c == 'd'); |
863 nesting_inline[nesting] = FALSE; | |
864 indent += 2; | |
865 } | |
866 } | |
867 } | |
868 | |
869 // Check for nested inline function. | |
870 end = p + STRLEN(p) - 1; | |
871 while (end > p && VIM_ISWHITE(*end)) | |
872 --end; | |
873 if (*end == '{') | |
874 { | |
875 --end; | |
876 while (end > p && VIM_ISWHITE(*end)) | |
877 --end; | |
878 if (end > p - 2 && end[-1] == '=' && end[0] == '>') | |
879 { | |
880 // found trailing "=> {", start of an inline function | |
881 if (nesting == MAX_FUNC_NESTING - 1) | |
882 emsg(_(e_function_nesting_too_deep)); | |
883 else | |
884 { | |
885 ++nesting; | |
886 nesting_def[nesting] = TRUE; | |
887 nesting_inline[nesting] = TRUE; | |
860 indent += 2; | 888 indent += 2; |
861 } | 889 } |
862 } | 890 } |
863 } | 891 } |
864 | 892 |