Fix BufferUnload event notification
Send the request as the unloaded buffer instead of the current buffer for the BufferUnload event notification. This fixes the issue where the filetype of the current buffer is not the same as the unloaded buffer one, making the ycmd server uses the wrong completer when handling the request.
This commit is contained in:
parent
b6d5af3424
commit
2fabac5a67
@ -91,7 +91,7 @@ function! youcompleteme#Enable()
|
||||
autocmd BufReadPre * call s:OnBufferReadPre( expand( '<afile>:p' ) )
|
||||
autocmd BufRead,FileType * call s:OnBufferRead()
|
||||
autocmd BufEnter * call s:OnBufferEnter()
|
||||
autocmd BufUnload * call s:OnBufferUnload( expand( '<afile>:p' ) )
|
||||
autocmd BufUnload * call s:OnBufferUnload()
|
||||
autocmd CursorHold,CursorHoldI * call s:OnCursorHold()
|
||||
autocmd InsertLeave * call s:OnInsertLeave()
|
||||
autocmd InsertEnter * call s:OnInsertEnter()
|
||||
@ -323,10 +323,12 @@ function! s:TurnOffSyntasticForCFamily()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:AllowedToCompleteInCurrentBuffer()
|
||||
if empty( &filetype ) ||
|
||||
\ getbufvar( winbufnr( winnr() ), "&buftype" ) ==# 'nofile' ||
|
||||
\ &filetype ==# 'qf'
|
||||
function! s:AllowedToCompleteInBuffer( buffer )
|
||||
let buffer_filetype = getbufvar( a:buffer, '&filetype' )
|
||||
|
||||
if empty( buffer_filetype ) ||
|
||||
\ getbufvar( a:buffer, '&buftype' ) ==# 'nofile' ||
|
||||
\ buffer_filetype ==# 'qf'
|
||||
return 0
|
||||
endif
|
||||
|
||||
@ -335,13 +337,18 @@ function! s:AllowedToCompleteInCurrentBuffer()
|
||||
endif
|
||||
|
||||
let whitelist_allows = has_key( g:ycm_filetype_whitelist, '*' ) ||
|
||||
\ has_key( g:ycm_filetype_whitelist, &filetype )
|
||||
let blacklist_allows = !has_key( g:ycm_filetype_blacklist, &filetype )
|
||||
\ has_key( g:ycm_filetype_whitelist, buffer_filetype )
|
||||
let blacklist_allows = !has_key( g:ycm_filetype_blacklist, buffer_filetype )
|
||||
|
||||
return whitelist_allows && blacklist_allows
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:AllowedToCompleteInCurrentBuffer()
|
||||
return s:AllowedToCompleteInBuffer( '%' )
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:VisitedBufferRequiresReparse()
|
||||
if !s:AllowedToCompleteInCurrentBuffer()
|
||||
return 0
|
||||
@ -471,13 +478,16 @@ function! s:OnBufferEnter()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:OnBufferUnload( deleted_buffer_file )
|
||||
if !s:AllowedToCompleteInCurrentBuffer() || empty( a:deleted_buffer_file )
|
||||
function! s:OnBufferUnload()
|
||||
" Expanding <abuf> returns the unloaded buffer number as a string but we want
|
||||
" it as a true number for the getbufvar function.
|
||||
if !s:AllowedToCompleteInBuffer( str2nr( expand( '<abuf>' ) ) )
|
||||
return
|
||||
endif
|
||||
|
||||
let deleted_buffer_file = expand( '<afile>:p' )
|
||||
exec s:python_command "ycm_state.OnBufferUnload("
|
||||
\ "vim.eval( 'a:deleted_buffer_file' ) )"
|
||||
\ "vim.eval( 'deleted_buffer_file' ) )"
|
||||
endfunction
|
||||
|
||||
|
||||
|
@ -154,20 +154,29 @@ class BaseRequest( object ):
|
||||
hmac_secret = ''
|
||||
|
||||
|
||||
def BuildRequestData( include_buffer_data = True ):
|
||||
def BuildRequestData( filepath = None ):
|
||||
"""Build request for the current buffer or the buffer corresponding to
|
||||
|filepath| if specified."""
|
||||
current_filepath = vimsupport.GetCurrentBufferFilepath()
|
||||
|
||||
if filepath and current_filepath != filepath:
|
||||
# Cursor position is irrelevant when filepath is not the current buffer.
|
||||
return {
|
||||
'filepath': filepath,
|
||||
'line_num': 1,
|
||||
'column_num': 1,
|
||||
'file_data': vimsupport.GetUnsavedAndSpecifiedBufferData( filepath )
|
||||
}
|
||||
|
||||
line, column = vimsupport.CurrentLineAndColumn()
|
||||
filepath = vimsupport.GetCurrentBufferFilepath()
|
||||
request_data = {
|
||||
|
||||
return {
|
||||
'filepath': current_filepath,
|
||||
'line_num': line + 1,
|
||||
'column_num': column + 1,
|
||||
'filepath': filepath
|
||||
'file_data': vimsupport.GetUnsavedAndSpecifiedBufferData( current_filepath )
|
||||
}
|
||||
|
||||
if include_buffer_data:
|
||||
request_data[ 'file_data' ] = vimsupport.GetUnsavedAndCurrentBufferData()
|
||||
|
||||
return request_data
|
||||
|
||||
|
||||
def JsonFromFuture( future ):
|
||||
response = future.result()
|
||||
|
@ -32,15 +32,16 @@ from ycm.client.base_request import ( BaseRequest, BuildRequestData,
|
||||
|
||||
|
||||
class EventNotification( BaseRequest ):
|
||||
def __init__( self, event_name, extra_data = None ):
|
||||
def __init__( self, event_name, filepath = None, extra_data = None ):
|
||||
super( EventNotification, self ).__init__()
|
||||
self._event_name = event_name
|
||||
self._filepath = filepath
|
||||
self._extra_data = extra_data
|
||||
self._cached_response = None
|
||||
|
||||
|
||||
def Start( self ):
|
||||
request_data = BuildRequestData()
|
||||
request_data = BuildRequestData( self._filepath )
|
||||
if self._extra_data:
|
||||
request_data.update( self._extra_data )
|
||||
request_data[ 'event_name' ] = self._event_name
|
||||
@ -74,8 +75,10 @@ class EventNotification( BaseRequest ):
|
||||
return self._cached_response if self._cached_response else []
|
||||
|
||||
|
||||
def SendEventNotificationAsync( event_name, extra_data = None ):
|
||||
event = EventNotification( event_name, extra_data )
|
||||
def SendEventNotificationAsync( event_name,
|
||||
filepath = None,
|
||||
extra_data = None ):
|
||||
event = EventNotification( event_name, filepath, extra_data )
|
||||
event.Start()
|
||||
|
||||
|
||||
|
@ -1403,15 +1403,17 @@ def OpenFilename_test( vim_current, vim_command ):
|
||||
|
||||
@patch( 'ycm.vimsupport.BufferModified', side_effect = [ True ] )
|
||||
@patch( 'ycm.vimsupport.FiletypesForBuffer', side_effect = [ [ 'cpp' ] ] )
|
||||
def GetUnsavedAndCurrentBufferData_EncodedUnicodeCharsInBuffers_test( *args ):
|
||||
def GetUnsavedAndSpecifiedBufferData_EncodedUnicodeCharsInBuffers_test( *args ):
|
||||
filepath = os.path.realpath( 'filename' )
|
||||
|
||||
mock_buffer = MagicMock()
|
||||
mock_buffer.name = os.path.realpath( 'filename' )
|
||||
mock_buffer.name = filepath
|
||||
mock_buffer.number = 1
|
||||
mock_buffer.__iter__.return_value = [ ToBytes ( u'abc' ), ToBytes( u'fДa' ) ]
|
||||
|
||||
with patch( 'vim.buffers', [ mock_buffer ] ):
|
||||
assert_that( vimsupport.GetUnsavedAndCurrentBufferData(),
|
||||
has_entry( mock_buffer.name,
|
||||
assert_that( vimsupport.GetUnsavedAndSpecifiedBufferData( filepath ),
|
||||
has_entry( filepath,
|
||||
has_entry( u'contents', u'abc\nfДa\n' ) ) )
|
||||
|
||||
|
||||
|
@ -116,14 +116,17 @@ def BufferModified( buffer_object ):
|
||||
return bool( int( GetBufferOption( buffer_object, 'mod' ) ) )
|
||||
|
||||
|
||||
def GetUnsavedAndCurrentBufferData():
|
||||
def GetUnsavedAndSpecifiedBufferData( including_filepath ):
|
||||
"""Build part of the request containing the contents and filetypes of all
|
||||
dirty buffers as well as the buffer with filepath |including_filepath|."""
|
||||
buffers_data = {}
|
||||
for buffer_object in vim.buffers:
|
||||
buffer_filepath = GetBufferFilepath( buffer_object )
|
||||
if not ( BufferModified( buffer_object ) or
|
||||
buffer_object == vim.current.buffer ):
|
||||
buffer_filepath == including_filepath ):
|
||||
continue
|
||||
|
||||
buffers_data[ GetBufferFilepath( buffer_object ) ] = {
|
||||
buffers_data[ buffer_filepath ] = {
|
||||
# Add a newline to match what gets saved to disk. See #1455 for details.
|
||||
'contents': JoinLinesAsUnicode( buffer_object ) + '\n',
|
||||
'filetypes': FiletypesForBuffer( buffer_object )
|
||||
|
@ -311,16 +311,18 @@ class YouCompleteMe( object ):
|
||||
self._AddSyntaxDataIfNeeded( extra_data )
|
||||
self._AddExtraConfDataIfNeeded( extra_data )
|
||||
|
||||
self._latest_file_parse_request = EventNotification( 'FileReadyToParse',
|
||||
extra_data )
|
||||
self._latest_file_parse_request = EventNotification(
|
||||
'FileReadyToParse', extra_data = extra_data )
|
||||
self._latest_file_parse_request.Start()
|
||||
|
||||
|
||||
def OnBufferUnload( self, deleted_buffer_file ):
|
||||
if not self.IsServerAlive():
|
||||
return
|
||||
SendEventNotificationAsync( 'BufferUnload',
|
||||
{ 'unloaded_buffer': deleted_buffer_file } )
|
||||
SendEventNotificationAsync(
|
||||
'BufferUnload',
|
||||
filepath = deleted_buffer_file,
|
||||
extra_data = { 'unloaded_buffer': deleted_buffer_file } )
|
||||
|
||||
|
||||
def OnBufferVisit( self ):
|
||||
@ -328,7 +330,7 @@ class YouCompleteMe( object ):
|
||||
return
|
||||
extra_data = {}
|
||||
self._AddUltiSnipsDataIfNeeded( extra_data )
|
||||
SendEventNotificationAsync( 'BufferVisit', extra_data )
|
||||
SendEventNotificationAsync( 'BufferVisit', extra_data = extra_data )
|
||||
|
||||
|
||||
def OnInsertLeave( self ):
|
||||
|
Loading…
Reference in New Issue
Block a user