2017-01-16 20:33 GMT+03:00 Taylor Venable <[email protected]>: > Hello developers, I believe I may have found a bug related to if/else and > spell checking with syntax regions and @Spell. Here's my .vimrc for testing: > > ======================================== > > set nocp > syntax on > > function! TweakSyntax1() > set spell > if 1 > syntax region test start=/</ end=/>/ > else > exit > syntax region test start=/</ end=/>/ contains=@Spell > endif > hi link test comment > endfunction > > function TweakSyntax2() > set spell > if 1 > syntax region test start=/</ end=/>/ > endif > hi link test comment > endfunction > > ======================================== > > Here's my test file: > > ======================================== > > <notaword> notaword > > ======================================== > > Here's a test script: > > ======================================== > > $ vim -u dot-vimrc test.txt > :call TweakSyntax1() > :syn > --- Syntax items --- > test xxx start=/</ end=/>/ > links to Comment > Spell cluster=NONE > > ======================================== > > $ vim -u dot-vimrc test.txt > :call TweakSyntax2() > :syn > --- Syntax items --- > test xxx start=/</ end=/>/ > links to Comment > > ======================================== > > If you open this file and call TweakSyntax1(): *neither* word is marked as > being spelled wrong. If you open this file and call TweakSyntax2(): *both* > words are marked as spelled wrong. The only difference is the existence of > the else clause, which isn't executed. I can't see a reason for it, what am > I missing? > > My version is attached. > > Thanks for looking!
Unlike most modern languages VimL does not have syntax parsing step, it directly executes strings. So in the first case in order to skip to `endif` it must first execute `else` part. Execution of parts which are not intended to be executed like here has a difference: `skip` argument is set to true (part of exarg_T structure for commands (`ex_*`), explicit argument for expressions (`eval*`)). Most of time you would not notice this implementation detail, but programs contain bugs and it leaks out. Specifically in your case when parsing the `else` clause `Spell` syntax cluster is implicitly defined. Implicitly defining syntax cluster if it appears in arguments like `contains=…` is actually intentional, but obviously not when in `else` clause. According to the documentation (:h spell-syntax) if there is Spell cluster spell checking should be limited only to groups in this cluster. Internally the offending function is `get_syn_options()`: while its callers have access to `exarg_T` argument which has `skip` member, `get_syn_options()` does not receive it and cannot determine whether it is skipping. Yet it calls `get_id_list()` which also does not have `skip` argument which in turn calls `syn_check_cluster()` which runs `syn_add_cluster()` if cluster was not found, so `Spell` cluster gets defined while it should not. Suggestion would be passing skip argument to `get_syn_options()` and then to `get_id_list()` which then should not run `syn_add_cluster()` (and better also avoid any memory allocations because result is supposed to be dropped in any case). > > -- > -- > 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]. > For more options, visit https://groups.google.com/d/optout. -- -- 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]. For more options, visit https://groups.google.com/d/optout.
