mirror of
				https://github.com/vim/vim.git
				synced 2025-10-30 09:47:20 -04:00 
			
		
		
		
	patch 9.1.1077: included syntax items do not understand contains=TOP
Problem:  Syntax engine interpreted contains=TOP as matching nothing
          inside included files, since :syn-include forces HL_CONTAINED
          on for every included item. After 8.2.2761, interprets
          contains=TOP as contains=@INCLUDED, which is also not correct
          since it doesn't respect exclusions, and doesn't work if there
          is no @INCLUDED cluster.
Solution: revert patch 8.2.2761, instead track groups that have had
          HL_CONTAINED forced, and interpret contains=TOP and
          contains=CONTAINED using this. (Theodore Dubois)
fixes: #11277
closes: #16571
Signed-off-by: Theodore Dubois <tblodt@icloud.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
			
			
This commit is contained in:
		
				
					committed by
					
						 Christian Brabandt
						Christian Brabandt
					
				
			
			
				
	
			
			
			
						parent
						
							34e1e8de91
						
					
				
				
					commit
					f50d5364d7
				
			
							
								
								
									
										41
									
								
								src/syntax.c
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								src/syntax.c
									
									
									
									
									
								
							| @@ -299,7 +299,7 @@ static void update_si_attr(int idx); | |||||||
| static void check_keepend(void); | static void check_keepend(void); | ||||||
| static void update_si_end(stateitem_T *sip, int startcol, int force); | static void update_si_end(stateitem_T *sip, int startcol, int force); | ||||||
| static short *copy_id_list(short *list); | static short *copy_id_list(short *list); | ||||||
| static int in_id_list(stateitem_T *item, short *cont_list, struct sp_syn *ssp, int contained); | static int in_id_list(stateitem_T *item, short *cont_list, struct sp_syn *ssp, int flags); | ||||||
| static int push_current_state(int idx); | static int push_current_state(int idx); | ||||||
| static void pop_current_state(void); | static void pop_current_state(void); | ||||||
| #ifdef FEAT_PROFILE | #ifdef FEAT_PROFILE | ||||||
| @@ -1943,7 +1943,7 @@ syn_current_attr( | |||||||
| 					? !(spp->sp_flags & HL_CONTAINED) | 					? !(spp->sp_flags & HL_CONTAINED) | ||||||
| 					: in_id_list(cur_si, | 					: in_id_list(cur_si, | ||||||
| 					    cur_si->si_cont_list, &spp->sp_syn, | 					    cur_si->si_cont_list, &spp->sp_syn, | ||||||
| 					    spp->sp_flags & HL_CONTAINED)))) | 					    spp->sp_flags)))) | ||||||
| 			{ | 			{ | ||||||
| 			    int r; | 			    int r; | ||||||
|  |  | ||||||
| @@ -3269,7 +3269,7 @@ check_keyword_id( | |||||||
| 			: (cur_si == NULL | 			: (cur_si == NULL | ||||||
| 			    ? !(kp->flags & HL_CONTAINED) | 			    ? !(kp->flags & HL_CONTAINED) | ||||||
| 			    : in_id_list(cur_si, cur_si->si_cont_list, | 			    : in_id_list(cur_si, cur_si->si_cont_list, | ||||||
| 				      &kp->k_syn, kp->flags & HL_CONTAINED))) | 				      &kp->k_syn, kp->flags))) | ||||||
| 		{ | 		{ | ||||||
| 		    *endcolp = startcol + kwlen; | 		    *endcolp = startcol + kwlen; | ||||||
| 		    *flagsp = kp->flags; | 		    *flagsp = kp->flags; | ||||||
| @@ -4681,7 +4681,7 @@ syn_incl_toplevel(int id, int *flagsp) | |||||||
| { | { | ||||||
|     if ((*flagsp & HL_CONTAINED) || curwin->w_s->b_syn_topgrp == 0) |     if ((*flagsp & HL_CONTAINED) || curwin->w_s->b_syn_topgrp == 0) | ||||||
| 	return; | 	return; | ||||||
|     *flagsp |= HL_CONTAINED; |     *flagsp |= HL_CONTAINED | HL_INCLUDED_TOPLEVEL; | ||||||
|     if (curwin->w_s->b_syn_topgrp >= SYNID_CLUSTER) |     if (curwin->w_s->b_syn_topgrp >= SYNID_CLUSTER) | ||||||
|     { |     { | ||||||
| 	// We have to alloc this, because syn_combine_list() will free it. | 	// We have to alloc this, because syn_combine_list() will free it. | ||||||
| @@ -5969,17 +5969,12 @@ get_id_list( | |||||||
| 		    break; | 		    break; | ||||||
| 		} | 		} | ||||||
| 		if (name[1] == 'A') | 		if (name[1] == 'A') | ||||||
| 		    id = SYNID_ALLBUT + current_syn_inc_tag; | 		    id = SYNID_ALLBUT; | ||||||
| 		else if (name[1] == 'T') | 		else if (name[1] == 'T') | ||||||
| 		{ | 		    id = SYNID_TOP; | ||||||
| 		    if (curwin->w_s->b_syn_topgrp >= SYNID_CLUSTER) |  | ||||||
| 			id = curwin->w_s->b_syn_topgrp; |  | ||||||
| 		else | 		else | ||||||
| 			id = SYNID_TOP + current_syn_inc_tag; | 		    id = SYNID_CONTAINED; | ||||||
| 		} | 		id += current_syn_inc_tag; | ||||||
| 		else |  | ||||||
| 		    id = SYNID_CONTAINED + current_syn_inc_tag; |  | ||||||
|  |  | ||||||
| 	    } | 	    } | ||||||
| 	    else if (name[1] == '@') | 	    else if (name[1] == '@') | ||||||
| 	    { | 	    { | ||||||
| @@ -6127,7 +6122,7 @@ in_id_list( | |||||||
|     stateitem_T	*cur_si,	// current item or NULL |     stateitem_T	*cur_si,	// current item or NULL | ||||||
|     short	*list,		// id list |     short	*list,		// id list | ||||||
|     struct sp_syn *ssp,		// group id and ":syn include" tag of group |     struct sp_syn *ssp,		// group id and ":syn include" tag of group | ||||||
|     int		contained)	// group id is contained |     int		flags)		// group flags | ||||||
| { | { | ||||||
|     int		retval; |     int		retval; | ||||||
|     short	*scl_list; |     short	*scl_list; | ||||||
| @@ -6135,6 +6130,7 @@ in_id_list( | |||||||
|     short	id = ssp->id; |     short	id = ssp->id; | ||||||
|     static int	depth = 0; |     static int	depth = 0; | ||||||
|     int		r; |     int		r; | ||||||
|  |     int		toplevel; | ||||||
|  |  | ||||||
|     // If ssp has a "containedin" list and "cur_si" is in it, return TRUE. |     // If ssp has a "containedin" list and "cur_si" is in it, return TRUE. | ||||||
|     if (cur_si != NULL && ssp->cont_in_list != NULL |     if (cur_si != NULL && ssp->cont_in_list != NULL | ||||||
| @@ -6148,7 +6144,7 @@ in_id_list( | |||||||
| 	// cur_si->si_idx is -1 for keywords, these never contain anything. | 	// cur_si->si_idx is -1 for keywords, these never contain anything. | ||||||
| 	if (cur_si->si_idx >= 0 && in_id_list(NULL, ssp->cont_in_list, | 	if (cur_si->si_idx >= 0 && in_id_list(NULL, ssp->cont_in_list, | ||||||
| 		&(SYN_ITEMS(syn_block)[cur_si->si_idx].sp_syn), | 		&(SYN_ITEMS(syn_block)[cur_si->si_idx].sp_syn), | ||||||
| 		  SYN_ITEMS(syn_block)[cur_si->si_idx].sp_flags & HL_CONTAINED)) | 		  SYN_ITEMS(syn_block)[cur_si->si_idx].sp_flags)) | ||||||
| 	    return TRUE; | 	    return TRUE; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -6160,7 +6156,14 @@ in_id_list( | |||||||
|      * inside anything.  Only allow not-contained groups. |      * inside anything.  Only allow not-contained groups. | ||||||
|      */ |      */ | ||||||
|     if (list == ID_LIST_ALL) |     if (list == ID_LIST_ALL) | ||||||
| 	return !contained; | 	return !(flags & HL_CONTAINED); | ||||||
|  |  | ||||||
|  |     /* | ||||||
|  |      * Is this top-level (i.e. not 'contained') in the file it was declared in? | ||||||
|  |      * For included files, this is different from HL_CONTAINED, which is set | ||||||
|  |      * unconditionally. | ||||||
|  |      */ | ||||||
|  |     toplevel = !(flags & HL_CONTAINED) || (flags & HL_INCLUDED_TOPLEVEL); | ||||||
|  |  | ||||||
|     /* |     /* | ||||||
|      * If the first item is "ALLBUT", return TRUE if "id" is NOT in the |      * If the first item is "ALLBUT", return TRUE if "id" is NOT in the | ||||||
| @@ -6179,13 +6182,13 @@ in_id_list( | |||||||
| 	else if (item < SYNID_CONTAINED) | 	else if (item < SYNID_CONTAINED) | ||||||
| 	{ | 	{ | ||||||
| 	    // TOP: accept all not-contained groups in the same file | 	    // TOP: accept all not-contained groups in the same file | ||||||
| 	    if (item - SYNID_TOP != ssp->inc_tag || contained) | 	    if (item - SYNID_TOP != ssp->inc_tag || !toplevel) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 	    // CONTAINED: accept all contained groups in the same file | 	    // CONTAINED: accept all contained groups in the same file | ||||||
| 	    if (item - SYNID_CONTAINED != ssp->inc_tag || !contained) | 	    if (item - SYNID_CONTAINED != ssp->inc_tag || toplevel) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
| 	item = *++list; | 	item = *++list; | ||||||
| @@ -6209,7 +6212,7 @@ in_id_list( | |||||||
| 	    if (scl_list != NULL && depth < 30) | 	    if (scl_list != NULL && depth < 30) | ||||||
| 	    { | 	    { | ||||||
| 		++depth; | 		++depth; | ||||||
| 		r = in_id_list(NULL, scl_list, ssp, contained); | 		r = in_id_list(NULL, scl_list, ssp, flags); | ||||||
| 		--depth; | 		--depth; | ||||||
| 		if (r) | 		if (r) | ||||||
| 		    return retval; | 		    return retval; | ||||||
|   | |||||||
| @@ -949,7 +949,7 @@ func Test_syn_contained_transparent() | |||||||
| endfunc | endfunc | ||||||
|  |  | ||||||
| func Test_syn_include_contains_TOP() | func Test_syn_include_contains_TOP() | ||||||
|   let l:case = "TOP in included syntax means its group list name" |   let l:case = "TOP in included syntax refers to top level of that included syntax" | ||||||
|   new |   new | ||||||
|   syntax include @INCLUDED syntax/c.vim |   syntax include @INCLUDED syntax/c.vim | ||||||
|   syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED |   syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED | ||||||
| @@ -964,6 +964,18 @@ func Test_syn_include_contains_TOP() | |||||||
|   bw! |   bw! | ||||||
| endfunc | endfunc | ||||||
|  |  | ||||||
|  | func Test_syn_include_contains_TOP_excluding() | ||||||
|  |   new | ||||||
|  |   syntax include @INCLUDED syntax/c.vim | ||||||
|  |   syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED | ||||||
|  |  | ||||||
|  |   call setline(1,  ['```c', '#if 0', 'int', '#else', 'int', '#if', '#endif', '```' ]) | ||||||
|  |   let l:expected = ["cCppOutElse", "cConditional"] | ||||||
|  |   eval AssertHighlightGroups(6, 1, l:expected, 1) | ||||||
|  |   syntax clear | ||||||
|  |   bw! | ||||||
|  | endfunc | ||||||
|  |  | ||||||
| " This was using freed memory | " This was using freed memory | ||||||
| func Test_WinEnter_synstack_synID() | func Test_WinEnter_synstack_synID() | ||||||
|   autocmd WinEnter * call synstack(line("."), col(".")) |   autocmd WinEnter * call synstack(line("."), col(".")) | ||||||
|   | |||||||
| @@ -704,6 +704,8 @@ static char *(features[]) = | |||||||
|  |  | ||||||
| static int included_patches[] = | static int included_patches[] = | ||||||
| {   /* Add new patch number below this line */ | {   /* Add new patch number below this line */ | ||||||
|  | /**/ | ||||||
|  |     1077, | ||||||
| /**/ | /**/ | ||||||
|     1076, |     1076, | ||||||
| /**/ | /**/ | ||||||
|   | |||||||
| @@ -953,6 +953,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring); | |||||||
| # define HL_TRANS_CONT	0x10000 // transparent item without contains arg | # define HL_TRANS_CONT	0x10000 // transparent item without contains arg | ||||||
| # define HL_CONCEAL	0x20000 // can be concealed | # define HL_CONCEAL	0x20000 // can be concealed | ||||||
| # define HL_CONCEALENDS	0x40000 // can be concealed | # define HL_CONCEALENDS	0x40000 // can be concealed | ||||||
|  | # define HL_INCLUDED_TOPLEVEL 0x80000 // toplevel item in included syntax, allowed by contains=TOP | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // Values for 'options' argument in do_search() and searchit() | // Values for 'options' argument in do_search() and searchit() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user