Auto merge of #2367 - micbou:on-buffer-unload, r=Valloric
[READY] Use deleted buffer instead of current buffer when sending BufferUnload event notification When deleting a buffer, we use the current buffer to send the `BufferUnload` event notification request to ycmd instead of the buffer being deleted. This is an issue when the current buffer is not of the same filetype as the deleted one. In this case, three different scenarios may occur: - the current buffer filetype is not allowed: no request is sent to the ycmd server. The `OnBufferUnload` method from the completer corresponding to the filetype of the deleted buffer is not called. If the filetype is a C-family language, the translation unit is not destroyed. If it is TypeScript, we don't tell TSServer to close the file (not really an issue unless the file is modified elsewhere); - the current buffer filetype has no semantic support in ycmd: the request is sent to the ycmd server but no semantic completer is used. Same result; - the current buffer filetype has semantic support in ycmd: the `OnBufferUnload` method from the wrong completer is called in ycmd. LibClang and TSServer are able to cope with that and ignore the file. Same result in definitive. The solution is obvious: build the request for the deleted buffer in this case. However, this involves more changes than expected because the code was written with the assumption that requests are always for the current buffer. The `include_buffer_data` parameter from `BuildRequestData` was removed as it is always used with its default value. This fix may alleviate issue https://github.com/Valloric/YouCompleteMe/issues/2232 in the sense that it now gives a reliable way to limit memory usage by deleting buffers in the case of multiple TUs. Next step is to update PR https://github.com/Valloric/ycmd/pull/542 by removing the `unloaded_buffer` parameter from ycmd API then remove it from the `BufferUnload` request in YCM. <!-- 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/2367) <!-- Reviewable:end -->
This commit is contained in:
commit
768aea435b
@ -91,7 +91,7 @@ function! youcompleteme#Enable()
|
|||||||
autocmd BufReadPre * call s:OnBufferReadPre( expand( '<afile>:p' ) )
|
autocmd BufReadPre * call s:OnBufferReadPre( expand( '<afile>:p' ) )
|
||||||
autocmd BufRead,FileType * call s:OnBufferRead()
|
autocmd BufRead,FileType * call s:OnBufferRead()
|
||||||
autocmd BufEnter * call s:OnBufferEnter()
|
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 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()
|
||||||
@ -323,10 +323,12 @@ function! s:TurnOffSyntasticForCFamily()
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! s:AllowedToCompleteInCurrentBuffer()
|
function! s:AllowedToCompleteInBuffer( buffer )
|
||||||
if empty( &filetype ) ||
|
let buffer_filetype = getbufvar( a:buffer, '&filetype' )
|
||||||
\ getbufvar( winbufnr( winnr() ), "&buftype" ) ==# 'nofile' ||
|
|
||||||
\ &filetype ==# 'qf'
|
if empty( buffer_filetype ) ||
|
||||||
|
\ getbufvar( a:buffer, '&buftype' ) ==# 'nofile' ||
|
||||||
|
\ buffer_filetype ==# 'qf'
|
||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -335,13 +337,18 @@ function! s:AllowedToCompleteInCurrentBuffer()
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
let whitelist_allows = has_key( g:ycm_filetype_whitelist, '*' ) ||
|
let whitelist_allows = has_key( g:ycm_filetype_whitelist, '*' ) ||
|
||||||
\ has_key( g:ycm_filetype_whitelist, &filetype )
|
\ has_key( g:ycm_filetype_whitelist, buffer_filetype )
|
||||||
let blacklist_allows = !has_key( g:ycm_filetype_blacklist, &filetype )
|
let blacklist_allows = !has_key( g:ycm_filetype_blacklist, buffer_filetype )
|
||||||
|
|
||||||
return whitelist_allows && blacklist_allows
|
return whitelist_allows && blacklist_allows
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:AllowedToCompleteInCurrentBuffer()
|
||||||
|
return s:AllowedToCompleteInBuffer( '%' )
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! s:VisitedBufferRequiresReparse()
|
function! s:VisitedBufferRequiresReparse()
|
||||||
if !s:AllowedToCompleteInCurrentBuffer()
|
if !s:AllowedToCompleteInCurrentBuffer()
|
||||||
return 0
|
return 0
|
||||||
@ -471,13 +478,16 @@ function! s:OnBufferEnter()
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! s:OnBufferUnload( deleted_buffer_file )
|
function! s:OnBufferUnload()
|
||||||
if !s:AllowedToCompleteInCurrentBuffer() || empty( a:deleted_buffer_file )
|
" 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
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
let deleted_buffer_file = expand( '<afile>:p' )
|
||||||
exec s:python_command "ycm_state.OnBufferUnload("
|
exec s:python_command "ycm_state.OnBufferUnload("
|
||||||
\ "vim.eval( 'a:deleted_buffer_file' ) )"
|
\ "vim.eval( 'deleted_buffer_file' ) )"
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,19 +154,28 @@ class BaseRequest( object ):
|
|||||||
hmac_secret = ''
|
hmac_secret = ''
|
||||||
|
|
||||||
|
|
||||||
def BuildRequestData( include_buffer_data = True ):
|
def BuildRequestData( filepath = None ):
|
||||||
line, column = vimsupport.CurrentLineAndColumn()
|
"""Build request for the current buffer or the buffer corresponding to
|
||||||
filepath = vimsupport.GetCurrentBufferFilepath()
|
|filepath| if specified."""
|
||||||
request_data = {
|
current_filepath = vimsupport.GetCurrentBufferFilepath()
|
||||||
'line_num': line + 1,
|
|
||||||
'column_num': column + 1,
|
if filepath and current_filepath != filepath:
|
||||||
'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 )
|
||||||
}
|
}
|
||||||
|
|
||||||
if include_buffer_data:
|
line, column = vimsupport.CurrentLineAndColumn()
|
||||||
request_data[ 'file_data' ] = vimsupport.GetUnsavedAndCurrentBufferData()
|
|
||||||
|
|
||||||
return request_data
|
return {
|
||||||
|
'filepath': current_filepath,
|
||||||
|
'line_num': line + 1,
|
||||||
|
'column_num': column + 1,
|
||||||
|
'file_data': vimsupport.GetUnsavedAndSpecifiedBufferData( current_filepath )
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def JsonFromFuture( future ):
|
def JsonFromFuture( future ):
|
||||||
|
@ -32,15 +32,16 @@ from ycm.client.base_request import ( BaseRequest, BuildRequestData,
|
|||||||
|
|
||||||
|
|
||||||
class EventNotification( BaseRequest ):
|
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__()
|
super( EventNotification, self ).__init__()
|
||||||
self._event_name = event_name
|
self._event_name = event_name
|
||||||
|
self._filepath = filepath
|
||||||
self._extra_data = extra_data
|
self._extra_data = extra_data
|
||||||
self._cached_response = None
|
self._cached_response = None
|
||||||
|
|
||||||
|
|
||||||
def Start( self ):
|
def Start( self ):
|
||||||
request_data = BuildRequestData()
|
request_data = BuildRequestData( self._filepath )
|
||||||
if self._extra_data:
|
if self._extra_data:
|
||||||
request_data.update( self._extra_data )
|
request_data.update( self._extra_data )
|
||||||
request_data[ 'event_name' ] = self._event_name
|
request_data[ 'event_name' ] = self._event_name
|
||||||
@ -74,8 +75,10 @@ class EventNotification( BaseRequest ):
|
|||||||
return self._cached_response if self._cached_response else []
|
return self._cached_response if self._cached_response else []
|
||||||
|
|
||||||
|
|
||||||
def SendEventNotificationAsync( event_name, extra_data = None ):
|
def SendEventNotificationAsync( event_name,
|
||||||
event = EventNotification( event_name, extra_data )
|
filepath = None,
|
||||||
|
extra_data = None ):
|
||||||
|
event = EventNotification( event_name, filepath, extra_data )
|
||||||
event.Start()
|
event.Start()
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,9 +33,12 @@ import functools
|
|||||||
from ycmd.utils import ToUnicode
|
from ycmd.utils import ToUnicode
|
||||||
|
|
||||||
|
|
||||||
BUFNR_REGEX = re.compile( r"^bufnr\('(.+)', ([0-9]+)\)$" )
|
BUFNR_REGEX = re.compile( '^bufnr\(\'(?P<buffer_filename>.+)\', ([01])\)$' )
|
||||||
BUFWINNR_REGEX = re.compile( r"^bufwinnr\(([0-9]+)\)$" )
|
BUFWINNR_REGEX = re.compile( '^bufwinnr\((?P<buffer_number>[0-9]+)\)$' )
|
||||||
BWIPEOUT_REGEX = re.compile( r"^(?:silent! )bwipeout!? ([0-9]+)$" )
|
BWIPEOUT_REGEX = re.compile(
|
||||||
|
'^(?:silent! )bwipeout!? (?P<buffer_number>[0-9]+)$' )
|
||||||
|
GETBUFVAR_REGEX = re.compile(
|
||||||
|
'^getbufvar\((?P<buffer_number>[0-9]+), "&(?P<option>.+)"\)$' )
|
||||||
|
|
||||||
# One-and only instance of mocked Vim object. The first 'import vim' that is
|
# One-and only instance of mocked Vim object. The first 'import vim' that is
|
||||||
# executed binds the vim module to the instance of MagicMock that is created,
|
# executed binds the vim module to the instance of MagicMock that is created,
|
||||||
@ -49,46 +52,74 @@ VIM_MOCK = MagicMock()
|
|||||||
|
|
||||||
|
|
||||||
def MockGetBufferNumber( buffer_filename ):
|
def MockGetBufferNumber( buffer_filename ):
|
||||||
for buffer in VIM_MOCK.buffers:
|
for vim_buffer in VIM_MOCK.buffers:
|
||||||
if buffer[ 'filename' ] == buffer_filename:
|
if vim_buffer.name == buffer_filename:
|
||||||
return buffer[ 'number' ]
|
return vim_buffer.number
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
|
||||||
def MockGetBufferWindowNumber( buffer_number ):
|
def MockGetBufferWindowNumber( buffer_number ):
|
||||||
for buffer in VIM_MOCK.buffers:
|
for vim_buffer in VIM_MOCK.buffers:
|
||||||
if buffer[ 'number' ] == buffer_number and 'window' in buffer:
|
if vim_buffer.number == buffer_number and vim_buffer.window:
|
||||||
return buffer[ 'window' ]
|
return vim_buffer.window
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
|
||||||
def MockVimEval( value ):
|
def MockGetBufferVariable( buffer_number, option ):
|
||||||
if value == "g:ycm_min_num_of_chars_for_completion":
|
for vim_buffer in VIM_MOCK.buffers:
|
||||||
return 0
|
if vim_buffer.number == buffer_number:
|
||||||
if value == "g:ycm_server_python_interpreter":
|
if option == 'mod':
|
||||||
|
return vim_buffer.modified
|
||||||
|
if option == 'ft':
|
||||||
|
return vim_buffer.filetype
|
||||||
return ''
|
return ''
|
||||||
if value == "tempname()":
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
def MockVimEval( value ):
|
||||||
|
if value == 'g:ycm_min_num_of_chars_for_completion':
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if value == 'g:ycm_server_python_interpreter':
|
||||||
|
return ''
|
||||||
|
|
||||||
|
if value == 'tempname()':
|
||||||
return '_TEMP_FILE_'
|
return '_TEMP_FILE_'
|
||||||
if value == "&previewheight":
|
|
||||||
|
if value == '&previewheight':
|
||||||
# Default value from Vim
|
# Default value from Vim
|
||||||
return 12
|
return 12
|
||||||
|
|
||||||
|
if value == '&omnifunc':
|
||||||
|
return VIM_MOCK.current.buffer.omnifunc
|
||||||
|
|
||||||
|
if value == '&filetype':
|
||||||
|
return VIM_MOCK.current.buffer.filetype
|
||||||
|
|
||||||
match = BUFNR_REGEX.search( value )
|
match = BUFNR_REGEX.search( value )
|
||||||
if match:
|
if match:
|
||||||
return MockGetBufferNumber( match.group( 1 ) )
|
buffer_filename = match.group( 'buffer_filename' )
|
||||||
|
return MockGetBufferNumber( buffer_filename )
|
||||||
|
|
||||||
match = BUFWINNR_REGEX.search( value )
|
match = BUFWINNR_REGEX.search( value )
|
||||||
if match:
|
if match:
|
||||||
return MockGetBufferWindowNumber( int( match.group( 1 ) ) )
|
buffer_number = int( match.group( 'buffer_number' ) )
|
||||||
|
return MockGetBufferWindowNumber( buffer_number )
|
||||||
|
|
||||||
raise ValueError( 'Unexpected evaluation: ' + value )
|
match = GETBUFVAR_REGEX.search( value )
|
||||||
|
if match:
|
||||||
|
buffer_number = int( match.group( 'buffer_number' ) )
|
||||||
|
option = match.group( 'option' )
|
||||||
|
return MockGetBufferVariable( buffer_number, option )
|
||||||
|
|
||||||
|
raise ValueError( 'Unexpected evaluation: {0}'.format( value ) )
|
||||||
|
|
||||||
|
|
||||||
def MockWipeoutBuffer( buffer_number ):
|
def MockWipeoutBuffer( buffer_number ):
|
||||||
buffers = VIM_MOCK.buffers
|
buffers = VIM_MOCK.buffers
|
||||||
|
|
||||||
for index, buffer in enumerate( buffers ):
|
for index, buffer in enumerate( buffers ):
|
||||||
if buffer[ 'number' ] == buffer_number:
|
if buffer.number == buffer_number:
|
||||||
return buffers.pop( index )
|
return buffers.pop( index )
|
||||||
|
|
||||||
|
|
||||||
@ -100,6 +131,50 @@ def MockVimCommand( command ):
|
|||||||
raise RuntimeError( 'Unexpected command: ' + command )
|
raise RuntimeError( 'Unexpected command: ' + command )
|
||||||
|
|
||||||
|
|
||||||
|
class VimBuffer( object ):
|
||||||
|
"""An object that looks like a vim.buffer object:
|
||||||
|
- |name| : full path of the buffer;
|
||||||
|
- |number| : buffer number;
|
||||||
|
- |contents|: list of lines representing the buffer contents;
|
||||||
|
- |filetype|: buffer filetype. Empty string if no filetype is set;
|
||||||
|
- |modified|: True if the buffer has unsaved changes, False otherwise;
|
||||||
|
- |window| : number of the buffer window. None if the buffer is hidden;
|
||||||
|
- |omnifunc|: omni completion function used by the buffer."""
|
||||||
|
|
||||||
|
def __init__( self, name,
|
||||||
|
number = 1,
|
||||||
|
contents = [],
|
||||||
|
filetype = '',
|
||||||
|
modified = True,
|
||||||
|
window = None,
|
||||||
|
omnifunc = '' ):
|
||||||
|
self.name = name
|
||||||
|
self.number = number
|
||||||
|
self.contents = contents
|
||||||
|
self.filetype = filetype
|
||||||
|
self.modified = modified
|
||||||
|
self.window = window
|
||||||
|
self.omnifunc = omnifunc
|
||||||
|
|
||||||
|
|
||||||
|
def __getitem__( self, index ):
|
||||||
|
"""Return the bytes for a given line at index |index|."""
|
||||||
|
return self.contents[ index ]
|
||||||
|
|
||||||
|
|
||||||
|
def __len__( self ):
|
||||||
|
return len( self.contents )
|
||||||
|
|
||||||
|
|
||||||
|
def __setitem__( self, key, value ):
|
||||||
|
return self.contents.__setitem__( key, value )
|
||||||
|
|
||||||
|
|
||||||
|
def GetLines( self ):
|
||||||
|
"""Return the contents of the buffer as a list of unicode strings."""
|
||||||
|
return [ ToUnicode( x ) for x in self.contents ]
|
||||||
|
|
||||||
|
|
||||||
def MockVimModule():
|
def MockVimModule():
|
||||||
"""The 'vim' module is something that is only present when running inside the
|
"""The 'vim' module is something that is only present when running inside the
|
||||||
Vim Python interpreter, so we replace it with a MagicMock for tests. If you
|
Vim Python interpreter, so we replace it with a MagicMock for tests. If you
|
||||||
|
@ -23,7 +23,7 @@ from future import standard_library
|
|||||||
standard_library.install_aliases()
|
standard_library.install_aliases()
|
||||||
from builtins import * # noqa
|
from builtins import * # noqa
|
||||||
|
|
||||||
from ycm.test_utils import MockVimModule, ExtendedMock
|
from ycm.test_utils import ExtendedMock, MockVimModule, VimBuffer
|
||||||
MockVimModule()
|
MockVimModule()
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
@ -33,6 +33,7 @@ from ycm.tests.server_test import Server_test
|
|||||||
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
|
||||||
from mock import call, MagicMock, patch
|
from mock import call, MagicMock, patch
|
||||||
from nose.tools import eq_, ok_
|
from nose.tools import eq_, ok_
|
||||||
|
|
||||||
@ -59,45 +60,18 @@ def MockArbitraryBuffer( filetype, native_available = True ):
|
|||||||
"""Used via the with statement, set up mocked versions of the vim module such
|
"""Used via the with statement, set up mocked versions of the vim module such
|
||||||
that a single buffer is open with an arbitrary name and arbirary contents. Its
|
that a single buffer is open with an arbitrary name and arbirary contents. Its
|
||||||
filetype is set to the supplied filetype"""
|
filetype is set to the supplied filetype"""
|
||||||
with patch( 'vim.current' ) as vim_current:
|
|
||||||
def VimEval( value ):
|
|
||||||
"""Local mock of the vim.eval() function, used to ensure we get the
|
|
||||||
correct behvaiour"""
|
|
||||||
|
|
||||||
if value == '&omnifunc':
|
# Arbitrary, but valid, single buffer open.
|
||||||
# The omnicompleter is not required here
|
current_buffer = VimBuffer( os.path.realpath( 'TEST_BUFFER' ),
|
||||||
return ''
|
window = 1,
|
||||||
|
filetype = filetype )
|
||||||
if value == 'getbufvar(0, "&mod")':
|
|
||||||
# Ensure that we actually send the even to the server
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if value == 'getbufvar(0, "&ft")' or value == '&filetype':
|
|
||||||
return filetype
|
|
||||||
|
|
||||||
if value.startswith( 'bufnr(' ):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if value.startswith( 'bufwinnr(' ):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
raise ValueError( 'Unexpected evaluation' )
|
|
||||||
|
|
||||||
# Arbitrary, but valid, cursor position
|
|
||||||
vim_current.window.cursor = ( 1, 2 )
|
|
||||||
|
|
||||||
# Arbitrary, but valid, single buffer open
|
|
||||||
current_buffer = MagicMock()
|
|
||||||
current_buffer.number = 0
|
|
||||||
current_buffer.filename = os.path.realpath( 'TEST_BUFFER' )
|
|
||||||
current_buffer.name = 'TEST_BUFFER'
|
|
||||||
current_buffer.window = 0
|
|
||||||
|
|
||||||
# The rest just mock up the Vim module so that our single arbitrary buffer
|
# The rest just mock up the Vim module so that our single arbitrary buffer
|
||||||
# makes sense to vimsupport module.
|
# makes sense to vimsupport module.
|
||||||
with patch( 'vim.buffers', [ current_buffer ] ):
|
with patch( 'vim.buffers', [ current_buffer ] ):
|
||||||
with patch( 'vim.current.buffer', current_buffer ):
|
with patch( 'vim.current.buffer', current_buffer ):
|
||||||
with patch( 'vim.eval', side_effect=VimEval ):
|
# Arbitrary but valid cursor position.
|
||||||
|
with patch( 'vim.current.window.cursor', ( 1, 2 ) ):
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
@ -310,7 +284,7 @@ class EventNotification_test( Server_test ):
|
|||||||
ok_( self._server_state.FileParseRequestReady() )
|
ok_( self._server_state.FileParseRequestReady() )
|
||||||
self._server_state.HandleFileParseRequest()
|
self._server_state.HandleFileParseRequest()
|
||||||
vim_command.assert_has_calls( [
|
vim_command.assert_has_calls( [
|
||||||
PlaceSign_Call( 1, 1, 0, True )
|
PlaceSign_Call( 1, 1, 1, True )
|
||||||
] )
|
] )
|
||||||
eq_( self._server_state.GetErrorCount(), 1 )
|
eq_( self._server_state.GetErrorCount(), 1 )
|
||||||
eq_( self._server_state.GetWarningCount(), 0 )
|
eq_( self._server_state.GetWarningCount(), 0 )
|
||||||
@ -343,8 +317,8 @@ class EventNotification_test( Server_test ):
|
|||||||
ok_( self._server_state.FileParseRequestReady() )
|
ok_( self._server_state.FileParseRequestReady() )
|
||||||
self._server_state.HandleFileParseRequest()
|
self._server_state.HandleFileParseRequest()
|
||||||
vim_command.assert_has_calls( [
|
vim_command.assert_has_calls( [
|
||||||
PlaceSign_Call( 2, 2, 0, False ),
|
PlaceSign_Call( 2, 2, 1, False ),
|
||||||
UnplaceSign_Call( 1, 0 )
|
UnplaceSign_Call( 1, 1 )
|
||||||
] )
|
] )
|
||||||
eq_( self._server_state.GetErrorCount(), 0 )
|
eq_( self._server_state.GetErrorCount(), 0 )
|
||||||
eq_( self._server_state.GetWarningCount(), 1 )
|
eq_( self._server_state.GetWarningCount(), 1 )
|
||||||
@ -369,7 +343,114 @@ class EventNotification_test( Server_test ):
|
|||||||
self._server_state.OnFileReadyToParse()
|
self._server_state.OnFileReadyToParse()
|
||||||
self._server_state.HandleFileParseRequest()
|
self._server_state.HandleFileParseRequest()
|
||||||
vim_command.assert_has_calls( [
|
vim_command.assert_has_calls( [
|
||||||
UnplaceSign_Call( 2, 0 )
|
UnplaceSign_Call( 2, 1 )
|
||||||
] )
|
] )
|
||||||
eq_( self._server_state.GetErrorCount(), 0 )
|
eq_( self._server_state.GetErrorCount(), 0 )
|
||||||
eq_( self._server_state.GetWarningCount(), 0 )
|
eq_( self._server_state.GetWarningCount(), 0 )
|
||||||
|
|
||||||
|
|
||||||
|
@patch( 'ycm.youcompleteme.YouCompleteMe._AddUltiSnipsDataIfNeeded' )
|
||||||
|
@patch( 'ycm.client.base_request.BaseRequest.PostDataToHandlerAsync',
|
||||||
|
new_callable = ExtendedMock )
|
||||||
|
def BufferVisit_BuildRequestForCurrentAndUnsavedBuffers_test(
|
||||||
|
self, post_data_to_handler_async, *args ):
|
||||||
|
|
||||||
|
current_buffer_file = os.path.realpath( 'current_buffer' )
|
||||||
|
current_buffer = VimBuffer( name = current_buffer_file,
|
||||||
|
number = 1,
|
||||||
|
contents = [ 'current_buffer_content' ],
|
||||||
|
filetype = 'some_filetype',
|
||||||
|
modified = False )
|
||||||
|
|
||||||
|
modified_buffer_file = os.path.realpath( 'modified_buffer' )
|
||||||
|
modified_buffer = VimBuffer( name = modified_buffer_file,
|
||||||
|
number = 2,
|
||||||
|
contents = [ 'modified_buffer_content' ],
|
||||||
|
filetype = 'some_filetype',
|
||||||
|
modified = True )
|
||||||
|
|
||||||
|
unmodified_buffer_file = os.path.realpath( 'unmodified_buffer' )
|
||||||
|
unmodified_buffer = VimBuffer( name = unmodified_buffer_file,
|
||||||
|
number = 3,
|
||||||
|
contents = [ 'unmodified_buffer_content' ],
|
||||||
|
filetype = 'some_filetype',
|
||||||
|
modified = False )
|
||||||
|
|
||||||
|
with patch( 'vim.buffers', [ current_buffer,
|
||||||
|
modified_buffer,
|
||||||
|
unmodified_buffer ] ):
|
||||||
|
with patch( 'vim.current.buffer', current_buffer ):
|
||||||
|
with patch( 'vim.current.window.cursor', ( 3, 5 ) ):
|
||||||
|
self._server_state.OnBufferVisit()
|
||||||
|
|
||||||
|
assert_that(
|
||||||
|
# Positional arguments passed to PostDataToHandlerAsync.
|
||||||
|
post_data_to_handler_async.call_args[ 0 ],
|
||||||
|
contains(
|
||||||
|
has_entries( {
|
||||||
|
'filepath': current_buffer_file,
|
||||||
|
'line_num': 3,
|
||||||
|
'column_num': 6,
|
||||||
|
'file_data': has_entries( {
|
||||||
|
current_buffer_file: has_entries( {
|
||||||
|
'contents': 'current_buffer_content\n',
|
||||||
|
'filetypes': [ 'some_filetype' ]
|
||||||
|
} ),
|
||||||
|
modified_buffer_file: has_entries( {
|
||||||
|
'contents': 'modified_buffer_content\n',
|
||||||
|
'filetypes': [ 'some_filetype' ]
|
||||||
|
} )
|
||||||
|
} ),
|
||||||
|
'event_name': 'BufferVisit'
|
||||||
|
} ),
|
||||||
|
'event_notification'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@patch( 'ycm.client.base_request.BaseRequest.PostDataToHandlerAsync',
|
||||||
|
new_callable = ExtendedMock )
|
||||||
|
def BufferUnload_BuildRequestForDeletedAndUnsavedBuffers_test(
|
||||||
|
self, post_data_to_handler_async ):
|
||||||
|
|
||||||
|
current_buffer_file = os.path.realpath( 'current_buffer' )
|
||||||
|
current_buffer = VimBuffer( name = current_buffer_file,
|
||||||
|
number = 1,
|
||||||
|
contents = [ 'current_buffer_content' ],
|
||||||
|
filetype = 'some_filetype',
|
||||||
|
modified = True )
|
||||||
|
|
||||||
|
deleted_buffer_file = os.path.realpath( 'deleted_buffer' )
|
||||||
|
deleted_buffer = VimBuffer( name = deleted_buffer_file,
|
||||||
|
number = 2,
|
||||||
|
contents = [ 'deleted_buffer_content' ],
|
||||||
|
filetype = 'some_filetype',
|
||||||
|
modified = False )
|
||||||
|
|
||||||
|
with patch( 'vim.buffers', [ current_buffer, deleted_buffer ] ):
|
||||||
|
with patch( 'vim.current.buffer', current_buffer ):
|
||||||
|
self._server_state.OnBufferUnload( deleted_buffer_file )
|
||||||
|
|
||||||
|
assert_that(
|
||||||
|
# Positional arguments passed to PostDataToHandlerAsync.
|
||||||
|
post_data_to_handler_async.call_args[ 0 ],
|
||||||
|
contains(
|
||||||
|
has_entries( {
|
||||||
|
'filepath': deleted_buffer_file,
|
||||||
|
'line_num': 1,
|
||||||
|
'column_num': 1,
|
||||||
|
'file_data': has_entries( {
|
||||||
|
current_buffer_file: has_entries( {
|
||||||
|
'contents': 'current_buffer_content\n',
|
||||||
|
'filetypes': [ 'some_filetype' ]
|
||||||
|
} ),
|
||||||
|
deleted_buffer_file: has_entries( {
|
||||||
|
'contents': 'deleted_buffer_content\n',
|
||||||
|
'filetypes': [ 'some_filetype' ]
|
||||||
|
} )
|
||||||
|
} ),
|
||||||
|
'event_name': 'BufferUnload'
|
||||||
|
} ),
|
||||||
|
'event_notification'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@ -25,14 +25,15 @@ from future import standard_library
|
|||||||
standard_library.install_aliases()
|
standard_library.install_aliases()
|
||||||
from builtins import * # noqa
|
from builtins import * # noqa
|
||||||
|
|
||||||
from ycm.test_utils import ExtendedMock, MockVimModule, MockVimCommand
|
from ycm.test_utils import ( ExtendedMock, MockVimCommand, VimBuffer,
|
||||||
|
MockVimModule )
|
||||||
MockVimModule()
|
MockVimModule()
|
||||||
|
|
||||||
from ycm import vimsupport
|
from ycm import vimsupport
|
||||||
from nose.tools import eq_
|
from nose.tools import eq_
|
||||||
from hamcrest import assert_that, calling, raises, none, has_entry
|
from hamcrest import assert_that, calling, raises, none, has_entry
|
||||||
from mock import MagicMock, call, patch
|
from mock import MagicMock, call, patch
|
||||||
from ycmd.utils import ToBytes, ToUnicode
|
from ycmd.utils import ToBytes
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
|
||||||
@ -705,34 +706,6 @@ def ReplaceChunksInBuffer_UnsortedChunks_test():
|
|||||||
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
|
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
|
||||||
|
|
||||||
|
|
||||||
class MockBuffer( object ):
|
|
||||||
"""An object that looks like a vim.buffer object, enough for ReplaceChunk to
|
|
||||||
generate a location list"""
|
|
||||||
|
|
||||||
def __init__( self, lines, name, number ):
|
|
||||||
self.lines = lines
|
|
||||||
self.name = name
|
|
||||||
self.number = number
|
|
||||||
|
|
||||||
|
|
||||||
def __getitem__( self, index ):
|
|
||||||
""" Return the bytes for a given line at index |index| """
|
|
||||||
return self.lines[ index ]
|
|
||||||
|
|
||||||
|
|
||||||
def __len__( self ):
|
|
||||||
return len( self.lines )
|
|
||||||
|
|
||||||
|
|
||||||
def __setitem__( self, key, value ):
|
|
||||||
return self.lines.__setitem__( key, value )
|
|
||||||
|
|
||||||
|
|
||||||
def GetLines( self ):
|
|
||||||
""" Return the contents of the buffer as a list of unicode strings"""
|
|
||||||
return [ ToUnicode( x ) for x in self.lines ]
|
|
||||||
|
|
||||||
|
|
||||||
@patch( 'ycm.vimsupport.VariableExists', return_value = False )
|
@patch( 'ycm.vimsupport.VariableExists', return_value = False )
|
||||||
@patch( 'ycm.vimsupport.SetFittingHeightForCurrentWindow' )
|
@patch( 'ycm.vimsupport.SetFittingHeightForCurrentWindow' )
|
||||||
@patch( 'ycm.vimsupport.GetBufferNumberForFilename',
|
@patch( 'ycm.vimsupport.GetBufferNumberForFilename',
|
||||||
@ -758,11 +731,14 @@ def ReplaceChunks_SingleFile_Open_test( vim_command,
|
|||||||
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
||||||
]
|
]
|
||||||
|
|
||||||
result_buffer = MockBuffer( [
|
result_buffer = VimBuffer(
|
||||||
|
'single_file',
|
||||||
|
contents = [
|
||||||
'line1',
|
'line1',
|
||||||
'line2',
|
'line2',
|
||||||
'line3',
|
'line3'
|
||||||
], 'single_file', 1 )
|
]
|
||||||
|
)
|
||||||
|
|
||||||
with patch( 'vim.buffers', [ None, result_buffer, None ] ):
|
with patch( 'vim.buffers', [ None, result_buffer, None ] ):
|
||||||
vimsupport.ReplaceChunks( chunks )
|
vimsupport.ReplaceChunks( chunks )
|
||||||
@ -845,11 +821,14 @@ def ReplaceChunks_SingleFile_NotOpen_test( vim_command,
|
|||||||
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
||||||
]
|
]
|
||||||
|
|
||||||
result_buffer = MockBuffer( [
|
result_buffer = VimBuffer(
|
||||||
|
'single_file',
|
||||||
|
contents = [
|
||||||
'line1',
|
'line1',
|
||||||
'line2',
|
'line2',
|
||||||
'line3',
|
'line3'
|
||||||
], 'single_file', 1 )
|
]
|
||||||
|
)
|
||||||
|
|
||||||
with patch( 'vim.buffers', [ None, result_buffer, None ] ):
|
with patch( 'vim.buffers', [ None, result_buffer, None ] ):
|
||||||
vimsupport.ReplaceChunks( chunks )
|
vimsupport.ReplaceChunks( chunks )
|
||||||
@ -954,11 +933,14 @@ def ReplaceChunks_User_Declines_To_Open_File_test(
|
|||||||
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
||||||
]
|
]
|
||||||
|
|
||||||
result_buffer = MockBuffer( [
|
result_buffer = VimBuffer(
|
||||||
|
'single_file',
|
||||||
|
contents = [
|
||||||
'line1',
|
'line1',
|
||||||
'line2',
|
'line2',
|
||||||
'line3',
|
'line3'
|
||||||
], 'single_file', 1 )
|
]
|
||||||
|
)
|
||||||
|
|
||||||
with patch( 'vim.buffers', [ None, result_buffer, None ] ):
|
with patch( 'vim.buffers', [ None, result_buffer, None ] ):
|
||||||
vimsupport.ReplaceChunks( chunks )
|
vimsupport.ReplaceChunks( chunks )
|
||||||
@ -1031,11 +1013,14 @@ def ReplaceChunks_User_Aborts_Opening_File_test(
|
|||||||
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
||||||
]
|
]
|
||||||
|
|
||||||
result_buffer = MockBuffer( [
|
result_buffer = VimBuffer(
|
||||||
|
'single_file',
|
||||||
|
contents = [
|
||||||
'line1',
|
'line1',
|
||||||
'line2',
|
'line2',
|
||||||
'line3',
|
'line3'
|
||||||
], 'single_file', 1 )
|
]
|
||||||
|
)
|
||||||
|
|
||||||
with patch( 'vim.buffers', [ None, result_buffer, None ] ):
|
with patch( 'vim.buffers', [ None, result_buffer, None ] ):
|
||||||
assert_that( calling( vimsupport.ReplaceChunks ).with_args( chunks ),
|
assert_that( calling( vimsupport.ReplaceChunks ).with_args( chunks ),
|
||||||
@ -1114,15 +1099,23 @@ def ReplaceChunks_MultiFile_Open_test( vim_command,
|
|||||||
_BuildChunk( 2, 1, 2, 1, 'second_file_replacement ', '2_another_file' ),
|
_BuildChunk( 2, 1, 2, 1, 'second_file_replacement ', '2_another_file' ),
|
||||||
]
|
]
|
||||||
|
|
||||||
first_file = MockBuffer( [
|
first_file = VimBuffer(
|
||||||
|
'1_first_file',
|
||||||
|
number = 22,
|
||||||
|
contents = [
|
||||||
'line1',
|
'line1',
|
||||||
'line2',
|
'line2',
|
||||||
'line3',
|
'line3',
|
||||||
], '1_first_file', 22 )
|
]
|
||||||
another_file = MockBuffer( [
|
)
|
||||||
|
another_file = VimBuffer(
|
||||||
|
'2_another_file',
|
||||||
|
number = 19,
|
||||||
|
contents = [
|
||||||
'another line1',
|
'another line1',
|
||||||
'ACME line2',
|
'ACME line2',
|
||||||
], '2_another_file', 19 )
|
]
|
||||||
|
)
|
||||||
|
|
||||||
vim_buffers = [ None ] * 23
|
vim_buffers = [ None ] * 23
|
||||||
vim_buffers[ 22 ] = first_file
|
vim_buffers[ 22 ] = first_file
|
||||||
@ -1222,9 +1215,10 @@ def _BuildChunk( start_line,
|
|||||||
|
|
||||||
@patch( 'vim.eval', new_callable = ExtendedMock )
|
@patch( 'vim.eval', new_callable = ExtendedMock )
|
||||||
def AddDiagnosticSyntaxMatch_ErrorInMiddleOfLine_test( vim_eval ):
|
def AddDiagnosticSyntaxMatch_ErrorInMiddleOfLine_test( vim_eval ):
|
||||||
current_buffer = MockBuffer( [
|
current_buffer = VimBuffer(
|
||||||
'Highlight this error please'
|
'some_file',
|
||||||
], 'some_file', 1 )
|
contents = [ 'Highlight this error please' ]
|
||||||
|
)
|
||||||
|
|
||||||
with patch( 'vim.current.buffer', current_buffer ):
|
with patch( 'vim.current.buffer', current_buffer ):
|
||||||
vimsupport.AddDiagnosticSyntaxMatch( 1, 16, 1, 21 )
|
vimsupport.AddDiagnosticSyntaxMatch( 1, 16, 1, 21 )
|
||||||
@ -1235,9 +1229,10 @@ def AddDiagnosticSyntaxMatch_ErrorInMiddleOfLine_test( vim_eval ):
|
|||||||
|
|
||||||
@patch( 'vim.eval', new_callable = ExtendedMock )
|
@patch( 'vim.eval', new_callable = ExtendedMock )
|
||||||
def AddDiagnosticSyntaxMatch_WarningAtEndOfLine_test( vim_eval ):
|
def AddDiagnosticSyntaxMatch_WarningAtEndOfLine_test( vim_eval ):
|
||||||
current_buffer = MockBuffer( [
|
current_buffer = VimBuffer(
|
||||||
'Highlight this warning'
|
'some_file',
|
||||||
], 'some_file', 1 )
|
contents = [ 'Highlight this warning' ]
|
||||||
|
)
|
||||||
|
|
||||||
with patch( 'vim.current.buffer', current_buffer ):
|
with patch( 'vim.current.buffer', current_buffer ):
|
||||||
vimsupport.AddDiagnosticSyntaxMatch( 1, 16, 1, 23, is_error = False )
|
vimsupport.AddDiagnosticSyntaxMatch( 1, 16, 1, 23, is_error = False )
|
||||||
@ -1339,30 +1334,41 @@ def CheckFilename_test():
|
|||||||
|
|
||||||
|
|
||||||
def BufferIsVisibleForFilename_test():
|
def BufferIsVisibleForFilename_test():
|
||||||
buffers = [
|
vim_buffers = [
|
||||||
{
|
VimBuffer(
|
||||||
'number': 1,
|
os.path.realpath( 'visible_filename' ),
|
||||||
'filename': os.path.realpath( 'visible_filename' ),
|
number = 1,
|
||||||
'window': 1
|
window = 1
|
||||||
},
|
),
|
||||||
{
|
VimBuffer(
|
||||||
'number': 2,
|
os.path.realpath( 'hidden_filename' ),
|
||||||
'filename': os.path.realpath( 'hidden_filename' ),
|
number = 2,
|
||||||
}
|
window = None
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
with patch( 'vim.buffers', buffers ):
|
with patch( 'vim.buffers', vim_buffers ):
|
||||||
eq_( vimsupport.BufferIsVisibleForFilename( 'visible_filename' ), True )
|
eq_( vimsupport.BufferIsVisibleForFilename( 'visible_filename' ), True )
|
||||||
eq_( vimsupport.BufferIsVisibleForFilename( 'hidden_filename' ), False )
|
eq_( vimsupport.BufferIsVisibleForFilename( 'hidden_filename' ), False )
|
||||||
eq_( vimsupport.BufferIsVisibleForFilename( 'another_filename' ), False )
|
eq_( vimsupport.BufferIsVisibleForFilename( 'another_filename' ), False )
|
||||||
|
|
||||||
|
|
||||||
@patch( 'ycm.vimsupport.GetBufferNumberForFilename',
|
|
||||||
side_effect = [ 2, 5, -1 ] )
|
|
||||||
@patch( 'vim.command',
|
@patch( 'vim.command',
|
||||||
side_effect = MockVimCommand,
|
side_effect = MockVimCommand,
|
||||||
new_callable = ExtendedMock )
|
new_callable = ExtendedMock )
|
||||||
def CloseBuffersForFilename_test( vim_command, *args ):
|
def CloseBuffersForFilename_test( vim_command, *args ):
|
||||||
|
vim_buffers = [
|
||||||
|
VimBuffer(
|
||||||
|
os.path.realpath( 'some_filename' ),
|
||||||
|
number = 2
|
||||||
|
),
|
||||||
|
VimBuffer(
|
||||||
|
os.path.realpath( 'some_filename' ),
|
||||||
|
number = 5
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
with patch( 'vim.buffers', vim_buffers ):
|
||||||
vimsupport.CloseBuffersForFilename( 'some_filename' )
|
vimsupport.CloseBuffersForFilename( 'some_filename' )
|
||||||
|
|
||||||
vim_command.assert_has_exact_calls( [
|
vim_command.assert_has_exact_calls( [
|
||||||
@ -1401,17 +1407,14 @@ def OpenFilename_test( vim_current, vim_command ):
|
|||||||
] )
|
] )
|
||||||
|
|
||||||
|
|
||||||
@patch( 'ycm.vimsupport.BufferModified', side_effect = [ True ] )
|
def GetUnsavedAndSpecifiedBufferData_EncodedUnicodeCharsInBuffers_test():
|
||||||
@patch( 'ycm.vimsupport.FiletypesForBuffer', side_effect = [ [ 'cpp' ] ] )
|
filepath = os.path.realpath( 'filename' )
|
||||||
def GetUnsavedAndCurrentBufferData_EncodedUnicodeCharsInBuffers_test( *args ):
|
contents = [ ToBytes( u'abc' ), ToBytes( u'fДa' ) ]
|
||||||
mock_buffer = MagicMock()
|
vim_buffer = VimBuffer( filepath, contents = contents )
|
||||||
mock_buffer.name = os.path.realpath( 'filename' )
|
|
||||||
mock_buffer.number = 1
|
|
||||||
mock_buffer.__iter__.return_value = [ ToBytes ( u'abc' ), ToBytes( u'fДa' ) ]
|
|
||||||
|
|
||||||
with patch( 'vim.buffers', [ mock_buffer ] ):
|
with patch( 'vim.buffers', [ vim_buffer ] ):
|
||||||
assert_that( vimsupport.GetUnsavedAndCurrentBufferData(),
|
assert_that( vimsupport.GetUnsavedAndSpecifiedBufferData( filepath ),
|
||||||
has_entry( mock_buffer.name,
|
has_entry( filepath,
|
||||||
has_entry( u'contents', u'abc\nfДa\n' ) ) )
|
has_entry( u'contents', u'abc\nfДa\n' ) ) )
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,14 +116,17 @@ def BufferModified( buffer_object ):
|
|||||||
return bool( int( GetBufferOption( buffer_object, 'mod' ) ) )
|
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 = {}
|
buffers_data = {}
|
||||||
for buffer_object in vim.buffers:
|
for buffer_object in vim.buffers:
|
||||||
|
buffer_filepath = GetBufferFilepath( buffer_object )
|
||||||
if not ( BufferModified( buffer_object ) or
|
if not ( BufferModified( buffer_object ) or
|
||||||
buffer_object == vim.current.buffer ):
|
buffer_filepath == including_filepath ):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
buffers_data[ GetBufferFilepath( buffer_object ) ] = {
|
buffers_data[ buffer_filepath ] = {
|
||||||
# Add a newline to match what gets saved to disk. See #1455 for details.
|
# Add a newline to match what gets saved to disk. See #1455 for details.
|
||||||
'contents': JoinLinesAsUnicode( buffer_object ) + '\n',
|
'contents': JoinLinesAsUnicode( buffer_object ) + '\n',
|
||||||
'filetypes': FiletypesForBuffer( buffer_object )
|
'filetypes': FiletypesForBuffer( buffer_object )
|
||||||
|
@ -311,16 +311,18 @@ class YouCompleteMe( object ):
|
|||||||
self._AddSyntaxDataIfNeeded( extra_data )
|
self._AddSyntaxDataIfNeeded( extra_data )
|
||||||
self._AddExtraConfDataIfNeeded( extra_data )
|
self._AddExtraConfDataIfNeeded( extra_data )
|
||||||
|
|
||||||
self._latest_file_parse_request = EventNotification( 'FileReadyToParse',
|
self._latest_file_parse_request = EventNotification(
|
||||||
extra_data )
|
'FileReadyToParse', extra_data = extra_data )
|
||||||
self._latest_file_parse_request.Start()
|
self._latest_file_parse_request.Start()
|
||||||
|
|
||||||
|
|
||||||
def OnBufferUnload( self, deleted_buffer_file ):
|
def OnBufferUnload( self, deleted_buffer_file ):
|
||||||
if not self.IsServerAlive():
|
if not self.IsServerAlive():
|
||||||
return
|
return
|
||||||
SendEventNotificationAsync( 'BufferUnload',
|
SendEventNotificationAsync(
|
||||||
{ 'unloaded_buffer': deleted_buffer_file } )
|
'BufferUnload',
|
||||||
|
filepath = deleted_buffer_file,
|
||||||
|
extra_data = { 'unloaded_buffer': deleted_buffer_file } )
|
||||||
|
|
||||||
|
|
||||||
def OnBufferVisit( self ):
|
def OnBufferVisit( self ):
|
||||||
@ -328,7 +330,7 @@ class YouCompleteMe( object ):
|
|||||||
return
|
return
|
||||||
extra_data = {}
|
extra_data = {}
|
||||||
self._AddUltiSnipsDataIfNeeded( extra_data )
|
self._AddUltiSnipsDataIfNeeded( extra_data )
|
||||||
SendEventNotificationAsync( 'BufferVisit', extra_data )
|
SendEventNotificationAsync( 'BufferVisit', extra_data = extra_data )
|
||||||
|
|
||||||
|
|
||||||
def OnInsertLeave( self ):
|
def OnInsertLeave( self ):
|
||||||
|
Loading…
Reference in New Issue
Block a user