event_notification_test.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. # Copyright (C) 2015-2018 YouCompleteMe contributors
  2. #
  3. # This file is part of YouCompleteMe.
  4. #
  5. # YouCompleteMe is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # YouCompleteMe is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
  17. from ycm.tests.test_utils import ( CurrentWorkingDirectory, ExtendedMock,
  18. MockVimBuffers, MockVimModule, VimBuffer,
  19. VimSign )
  20. MockVimModule()
  21. import contextlib
  22. import os
  23. from ycm.tests import ( PathToTestFile, test_utils, YouCompleteMeInstance,
  24. WaitUntilReady )
  25. from ycmd.responses import ( BuildDiagnosticData, Diagnostic, Location, Range,
  26. UnknownExtraConf, ServerError )
  27. from hamcrest import ( assert_that, contains_exactly, empty, equal_to,
  28. has_entries, has_entry, has_item, has_items, has_key,
  29. is_not )
  30. from unittest import TestCase
  31. from unittest.mock import call, MagicMock, patch
  32. def PresentDialog_Confirm_Call( message ):
  33. """Return a mock.call object for a call to vimsupport.PresentDialog, as called
  34. why vimsupport.Confirm with the supplied confirmation message"""
  35. return call( message, [ 'Ok', 'Cancel' ] )
  36. @contextlib.contextmanager
  37. def MockArbitraryBuffer( filetype ):
  38. """Used via the with statement, set up a single buffer with an arbitrary name
  39. and no contents. Its filetype is set to the supplied filetype."""
  40. # Arbitrary, but valid, single buffer open.
  41. current_buffer = VimBuffer( os.path.realpath( 'TEST_BUFFER' ),
  42. filetype = filetype )
  43. with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
  44. yield
  45. @contextlib.contextmanager
  46. def MockEventNotification( response_method, native_filetype_completer = True ):
  47. """Mock out the EventNotification client request object, replacing the
  48. Response handler's JsonFromFuture with the supplied |response_method|.
  49. Additionally mock out YouCompleteMe's FiletypeCompleterExistsForFiletype
  50. method to return the supplied |native_filetype_completer| parameter, rather
  51. than querying the server"""
  52. # We don't want the event to actually be sent to the server, just have it
  53. # return success
  54. with patch( 'ycm.client.event_notification.EventNotification.'
  55. 'PostDataToHandlerAsync',
  56. return_value = MagicMock( return_value=True ) ):
  57. # We set up a fake a Response (as called by EventNotification.Response)
  58. # which calls the supplied callback method. Generally this callback just
  59. # raises an apropriate exception, otherwise it would have to return a mock
  60. # future object.
  61. with patch( 'ycm.client.base_request._JsonFromFuture',
  62. side_effect = response_method ):
  63. # Filetype available information comes from the server, so rather than
  64. # relying on that request, we mock out the check. The caller decides if
  65. # filetype completion is available
  66. with patch(
  67. 'ycm.youcompleteme.YouCompleteMe.FiletypeCompleterExistsForFiletype',
  68. return_value = native_filetype_completer ):
  69. yield
  70. def _Check_FileReadyToParse_Diagnostic_Error( ycm ):
  71. # Tests Vim sign placement and error/warning count python API
  72. # when one error is returned.
  73. def DiagnosticResponse( *args ):
  74. start = Location( 1, 2, 'TEST_BUFFER' )
  75. end = Location( 1, 4, 'TEST_BUFFER' )
  76. extent = Range( start, end )
  77. diagnostic = Diagnostic( [], start, extent, 'expected ;', 'ERROR' )
  78. return [ BuildDiagnosticData( diagnostic ) ]
  79. with MockArbitraryBuffer( 'cpp' ):
  80. with MockEventNotification( DiagnosticResponse ):
  81. ycm.OnFileReadyToParse()
  82. assert_that( ycm.FileParseRequestReady() )
  83. ycm.HandleFileParseRequest()
  84. assert_that(
  85. test_utils.VIM_SIGNS,
  86. contains_exactly(
  87. VimSign( 1, 'YcmError', 1 )
  88. )
  89. )
  90. assert_that( ycm.GetErrorCount(), equal_to( 1 ) )
  91. assert_that( ycm.GetWarningCount(), equal_to( 0 ) )
  92. # Consequent calls to HandleFileParseRequest shouldn't mess with
  93. # existing diagnostics, when there is no new parse request.
  94. ycm.HandleFileParseRequest()
  95. assert_that(
  96. test_utils.VIM_SIGNS,
  97. contains_exactly(
  98. VimSign( 1, 'YcmError', 1 )
  99. )
  100. )
  101. assert_that( ycm.GetErrorCount(), equal_to( 1 ) )
  102. assert_that( ycm.GetWarningCount(), equal_to( 0 ) )
  103. assert_that( not ycm.ShouldResendFileParseRequest() )
  104. # New identical requests should result in the same diagnostics.
  105. ycm.OnFileReadyToParse()
  106. assert_that( ycm.FileParseRequestReady() )
  107. ycm.HandleFileParseRequest()
  108. assert_that(
  109. test_utils.VIM_SIGNS,
  110. contains_exactly(
  111. VimSign( 1, 'YcmError', 1 )
  112. )
  113. )
  114. assert_that( ycm.GetErrorCount(), equal_to( 1 ) )
  115. assert_that( ycm.GetWarningCount(), equal_to( 0 ) )
  116. assert_that( not ycm.ShouldResendFileParseRequest() )
  117. def _Check_FileReadyToParse_Diagnostic_Warning( ycm ):
  118. # Tests Vim sign placement/unplacement and error/warning count python API
  119. # when one warning is returned.
  120. # Should be called after _Check_FileReadyToParse_Diagnostic_Error
  121. def DiagnosticResponse( *args ):
  122. start = Location( 2, 2, 'TEST_BUFFER' )
  123. end = Location( 2, 4, 'TEST_BUFFER' )
  124. extent = Range( start, end )
  125. diagnostic = Diagnostic( [], start, extent, 'cast', 'WARNING' )
  126. return [ BuildDiagnosticData( diagnostic ) ]
  127. with MockArbitraryBuffer( 'cpp' ):
  128. with MockEventNotification( DiagnosticResponse ):
  129. ycm.OnFileReadyToParse()
  130. assert_that( ycm.FileParseRequestReady() )
  131. ycm.HandleFileParseRequest()
  132. assert_that(
  133. test_utils.VIM_SIGNS,
  134. contains_exactly(
  135. VimSign( 2, 'YcmWarning', 1 )
  136. )
  137. )
  138. assert_that( ycm.GetErrorCount(), equal_to( 0 ) )
  139. assert_that( ycm.GetWarningCount(), equal_to( 1 ) )
  140. # Consequent calls to HandleFileParseRequest shouldn't mess with
  141. # existing diagnostics, when there is no new parse request.
  142. ycm.HandleFileParseRequest()
  143. assert_that(
  144. test_utils.VIM_SIGNS,
  145. contains_exactly(
  146. VimSign( 2, 'YcmWarning', 1 )
  147. )
  148. )
  149. assert_that( ycm.GetErrorCount(), equal_to( 0 ) )
  150. assert_that( ycm.GetWarningCount(), equal_to( 1 ) )
  151. assert_that( not ycm.ShouldResendFileParseRequest() )
  152. def _Check_FileReadyToParse_Diagnostic_Clean( ycm ):
  153. # Tests Vim sign unplacement and error/warning count python API
  154. # when there are no errors/warnings left.
  155. # Should be called after _Check_FileReadyToParse_Diagnostic_Warning
  156. with MockArbitraryBuffer( 'cpp' ):
  157. with MockEventNotification( MagicMock( return_value = [] ) ):
  158. ycm.OnFileReadyToParse()
  159. ycm.HandleFileParseRequest()
  160. assert_that(
  161. test_utils.VIM_SIGNS,
  162. empty()
  163. )
  164. assert_that( ycm.GetErrorCount(), equal_to( 0 ) )
  165. assert_that( ycm.GetWarningCount(), equal_to( 0 ) )
  166. assert_that( not ycm.ShouldResendFileParseRequest() )
  167. class EventNotificationTest( TestCase ):
  168. @patch( 'ycm.vimsupport.PostVimMessage', new_callable = ExtendedMock )
  169. @YouCompleteMeInstance()
  170. def test_EventNotification_FileReadyToParse_NonDiagnostic_Error(
  171. self, ycm, post_vim_message ):
  172. # This test validates the behaviour of YouCompleteMe.HandleFileParseRequest
  173. # in combination with YouCompleteMe.OnFileReadyToParse when the completer
  174. # raises an exception handling FileReadyToParse event notification
  175. ERROR_TEXT = 'Some completer response text'
  176. def ErrorResponse( *args ):
  177. raise ServerError( ERROR_TEXT )
  178. with MockArbitraryBuffer( 'some_filetype' ):
  179. with MockEventNotification( ErrorResponse ):
  180. ycm.OnFileReadyToParse()
  181. assert_that( ycm.FileParseRequestReady() )
  182. ycm.HandleFileParseRequest()
  183. # The first call raises a warning
  184. post_vim_message.assert_has_exact_calls( [
  185. call( ERROR_TEXT, truncate = True )
  186. ] )
  187. # Subsequent calls don't re-raise the warning
  188. ycm.HandleFileParseRequest()
  189. post_vim_message.assert_has_exact_calls( [
  190. call( ERROR_TEXT, truncate = True )
  191. ] )
  192. assert_that( not ycm.ShouldResendFileParseRequest() )
  193. # But it does if a subsequent event raises again
  194. ycm.OnFileReadyToParse()
  195. assert_that( ycm.FileParseRequestReady() )
  196. ycm.HandleFileParseRequest()
  197. post_vim_message.assert_has_exact_calls( [
  198. call( ERROR_TEXT, truncate = True ),
  199. call( ERROR_TEXT, truncate = True )
  200. ] )
  201. assert_that( not ycm.ShouldResendFileParseRequest() )
  202. @YouCompleteMeInstance()
  203. def test_EventNotification_FileReadyToParse_NonDiagnostic_Error_NonNative(
  204. self, ycm ):
  205. test_utils.VIM_MATCHES = []
  206. test_utils.VIM_SIGNS = []
  207. with MockArbitraryBuffer( 'some_filetype' ):
  208. with MockEventNotification( None, False ):
  209. ycm.OnFileReadyToParse()
  210. ycm.HandleFileParseRequest()
  211. assert_that( test_utils.VIM_MATCHES, empty() )
  212. assert_that( test_utils.VIM_SIGNS, empty() )
  213. assert_that( not ycm.ShouldResendFileParseRequest() )
  214. @YouCompleteMeInstance()
  215. def test_EventNotification_FileReadyToParse_NonDiagnostic_ConfirmExtraConf(
  216. self, ycm ):
  217. # This test validates the behaviour of YouCompleteMe.HandleFileParseRequest
  218. # in combination with YouCompleteMe.OnFileReadyToParse when the completer
  219. # raises the (special) UnknownExtraConf exception
  220. FILE_NAME = 'a_file'
  221. MESSAGE = ( 'Found ' + FILE_NAME + '. Load? \n\n(Question can be '
  222. 'turned off with options, see YCM docs)' )
  223. def UnknownExtraConfResponse( *args ):
  224. raise UnknownExtraConf( FILE_NAME )
  225. with patch( 'ycm.client.base_request.BaseRequest.PostDataToHandler',
  226. new_callable = ExtendedMock ) as post_data_to_handler:
  227. with MockArbitraryBuffer( 'some_filetype' ):
  228. with MockEventNotification( UnknownExtraConfResponse ):
  229. # When the user accepts the extra conf, we load it
  230. with patch( 'ycm.vimsupport.PresentDialog',
  231. return_value = 0,
  232. new_callable = ExtendedMock ) as present_dialog:
  233. ycm.OnFileReadyToParse()
  234. assert_that( ycm.FileParseRequestReady() )
  235. ycm.HandleFileParseRequest()
  236. present_dialog.assert_has_exact_calls( [
  237. PresentDialog_Confirm_Call( MESSAGE ),
  238. ] )
  239. post_data_to_handler.assert_has_exact_calls( [
  240. call( { 'filepath': FILE_NAME }, 'load_extra_conf_file' )
  241. ] )
  242. # Subsequent calls don't re-raise the warning
  243. ycm.HandleFileParseRequest()
  244. present_dialog.assert_has_exact_calls( [
  245. PresentDialog_Confirm_Call( MESSAGE )
  246. ] )
  247. post_data_to_handler.assert_has_exact_calls( [
  248. call( { 'filepath': FILE_NAME }, 'load_extra_conf_file' )
  249. ] )
  250. assert_that( ycm.ShouldResendFileParseRequest() )
  251. # But it does if a subsequent event raises again
  252. ycm.OnFileReadyToParse()
  253. assert_that( ycm.FileParseRequestReady() )
  254. ycm.HandleFileParseRequest()
  255. present_dialog.assert_has_exact_calls( [
  256. PresentDialog_Confirm_Call( MESSAGE ),
  257. PresentDialog_Confirm_Call( MESSAGE ),
  258. ] )
  259. post_data_to_handler.assert_has_exact_calls( [
  260. call( { 'filepath': FILE_NAME }, 'load_extra_conf_file' ),
  261. call( { 'filepath': FILE_NAME }, 'load_extra_conf_file' )
  262. ] )
  263. assert_that( ycm.ShouldResendFileParseRequest() )
  264. post_data_to_handler.reset_mock()
  265. # When the user rejects the extra conf, we reject it
  266. with patch( 'ycm.vimsupport.PresentDialog',
  267. return_value = 1,
  268. new_callable = ExtendedMock ) as present_dialog:
  269. ycm.OnFileReadyToParse()
  270. assert_that( ycm.FileParseRequestReady() )
  271. ycm.HandleFileParseRequest()
  272. present_dialog.assert_has_exact_calls( [
  273. PresentDialog_Confirm_Call( MESSAGE ),
  274. ] )
  275. post_data_to_handler.assert_has_exact_calls( [
  276. call( { 'filepath': FILE_NAME }, 'ignore_extra_conf_file' )
  277. ] )
  278. # Subsequent calls don't re-raise the warning
  279. ycm.HandleFileParseRequest()
  280. present_dialog.assert_has_exact_calls( [
  281. PresentDialog_Confirm_Call( MESSAGE )
  282. ] )
  283. post_data_to_handler.assert_has_exact_calls( [
  284. call( { 'filepath': FILE_NAME }, 'ignore_extra_conf_file' )
  285. ] )
  286. assert_that( ycm.ShouldResendFileParseRequest() )
  287. # But it does if a subsequent event raises again
  288. ycm.OnFileReadyToParse()
  289. assert_that( ycm.FileParseRequestReady() )
  290. ycm.HandleFileParseRequest()
  291. present_dialog.assert_has_exact_calls( [
  292. PresentDialog_Confirm_Call( MESSAGE ),
  293. PresentDialog_Confirm_Call( MESSAGE ),
  294. ] )
  295. post_data_to_handler.assert_has_exact_calls( [
  296. call( { 'filepath': FILE_NAME }, 'ignore_extra_conf_file' ),
  297. call( { 'filepath': FILE_NAME }, 'ignore_extra_conf_file' )
  298. ] )
  299. assert_that( ycm.ShouldResendFileParseRequest() )
  300. @YouCompleteMeInstance()
  301. def test_EventNotification_FileReadyToParse_Diagnostic_Error_Native(
  302. self, ycm ):
  303. test_utils.VIM_SIGNS = []
  304. _Check_FileReadyToParse_Diagnostic_Error( ycm )
  305. _Check_FileReadyToParse_Diagnostic_Warning( ycm )
  306. _Check_FileReadyToParse_Diagnostic_Clean( ycm )
  307. @patch( 'ycm.youcompleteme.YouCompleteMe._AddUltiSnipsDataIfNeeded' )
  308. @YouCompleteMeInstance( { 'g:ycm_collect_identifiers_from_tags_files': 1 } )
  309. def test_EventNotification_FileReadyToParse_TagFiles_UnicodeWorkingDirectory(
  310. self, ycm, *args ):
  311. unicode_dir = PathToTestFile( 'uni¢od€' )
  312. current_buffer_file = PathToTestFile( 'uni¢𐍈d€', 'current_buffer' )
  313. current_buffer = VimBuffer( name = current_buffer_file,
  314. contents = [ 'current_buffer_contents' ],
  315. filetype = 'some_filetype' )
  316. with patch( 'ycm.client.event_notification.EventNotification.'
  317. 'PostDataToHandlerAsync' ) as post_data_to_handler_async:
  318. with CurrentWorkingDirectory( unicode_dir ):
  319. with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 5 ) ):
  320. ycm.OnFileReadyToParse()
  321. assert_that(
  322. # Positional arguments passed to PostDataToHandlerAsync.
  323. post_data_to_handler_async.call_args[ 0 ],
  324. contains_exactly(
  325. has_entries( {
  326. 'filepath': current_buffer_file,
  327. 'line_num': 1,
  328. 'column_num': 6,
  329. 'file_data': has_entries( {
  330. current_buffer_file: has_entries( {
  331. 'contents': 'current_buffer_contents\n',
  332. 'filetypes': [ 'some_filetype' ]
  333. } )
  334. } ),
  335. 'event_name': 'FileReadyToParse',
  336. 'tag_files': has_item( PathToTestFile( 'uni¢od€', 'tags' ) )
  337. } ),
  338. 'event_notification'
  339. )
  340. )
  341. @patch( 'ycm.youcompleteme.YouCompleteMe._AddUltiSnipsDataIfNeeded' )
  342. @YouCompleteMeInstance()
  343. def test_EventNotification_BufferVisit_BuildRequestForCurrentAndUnsavedBuffers( # noqa
  344. self, ycm, *args ):
  345. current_buffer_file = os.path.realpath( 'current_buffer' )
  346. current_buffer = VimBuffer( name = current_buffer_file,
  347. number = 1,
  348. contents = [ 'current_buffer_contents' ],
  349. filetype = 'some_filetype',
  350. modified = False )
  351. modified_buffer_file = os.path.realpath( 'modified_buffer' )
  352. modified_buffer = VimBuffer( name = modified_buffer_file,
  353. number = 2,
  354. contents = [ 'modified_buffer_contents' ],
  355. filetype = 'some_filetype',
  356. modified = True )
  357. unmodified_buffer_file = os.path.realpath( 'unmodified_buffer' )
  358. unmodified_buffer = VimBuffer( name = unmodified_buffer_file,
  359. number = 3,
  360. contents = [ 'unmodified_buffer_contents' ],
  361. filetype = 'some_filetype',
  362. modified = False )
  363. with patch( 'ycm.client.event_notification.EventNotification.'
  364. 'PostDataToHandlerAsync' ) as post_data_to_handler_async:
  365. with MockVimBuffers( [ current_buffer,
  366. modified_buffer,
  367. unmodified_buffer ],
  368. [ current_buffer ],
  369. ( 1, 5 ) ):
  370. ycm.OnBufferVisit()
  371. assert_that(
  372. # Positional arguments passed to PostDataToHandlerAsync.
  373. post_data_to_handler_async.call_args[ 0 ],
  374. contains_exactly(
  375. has_entries( {
  376. 'filepath': current_buffer_file,
  377. 'line_num': 1,
  378. 'column_num': 6,
  379. 'file_data': has_entries( {
  380. current_buffer_file: has_entries( {
  381. 'contents': 'current_buffer_contents\n',
  382. 'filetypes': [ 'some_filetype' ]
  383. } ),
  384. modified_buffer_file: has_entries( {
  385. 'contents': 'modified_buffer_contents\n',
  386. 'filetypes': [ 'some_filetype' ]
  387. } )
  388. } ),
  389. 'event_name': 'BufferVisit'
  390. } ),
  391. 'event_notification'
  392. )
  393. )
  394. @YouCompleteMeInstance()
  395. def test_EventNotification_BufferUnload_BuildRequestForDeletedAndUnsavedBuffers( # noqa
  396. self, ycm ):
  397. current_buffer_file = os.path.realpath( 'current_βuffer' )
  398. current_buffer = VimBuffer( name = current_buffer_file,
  399. number = 1,
  400. contents = [ 'current_buffer_contents' ],
  401. filetype = 'some_filetype',
  402. modified = True )
  403. deleted_buffer_file = os.path.realpath( 'deleted_βuffer' )
  404. deleted_buffer = VimBuffer( name = deleted_buffer_file,
  405. number = 2,
  406. contents = [ 'deleted_buffer_contents' ],
  407. filetype = 'some_filetype',
  408. modified = False )
  409. with patch( 'ycm.client.event_notification.EventNotification.'
  410. 'PostDataToHandlerAsync' ) as post_data_to_handler_async:
  411. with MockVimBuffers( [ current_buffer, deleted_buffer ],
  412. [ current_buffer ] ):
  413. ycm.OnBufferUnload( deleted_buffer.number )
  414. assert_that(
  415. # Positional arguments passed to PostDataToHandlerAsync.
  416. post_data_to_handler_async.call_args[ 0 ],
  417. contains_exactly(
  418. has_entries( {
  419. 'filepath': deleted_buffer_file,
  420. 'line_num': 1,
  421. 'column_num': 1,
  422. 'file_data': has_entries( {
  423. current_buffer_file: has_entries( {
  424. 'contents': 'current_buffer_contents\n',
  425. 'filetypes': [ 'some_filetype' ]
  426. } ),
  427. deleted_buffer_file: has_entries( {
  428. 'contents': 'deleted_buffer_contents\n',
  429. 'filetypes': [ 'some_filetype' ]
  430. } )
  431. } ),
  432. 'event_name': 'BufferUnload'
  433. } ),
  434. 'event_notification'
  435. )
  436. )
  437. @patch( 'ycm.vimsupport.CaptureVimCommand', return_value = """
  438. fooGroup xxx foo bar
  439. links to Statement""" )
  440. @YouCompleteMeInstance( { 'g:ycm_seed_identifiers_with_syntax': 1 } )
  441. def test_EventNotification_FileReadyToParse_SyntaxKeywords_SeedWithCache(
  442. self, ycm, *args ):
  443. current_buffer = VimBuffer( name = 'current_buffer',
  444. filetype = 'some_filetype' )
  445. with patch( 'ycm.client.event_notification.EventNotification.'
  446. 'PostDataToHandlerAsync' ) as post_data_to_handler_async:
  447. with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
  448. ycm.OnFileReadyToParse()
  449. assert_that(
  450. # Positional arguments passed to PostDataToHandlerAsync.
  451. post_data_to_handler_async.call_args[ 0 ],
  452. contains_exactly(
  453. has_entry( 'syntax_keywords', has_items( 'foo', 'bar' ) ),
  454. 'event_notification'
  455. )
  456. )
  457. # Do not send again syntax keywords in subsequent requests.
  458. ycm.OnFileReadyToParse()
  459. assert_that(
  460. # Positional arguments passed to PostDataToHandlerAsync.
  461. post_data_to_handler_async.call_args[ 0 ],
  462. contains_exactly(
  463. is_not( has_key( 'syntax_keywords' ) ),
  464. 'event_notification'
  465. )
  466. )
  467. @patch( 'ycm.vimsupport.CaptureVimCommand', return_value = """
  468. fooGroup xxx foo bar
  469. links to Statement""" )
  470. @YouCompleteMeInstance( { 'g:ycm_seed_identifiers_with_syntax': 1 } )
  471. def test_EventNotification_FileReadyToParse_SyntaxKeywords_ClearCacheIfRestart( # noqa
  472. self, ycm, *args ):
  473. current_buffer = VimBuffer( name = 'current_buffer',
  474. filetype = 'some_filetype' )
  475. with patch( 'ycm.client.event_notification.EventNotification.'
  476. 'PostDataToHandlerAsync' ) as post_data_to_handler_async:
  477. with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
  478. ycm.OnFileReadyToParse()
  479. assert_that(
  480. # Positional arguments passed to PostDataToHandlerAsync.
  481. post_data_to_handler_async.call_args[ 0 ],
  482. contains_exactly(
  483. has_entry( 'syntax_keywords', has_items( 'foo', 'bar' ) ),
  484. 'event_notification'
  485. )
  486. )
  487. # Send again the syntax keywords after restarting the server.
  488. ycm.RestartServer()
  489. WaitUntilReady()
  490. ycm.OnFileReadyToParse()
  491. assert_that(
  492. # Positional arguments passed to PostDataToHandlerAsync.
  493. post_data_to_handler_async.call_args[ 0 ],
  494. contains_exactly(
  495. has_entry( 'syntax_keywords', has_items( 'foo', 'bar' ) ),
  496. 'event_notification'
  497. )
  498. )