Fixing the diagnostic-related race conditions
Now, every FileReadyToParse event returns diagnostics, if any. This is instead of the previous system where the diagnostics were being fetched in a different request (this caused race conditions).
This commit is contained in:
parent
b9bb788a2a
commit
c274b7d4f8
@ -258,9 +258,6 @@ function! s:OnCursorHold()
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
call s:SetUpCompleteopt()
|
call s:SetUpCompleteopt()
|
||||||
" Order is important here; we need to extract any done diagnostics before
|
|
||||||
" reparsing the file again
|
|
||||||
call s:UpdateDiagnosticNotifications()
|
|
||||||
call s:OnFileReadyToParse()
|
call s:OnFileReadyToParse()
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@ -270,9 +267,14 @@ function! s:OnFileReadyToParse()
|
|||||||
" happen for special buffers.
|
" happen for special buffers.
|
||||||
call s:SetUpYcmChangedTick()
|
call s:SetUpYcmChangedTick()
|
||||||
|
|
||||||
|
" Order is important here; we need to extract any done diagnostics before
|
||||||
|
" reparsing the file again. If we sent the new parse request first, then
|
||||||
|
" the response would always be pending when we called
|
||||||
|
" UpdateDiagnosticNotifications.
|
||||||
|
call s:UpdateDiagnosticNotifications()
|
||||||
|
|
||||||
let buffer_changed = b:changedtick != b:ycm_changedtick.file_ready_to_parse
|
let buffer_changed = b:changedtick != b:ycm_changedtick.file_ready_to_parse
|
||||||
if buffer_changed
|
if buffer_changed
|
||||||
py ycm_state.RequestDiagnosticsForCurrentFile()
|
|
||||||
py ycm_state.OnFileReadyToParse()
|
py ycm_state.OnFileReadyToParse()
|
||||||
endif
|
endif
|
||||||
let b:ycm_changedtick.file_ready_to_parse = b:changedtick
|
let b:ycm_changedtick.file_ready_to_parse = b:changedtick
|
||||||
@ -328,7 +330,6 @@ function! s:OnCursorMovedNormalMode()
|
|||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call s:UpdateDiagnosticNotifications()
|
|
||||||
call s:OnFileReadyToParse()
|
call s:OnFileReadyToParse()
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@ -339,7 +340,6 @@ function! s:OnInsertLeave()
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
let s:omnifunc_mode = 0
|
let s:omnifunc_mode = 0
|
||||||
call s:UpdateDiagnosticNotifications()
|
|
||||||
call s:OnFileReadyToParse()
|
call s:OnFileReadyToParse()
|
||||||
py ycm_state.OnInsertLeave()
|
py ycm_state.OnInsertLeave()
|
||||||
if g:ycm_autoclose_preview_window_after_completion ||
|
if g:ycm_autoclose_preview_window_after_completion ||
|
||||||
@ -660,13 +660,14 @@ function! s:ForceCompile()
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" TODO: Make this work again.
|
||||||
function! s:ForceCompileAndDiagnostics()
|
function! s:ForceCompileAndDiagnostics()
|
||||||
let compilation_succeeded = s:ForceCompile()
|
let compilation_succeeded = s:ForceCompile()
|
||||||
if !compilation_succeeded
|
if !compilation_succeeded
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call s:UpdateDiagnosticNotifications()
|
" call s:UpdateDiagnosticNotifications()
|
||||||
echom "Diagnostics refreshed."
|
echom "Diagnostics refreshed."
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
@ -58,17 +58,6 @@ ClangCompleter::~ClangCompleter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector< Diagnostic > ClangCompleter::DiagnosticsForFile(
|
|
||||||
const std::string &filename ) {
|
|
||||||
shared_ptr< TranslationUnit > unit = translation_unit_store_.Get( filename );
|
|
||||||
|
|
||||||
if ( !unit )
|
|
||||||
return std::vector< Diagnostic >();
|
|
||||||
|
|
||||||
return unit->LatestDiagnostics();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ClangCompleter::UpdatingTranslationUnit( const std::string &filename ) {
|
bool ClangCompleter::UpdatingTranslationUnit( const std::string &filename ) {
|
||||||
shared_ptr< TranslationUnit > unit = translation_unit_store_.Get( filename );
|
shared_ptr< TranslationUnit > unit = translation_unit_store_.Get( filename );
|
||||||
|
|
||||||
@ -82,7 +71,7 @@ bool ClangCompleter::UpdatingTranslationUnit( const std::string &filename ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ClangCompleter::UpdateTranslationUnit(
|
std::vector< Diagnostic > ClangCompleter::UpdateTranslationUnit(
|
||||||
const std::string &filename,
|
const std::string &filename,
|
||||||
const std::vector< UnsavedFile > &unsaved_files,
|
const std::vector< UnsavedFile > &unsaved_files,
|
||||||
const std::vector< std::string > &flags ) {
|
const std::vector< std::string > &flags ) {
|
||||||
@ -94,13 +83,14 @@ void ClangCompleter::UpdateTranslationUnit(
|
|||||||
translation_unit_created );
|
translation_unit_created );
|
||||||
|
|
||||||
if ( !unit )
|
if ( !unit )
|
||||||
return;
|
return std::vector< Diagnostic >();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// There's no point in reparsing a TU that was just created, it was just
|
// There's no point in reparsing a TU that was just created, it was just
|
||||||
// parsed in the TU constructor
|
// parsed in the TU constructor
|
||||||
if ( !translation_unit_created )
|
if ( !translation_unit_created )
|
||||||
unit->Reparse( unsaved_files );
|
return unit->Reparse( unsaved_files );
|
||||||
|
return unit->LatestDiagnostics();
|
||||||
}
|
}
|
||||||
|
|
||||||
catch ( ClangParseError & ) {
|
catch ( ClangParseError & ) {
|
||||||
@ -109,6 +99,8 @@ void ClangCompleter::UpdateTranslationUnit(
|
|||||||
// TU map.
|
// TU map.
|
||||||
translation_unit_store_.Remove( filename );
|
translation_unit_store_.Remove( filename );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return std::vector< Diagnostic >();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,11 +43,9 @@ public:
|
|||||||
ClangCompleter();
|
ClangCompleter();
|
||||||
~ClangCompleter();
|
~ClangCompleter();
|
||||||
|
|
||||||
std::vector< Diagnostic > DiagnosticsForFile( const std::string &filename );
|
|
||||||
|
|
||||||
bool UpdatingTranslationUnit( const std::string &filename );
|
bool UpdatingTranslationUnit( const std::string &filename );
|
||||||
|
|
||||||
void UpdateTranslationUnit(
|
std::vector< Diagnostic > UpdateTranslationUnit(
|
||||||
const std::string &filename,
|
const std::string &filename,
|
||||||
const std::vector< UnsavedFile > &unsaved_files,
|
const std::vector< UnsavedFile > &unsaved_files,
|
||||||
const std::vector< std::string > &flags );
|
const std::vector< std::string > &flags );
|
||||||
|
@ -111,12 +111,15 @@ bool TranslationUnit::IsCurrentlyUpdating() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TranslationUnit::Reparse(
|
std::vector< Diagnostic > TranslationUnit::Reparse(
|
||||||
const std::vector< UnsavedFile > &unsaved_files ) {
|
const std::vector< UnsavedFile > &unsaved_files ) {
|
||||||
std::vector< CXUnsavedFile > cxunsaved_files =
|
std::vector< CXUnsavedFile > cxunsaved_files =
|
||||||
ToCXUnsavedFiles( unsaved_files );
|
ToCXUnsavedFiles( unsaved_files );
|
||||||
|
|
||||||
Reparse( cxunsaved_files );
|
Reparse( cxunsaved_files );
|
||||||
|
|
||||||
|
unique_lock< mutex > lock( diagnostics_mutex_ );
|
||||||
|
return latest_diagnostics_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,7 +56,8 @@ public:
|
|||||||
|
|
||||||
bool IsCurrentlyUpdating() const;
|
bool IsCurrentlyUpdating() const;
|
||||||
|
|
||||||
void Reparse( const std::vector< UnsavedFile > &unsaved_files );
|
std::vector< Diagnostic > Reparse(
|
||||||
|
const std::vector< UnsavedFile > &unsaved_files );
|
||||||
|
|
||||||
void ReparseForIndexing( const std::vector< UnsavedFile > &unsaved_files );
|
void ReparseForIndexing( const std::vector< UnsavedFile > &unsaved_files );
|
||||||
|
|
||||||
|
@ -95,7 +95,6 @@ BOOST_PYTHON_MODULE(ycm_core)
|
|||||||
.def( vector_indexing_suite< std::vector< UnsavedFile > >() );
|
.def( vector_indexing_suite< std::vector< UnsavedFile > >() );
|
||||||
|
|
||||||
class_< ClangCompleter, boost::noncopyable >( "ClangCompleter" )
|
class_< ClangCompleter, boost::noncopyable >( "ClangCompleter" )
|
||||||
.def( "DiagnosticsForFile", &ClangCompleter::DiagnosticsForFile )
|
|
||||||
.def( "GetDeclarationLocation", &ClangCompleter::GetDeclarationLocation )
|
.def( "GetDeclarationLocation", &ClangCompleter::GetDeclarationLocation )
|
||||||
.def( "GetDefinitionLocation", &ClangCompleter::GetDefinitionLocation )
|
.def( "GetDefinitionLocation", &ClangCompleter::GetDefinitionLocation )
|
||||||
.def( "DeleteCachesForFile", &ClangCompleter::DeleteCachesForFile )
|
.def( "DeleteCachesForFile", &ClangCompleter::DeleteCachesForFile )
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
# Copyright (C) 2013 Strahinja Val Markovic <val@markovic.io>
|
|
||||||
#
|
|
||||||
# This file is part of YouCompleteMe.
|
|
||||||
#
|
|
||||||
# YouCompleteMe is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# YouCompleteMe is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import traceback
|
|
||||||
from ycm import vimsupport
|
|
||||||
from ycm.client.base_request import ( BaseRequest, BuildRequestData,
|
|
||||||
JsonFromFuture )
|
|
||||||
|
|
||||||
|
|
||||||
class DiagnosticsRequest( BaseRequest ):
|
|
||||||
def __init__( self ):
|
|
||||||
super( DiagnosticsRequest, self ).__init__()
|
|
||||||
self._cached_response = None
|
|
||||||
|
|
||||||
|
|
||||||
def Start( self ):
|
|
||||||
request_data = BuildRequestData()
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._response_future = self.PostDataToHandlerAsync( request_data,
|
|
||||||
'diagnostics' )
|
|
||||||
except:
|
|
||||||
vimsupport.EchoText( traceback.format_exc() )
|
|
||||||
|
|
||||||
|
|
||||||
def Done( self ):
|
|
||||||
return self._response_future.done()
|
|
||||||
|
|
||||||
|
|
||||||
def Response( self ):
|
|
||||||
if self._cached_response:
|
|
||||||
return self._cached_response
|
|
||||||
|
|
||||||
if not self._response_future:
|
|
||||||
return []
|
|
||||||
try:
|
|
||||||
self._cached_response = [ _ConvertDiagnosticDataToVimData( x )
|
|
||||||
for x in JsonFromFuture(
|
|
||||||
self._response_future ) ]
|
|
||||||
return self._cached_response
|
|
||||||
except Exception as e:
|
|
||||||
vimsupport.PostVimMessage( str( e ) )
|
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
def _ConvertDiagnosticDataToVimData( diagnostic ):
|
|
||||||
# see :h getqflist for a description of the dictionary fields
|
|
||||||
# Note that, as usual, Vim is completely inconsistent about whether
|
|
||||||
# line/column numbers are 1 or 0 based in its various APIs. Here, it wants
|
|
||||||
# them to be 1-based.
|
|
||||||
return {
|
|
||||||
'bufnr' : vimsupport.GetBufferNumberForFilename( diagnostic[ 'filepath' ]),
|
|
||||||
'lnum' : diagnostic[ 'line_num' ] + 1,
|
|
||||||
'col' : diagnostic[ 'column_num' ] + 1,
|
|
||||||
'text' : diagnostic[ 'text' ],
|
|
||||||
'type' : diagnostic[ 'kind' ],
|
|
||||||
'valid' : 1
|
|
||||||
}
|
|
||||||
|
|
@ -17,14 +17,16 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from ycm.client.base_request import BaseRequest, BuildRequestData
|
from ycm import vimsupport
|
||||||
|
from ycm.client.base_request import ( BaseRequest, BuildRequestData,
|
||||||
|
JsonFromFuture )
|
||||||
|
|
||||||
class EventNotification( BaseRequest ):
|
class EventNotification( BaseRequest ):
|
||||||
def __init__( self, event_name, extra_data = None ):
|
def __init__( self, event_name, extra_data = None ):
|
||||||
super( EventNotification, self ).__init__()
|
super( EventNotification, self ).__init__()
|
||||||
self._event_name = event_name
|
self._event_name = event_name
|
||||||
self._extra_data = extra_data
|
self._extra_data = extra_data
|
||||||
|
self._cached_response = None
|
||||||
|
|
||||||
|
|
||||||
def Start( self ):
|
def Start( self ):
|
||||||
@ -33,7 +35,44 @@ class EventNotification( BaseRequest ):
|
|||||||
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
|
||||||
|
|
||||||
self.PostDataToHandlerAsync( request_data, 'event_notification' )
|
self._response_future = self.PostDataToHandlerAsync( request_data,
|
||||||
|
'event_notification' )
|
||||||
|
|
||||||
|
|
||||||
|
def Done( self ):
|
||||||
|
return self._response_future.done()
|
||||||
|
|
||||||
|
|
||||||
|
def Response( self ):
|
||||||
|
if self._cached_response:
|
||||||
|
return self._cached_response
|
||||||
|
|
||||||
|
if not self._response_future or self._event_name != 'FileReadyToParse':
|
||||||
|
return []
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._cached_response = [ _ConvertDiagnosticDataToVimData( x )
|
||||||
|
for x in JsonFromFuture(
|
||||||
|
self._response_future ) ]
|
||||||
|
return self._cached_response
|
||||||
|
except Exception as e:
|
||||||
|
vimsupport.PostVimMessage( str( e ) )
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def _ConvertDiagnosticDataToVimData( diagnostic ):
|
||||||
|
# see :h getqflist for a description of the dictionary fields
|
||||||
|
# Note that, as usual, Vim is completely inconsistent about whether
|
||||||
|
# line/column numbers are 1 or 0 based in its various APIs. Here, it wants
|
||||||
|
# them to be 1-based.
|
||||||
|
return {
|
||||||
|
'bufnr' : vimsupport.GetBufferNumberForFilename( diagnostic[ 'filepath' ]),
|
||||||
|
'lnum' : diagnostic[ 'line_num' ] + 1,
|
||||||
|
'col' : diagnostic[ 'column_num' ] + 1,
|
||||||
|
'text' : diagnostic[ 'text' ],
|
||||||
|
'type' : diagnostic[ 'kind' ],
|
||||||
|
'valid' : 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def SendEventNotificationAsync( event_name, extra_data = None ):
|
def SendEventNotificationAsync( event_name, extra_data = None ):
|
||||||
|
@ -201,11 +201,15 @@ class ClangCompleter( Completer ):
|
|||||||
self._logger.info( NO_COMPILE_FLAGS_MESSAGE )
|
self._logger.info( NO_COMPILE_FLAGS_MESSAGE )
|
||||||
raise ValueError( NO_COMPILE_FLAGS_MESSAGE )
|
raise ValueError( NO_COMPILE_FLAGS_MESSAGE )
|
||||||
|
|
||||||
self._completer.UpdateTranslationUnit(
|
diagnostics = self._completer.UpdateTranslationUnit(
|
||||||
ToUtf8IfNeeded( filename ),
|
ToUtf8IfNeeded( filename ),
|
||||||
self.GetUnsavedFilesVector( request_data ),
|
self.GetUnsavedFilesVector( request_data ),
|
||||||
flags )
|
flags )
|
||||||
|
|
||||||
|
self._diagnostic_store = DiagnosticsToDiagStructure( diagnostics )
|
||||||
|
return [ ConvertToDiagnosticResponse( x ) for x in
|
||||||
|
diagnostics[ : self._max_diagnostics_to_display ] ]
|
||||||
|
|
||||||
|
|
||||||
def OnBufferUnload( self, request_data ):
|
def OnBufferUnload( self, request_data ):
|
||||||
self._completer.DeleteCachesForFile(
|
self._completer.DeleteCachesForFile(
|
||||||
@ -217,15 +221,6 @@ class ClangCompleter( Completer ):
|
|||||||
ToUtf8IfNeeded( request_data[ 'filepath' ] ) )
|
ToUtf8IfNeeded( request_data[ 'filepath' ] ) )
|
||||||
|
|
||||||
|
|
||||||
def GetDiagnosticsForCurrentFile( self, request_data ):
|
|
||||||
filename = request_data[ 'filepath' ]
|
|
||||||
diagnostics = self._completer.DiagnosticsForFile(
|
|
||||||
ToUtf8IfNeeded( filename ) )
|
|
||||||
self._diagnostic_store = DiagnosticsToDiagStructure( diagnostics )
|
|
||||||
return [ ConvertToDiagnosticResponse( x ) for x in
|
|
||||||
diagnostics[ : self._max_diagnostics_to_display ] ]
|
|
||||||
|
|
||||||
|
|
||||||
def GetDetailedDiagnostic( self, request_data ):
|
def GetDetailedDiagnostic( self, request_data ):
|
||||||
current_line = request_data[ 'line_num' ] + 1
|
current_line = request_data[ 'line_num' ] + 1
|
||||||
current_column = request_data[ 'column_num' ] + 1
|
current_column = request_data[ 'column_num' ] + 1
|
||||||
|
@ -1 +1 @@
|
|||||||
{
"filepath_completion_use_working_dir": 0,
"min_num_of_chars_for_completion": 2,
"semantic_triggers": {},
"collect_identifiers_from_comments_and_strings": 0,
"filetype_specific_completion_to_disable": {
"gitcommit": 1,
},
"collect_identifiers_from_tags_files": 0,
"extra_conf_globlist": [],
"global_ycm_extra_conf": "",
"confirm_extra_conf": 1,
"complete_in_comments": 0,
"complete_in_strings": 1,
"min_num_identifier_candidate_chars": 0,
"max_diagnostics_to_display": 30,
"auto_stop_csharp_server": 1,
"seed_identifiers_with_syntax": 0,
"csharp_server_port": 2000,
"filetype_whitelist": {
"*": "1"
},
"auto_start_csharp_server": 1,
"filetype_blacklist": {
"tagbar": "1",
"qf": "1",
"notes": "1",
"markdown": "1",
"unite": "1",
"text": "1"
}
}
|
{
"filepath_completion_use_working_dir": 0,
"min_num_of_chars_for_completion": 2,
"semantic_triggers": {},
"collect_identifiers_from_comments_and_strings": 0,
"filetype_specific_completion_to_disable": {
"gitcommit": 1
},
"collect_identifiers_from_tags_files": 0,
"extra_conf_globlist": [],
"global_ycm_extra_conf": "",
"confirm_extra_conf": 1,
"complete_in_comments": 0,
"complete_in_strings": 1,
"min_num_identifier_candidate_chars": 0,
"max_diagnostics_to_display": 30,
"auto_stop_csharp_server": 1,
"seed_identifiers_with_syntax": 0,
"csharp_server_port": 2000,
"filetype_whitelist": {
"*": "1"
},
"auto_start_csharp_server": 1,
"filetype_blacklist": {
"tagbar": "1",
"qf": "1",
"notes": "1",
"markdown": "1",
"unite": "1",
"text": "1"
}
}
|
@ -283,7 +283,7 @@ def DefinedSubcommands_WorksWhenNoExplicitCompleterTargetSpecified_test():
|
|||||||
|
|
||||||
|
|
||||||
@with_setup( Setup )
|
@with_setup( Setup )
|
||||||
def GetDiagnostics_ClangCompleter_ZeroBasedLineAndColumn_test():
|
def Diagnostics_ClangCompleter_ZeroBasedLineAndColumn_test():
|
||||||
app = TestApp( ycmd.app )
|
app = TestApp( ycmd.app )
|
||||||
contents = """
|
contents = """
|
||||||
struct Foo {
|
struct Foo {
|
||||||
@ -314,8 +314,7 @@ struct Foo {
|
|||||||
'event_name': 'FileReadyToParse',
|
'event_name': 'FileReadyToParse',
|
||||||
} )
|
} )
|
||||||
|
|
||||||
app.post_json( '/event_notification', event_data )
|
results = app.post_json( '/event_notification', event_data ).json
|
||||||
results = app.post_json( '/diagnostics', diag_data ).json
|
|
||||||
assert_that( results,
|
assert_that( results,
|
||||||
contains(
|
contains(
|
||||||
has_entries( { 'text': contains_string( "expected ';'" ),
|
has_entries( { 'text': contains_string( "expected ';'" ),
|
||||||
|
@ -63,10 +63,15 @@ def EventNotification():
|
|||||||
getattr( SERVER_STATE.GetGeneralCompleter(), event_handler )( request_data )
|
getattr( SERVER_STATE.GetGeneralCompleter(), event_handler )( request_data )
|
||||||
|
|
||||||
filetypes = request_data[ 'filetypes' ]
|
filetypes = request_data[ 'filetypes' ]
|
||||||
|
response_data = None
|
||||||
if SERVER_STATE.FiletypeCompletionUsable( filetypes ):
|
if SERVER_STATE.FiletypeCompletionUsable( filetypes ):
|
||||||
getattr( SERVER_STATE.GetFiletypeCompleter( filetypes ),
|
response_data = getattr( SERVER_STATE.GetFiletypeCompleter( filetypes ),
|
||||||
event_handler )( request_data )
|
event_handler )( request_data )
|
||||||
|
|
||||||
|
if response_data:
|
||||||
|
return _JsonResponse( response_data )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.post( '/run_completer_command' )
|
@app.post( '/run_completer_command' )
|
||||||
def RunCompleterCommand():
|
def RunCompleterCommand():
|
||||||
@ -94,16 +99,6 @@ def GetCompletions():
|
|||||||
return _JsonResponse( completer.ComputeCandidates( request_data ) )
|
return _JsonResponse( completer.ComputeCandidates( request_data ) )
|
||||||
|
|
||||||
|
|
||||||
@app.post( '/diagnostics' )
|
|
||||||
def GetDiagnostics():
|
|
||||||
LOGGER.info( 'Received diagnostics request')
|
|
||||||
request_data = request.json
|
|
||||||
completer = _GetCompleterForRequestData( request_data )
|
|
||||||
|
|
||||||
return _JsonResponse( completer.GetDiagnosticsForCurrentFile(
|
|
||||||
request_data ) )
|
|
||||||
|
|
||||||
|
|
||||||
@app.get( '/user_options' )
|
@app.get( '/user_options' )
|
||||||
def GetUserOptions():
|
def GetUserOptions():
|
||||||
LOGGER.info( 'Received user options GET request')
|
LOGGER.info( 'Received user options GET request')
|
||||||
|
@ -29,8 +29,8 @@ from ycm.completers.general import syntax_parse
|
|||||||
from ycm.client.base_request import BaseRequest, BuildRequestData
|
from ycm.client.base_request import BaseRequest, BuildRequestData
|
||||||
from ycm.client.command_request import SendCommandRequest
|
from ycm.client.command_request import SendCommandRequest
|
||||||
from ycm.client.completion_request import CompletionRequest
|
from ycm.client.completion_request import CompletionRequest
|
||||||
from ycm.client.diagnostics_request import DiagnosticsRequest
|
from ycm.client.event_notification import ( SendEventNotificationAsync,
|
||||||
from ycm.client.event_notification import SendEventNotificationAsync
|
EventNotification )
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from UltiSnips import UltiSnips_Manager
|
from UltiSnips import UltiSnips_Manager
|
||||||
@ -45,7 +45,7 @@ class YouCompleteMe( object ):
|
|||||||
self._user_options = user_options
|
self._user_options = user_options
|
||||||
self._omnicomp = OmniCompleter( user_options )
|
self._omnicomp = OmniCompleter( user_options )
|
||||||
self._latest_completion_request = None
|
self._latest_completion_request = None
|
||||||
self._latest_diagnostics_request = None
|
self._latest_file_parse_request = None
|
||||||
self._server_stdout = None
|
self._server_stdout = None
|
||||||
self._server_stderr = None
|
self._server_stderr = None
|
||||||
self._server_popen = None
|
self._server_popen = None
|
||||||
@ -147,7 +147,9 @@ class YouCompleteMe( object ):
|
|||||||
if self._user_options[ 'seed_identifiers_with_syntax' ]:
|
if self._user_options[ 'seed_identifiers_with_syntax' ]:
|
||||||
self._AddSyntaxDataIfNeeded( extra_data )
|
self._AddSyntaxDataIfNeeded( extra_data )
|
||||||
|
|
||||||
SendEventNotificationAsync( 'FileReadyToParse', extra_data )
|
self._latest_file_parse_request = EventNotification( 'FileReadyToParse',
|
||||||
|
extra_data )
|
||||||
|
self._latest_file_parse_request.Start()
|
||||||
|
|
||||||
|
|
||||||
def OnBufferUnload( self, deleted_buffer_file ):
|
def OnBufferUnload( self, deleted_buffer_file ):
|
||||||
@ -176,23 +178,18 @@ class YouCompleteMe( object ):
|
|||||||
|
|
||||||
|
|
||||||
def DiagnosticsForCurrentFileReady( self ):
|
def DiagnosticsForCurrentFileReady( self ):
|
||||||
return bool( self._latest_diagnostics_request and
|
return bool( self._latest_file_parse_request and
|
||||||
self._latest_diagnostics_request.Done() )
|
self._latest_file_parse_request.Done() )
|
||||||
|
|
||||||
|
|
||||||
def RequestDiagnosticsForCurrentFile( self ):
|
|
||||||
self._latest_diagnostics_request = DiagnosticsRequest()
|
|
||||||
self._latest_diagnostics_request.Start()
|
|
||||||
|
|
||||||
|
|
||||||
def GetDiagnosticsFromStoredRequest( self ):
|
def GetDiagnosticsFromStoredRequest( self ):
|
||||||
if self._latest_diagnostics_request:
|
if self._latest_file_parse_request:
|
||||||
to_return = self._latest_diagnostics_request.Response()
|
to_return = self._latest_file_parse_request.Response()
|
||||||
# We set the diagnostics request to None because we want to prevent
|
# We set the diagnostics request to None because we want to prevent
|
||||||
# Syntastic from repeatedly refreshing the buffer with the same diags.
|
# Syntastic from repeatedly refreshing the buffer with the same diags.
|
||||||
# Setting this to None makes DiagnosticsForCurrentFileReady return False
|
# Setting this to None makes DiagnosticsForCurrentFileReady return False
|
||||||
# until the next request is created.
|
# until the next request is created.
|
||||||
self._latest_diagnostics_request = None
|
self._latest_file_parse_request = None
|
||||||
return to_return
|
return to_return
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user