Auto merge of #2636 - micbou:display-diagnostics-asynchronously, r=micbou

[READY] Display diagnostics and parse initial buffer asynchronously using timers

Currently, we wait for an autocommand to trigger to display diagnostics. This is not ideal as users have to do some actions like moving the cursor or editing the buffer to see them. We can improve that by using [the timers feature introduced in Vim 7.4.1578](975b5271ee) to display diagnostics asynchronously. Here's a demo:

![ycm-diagnostics-async](https://cloud.githubusercontent.com/assets/10026824/25772105/5aac4706-3263-11e7-8304-643a39599d29.gif)

By displaying diagnostics asynchronously, we can drop the `CursorHold` and `CursorHoldI` autocommands as well as [the `g:ycm_allow_changing_updatetime` option](5a806dcb30/README.md (the-gycm_allow_changing_updatetime-option)). In addition, we can now parse the current buffer and display diagnostics on the `TextChanged` event instead of the `CursorMoved` one. Note that we still need to check `b:changed_tick` for the `InsertLeave` event.

Given that our policy is to support the latest version of Ubuntu LTS which is 16.04, and that version [bundles Vim 7.4.1689](http://packages.ubuntu.com/xenial/vim), we can increase our Vim version requirement to 7.4.1578.

Next steps will be to use timers for parsing the buffer when the server becomes ready and for completions.

Fixes https://github.com/Valloric/YouCompleteMe/issues/2165.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/valloric/youcompleteme/2636)
<!-- Reviewable:end -->
This commit is contained in:
zzbot 2017-05-17 09:48:20 -07:00 committed by GitHub
commit c1c4ebd7e5
7 changed files with 226 additions and 199 deletions

View File

@ -216,7 +216,7 @@ YouCompleteMe, however they may not work for everyone. If the following
instructions don't work for you, check out the [full installation instructions don't work for you, check out the [full installation
guide](#full-installation-guide). guide](#full-installation-guide).
Make sure you have Vim 7.4.143 with Python 2 or Python 3 support. Ubuntu 14.10 Make sure you have Vim 7.4.1578 with Python 2 or Python 3 support. Ubuntu 16.04
and later have a Vim that's recent enough. You can see the version of Vim and later have a Vim that's recent enough. You can see the version of Vim
installed by running `vim --version`. If the version is too old, you may need to installed by running `vim --version`. If the version is too old, you may need to
[compile Vim from source][vim-build] (don't worry, it's easy). [compile Vim from source][vim-build] (don't worry, it's easy).
@ -283,7 +283,7 @@ YouCompleteMe, however they may not work for everyone. If the following
instructions don't work for you, check out the [full installation instructions don't work for you, check out the [full installation
guide](#full-installation-guide). guide](#full-installation-guide).
Make sure you have Vim 7.4.143 with Python 2 or Python 3 support. Fedora 21 and Make sure you have Vim 7.4.1578 with Python 2 or Python 3 support. Fedora 21 and
later have a Vim that's recent enough. You can see the version of Vim installed later have a Vim that's recent enough. You can see the version of Vim installed
by running `vim --version`. If the version is too old, you may need to [compile by running `vim --version`. If the version is too old, you may need to [compile
Vim from source][vim-build] (don't worry, it's easy). Vim from source][vim-build] (don't worry, it's easy).
@ -353,7 +353,7 @@ guide](#full-installation-guide).
**Important:** we assume that you are using the `cmd.exe` command prompt and **Important:** we assume that you are using the `cmd.exe` command prompt and
that you know how to add an executable to the PATH environment variable. that you know how to add an executable to the PATH environment variable.
Make sure you have at least Vim 7.4.143 with Python 2 or Python 3 support. You Make sure you have at least Vim 7.4.1578 with Python 2 or Python 3 support. You
can check the version and which Python is supported by typing `:version` inside can check the version and which Python is supported by typing `:version` inside
Vim. Look at the features included: `+python/dyn` for Python 2 and Vim. Look at the features included: `+python/dyn` for Python 2 and
`+python3/dyn` for Python 3. Take note of the Vim architecture, i.e. 32 or `+python3/dyn` for Python 3. Take note of the Vim architecture, i.e. 32 or
@ -432,7 +432,7 @@ guide](#full-installation-guide).
**NOTE:** OpenBSD / FreeBSD are not officially supported platforms by YCM. **NOTE:** OpenBSD / FreeBSD are not officially supported platforms by YCM.
Make sure you have Vim 7.4.143 with Python 2 or Python 3 support. Make sure you have Vim 7.4.1578 with Python 2 or Python 3 support.
OpenBSD 5.5 and later have a Vim that's recent enough. You can see the version of OpenBSD 5.5 and later have a Vim that's recent enough. You can see the version of
Vim installed by running `vim --version`. Vim installed by running `vim --version`.
@ -509,7 +509,7 @@ process.
**Please follow the instructions carefully. Read EVERY WORD.** **Please follow the instructions carefully. Read EVERY WORD.**
1. **Ensure that your version of Vim is _at least_ 7.4.143 _and_ that it has 1. **Ensure that your version of Vim is _at least_ 7.4.1578 _and_ that it has
support for Python 2 or Python 3 scripting**. support for Python 2 or Python 3 scripting**.
Inside Vim, type `:version`. Look at the first two to three lines of output; Inside Vim, type `:version`. Look at the first two to three lines of output;
@ -521,7 +521,7 @@ process.
If your version of Vim is not recent enough, you may need to [compile Vim If your version of Vim is not recent enough, you may need to [compile Vim
from source][vim-build] (don't worry, it's easy). from source][vim-build] (don't worry, it's easy).
After you have made sure that you have Vim 7.4.143+, type the following in After you have made sure that you have Vim 7.4.1578+, type the following in
Vim: `:echo has('python') || has('python3')`. The output should be 1. If Vim: `:echo has('python') || has('python3')`. The output should be 1. If
it's 0, then get a version of Vim with Python support. it's 0, then get a version of Vim with Python support.
@ -1995,26 +1995,6 @@ Default: `1`
let g:ycm_open_loclist_on_ycm_diags = 1 let g:ycm_open_loclist_on_ycm_diags = 1
``` ```
### The `g:ycm_allow_changing_updatetime` option
When this option is set to `1`, YCM will change the `updatetime` Vim option to
`2000` (see `:h updatetime`). This may conflict with some other plugins you have
(but it's unlikely). The `updatetime` option is the number of milliseconds that
have to pass before Vim's `CursorHold` (see `:h CursorHold`) event fires. YCM
runs the completion engines' "file comprehension" systems in the background on
every such event; the identifier-based engine collects the identifiers whereas
the semantic engine compiles the file to build an AST.
The Vim default of `4000` for `updatetime` is a bit long, so YCM reduces
this. Set this option to `0` to force YCM to leave your `updatetime` setting
alone.
Default: `1`
```viml
let g:ycm_allow_changing_updatetime = 1
```
### The `g:ycm_complete_in_comments` option ### The `g:ycm_complete_in_comments` option
When this option is set to `1`, YCM will show the completion menu even when When this option is set to `1`, YCM will show the completion menu even when
@ -2838,19 +2818,8 @@ current file and simple prefix-based filtering.
### Why does YCM demand such a recent version of Vim? ### Why does YCM demand such a recent version of Vim?
During YCM's development several show-stopper bugs were encountered in Vim. YCM needs a version of Vim with the timers feature to achieve full
Those needed to be fixed upstream (and were). A few months after those bugs were asynchronicity. This feature is available since Vim 7.4.1578.
fixed, Vim trunk landed the `pyeval()` function which improved YCM performance
even more since less time was spent serializing and deserializing data between
Vim and the embedded Python interpreter. A few critical bugfixes for `pyeval()`
landed in Vim 7.3.584 (and a few commits before that), and given the current
availability of Vim 7.4.143, which features improved events for text change
detection, it has been chosen.
### I get annoying messages in Vim's status area when I type
If you're referring to the `User defined completion <bla bla> back at original`
and similar, then just update to Vim 7.4.314 (or later) and they'll go away.
### Nasty bugs happen if I have the `vim-autoclose` plugin installed ### Nasty bugs happen if I have the `vim-autoclose` plugin installed

View File

@ -26,6 +26,16 @@ let s:omnifunc_mode = 0
let s:old_cursor_position = [] let s:old_cursor_position = []
let s:cursor_moved = 0 let s:cursor_moved = 0
let s:previous_allowed_buffer_number = 0 let s:previous_allowed_buffer_number = 0
let s:pollers = {
\ 'file_parse_response': {
\ 'id': -1,
\ 'wait_milliseconds': 100
\ },
\ 'server_ready': {
\ 'id': -1,
\ 'wait_milliseconds': 100
\ }
\ }
" When both versions are available, we prefer Python 3 over Python 2: " When both versions are available, we prefer Python 3 over Python 2:
@ -75,10 +85,6 @@ function! youcompleteme#Enable()
call s:SetUpSigns() call s:SetUpSigns()
call s:SetUpSyntaxHighlighting() call s:SetUpSyntaxHighlighting()
if g:ycm_allow_changing_updatetime && &updatetime > 2000
set ut=2000
endif
call youcompleteme#EnableCursorMovedAutocommands() call youcompleteme#EnableCursorMovedAutocommands()
augroup youcompleteme augroup youcompleteme
autocmd! autocmd!
@ -93,20 +99,17 @@ function! youcompleteme#Enable()
autocmd FileType * call s:OnFileTypeSet() autocmd FileType * call s:OnFileTypeSet()
autocmd BufEnter * call s:OnBufferEnter() autocmd BufEnter * call s:OnBufferEnter()
autocmd BufUnload * call s:OnBufferUnload() autocmd BufUnload * call s:OnBufferUnload()
autocmd CursorHold,CursorHoldI * call s:OnCursorHold()
autocmd InsertLeave * call s:OnInsertLeave() autocmd InsertLeave * call s:OnInsertLeave()
autocmd InsertEnter * call s:OnInsertEnter() autocmd InsertEnter * call s:OnInsertEnter()
autocmd VimLeave * call s:OnVimLeave() autocmd VimLeave * call s:OnVimLeave()
autocmd CompleteDone * call s:OnCompleteDone() autocmd CompleteDone * call s:OnCompleteDone()
augroup END augroup END
" The FileType event is not triggered for the first loaded file. However, we " The FileType event is not triggered for the first loaded file. We wait until
" don't directly call the s:OnFileTypeSet function because it would send " the server is ready to manually run the s:OnFileTypeSet function.
" requests that can't succeed as the server is not ready yet and would slow let s:pollers.server_ready.id = timer_start(
" down startup. \ s:pollers.server_ready.wait_milliseconds,
if s:AllowedToCompleteInCurrentBuffer() \ function( 's:PollServerReady' ) )
call s:SetCompleteFunc()
endif
endfunction endfunction
@ -114,6 +117,7 @@ function! youcompleteme#EnableCursorMovedAutocommands()
augroup ycmcompletemecursormove augroup ycmcompletemecursormove
autocmd! autocmd!
autocmd CursorMoved * call s:OnCursorMovedNormalMode() autocmd CursorMoved * call s:OnCursorMovedNormalMode()
autocmd TextChanged * call s:OnTextChangedNormalMode()
autocmd TextChangedI * call s:OnTextChangedInsertMode() autocmd TextChangedI * call s:OnTextChangedInsertMode()
augroup END augroup END
endfunction endfunction
@ -373,10 +377,8 @@ function! s:SetUpCpoptions()
set cpoptions+=B set cpoptions+=B
" This prevents the display of "Pattern not found" & similar messages during " This prevents the display of "Pattern not found" & similar messages during
" completion. This is only available since Vim 7.4.314 " completion.
if s:Pyeval( 'vimsupport.VimVersionAtLeast("7.4.314")' ) set shortmess+=c
set shortmess+=c
endif
endfunction endfunction
@ -457,13 +459,15 @@ function! s:OnBufferUnload()
endfunction endfunction
function! s:OnCursorHold() function! s:PollServerReady( timer_id )
if !s:AllowedToCompleteInCurrentBuffer() if !s:Pyeval( 'ycm_state.IsServerReady()' )
let s:pollers.server_ready.id = timer_start(
\ s:pollers.server_ready.wait_milliseconds,
\ function( 's:PollServerReady' ) )
return return
endif endif
call s:SetUpCompleteopt() call s:OnFileTypeSet()
call s:OnFileReadyToParse()
endfunction endfunction
@ -473,34 +477,33 @@ function! s:OnFileReadyToParse( ... )
" effectively forcing a parse of the buffer. Default is 0. " effectively forcing a parse of the buffer. Default is 0.
let force_parsing = a:0 > 0 && a:1 let force_parsing = a:0 > 0 && a:1
if s:Pyeval( 'ycm_state.ServerBecomesReady()' )
" Server was not ready until now and could not parse previous requests for
" the current buffer. We need to send them again.
exec s:python_command "ycm_state.OnBufferVisit()"
exec s:python_command "ycm_state.OnFileReadyToParse()"
" Setting the omnifunc requires us to ask the server if it has a native
" semantic completer for the current buffer's filetype. Since we only set it
" when entering a buffer or changing the filetype, we try to set it again
" now that the server is ready.
call s:SetOmnicompleteFunc()
return
endif
" Order is important here; we need to extract any information before
" reparsing the file again. If we sent the new parse request first, then
" the response would always be pending when we called
" HandleFileParseRequest.
exec s:python_command "ycm_state.HandleFileParseRequest()"
" We only want to send a new FileReadyToParse event notification if the buffer " We only want to send a new FileReadyToParse event notification if the buffer
" has changed since the last time we sent one, or if forced. " has changed since the last time we sent one, or if forced.
if force_parsing || b:changedtick != get( b:, 'ycm_changedtick', -1 ) if force_parsing || b:changedtick != get( b:, 'ycm_changedtick', -1 )
exec s:python_command "ycm_state.OnFileReadyToParse()" exec s:python_command "ycm_state.OnFileReadyToParse()"
call timer_stop( s:pollers.file_parse_response.id )
let s:pollers.file_parse_response.id = timer_start(
\ s:pollers.file_parse_response.wait_milliseconds,
\ function( 's:PollFileParseResponse' ) )
let b:ycm_changedtick = b:changedtick let b:ycm_changedtick = b:changedtick
endif endif
endfunction endfunction
function! s:PollFileParseResponse( ... )
if !s:Pyeval( "ycm_state.FileParseRequestReady()" )
let s:pollers.file_parse_response.id = timer_start(
\ s:pollers.file_parse_response.wait_milliseconds,
\ function( 's:PollFileParseResponse' ) )
return
endif
exec s:python_command "ycm_state.HandleFileParseRequest()"
endfunction
function! s:SetCompleteFunc() function! s:SetCompleteFunc()
let &completefunc = 'youcompleteme#Complete' let &completefunc = 'youcompleteme#Complete'
let &l:completefunc = 'youcompleteme#Complete' let &l:completefunc = 'youcompleteme#Complete'
@ -522,6 +525,24 @@ function! s:SetOmnicompleteFunc()
endfunction endfunction
function! s:OnCursorMovedNormalMode()
if !s:AllowedToCompleteInCurrentBuffer()
return
endif
exec s:python_command "ycm_state.OnCursorMoved()"
endfunction
function! s:OnTextChangedNormalMode()
if !s:AllowedToCompleteInCurrentBuffer()
return
endif
call s:OnFileReadyToParse()
endfunction
function! s:OnTextChangedInsertMode() function! s:OnTextChangedInsertMode()
if !s:AllowedToCompleteInCurrentBuffer() if !s:AllowedToCompleteInCurrentBuffer()
return return
@ -548,16 +569,6 @@ function! s:OnTextChangedInsertMode()
endfunction endfunction
function! s:OnCursorMovedNormalMode()
if !s:AllowedToCompleteInCurrentBuffer()
return
endif
call s:OnFileReadyToParse()
exec s:python_command "ycm_state.OnCursorMoved()"
endfunction
function! s:OnInsertLeave() function! s:OnInsertLeave()
if !s:AllowedToCompleteInCurrentBuffer() if !s:AllowedToCompleteInCurrentBuffer()
return return
@ -579,8 +590,6 @@ function! s:OnInsertEnter()
endif endif
let s:old_cursor_position = [] let s:old_cursor_position = []
call s:OnFileReadyToParse()
endfunction endfunction
@ -746,6 +755,10 @@ endfunction
function! s:RestartServer() function! s:RestartServer()
exec s:python_command "ycm_state.RestartServer()" exec s:python_command "ycm_state.RestartServer()"
call timer_stop( s:pollers.server_ready.id )
let s:pollers.server_ready.id = timer_start(
\ s:pollers.server_ready.wait_milliseconds,
\ function( 's:PollServerReady' ) )
endfunction endfunction

View File

@ -96,38 +96,37 @@ Contents ~
13. The |g:ycm_filter_diagnostics| option 13. The |g:ycm_filter_diagnostics| option
14. The |g:ycm_always_populate_location_list| option 14. The |g:ycm_always_populate_location_list| option
15. The |g:ycm_open_loclist_on_ycm_diags| option 15. The |g:ycm_open_loclist_on_ycm_diags| option
16. The |g:ycm_allow_changing_updatetime| option 16. The |g:ycm_complete_in_comments| option
17. The |g:ycm_complete_in_comments| option 17. The |g:ycm_complete_in_strings| option
18. The |g:ycm_complete_in_strings| option 18. The |g:ycm_collect_identifiers_from_comments_and_strings| option
19. The |g:ycm_collect_identifiers_from_comments_and_strings| option 19. The |g:ycm_collect_identifiers_from_tags_files| option
20. The |g:ycm_collect_identifiers_from_tags_files| option 20. The |g:ycm_seed_identifiers_with_syntax| option
21. The |g:ycm_seed_identifiers_with_syntax| option 21. The |g:ycm_extra_conf_vim_data| option
22. The |g:ycm_extra_conf_vim_data| option 22. The |g:ycm_server_python_interpreter| option
23. The |g:ycm_server_python_interpreter| option 23. The |g:ycm_keep_logfiles| option
24. The |g:ycm_keep_logfiles| option 24. The |g:ycm_log_level| option
25. The |g:ycm_log_level| option 25. The |g:ycm_auto_start_csharp_server| option
26. The |g:ycm_auto_start_csharp_server| option 26. The |g:ycm_auto_stop_csharp_server| option
27. The |g:ycm_auto_stop_csharp_server| option 27. The |g:ycm_csharp_server_port| option
28. The |g:ycm_csharp_server_port| option 28. The |g:ycm_csharp_insert_namespace_expr| option
29. The |g:ycm_csharp_insert_namespace_expr| option 29. The |g:ycm_add_preview_to_completeopt| option
30. The |g:ycm_add_preview_to_completeopt| option 30. The |g:ycm_autoclose_preview_window_after_completion| option
31. The |g:ycm_autoclose_preview_window_after_completion| option 31. The |g:ycm_autoclose_preview_window_after_insertion| option
32. The |g:ycm_autoclose_preview_window_after_insertion| option 32. The |g:ycm_max_diagnostics_to_display| option
33. The |g:ycm_max_diagnostics_to_display| option 33. The |g:ycm_key_list_select_completion| option
34. The |g:ycm_key_list_select_completion| option 34. The |g:ycm_key_list_previous_completion| option
35. The |g:ycm_key_list_previous_completion| option 35. The |g:ycm_key_invoke_completion| option
36. The |g:ycm_key_invoke_completion| option 36. The |g:ycm_key_detailed_diagnostics| option
37. The |g:ycm_key_detailed_diagnostics| option 37. The |g:ycm_global_ycm_extra_conf| option
38. The |g:ycm_global_ycm_extra_conf| option 38. The |g:ycm_confirm_extra_conf| option
39. The |g:ycm_confirm_extra_conf| option 39. The |g:ycm_extra_conf_globlist| option
40. The |g:ycm_extra_conf_globlist| option 40. The |g:ycm_filepath_completion_use_working_dir| option
41. The |g:ycm_filepath_completion_use_working_dir| option 41. The |g:ycm_semantic_triggers| option
42. The |g:ycm_semantic_triggers| option 42. The |g:ycm_cache_omnifunc| option
43. The |g:ycm_cache_omnifunc| option 43. The |g:ycm_use_ultisnips_completer| option
44. The |g:ycm_use_ultisnips_completer| option 44. The |g:ycm_goto_buffer_command| option
45. The |g:ycm_goto_buffer_command| option 45. The |g:ycm_disable_for_files_larger_than_kb| option
46. The |g:ycm_disable_for_files_larger_than_kb| option 46. The |g:ycm_python_binary_path| option
47. The |g:ycm_python_binary_path| option
11. FAQ |youcompleteme-faq| 11. FAQ |youcompleteme-faq|
1. I used to be able to 'import vim' in '.ycm_extra_conf.py', but now can't |youcompleteme-i-used-to-be-able-to-import-vim-in-.ycm_extra_conf.py-but-now-cant| 1. I used to be able to 'import vim' in '.ycm_extra_conf.py', but now can't |youcompleteme-i-used-to-be-able-to-import-vim-in-.ycm_extra_conf.py-but-now-cant|
2. I get 'ImportError' exceptions that mention 'PyInit_ycm_core' or 'initycm_core' |youcompleteme-i-get-importerror-exceptions-that-mention-pyinit_ycm_core-or-initycm_core| 2. I get 'ImportError' exceptions that mention 'PyInit_ycm_core' or 'initycm_core' |youcompleteme-i-get-importerror-exceptions-that-mention-pyinit_ycm_core-or-initycm_core|
@ -151,23 +150,22 @@ Contents ~
20. Snippets added with ':UltiSnipsAddFiletypes' do not appear in the popup menu |youcompleteme-snippets-added-with-ultisnipsaddfiletypes-do-not-appear-in-popup-menu| 20. Snippets added with ':UltiSnipsAddFiletypes' do not appear in the popup menu |youcompleteme-snippets-added-with-ultisnipsaddfiletypes-do-not-appear-in-popup-menu|
21. Why isn't YCM just written in plain VimScript, FFS? |youcompleteme-why-isnt-ycm-just-written-in-plain-vimscript-ffs| 21. Why isn't YCM just written in plain VimScript, FFS? |youcompleteme-why-isnt-ycm-just-written-in-plain-vimscript-ffs|
22. Why does YCM demand such a recent version of Vim? |youcompleteme-why-does-ycm-demand-such-recent-version-of-vim| 22. Why does YCM demand such a recent version of Vim? |youcompleteme-why-does-ycm-demand-such-recent-version-of-vim|
23. I get annoying messages in Vim's status area when I type |youcompleteme-i-get-annoying-messages-in-vims-status-area-when-i-type| 23. Nasty bugs happen if I have the 'vim-autoclose' plugin installed |youcompleteme-nasty-bugs-happen-if-i-have-vim-autoclose-plugin-installed|
24. Nasty bugs happen if I have the 'vim-autoclose' plugin installed |youcompleteme-nasty-bugs-happen-if-i-have-vim-autoclose-plugin-installed| 24. Is there some sort of YCM mailing list? I have questions |youcompleteme-is-there-sort-of-ycm-mailing-list-i-have-questions|
25. Is there some sort of YCM mailing list? I have questions |youcompleteme-is-there-sort-of-ycm-mailing-list-i-have-questions| 25. I get an internal compiler error when installing |youcompleteme-i-get-an-internal-compiler-error-when-installing|
26. I get an internal compiler error when installing |youcompleteme-i-get-an-internal-compiler-error-when-installing| 26. I get weird errors when I press 'Ctrl-C' in Vim |youcompleteme-i-get-weird-errors-when-i-press-ctrl-c-in-vim|
27. I get weird errors when I press 'Ctrl-C' in Vim |youcompleteme-i-get-weird-errors-when-i-press-ctrl-c-in-vim| 27. Why did YCM stop using Syntastic for diagnostics display? |youcompleteme-why-did-ycm-stop-using-syntastic-for-diagnostics-display|
28. Why did YCM stop using Syntastic for diagnostics display? |youcompleteme-why-did-ycm-stop-using-syntastic-for-diagnostics-display| 28. Completion doesn't work with the C++ standard library headers |youcompleteme-completion-doesnt-work-with-c-standard-library-headers|
29. Completion doesn't work with the C++ standard library headers |youcompleteme-completion-doesnt-work-with-c-standard-library-headers| 29. When I open a JavaScript file, I get an annoying warning about '.tern-project'
30. When I open a JavaScript file, I get an annoying warning about '.tern-project'
file |youcompleteme-when-i-open-javascript-file-i-get-an-annoying-warning-about-.tern-project-file| file |youcompleteme-when-i-open-javascript-file-i-get-an-annoying-warning-about-.tern-project-file|
31. When I start vim I get a runtime error saying 'R6034 An application has made an 30. When I start vim I get a runtime error saying 'R6034 An application has made an
attempt to load the C runtime library incorrectly.' |youcompleteme-when-i-start-vim-i-get-runtime-error-saying-r6034-an-application-has-made-an-attempt-to-load-c-runtime-library-incorrectly.| attempt to load the C runtime library incorrectly.' |youcompleteme-when-i-start-vim-i-get-runtime-error-saying-r6034-an-application-has-made-an-attempt-to-load-c-runtime-library-incorrectly.|
32. I hear that YCM only supports Python 2, is that true? |youcompleteme-i-hear-that-ycm-only-supports-python-2-is-that-true| 31. I hear that YCM only supports Python 2, is that true? |youcompleteme-i-hear-that-ycm-only-supports-python-2-is-that-true|
33. On Windows I get "E887: Sorry, this command is disabled, the Python's site 32. On Windows I get "E887: Sorry, this command is disabled, the Python's site
module could not be loaded" |youcompleteme-on-windows-i-get-e887-sorry-this-command-is-disabled-pythons-site-module-could-not-be-loaded| module could not be loaded" |youcompleteme-on-windows-i-get-e887-sorry-this-command-is-disabled-pythons-site-module-could-not-be-loaded|
34. I can't complete python packages in a virtual environment. |youcompleteme-i-cant-complete-python-packages-in-virtual-environment.| 33. I can't complete python packages in a virtual environment. |youcompleteme-i-cant-complete-python-packages-in-virtual-environment.|
35. I want to defer loading of YouCompleteMe until after Vim finishes booting |i-want-to-defer-loading-of-youcompleteme-until-after-vim-finishes-booting| 34. I want to defer loading of YouCompleteMe until after Vim finishes booting |i-want-to-defer-loading-of-youcompleteme-until-after-vim-finishes-booting|
36. YCM does not shut down when I quit Vim |youcompleteme-ycm-does-not-shut-down-when-i-quit-vim| 35. YCM does not shut down when I quit Vim |youcompleteme-ycm-does-not-shut-down-when-i-quit-vim|
12. Contributor Code of Conduct |youcompleteme-contributor-code-of-conduct| 12. Contributor Code of Conduct |youcompleteme-contributor-code-of-conduct|
13. Contact |youcompleteme-contact| 13. Contact |youcompleteme-contact|
14. License |youcompleteme-license| 14. License |youcompleteme-license|
@ -413,7 +411,7 @@ These instructions (using 'install.py') are the quickest way to install
YouCompleteMe, however they may not work for everyone. If the following YouCompleteMe, however they may not work for everyone. If the following
instructions don't work for you, check out the full installation guide. instructions don't work for you, check out the full installation guide.
Make sure you have Vim 7.4.143 with Python 2 or Python 3 support. Ubuntu 14.10 Make sure you have Vim 7.4.1578 with Python 2 or Python 3 support. Ubuntu 16.04
and later have a Vim that's recent enough. You can see the version of Vim and later have a Vim that's recent enough. You can see the version of Vim
installed by running 'vim --version'. If the version is too old, you may need installed by running 'vim --version'. If the version is too old, you may need
to compile Vim from source [30] (don't worry, it's easy). to compile Vim from source [30] (don't worry, it's easy).
@ -484,10 +482,10 @@ These instructions (using 'install.py') are the quickest way to install
YouCompleteMe, however they may not work for everyone. If the following YouCompleteMe, however they may not work for everyone. If the following
instructions don't work for you, check out the full installation guide. instructions don't work for you, check out the full installation guide.
Make sure you have Vim 7.4.143 with Python 2 or Python 3 support. Fedora 21 and Make sure you have Vim 7.4.1578 with Python 2 or Python 3 support. Fedora 21
later have a Vim that's recent enough. You can see the version of Vim installed and later have a Vim that's recent enough. You can see the version of Vim
by running 'vim --version'. If the version is too old, you may need to compile installed by running 'vim --version'. If the version is too old, you may need
Vim from source [30] (don't worry, it's easy). to compile Vim from source [30] (don't worry, it's easy).
Install YouCompleteMe with Vundle [23]. Install YouCompleteMe with Vundle [23].
@ -558,7 +556,7 @@ instructions don't work for you, check out the full installation guide.
**Important:** we assume that you are using the 'cmd.exe' command prompt and **Important:** we assume that you are using the 'cmd.exe' command prompt and
that you know how to add an executable to the PATH environment variable. that you know how to add an executable to the PATH environment variable.
Make sure you have at least Vim 7.4.143 with Python 2 or Python 3 support. You Make sure you have at least Vim 7.4.1578 with Python 2 or Python 3 support. You
can check the version and which Python is supported by typing ':version' inside can check the version and which Python is supported by typing ':version' inside
Vim. Look at the features included: '+python/dyn' for Python 2 and Vim. Look at the features included: '+python/dyn' for Python 2 and
'+python3/dyn' for Python 3. Take note of the Vim architecture, i.e. 32 or '+python3/dyn' for Python 3. Take note of the Vim architecture, i.e. 32 or
@ -643,7 +641,7 @@ instructions don't work for you, check out the full installation guide.
**NOTE:** OpenBSD / FreeBSD are not officially supported platforms by YCM. **NOTE:** OpenBSD / FreeBSD are not officially supported platforms by YCM.
Make sure you have Vim 7.4.143 with Python 2 or Python 3 support. Make sure you have Vim 7.4.1578 with Python 2 or Python 3 support.
OpenBSD 5.5 and later have a Vim that's recent enough. You can see the version OpenBSD 5.5 and later have a Vim that's recent enough. You can see the version
of Vim installed by running 'vim --version'. of Vim installed by running 'vim --version'.
@ -724,8 +722,8 @@ will notify you to recompile it. You should then rerun the install process.
**Please follow the instructions carefully. Read EVERY WORD.** **Please follow the instructions carefully. Read EVERY WORD.**
1. **Ensure that your version of Vim is _at least_ 7.4.143 _and_ that it has 1. **Ensure that your version of Vim is _at least_ 7.4.1578 _and_ that it
support for Python 2 or Python 3 scripting**. has support for Python 2 or Python 3 scripting**.
Inside Vim, type ':version'. Look at the first two to three lines of Inside Vim, type ':version'. Look at the first two to three lines of
output; it should say 'Vi IMproved X.Y', where X.Y is the major version output; it should say 'Vi IMproved X.Y', where X.Y is the major version
@ -736,7 +734,7 @@ will notify you to recompile it. You should then rerun the install process.
If your version of Vim is not recent enough, you may need to compile Vim If your version of Vim is not recent enough, you may need to compile Vim
from source [30] (don't worry, it's easy). from source [30] (don't worry, it's easy).
After you have made sure that you have Vim 7.4.143+, type the following After you have made sure that you have Vim 7.4.1578+, type the following
in Vim: ":echo has('python') || has('python3')". The output should be 1. in Vim: ":echo has('python') || has('python3')". The output should be 1.
If it's 0, then get a version of Vim with Python support. If it's 0, then get a version of Vim with Python support.
@ -2275,24 +2273,6 @@ Default: '1'
let g:ycm_open_loclist_on_ycm_diags = 1 let g:ycm_open_loclist_on_ycm_diags = 1
< <
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
The *g:ycm_allow_changing_updatetime* option
When this option is set to '1', YCM will change the 'updatetime' Vim option to
'2000' (see ':h updatetime'). This may conflict with some other plugins you
have (but it's unlikely). The 'updatetime' option is the number of milliseconds
that have to pass before Vim's 'CursorHold' (see ':h CursorHold') event fires.
YCM runs the completion engines' "file comprehension" systems in the background
on every such event; the identifier-based engine collects the identifiers
whereas the semantic engine compiles the file to build an AST.
The Vim default of '4000' for 'updatetime' is a bit long, so YCM reduces this.
Set this option to '0' to force YCM to leave your 'updatetime' setting alone.
Default: '1'
>
let g:ycm_allow_changing_updatetime = 1
<
-------------------------------------------------------------------------------
The *g:ycm_complete_in_comments* option The *g:ycm_complete_in_comments* option
When this option is set to '1', YCM will show the completion menu even when When this option is set to '1', YCM will show the completion menu even when
@ -3102,21 +3082,8 @@ in the current file and simple prefix-based filtering.
*youcompleteme-why-does-ycm-demand-such-recent-version-of-vim* *youcompleteme-why-does-ycm-demand-such-recent-version-of-vim*
Why does YCM demand such a recent version of Vim? ~ Why does YCM demand such a recent version of Vim? ~
During YCM's development several show-stopper bugs were encountered in Vim. YCM needs a version of Vim with the timers feature to achieve full
Those needed to be fixed upstream (and were). A few months after those bugs asynchronicity. This feature is available since Vim 7.4.1578.
were fixed, Vim trunk landed the 'pyeval()' function which improved YCM
performance even more since less time was spent serializing and deserializing
data between Vim and the embedded Python interpreter. A few critical bugfixes
for 'pyeval()' landed in Vim 7.3.584 (and a few commits before that), and given
the current availability of Vim 7.4.143, which features improved events for
text change detection, it has been chosen.
-------------------------------------------------------------------------------
*youcompleteme-i-get-annoying-messages-in-vims-status-area-when-i-type*
I get annoying messages in Vim's status area when I type ~
If you're referring to the 'User defined completion <bla bla> back at original'
and similar, then just update to Vim 7.4.314 (or later) and they'll go away.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*youcompleteme-nasty-bugs-happen-if-i-have-vim-autoclose-plugin-installed* *youcompleteme-nasty-bugs-happen-if-i-have-vim-autoclose-plugin-installed*

View File

@ -27,9 +27,16 @@ endfunction
if exists( "g:loaded_youcompleteme" ) if exists( "g:loaded_youcompleteme" )
call s:restore_cpo() call s:restore_cpo()
finish finish
elseif v:version < 704 || (v:version == 704 && !has('patch143')) elseif v:version < 704 || (v:version == 704 && !has( 'patch1578' ))
echohl WarningMsg | echohl WarningMsg |
\ echomsg "YouCompleteMe unavailable: requires Vim 7.4.143+" | \ echomsg "YouCompleteMe unavailable: requires Vim 7.4.1578+" |
\ echohl None
call s:restore_cpo()
finish
elseif !has( 'timers' )
echohl WarningMsg |
\ echomsg "YouCompleteMe unavailable: requires Vim compiled with " .
\ "the timers feature" |
\ echohl None \ echohl None
call s:restore_cpo() call s:restore_cpo()
finish finish

View File

@ -65,7 +65,7 @@ def _IsReady():
return BaseRequest.GetDataFromHandler( 'ready' ) return BaseRequest.GetDataFromHandler( 'ready' )
def _WaitUntilReady( timeout = 5 ): def WaitUntilReady( timeout = 5 ):
expiration = time.time() + timeout expiration = time.time() + timeout
while True: while True:
try: try:
@ -109,7 +109,7 @@ def YouCompleteMeInstance( custom_options = {} ):
@functools.wraps( test ) @functools.wraps( test )
def Wrapper( *args, **kwargs ): def Wrapper( *args, **kwargs ):
ycm = YouCompleteMe( _MakeUserOptions( custom_options ) ) ycm = YouCompleteMe( _MakeUserOptions( custom_options ) )
_WaitUntilReady() WaitUntilReady()
try: try:
test( ycm, *args, **kwargs ) test( ycm, *args, **kwargs )
finally: finally:

View File

@ -31,11 +31,12 @@ MockVimModule()
import contextlib import contextlib
import os import os
from ycm.tests import PathToTestFile, YouCompleteMeInstance from ycm.tests import PathToTestFile, YouCompleteMeInstance, WaitUntilReady
from ycmd.responses import ( BuildDiagnosticData, Diagnostic, Location, Range, from ycmd.responses import ( BuildDiagnosticData, Diagnostic, Location, Range,
UnknownExtraConf, ServerError ) UnknownExtraConf, ServerError )
from hamcrest import assert_that, contains, has_entries, has_item from hamcrest import ( assert_that, contains, has_entries, has_entry, has_item,
has_items, has_key, is_not )
from mock import call, MagicMock, patch from mock import call, MagicMock, patch
from nose.tools import eq_, ok_ from nose.tools import eq_, ok_
@ -81,7 +82,8 @@ def MockEventNotification( response_method, native_filetype_completer = True ):
# We don't want the event to actually be sent to the server, just have it # We don't want the event to actually be sent to the server, just have it
# return success # return success
with patch( 'ycm.client.base_request.BaseRequest.PostDataToHandlerAsync', with patch( 'ycm.client.event_notification.EventNotification.'
'PostDataToHandlerAsync',
return_value = MagicMock( return_value=True ) ): return_value = MagicMock( return_value=True ) ):
# We set up a fake a Response (as called by EventNotification.Response) # We set up a fake a Response (as called by EventNotification.Response)
@ -358,7 +360,7 @@ def EventNotification_FileReadyToParse_TagFiles_UnicodeWorkingDirectory_test(
contents = [ 'current_buffer_contents' ], contents = [ 'current_buffer_contents' ],
filetype = 'some_filetype' ) filetype = 'some_filetype' )
with patch( 'ycm.client.base_request.BaseRequest.' with patch( 'ycm.client.event_notification.EventNotification.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async: 'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with CurrentWorkingDirectory( unicode_dir ): with CurrentWorkingDirectory( unicode_dir ):
with MockVimBuffers( [ current_buffer ], current_buffer, ( 6, 5 ) ): with MockVimBuffers( [ current_buffer ], current_buffer, ( 6, 5 ) ):
@ -412,7 +414,7 @@ def EventNotification_BufferVisit_BuildRequestForCurrentAndUnsavedBuffers_test(
filetype = 'some_filetype', filetype = 'some_filetype',
modified = False ) modified = False )
with patch( 'ycm.client.base_request.BaseRequest.' with patch( 'ycm.client.event_notification.EventNotification.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async: 'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with MockVimBuffers( [ current_buffer, modified_buffer, unmodified_buffer ], with MockVimBuffers( [ current_buffer, modified_buffer, unmodified_buffer ],
current_buffer, current_buffer,
@ -461,7 +463,7 @@ def EventNotification_BufferUnload_BuildRequestForDeletedAndUnsavedBuffers_test(
filetype = 'some_filetype', filetype = 'some_filetype',
modified = False ) modified = False )
with patch( 'ycm.client.base_request.BaseRequest.' with patch( 'ycm.client.event_notification.EventNotification.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async: 'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with MockVimBuffers( [ current_buffer, deleted_buffer ], current_buffer ): with MockVimBuffers( [ current_buffer, deleted_buffer ], current_buffer ):
ycm.OnBufferUnload( deleted_buffer_file ) ycm.OnBufferUnload( deleted_buffer_file )
@ -489,3 +491,73 @@ def EventNotification_BufferUnload_BuildRequestForDeletedAndUnsavedBuffers_test(
'event_notification' 'event_notification'
) )
) )
@patch( 'ycm.syntax_parse.SyntaxKeywordsForCurrentBuffer',
return_value = [ 'foo', 'bar' ] )
@YouCompleteMeInstance( { 'seed_identifiers_with_syntax': 1 } )
def EventNotification_FileReadyToParse_SyntaxKeywords_SeedWithCache_test(
ycm, *args ):
current_buffer = VimBuffer( name = 'current_buffer',
filetype = 'some_filetype' )
with patch( 'ycm.client.event_notification.EventNotification.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with MockVimBuffers( [ current_buffer ], current_buffer ):
ycm.OnFileReadyToParse()
assert_that(
# Positional arguments passed to PostDataToHandlerAsync.
post_data_to_handler_async.call_args[ 0 ],
contains(
has_entry( 'syntax_keywords', has_items( 'foo', 'bar' ) ),
'event_notification'
)
)
# Do not send again syntax keywords in subsequent requests.
ycm.OnFileReadyToParse()
assert_that(
# Positional arguments passed to PostDataToHandlerAsync.
post_data_to_handler_async.call_args[ 0 ],
contains(
is_not( has_key( 'syntax_keywords' ) ),
'event_notification'
)
)
@patch( 'ycm.syntax_parse.SyntaxKeywordsForCurrentBuffer',
return_value = [ 'foo', 'bar' ] )
@YouCompleteMeInstance( { 'seed_identifiers_with_syntax': 1 } )
def EventNotification_FileReadyToParse_SyntaxKeywords_ClearCacheIfRestart_test(
ycm, *args ):
current_buffer = VimBuffer( name = 'current_buffer',
filetype = 'some_filetype' )
with patch( 'ycm.client.event_notification.EventNotification.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with MockVimBuffers( [ current_buffer ], current_buffer ):
ycm.OnFileReadyToParse()
assert_that(
# Positional arguments passed to PostDataToHandlerAsync.
post_data_to_handler_async.call_args[ 0 ],
contains(
has_entry( 'syntax_keywords', has_items( 'foo', 'bar' ) ),
'event_notification'
)
)
# Send again the syntax keywords after restarting the server.
ycm.RestartServer()
WaitUntilReady()
ycm.OnFileReadyToParse()
assert_that(
# Positional arguments passed to PostDataToHandlerAsync.
post_data_to_handler_async.call_args[ 0 ],
contains(
has_entry( 'syntax_keywords', has_items( 'foo', 'bar' ) ),
'event_notification'
)
)

View File

@ -223,6 +223,14 @@ class YouCompleteMe( object ):
return return_code is None return return_code is None
def IsServerReady( self ):
if not self._server_is_ready_with_cache and self.IsServerAlive():
with HandleServerException( display = False ):
self._server_is_ready_with_cache = BaseRequest.GetDataFromHandler(
'ready' )
return self._server_is_ready_with_cache
def _NotifyUserIfServerCrashed( self ): def _NotifyUserIfServerCrashed( self ):
if self._user_notified_about_crash or self.IsServerAlive(): if self._user_notified_about_crash or self.IsServerAlive():
return return
@ -346,15 +354,6 @@ class YouCompleteMe( object ):
self.NativeFiletypeCompletionAvailable() ) self.NativeFiletypeCompletionAvailable() )
def ServerBecomesReady( self ):
if not self._server_is_ready_with_cache:
with HandleServerException( display = False ):
self._server_is_ready_with_cache = BaseRequest.GetDataFromHandler(
'ready' )
return self._server_is_ready_with_cache
return False
def OnFileReadyToParse( self ): def OnFileReadyToParse( self ):
if not self.IsServerAlive(): if not self.IsServerAlive():
self._NotifyUserIfServerCrashed() self._NotifyUserIfServerCrashed()
@ -766,7 +765,7 @@ class YouCompleteMe( object ):
if filetype in self._filetypes_with_keywords_loaded: if filetype in self._filetypes_with_keywords_loaded:
return return
if self._server_is_ready_with_cache: if self.IsServerReady():
self._filetypes_with_keywords_loaded.add( filetype ) self._filetypes_with_keywords_loaded.add( filetype )
extra_data[ 'syntax_keywords' ] = list( extra_data[ 'syntax_keywords' ] = list(
syntax_parse.SyntaxKeywordsForCurrentBuffer() ) syntax_parse.SyntaxKeywordsForCurrentBuffer() )