Fix for "lclose not allowed here" error on open

The problem was caused by a race condition of all things. ClangCompleter would
set possibly_completions_ready when starting the first parse pass for the file
and then would try to extract diagnostics for the file before the diagnostics
were done. Technically this was not a problem because only an empty diagnostics
vector would be returned, but this triggered Syntastic because hey, we have some
diagnostics to show (even though we don't).

And then Syntastic would try to close the location list window during startup
when this operation is not available. Technically it's Syntastic's fault, but a
more principled way to check for done diagnostics is to return and use a future
for file parsing operations and this solution also works around the Syntastic
issue.
This commit is contained in:
Strahinja Val Markovic 2012-08-12 14:36:36 -07:00
parent fef702eef0
commit f99e89f812
5 changed files with 22 additions and 10 deletions

View File

@ -108,8 +108,10 @@ endfunction
function! s:OnCursorHold()
call s:OnFileReadyToParse()
" Order is important here; we need to extract any done diagnostics before
" reparsing the file again
call s:UpdateDiagnosticNotifications()
call s:OnFileReadyToParse()
endfunction

View File

@ -171,7 +171,7 @@ void ClangCompleter::UpdateTranslationUnit(
}
void ClangCompleter::UpdateTranslationUnitAsync(
Future< void > ClangCompleter::UpdateTranslationUnitAsync(
std::string filename,
std::vector< UnsavedFile > unsaved_files,
std::vector< std::string > flags )
@ -186,8 +186,14 @@ void ClangCompleter::UpdateTranslationUnitAsync(
shared_ptr< ClangPackagedTask > clang_packaged_task =
make_shared< ClangPackagedTask >();
// TODO: vim hangs when we just open it and try to enter insert mode after the
// last '_' in ->parsing_task_ here
clang_packaged_task->parsing_task_ = packaged_task< void >( functor );
unique_future< void > future =
clang_packaged_task->parsing_task_.get_future();
clang_task_.Set( clang_packaged_task );
return Future< void >( boost::move( future ) );
}

View File

@ -69,7 +69,7 @@ public:
// NOTE: params are taken by value on purpose! With a C++11 compiler we can
// avoid internal copies if params are taken by value (move ctors FTW)
void UpdateTranslationUnitAsync(
Future< void > UpdateTranslationUnitAsync(
std::string filename,
std::vector< UnsavedFile > unsaved_files,
std::vector< std::string > flags );

View File

@ -67,6 +67,10 @@ BOOST_PYTHON_MODULE(ycm_core)
.def( "ResultsReady", &Future< AsyncCompletions >::ResultsReady )
.def( "GetResults", &Future< AsyncCompletions >::GetResults );
class_< Future< void > >( "FutureVoid" )
.def( "ResultsReady", &Future< void >::ResultsReady )
.def( "GetResults", &Future< void >::GetResults );
class_< IdentifierCompleter, boost::noncopyable >( "IdentifierCompleter" )
.def( "EnableThreading", &IdentifierCompleter::EnableThreading )
.def( "AddCandidatesToDatabase",

View File

@ -33,7 +33,7 @@ class ClangCompleter( Completer ):
self.contents_holder = []
self.filename_holder = []
self.last_diagnostics = []
self.possibly_new_diagnostics = False
self.parse_future = None
self.flags = Flags()
@ -88,6 +88,7 @@ class ClangCompleter( Completer ):
line, _ = vim.current.window.cursor
column = int( vim.eval( "s:completion_start_column" ) ) + 1
current_buffer = vim.current.buffer
# TODO: rename future to completions_future
self.future = self.completer.CandidatesForQueryAndLocationInFileAsync(
query,
current_buffer.name,
@ -110,26 +111,25 @@ class ClangCompleter( Completer ):
if vimsupport.NumLinesInBuffer( vim.current.buffer ) < 5:
return
self.possibly_new_diagnostics = True
filename = vim.current.buffer.name
self.completer.UpdateTranslationUnitAsync(
self.parse_future = self.completer.UpdateTranslationUnitAsync(
filename,
self.GetUnsavedFilesVector(),
self.flags.FlagsForFile( filename ) )
def DiagnosticsForCurrentFileReady( self ):
return ( self.possibly_new_diagnostics and not
self.completer.UpdatingTranslationUnit( vim.current.buffer.name ) )
if not self.parse_future:
return False
return self.parse_future.ResultsReady()
def GetDiagnosticsForCurrentFile( self ):
if self.DiagnosticsForCurrentFileReady():
self.last_diagnostics = [ DiagnosticToDict( x ) for x in
self.completer.DiagnosticsForFile(
vim.current.buffer.name ) ]
self.possibly_new_diagnostics = False
self.parse_future = None
return self.last_diagnostics