From b1d71bbb916d591c434eb0c564fabcb6ce7348d8 Mon Sep 17 00:00:00 2001 From: Strahinja Val Markovic Date: Sat, 21 Dec 2013 11:16:50 -0800 Subject: [PATCH] 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 --- python/ycm/client/event_notification.py | 6 ++++++ python/ycm/completers/cpp/flags.py | 8 ++------ python/ycm/extra_conf_store.py | 13 +++---------- python/ycm/server/handlers.py | 7 +++++++ python/ycm/server/responses.py | 12 ++++++++++++ .../ycm/server/tests/get_completions_test.py | 18 +++++++++++++++++- 6 files changed, 47 insertions(+), 17 deletions(-) diff --git a/python/ycm/client/event_notification.py b/python/ycm/client/event_notification.py index 9652413f..9300e174 100644 --- a/python/ycm/client/event_notification.py +++ b/python/ycm/client/event_notification.py @@ -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' ) diff --git a/python/ycm/completers/cpp/flags.py b/python/ycm/completers/cpp/flags.py index cbf72fa6..6c2fee1c 100644 --- a/python/ycm/completers/cpp/flags.py +++ b/python/ycm/completers/cpp/flags.py @@ -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, diff --git a/python/ycm/extra_conf_store.py b/python/ycm/extra_conf_store.py index d49576c4..6267a0db 100644 --- a/python/ycm/extra_conf_store.py +++ b/python/ycm/extra_conf_store.py @@ -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 diff --git a/python/ycm/server/handlers.py b/python/ycm/server/handlers.py index eae41ab6..0319bde9 100644 --- a/python/ycm/server/handlers.py +++ b/python/ycm/server/handlers.py @@ -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' ) diff --git a/python/ycm/server/responses.py b/python/ycm/server/responses.py index f0ca6364..a44adfe7 100644 --- a/python/ycm/server/responses.py +++ b/python/ycm/server/responses.py @@ -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 = { diff --git a/python/ycm/server/tests/get_completions_test.py b/python/ycm/server/tests/get_completions_test.py index 6386cb0e..7762f414 100644 --- a/python/ycm/server/tests/get_completions_test.py +++ b/python/ycm/server/tests/get_completions_test.py @@ -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():