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:
if vimsupport.Confirm( str( e ) ):
_LoadExtraConfFile( e.extra_conf_file )
else:
_IgnoreExtraConfFile( e.extra_conf_file )
except Exception as e:
vimsupport.PostVimMessage( str( e ) )
@ -91,3 +93,7 @@ def SendEventNotificationAsync( event_name, extra_data = None ):
def _LoadExtraConfFile( filepath ):
BaseRequest.PostDataToHandler( { 'filepath': filepath },
'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
from ycm import extra_conf_store
from ycm.utils import ToUtf8IfNeeded
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 )
from ycm.server.responses import NoExtraConfDetected
INCLUDE_FLAGS = [ '-isystem', '-I', '-iquote', '--sysroot=', '-isysroot',
'-include' ]
@ -54,7 +50,7 @@ class Flags( object ):
if not module:
if not self.no_extra_conf_file_warning_posted:
self.no_extra_conf_file_warning_posted = True
raise RuntimeError( NO_EXTRA_CONF_FILENAME_MESSAGE )
raise NoExtraConfDetected
return None
results = _CallExtraConfFlagsForFile( module,

View File

@ -27,11 +27,9 @@ import sys
import logging
from threading import Lock
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
# Constants
YCM_EXTRA_CONF_FILENAME = '.ycm_extra_conf.py'
# Singleton variables
_module_for_module_file = {}
@ -95,7 +93,7 @@ def _CallGlobalExtraConfMethod( function_name ):
getattr( module, function_name )()
def _Disable( module_file ):
def Disable( module_file ):
"""Disables the loading of a module for the current session."""
with _module_for_module_file_lock:
_module_for_module_file[ module_file ] = None
@ -116,11 +114,6 @@ def _ShouldLoad( module_file ):
if _MatchesGlobPattern( module_file, glob.lstrip('!') ):
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 )
@ -139,7 +132,7 @@ def Load( module_file, force = False ):
return _module_for_module_file[ module_file ]
if not _ShouldLoad( module_file ):
_Disable( module_file )
Disable( module_file )
return None
# 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 )
@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' )
def DebugInfo():
LOGGER.info( 'Received debug info request' )

View File

@ -19,9 +19,16 @@
import os
YCM_EXTRA_CONF_FILENAME = '.ycm_extra_conf.py'
CONFIRM_CONF_FILE_MESSAGE = ('Found {0}. Load? \n\n(Question can be turned '
'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 ):
def __init__( self, message ):
super( ServerError, self ).__init__( message )
@ -34,6 +41,11 @@ class UnknownExtraConf( ServerError ):
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 ):
response = {

View File

@ -27,7 +27,8 @@ from webtest import TestApp, AppError
from nose.tools import eq_, with_setup
from hamcrest import ( assert_that, has_item, has_items, has_entry,
contains_inanyorder, empty )
from ..responses import BuildCompletionData, UnknownExtraConf
from ..responses import ( BuildCompletionData, UnknownExtraConf,
NoExtraConfDetected )
from .. import handlers
import bottle
@ -239,6 +240,9 @@ def GetCompletions_ClangCompleter_UnknownExtraConfException_test():
completion_data = BuildRequest( filepath = filepath,
filetype = 'cpp',
contents = open( filepath ).read(),
line_num = 10,
column_num = 6,
start_column = 6,
force_semantic = True )
response = app.post_json( '/completions',
@ -250,6 +254,18 @@ def GetCompletions_ClangCompleter_UnknownExtraConfException_test():
has_entry( 'exception',
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 )
def GetCompletions_ClangCompleter_WorksWhenExtraConfExplicitlyAllowed_test():