Better handling of unknown extra conf files

Previously, we'd implicitly turn off future notices about unknown extra conf
files if we already raised one exception about it. This breaks when the user
ends up not receiving the "unknown extra conf, load?" message.

Now we only turn off the notice as a result of the user saying "don't load this"
so that if the first request fails to reach them, they'll get a second (and
third etc) request about it.

Fixes #615
This commit is contained in:
Strahinja Val Markovic 2013-12-21 11:16:50 -08:00
parent 1edf22357f
commit b1d71bbb91
6 changed files with 47 additions and 17 deletions

View File

@ -58,6 +58,8 @@ class EventNotification( BaseRequest ):
except UnknownExtraConf as e: except UnknownExtraConf as e:
if vimsupport.Confirm( str( e ) ): if vimsupport.Confirm( str( e ) ):
_LoadExtraConfFile( e.extra_conf_file ) _LoadExtraConfFile( e.extra_conf_file )
else:
_IgnoreExtraConfFile( e.extra_conf_file )
except Exception as e: except Exception as e:
vimsupport.PostVimMessage( str( e ) ) vimsupport.PostVimMessage( str( e ) )
@ -91,3 +93,7 @@ def SendEventNotificationAsync( event_name, extra_data = None ):
def _LoadExtraConfFile( filepath ): def _LoadExtraConfFile( filepath ):
BaseRequest.PostDataToHandler( { 'filepath': filepath }, BaseRequest.PostDataToHandler( { 'filepath': filepath },
'load_extra_conf_file' ) 'load_extra_conf_file' )
def _IgnoreExtraConfFile( filepath ):
BaseRequest.PostDataToHandler( { 'filepath': filepath },
'ignore_extra_conf_file' )

View File

@ -22,11 +22,7 @@ import os
import inspect import inspect
from ycm import extra_conf_store from ycm import extra_conf_store
from ycm.utils import ToUtf8IfNeeded from ycm.utils import ToUtf8IfNeeded
from ycm.server.responses import NoExtraConfDetected
NO_EXTRA_CONF_FILENAME_MESSAGE = ( 'No {0} file detected, so no compile flags '
'are available. Thus no semantic support for C/C++/ObjC/ObjC++. Go READ THE '
'DOCS *NOW*, DON\'T file a bug report.' ).format(
extra_conf_store.YCM_EXTRA_CONF_FILENAME )
INCLUDE_FLAGS = [ '-isystem', '-I', '-iquote', '--sysroot=', '-isysroot', INCLUDE_FLAGS = [ '-isystem', '-I', '-iquote', '--sysroot=', '-isysroot',
'-include' ] '-include' ]
@ -54,7 +50,7 @@ class Flags( object ):
if not module: if not module:
if not self.no_extra_conf_file_warning_posted: if not self.no_extra_conf_file_warning_posted:
self.no_extra_conf_file_warning_posted = True self.no_extra_conf_file_warning_posted = True
raise RuntimeError( NO_EXTRA_CONF_FILENAME_MESSAGE ) raise NoExtraConfDetected
return None return None
results = _CallExtraConfFlagsForFile( module, results = _CallExtraConfFlagsForFile( module,

View File

@ -27,11 +27,9 @@ import sys
import logging import logging
from threading import Lock from threading import Lock
from ycm import user_options_store from ycm import user_options_store
from ycm.server.responses import UnknownExtraConf from ycm.server.responses import UnknownExtraConf, YCM_EXTRA_CONF_FILENAME
from fnmatch import fnmatch from fnmatch import fnmatch
# Constants
YCM_EXTRA_CONF_FILENAME = '.ycm_extra_conf.py'
# Singleton variables # Singleton variables
_module_for_module_file = {} _module_for_module_file = {}
@ -95,7 +93,7 @@ def _CallGlobalExtraConfMethod( function_name ):
getattr( module, function_name )() getattr( module, function_name )()
def _Disable( module_file ): def Disable( module_file ):
"""Disables the loading of a module for the current session.""" """Disables the loading of a module for the current session."""
with _module_for_module_file_lock: with _module_for_module_file_lock:
_module_for_module_file[ module_file ] = None _module_for_module_file[ module_file ] = None
@ -116,11 +114,6 @@ def _ShouldLoad( module_file ):
if _MatchesGlobPattern( module_file, glob.lstrip('!') ): if _MatchesGlobPattern( module_file, glob.lstrip('!') ):
return not is_blacklisted return not is_blacklisted
# We disable the file if it's unknown so that we don't ask the user about it
# repeatedly. Raising UnknownExtraConf should result in the client sending
# another request to load the module file if the user explicitly chooses to do
# that.
_Disable( module_file )
raise UnknownExtraConf( module_file ) raise UnknownExtraConf( module_file )
@ -139,7 +132,7 @@ def Load( module_file, force = False ):
return _module_for_module_file[ module_file ] return _module_for_module_file[ module_file ]
if not _ShouldLoad( module_file ): if not _ShouldLoad( module_file ):
_Disable( module_file ) Disable( module_file )
return None return None
# This has to be here because a long time ago, the ycm_extra_conf.py files # This has to be here because a long time ago, the ycm_extra_conf.py files

View File

@ -146,6 +146,13 @@ def LoadExtraConfFile():
extra_conf_store.Load( request_data[ 'filepath' ], force = True ) extra_conf_store.Load( request_data[ 'filepath' ], force = True )
@app.post( '/ignore_extra_conf_file' )
def IgnoreExtraConfFile():
LOGGER.info( 'Received extra conf ignore request' )
request_data = request.json
extra_conf_store.Disable( request_data[ 'filepath' ] )
@app.post( '/debug_info' ) @app.post( '/debug_info' )
def DebugInfo(): def DebugInfo():
LOGGER.info( 'Received debug info request' ) LOGGER.info( 'Received debug info request' )

View File

@ -19,9 +19,16 @@
import os import os
YCM_EXTRA_CONF_FILENAME = '.ycm_extra_conf.py'
CONFIRM_CONF_FILE_MESSAGE = ('Found {0}. Load? \n\n(Question can be turned ' CONFIRM_CONF_FILE_MESSAGE = ('Found {0}. Load? \n\n(Question can be turned '
'off with options, see YCM docs)') 'off with options, see YCM docs)')
NO_EXTRA_CONF_FILENAME_MESSAGE = ( 'No {0} file detected, so no compile flags '
'are available. Thus no semantic support for C/C++/ObjC/ObjC++. Go READ THE '
'DOCS *NOW*, DON\'T file a bug report.' ).format( YCM_EXTRA_CONF_FILENAME )
class ServerError( Exception ): class ServerError( Exception ):
def __init__( self, message ): def __init__( self, message ):
super( ServerError, self ).__init__( message ) super( ServerError, self ).__init__( message )
@ -34,6 +41,11 @@ class UnknownExtraConf( ServerError ):
self.extra_conf_file = extra_conf_file self.extra_conf_file = extra_conf_file
class NoExtraConfDetected( ServerError ):
def __init__( self ):
super( NoExtraConfDetected, self ).__init__(
NO_EXTRA_CONF_FILENAME_MESSAGE )
def BuildGoToResponse( filepath, line_num, column_num, description = None ): def BuildGoToResponse( filepath, line_num, column_num, description = None ):
response = { response = {

View File

@ -27,7 +27,8 @@ from webtest import TestApp, AppError
from nose.tools import eq_, with_setup from nose.tools import eq_, with_setup
from hamcrest import ( assert_that, has_item, has_items, has_entry, from hamcrest import ( assert_that, has_item, has_items, has_entry,
contains_inanyorder, empty ) contains_inanyorder, empty )
from ..responses import BuildCompletionData, UnknownExtraConf from ..responses import ( BuildCompletionData, UnknownExtraConf,
NoExtraConfDetected )
from .. import handlers from .. import handlers
import bottle import bottle
@ -239,6 +240,9 @@ def GetCompletions_ClangCompleter_UnknownExtraConfException_test():
completion_data = BuildRequest( filepath = filepath, completion_data = BuildRequest( filepath = filepath,
filetype = 'cpp', filetype = 'cpp',
contents = open( filepath ).read(), contents = open( filepath ).read(),
line_num = 10,
column_num = 6,
start_column = 6,
force_semantic = True ) force_semantic = True )
response = app.post_json( '/completions', response = app.post_json( '/completions',
@ -250,6 +254,18 @@ def GetCompletions_ClangCompleter_UnknownExtraConfException_test():
has_entry( 'exception', has_entry( 'exception',
has_entry( 'TYPE', UnknownExtraConf.__name__ ) ) ) has_entry( 'TYPE', UnknownExtraConf.__name__ ) ) )
app.post_json( '/ignore_extra_conf_file',
{ 'filepath': PathToTestFile( '.ycm_extra_conf.py' ) } )
response = app.post_json( '/completions',
completion_data,
expect_errors = True )
eq_( response.status_code, httplib.INTERNAL_SERVER_ERROR )
assert_that( response.json,
has_entry( 'exception',
has_entry( 'TYPE', NoExtraConfDetected.__name__ ) ) )
@with_setup( Setup ) @with_setup( Setup )
def GetCompletions_ClangCompleter_WorksWhenExtraConfExplicitlyAllowed_test(): def GetCompletions_ClangCompleter_WorksWhenExtraConfExplicitlyAllowed_test():