diff --git a/README.md b/README.md index 2d76201c..fae38bc7 100644 --- a/README.md +++ b/README.md @@ -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 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 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). @@ -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 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 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). @@ -353,7 +353,7 @@ guide](#full-installation-guide). **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. -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 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 @@ -432,7 +432,7 @@ guide](#full-installation-guide). **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 Vim installed by running `vim --version`. @@ -509,7 +509,7 @@ process. **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**. 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 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 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 ``` -### 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 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? -During YCM's development several show-stopper bugs were encountered in Vim. -Those needed to be fixed upstream (and were). A few months after those bugs 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. - -### I get annoying messages in Vim's status area when I type - -If you're referring to the `User defined completion back at original` -and similar, then just update to Vim 7.4.314 (or later) and they'll go away. +YCM needs a version of Vim with the timers feature to achieve full +asynchronicity. This feature is available since Vim 7.4.1578. ### Nasty bugs happen if I have the `vim-autoclose` plugin installed diff --git a/autoload/youcompleteme.vim b/autoload/youcompleteme.vim index 150af967..b09c4d38 100644 --- a/autoload/youcompleteme.vim +++ b/autoload/youcompleteme.vim @@ -26,6 +26,16 @@ let s:omnifunc_mode = 0 let s:old_cursor_position = [] let s:cursor_moved = 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: @@ -75,10 +85,6 @@ function! youcompleteme#Enable() call s:SetUpSigns() call s:SetUpSyntaxHighlighting() - if g:ycm_allow_changing_updatetime && &updatetime > 2000 - set ut=2000 - endif - call youcompleteme#EnableCursorMovedAutocommands() augroup youcompleteme autocmd! @@ -93,20 +99,17 @@ function! youcompleteme#Enable() autocmd FileType * call s:OnFileTypeSet() autocmd BufEnter * call s:OnBufferEnter() autocmd BufUnload * call s:OnBufferUnload() - autocmd CursorHold,CursorHoldI * call s:OnCursorHold() autocmd InsertLeave * call s:OnInsertLeave() autocmd InsertEnter * call s:OnInsertEnter() autocmd VimLeave * call s:OnVimLeave() autocmd CompleteDone * call s:OnCompleteDone() augroup END - " The FileType event is not triggered for the first loaded file. However, we - " don't directly call the s:OnFileTypeSet function because it would send - " requests that can't succeed as the server is not ready yet and would slow - " down startup. - if s:AllowedToCompleteInCurrentBuffer() - call s:SetCompleteFunc() - endif + " The FileType event is not triggered for the first loaded file. We wait until + " the server is ready to manually run the s:OnFileTypeSet function. + let s:pollers.server_ready.id = timer_start( + \ s:pollers.server_ready.wait_milliseconds, + \ function( 's:PollServerReady' ) ) endfunction @@ -114,6 +117,7 @@ function! youcompleteme#EnableCursorMovedAutocommands() augroup ycmcompletemecursormove autocmd! autocmd CursorMoved * call s:OnCursorMovedNormalMode() + autocmd TextChanged * call s:OnTextChangedNormalMode() autocmd TextChangedI * call s:OnTextChangedInsertMode() augroup END endfunction @@ -373,10 +377,8 @@ function! s:SetUpCpoptions() set cpoptions+=B " This prevents the display of "Pattern not found" & similar messages during - " completion. This is only available since Vim 7.4.314 - if s:Pyeval( 'vimsupport.VimVersionAtLeast("7.4.314")' ) - set shortmess+=c - endif + " completion. + set shortmess+=c endfunction @@ -457,13 +459,15 @@ function! s:OnBufferUnload() endfunction -function! s:OnCursorHold() - if !s:AllowedToCompleteInCurrentBuffer() +function! s:PollServerReady( timer_id ) + if !s:Pyeval( 'ycm_state.IsServerReady()' ) + let s:pollers.server_ready.id = timer_start( + \ s:pollers.server_ready.wait_milliseconds, + \ function( 's:PollServerReady' ) ) return endif - call s:SetUpCompleteopt() - call s:OnFileReadyToParse() + call s:OnFileTypeSet() endfunction @@ -473,34 +477,33 @@ function! s:OnFileReadyToParse( ... ) " effectively forcing a parse of the buffer. Default is 0. 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 " has changed since the last time we sent one, or if forced. if force_parsing || b:changedtick != get( b:, 'ycm_changedtick', -1 ) 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 endif 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() let &completefunc = 'youcompleteme#Complete' let &l:completefunc = 'youcompleteme#Complete' @@ -522,6 +525,24 @@ function! s:SetOmnicompleteFunc() 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() if !s:AllowedToCompleteInCurrentBuffer() return @@ -548,16 +569,6 @@ function! s:OnTextChangedInsertMode() endfunction -function! s:OnCursorMovedNormalMode() - if !s:AllowedToCompleteInCurrentBuffer() - return - endif - - call s:OnFileReadyToParse() - exec s:python_command "ycm_state.OnCursorMoved()" -endfunction - - function! s:OnInsertLeave() if !s:AllowedToCompleteInCurrentBuffer() return @@ -579,8 +590,6 @@ function! s:OnInsertEnter() endif let s:old_cursor_position = [] - - call s:OnFileReadyToParse() endfunction @@ -746,6 +755,10 @@ endfunction function! s: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 diff --git a/doc/youcompleteme.txt b/doc/youcompleteme.txt index 9ad76389..9a6e96d7 100644 --- a/doc/youcompleteme.txt +++ b/doc/youcompleteme.txt @@ -96,38 +96,37 @@ Contents ~ 13. The |g:ycm_filter_diagnostics| option 14. The |g:ycm_always_populate_location_list| option 15. The |g:ycm_open_loclist_on_ycm_diags| option - 16. The |g:ycm_allow_changing_updatetime| option - 17. The |g:ycm_complete_in_comments| option - 18. The |g:ycm_complete_in_strings| option - 19. The |g:ycm_collect_identifiers_from_comments_and_strings| option - 20. The |g:ycm_collect_identifiers_from_tags_files| option - 21. The |g:ycm_seed_identifiers_with_syntax| option - 22. The |g:ycm_extra_conf_vim_data| option - 23. The |g:ycm_server_python_interpreter| option - 24. The |g:ycm_keep_logfiles| option - 25. The |g:ycm_log_level| option - 26. The |g:ycm_auto_start_csharp_server| option - 27. The |g:ycm_auto_stop_csharp_server| option - 28. The |g:ycm_csharp_server_port| option - 29. The |g:ycm_csharp_insert_namespace_expr| option - 30. The |g:ycm_add_preview_to_completeopt| option - 31. The |g:ycm_autoclose_preview_window_after_completion| option - 32. The |g:ycm_autoclose_preview_window_after_insertion| option - 33. The |g:ycm_max_diagnostics_to_display| option - 34. The |g:ycm_key_list_select_completion| option - 35. The |g:ycm_key_list_previous_completion| option - 36. The |g:ycm_key_invoke_completion| option - 37. The |g:ycm_key_detailed_diagnostics| option - 38. The |g:ycm_global_ycm_extra_conf| option - 39. The |g:ycm_confirm_extra_conf| option - 40. The |g:ycm_extra_conf_globlist| option - 41. The |g:ycm_filepath_completion_use_working_dir| option - 42. The |g:ycm_semantic_triggers| option - 43. The |g:ycm_cache_omnifunc| option - 44. The |g:ycm_use_ultisnips_completer| option - 45. The |g:ycm_goto_buffer_command| option - 46. The |g:ycm_disable_for_files_larger_than_kb| option - 47. The |g:ycm_python_binary_path| option + 16. The |g:ycm_complete_in_comments| option + 17. 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_tags_files| option + 20. The |g:ycm_seed_identifiers_with_syntax| option + 21. The |g:ycm_extra_conf_vim_data| option + 22. The |g:ycm_server_python_interpreter| option + 23. The |g:ycm_keep_logfiles| option + 24. The |g:ycm_log_level| option + 25. The |g:ycm_auto_start_csharp_server| option + 26. The |g:ycm_auto_stop_csharp_server| option + 27. The |g:ycm_csharp_server_port| option + 28. The |g:ycm_csharp_insert_namespace_expr| option + 29. 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_insertion| option + 32. The |g:ycm_max_diagnostics_to_display| option + 33. The |g:ycm_key_list_select_completion| option + 34. The |g:ycm_key_list_previous_completion| option + 35. The |g:ycm_key_invoke_completion| option + 36. The |g:ycm_key_detailed_diagnostics| option + 37. The |g:ycm_global_ycm_extra_conf| option + 38. The |g:ycm_confirm_extra_conf| option + 39. The |g:ycm_extra_conf_globlist| option + 40. The |g:ycm_filepath_completion_use_working_dir| option + 41. The |g:ycm_semantic_triggers| option + 42. The |g:ycm_cache_omnifunc| option + 43. The |g:ycm_use_ultisnips_completer| option + 44. The |g:ycm_goto_buffer_command| option + 45. The |g:ycm_disable_for_files_larger_than_kb| option + 46. The |g:ycm_python_binary_path| option 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| 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| 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| - 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| - 24. Nasty bugs happen if I have the 'vim-autoclose' plugin installed |youcompleteme-nasty-bugs-happen-if-i-have-vim-autoclose-plugin-installed| - 25. Is there some sort of YCM mailing list? I have questions |youcompleteme-is-there-sort-of-ycm-mailing-list-i-have-questions| - 26. I get an internal compiler error when installing |youcompleteme-i-get-an-internal-compiler-error-when-installing| - 27. I get weird errors when I press 'Ctrl-C' in Vim |youcompleteme-i-get-weird-errors-when-i-press-ctrl-c-in-vim| - 28. Why did YCM stop using Syntastic for diagnostics display? |youcompleteme-why-did-ycm-stop-using-syntastic-for-diagnostics-display| - 29. Completion doesn't work with the C++ standard library headers |youcompleteme-completion-doesnt-work-with-c-standard-library-headers| - 30. When I open a JavaScript file, I get an annoying warning about '.tern-project' + 23. 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. 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. 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. 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| - 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.| - 32. 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 + 31. I hear that YCM only supports Python 2, is that true? |youcompleteme-i-hear-that-ycm-only-supports-python-2-is-that-true| + 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| - 34. 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| - 36. YCM does not shut down when I quit Vim |youcompleteme-ycm-does-not-shut-down-when-i-quit-vim| + 33. I can't complete python packages in a virtual environment. |youcompleteme-i-cant-complete-python-packages-in-virtual-environment.| + 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| + 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| 13. Contact |youcompleteme-contact| 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 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 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). @@ -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 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 -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 -Vim from source [30] (don't worry, it's easy). +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 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). 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 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 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 @@ -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. -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 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.** -1. **Ensure that your version of Vim is _at least_ 7.4.143 _and_ that it has - support for Python 2 or Python 3 scripting**. +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**. 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 @@ -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 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. 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 < ------------------------------------------------------------------------------- -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 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* Why does YCM demand such a recent version of Vim? ~ -During YCM's development several show-stopper bugs were encountered in Vim. -Those needed to be fixed upstream (and were). A few months after those bugs -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 back at original' -and similar, then just update to Vim 7.4.314 (or later) and they'll go away. +YCM needs a version of Vim with the timers feature to achieve full +asynchronicity. This feature is available since Vim 7.4.1578. ------------------------------------------------------------------------------- *youcompleteme-nasty-bugs-happen-if-i-have-vim-autoclose-plugin-installed* diff --git a/plugin/youcompleteme.vim b/plugin/youcompleteme.vim index d7aee0cf..45d24721 100644 --- a/plugin/youcompleteme.vim +++ b/plugin/youcompleteme.vim @@ -27,9 +27,16 @@ endfunction if exists( "g:loaded_youcompleteme" ) call s:restore_cpo() finish -elseif v:version < 704 || (v:version == 704 && !has('patch143')) +elseif v:version < 704 || (v:version == 704 && !has( 'patch1578' )) 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 call s:restore_cpo() finish diff --git a/python/ycm/tests/__init__.py b/python/ycm/tests/__init__.py index 40d4422d..325b4208 100644 --- a/python/ycm/tests/__init__.py +++ b/python/ycm/tests/__init__.py @@ -65,7 +65,7 @@ def _IsReady(): return BaseRequest.GetDataFromHandler( 'ready' ) -def _WaitUntilReady( timeout = 5 ): +def WaitUntilReady( timeout = 5 ): expiration = time.time() + timeout while True: try: @@ -109,7 +109,7 @@ def YouCompleteMeInstance( custom_options = {} ): @functools.wraps( test ) def Wrapper( *args, **kwargs ): ycm = YouCompleteMe( _MakeUserOptions( custom_options ) ) - _WaitUntilReady() + WaitUntilReady() try: test( ycm, *args, **kwargs ) finally: diff --git a/python/ycm/tests/event_notification_test.py b/python/ycm/tests/event_notification_test.py index b83c35bb..fa4e082a 100644 --- a/python/ycm/tests/event_notification_test.py +++ b/python/ycm/tests/event_notification_test.py @@ -31,11 +31,12 @@ MockVimModule() import contextlib import os -from ycm.tests import PathToTestFile, YouCompleteMeInstance +from ycm.tests import PathToTestFile, YouCompleteMeInstance, WaitUntilReady from ycmd.responses import ( BuildDiagnosticData, Diagnostic, Location, Range, 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 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 # return success - with patch( 'ycm.client.base_request.BaseRequest.PostDataToHandlerAsync', + with patch( 'ycm.client.event_notification.EventNotification.' + 'PostDataToHandlerAsync', return_value = MagicMock( return_value=True ) ): # 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' ], filetype = 'some_filetype' ) - with patch( 'ycm.client.base_request.BaseRequest.' + with patch( 'ycm.client.event_notification.EventNotification.' 'PostDataToHandlerAsync' ) as post_data_to_handler_async: with CurrentWorkingDirectory( unicode_dir ): with MockVimBuffers( [ current_buffer ], current_buffer, ( 6, 5 ) ): @@ -412,7 +414,7 @@ def EventNotification_BufferVisit_BuildRequestForCurrentAndUnsavedBuffers_test( filetype = 'some_filetype', modified = False ) - with patch( 'ycm.client.base_request.BaseRequest.' + with patch( 'ycm.client.event_notification.EventNotification.' 'PostDataToHandlerAsync' ) as post_data_to_handler_async: with MockVimBuffers( [ current_buffer, modified_buffer, unmodified_buffer ], current_buffer, @@ -461,7 +463,7 @@ def EventNotification_BufferUnload_BuildRequestForDeletedAndUnsavedBuffers_test( filetype = 'some_filetype', modified = False ) - with patch( 'ycm.client.base_request.BaseRequest.' + with patch( 'ycm.client.event_notification.EventNotification.' 'PostDataToHandlerAsync' ) as post_data_to_handler_async: with MockVimBuffers( [ current_buffer, deleted_buffer ], current_buffer ): ycm.OnBufferUnload( deleted_buffer_file ) @@ -489,3 +491,73 @@ def EventNotification_BufferUnload_BuildRequestForDeletedAndUnsavedBuffers_test( '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' + ) + ) diff --git a/python/ycm/youcompleteme.py b/python/ycm/youcompleteme.py index d584c926..08c4d335 100644 --- a/python/ycm/youcompleteme.py +++ b/python/ycm/youcompleteme.py @@ -223,6 +223,14 @@ class YouCompleteMe( object ): 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 ): if self._user_notified_about_crash or self.IsServerAlive(): return @@ -346,15 +354,6 @@ class YouCompleteMe( object ): 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 ): if not self.IsServerAlive(): self._NotifyUserIfServerCrashed() @@ -766,7 +765,7 @@ class YouCompleteMe( object ): if filetype in self._filetypes_with_keywords_loaded: return - if self._server_is_ready_with_cache: + if self.IsServerReady(): self._filetypes_with_keywords_loaded.add( filetype ) extra_data[ 'syntax_keywords' ] = list( syntax_parse.SyntaxKeywordsForCurrentBuffer() )