Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move subcommands logic to Completer class #264

Merged
merged 3 commits into from
Nov 29, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions ycmd/completers/completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,10 @@ class Completer( object ):
command :YcmCompleter and is passed all extra arguments used on command
invocation (e.g. OnUserCommand(['first argument', 'second'])). This can be
used for completer-specific commands such as reloading external configuration.
When the command is called with no arguments you should print a short summary
of the supported commands or point the user to the help section where this
information can be found.
Do not override this function. Instead, you need to implement the
GetSubcommandsMap method. It should return a map between the user commands
and the methods of your completer. See the documentation of this method for
more informations on how to implement it.

Override the Shutdown() member function if your Completer subclass needs to do
custom cleanup logic on server shutdown."""
Expand Down Expand Up @@ -190,7 +191,19 @@ def ComputeCandidatesInner( self, request_data ):


def DefinedSubcommands( self ):
return []
return sorted( self.GetSubcommandsMap().keys() )


def GetSubcommandsMap( self ):
"""This method should return a dictionary where each key represents the
completer command name and its value is a lambda function of this form:

( self, request_data ) -> method

where "method" is the call to the completer method with corresponding
parameters. See the already implemented completers for examples.
"""
return {}


def UserCommandsHelpMessage( self ):
Expand Down Expand Up @@ -242,7 +255,17 @@ def OnInsertLeave( self, request_data ):


def OnUserCommand( self, arguments, request_data ):
raise NotImplementedError( NO_USER_COMMANDS )
if not arguments:
raise ValueError( self.UserCommandsHelpMessage() )

command_map = self.GetSubcommandsMap()

try:
command = command_map[ arguments[ 0 ] ]
except KeyError:
raise ValueError( self.UserCommandsHelpMessage() )

return command( self, request_data )


def OnCurrentIdentifierFinished( self, request_data ):
Expand Down
123 changes: 33 additions & 90 deletions ycmd/completers/cpp/clang_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,96 +106,39 @@ def ComputeCandidatesInner( self, request_data ):
return [ ConvertCompletionData( x ) for x in results ]


def DefinedSubcommands( self ):
return [ 'GoToDefinition',
'GoToDeclaration',
'GoTo',
'GoToImprecise',
'GoToInclude',
'ClearCompilationFlagCache',
'GetType',
'GetParent',
'FixIt',
'GetDoc',
'GetDocQuick' ]


def OnUserCommand( self, arguments, request_data ):
if not arguments:
raise ValueError( self.UserCommandsHelpMessage() )

# command_map maps: command -> { method, args }
#
# where:
# "command" is the completer command entered by the user
# (e.g. GoToDefinition)
# "method" is a method to call for that command
# (e.g. self._GoToDefinition)
# "args" is a dictionary of
# "method_argument" : "value" ...
# which defines the kwargs (via the ** double splat)
# when calling "method"
command_map = {
'GoToDefinition' : {
'method' : self._GoToDefinition,
'args' : { 'request_data' : request_data }
},
'GoToDeclaration' : {
'method' : self._GoToDeclaration,
'args' : { 'request_data' : request_data }
},
'GoTo' : {
'method' : self._GoTo,
'args' : { 'request_data' : request_data }
},
'GoToImprecise' : {
'method' : self._GoToImprecise,
'args' : { 'request_data' : request_data }
},
'GoToInclude' : {
'method' : self._GoToInclude,
'args' : { 'request_data' : request_data }
},
'ClearCompilationFlagCache' : {
'method' : self._ClearCompilationFlagCache,
'args' : { }
},
'GetType' : {
'method' : self._GetSemanticInfo,
'args' : { 'request_data' : request_data,
'func' : 'GetTypeAtLocation' }
},
'GetParent' : {
'method' : self._GetSemanticInfo,
'args' : { 'request_data' : request_data,
'func' : 'GetEnclosingFunctionAtLocation' }
},
'FixIt' : {
'method' : self._FixIt,
'args' : { 'request_data' : request_data }
},
'GetDoc' : {
'method' : self._GetSemanticInfo,
'args' : { 'request_data' : request_data,
'reparse' : True,
'func' : 'GetDocsForLocationInFile',
'response_buider' : _BuildGetDocResponse, }
},
'GetDocQuick' : {
'method' : self._GetSemanticInfo,
'args' : { 'request_data' : request_data,
'reparse' : False,
'func' : 'GetDocsForLocationInFile',
'response_buider' : _BuildGetDocResponse, }
},
def GetSubcommandsMap( self ):
return {
'GoToDefinition' : ( lambda self, request_data:
self._GoToDefinition( request_data ) ),
'GoToDeclaration' : ( lambda self, request_data:
self._GoToDeclaration( request_data ) ),
'GoTo' : ( lambda self, request_data:
self._GoTo( request_data ) ),
'GoToImprecise' : ( lambda self, request_data:
self._GoToImprecise( request_data ) ),
'GoToInclude' : ( lambda self, request_data:
self._GoToInclude( request_data ) ),
'ClearCompilationFlagCache': ( lambda self, request_data:
self._ClearCompilationFlagCache() ),
'GetType' : ( lambda self, request_data:
self._GetSemanticInfo( request_data, func = 'GetTypeAtLocation' ) ),
'GetParent' : ( lambda self, request_data:
self._GetSemanticInfo( request_data,
func = 'GetEnclosingFunctionAtLocation' ) ),
'FixIt' : ( lambda self, request_data:
self._FixIt( request_data ) ),
'GetDoc' : ( lambda self, request_data:
self._GetSemanticInfo( request_data,
reparse = True,
func = 'GetDocsForLocationInFile',
response_builder = _BuildGetDocResponse ) ),
'GetDocQuick' : ( lambda self, request_data:
self._GetSemanticInfo( request_data,
reparse = False,
func = 'GetDocsForLocationInFile',
response_builder = _BuildGetDocResponse ) ),
}

try:
command_def = command_map[ arguments[ 0 ] ]
except KeyError:
raise ValueError( self.UserCommandsHelpMessage() )

return command_def[ 'method' ]( **( command_def[ 'args' ] ) )

def _LocationForGoTo( self, goto_function, request_data, reparse = True ):
filename = request_data[ 'filepath' ]
Expand Down Expand Up @@ -302,7 +245,7 @@ def _GoToInclude( self, request_data ):
def _GetSemanticInfo( self,
request_data,
func,
response_buider = responses.BuildDisplayMessageResponse,
response_builder = responses.BuildDisplayMessageResponse,
reparse = True ):
filename = request_data[ 'filepath' ]
if not filename:
Expand All @@ -327,7 +270,7 @@ def _GetSemanticInfo( self,
if not message:
message = "No semantic information available"

return response_buider( message )
return response_builder( message )

def _ClearCompilationFlagCache( self ):
self._flags.Clear()
Expand Down
124 changes: 73 additions & 51 deletions ycmd/completers/cs/cs_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,79 @@ def FilterAndSortCandidates( self, candidates, query ):
return result


def DefinedSubcommands( self ):
return CsharpSolutionCompleter.subcommands.keys()
def GetSubcommandsMap( self ):
return {
'StartServer' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_StartServer',
no_request_data = True ) ),
'StopServer' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_StopServer',
no_request_data = True ) ),
'RestartServer' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_RestartServer',
no_request_data = True ) ),
'ReloadSolution' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_ReloadSolution',
no_request_data = True ) ),
'SolutionFile' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_SolutionFile',
no_request_data = True ) ),
'GoToDefinition' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_GoToDefinition' ) ),
'GoToDeclaration' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_GoToDefinition' ) ),
'GoTo' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_GoToImplementation',
fallback_to_declaration = True ) ),
'GoToDefinitionElseDeclaration' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_GoToDefinition' ) ),
'GoToImplementation' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_GoToImplementation',
fallback_to_declaration = False ) ),
'GoToImplementationElseDeclaration': ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_GoToImplementation',
fallback_to_declaration = True ) ),
'GetType' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_GetType' ) ),
'FixIt' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_FixIt' ) ),
'GetDoc' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = '_GetDoc' ) ),
'ServerRunning' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = 'ServerIsRunning',
no_request_data = True ) ),
'ServerReady' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = 'ServerIsReady',
no_request_data = True ) ),
'ServerTerminated' : ( lambda self, request_data:
self._SolutionSubcommand( request_data,
method = 'ServerTerminated',
no_request_data = True ) )
}


def _SolutionSubcommand( self, request_data, method,
no_request_data = False, **kwargs ):
solutioncompleter = self._GetSolutionCompleter( request_data )
if not no_request_data:
kwargs[ 'request_data' ] = request_data
return getattr( solutioncompleter, method )( **kwargs )


def OnFileReadyToParse( self, request_data ):
Expand Down Expand Up @@ -210,18 +281,6 @@ def GetDetailedDiagnostic( self, request_data ):
closest_diagnostic.text_ )


def OnUserCommand( self, arguments, request_data ):
if not arguments:
raise ValueError( self.UserCommandsHelpMessage() )

command = arguments[ 0 ]
if command in CsharpSolutionCompleter.subcommands:
solutioncompleter = self._GetSolutionCompleter( request_data )
return solutioncompleter.Subcommand( command, arguments, request_data )
else:
raise ValueError( self.UserCommandsHelpMessage() )


def DebugInfo( self, request_data ):
solutioncompleter = self._GetSolutionCompleter( request_data )
if solutioncompleter.ServerIsRunning():
Expand Down Expand Up @@ -275,34 +334,6 @@ def _GetSolutionFile( self, filepath ):


class CsharpSolutionCompleter:
subcommands = {
'StartServer': ( lambda self, request_data: self._StartServer() ),
'StopServer': ( lambda self, request_data: self._StopServer() ),
'RestartServer': ( lambda self, request_data: self._RestartServer() ),
'ReloadSolution': ( lambda self, request_data: self._ReloadSolution() ),
'SolutionFile': ( lambda self, request_data: self._SolutionFile() ),
'GoToDefinition': ( lambda self, request_data: self._GoToDefinition(
request_data ) ),
'GoToDeclaration': ( lambda self, request_data: self._GoToDefinition(
request_data ) ),
'GoTo': ( lambda self, request_data: self._GoToImplementation(
request_data, True ) ),
'GoToDefinitionElseDeclaration': ( lambda self, request_data:
self._GoToDefinition( request_data ) ),
'GoToImplementation': ( lambda self, request_data:
self._GoToImplementation( request_data, False ) ),
'GoToImplementationElseDeclaration': ( lambda self, request_data:
self._GoToImplementation( request_data, True ) ),
'GetType': ( lambda self, request_data: self._GetType(
request_data ) ),
'FixIt': ( lambda self, request_data: self._FixIt( request_data ) ),
'GetDoc': ( lambda self, request_data: self._GetDoc( request_data ) ),
'ServerRunning': ( lambda self, request_data: self.ServerIsRunning() ),
'ServerReady': ( lambda self, request_data: self.ServerIsReady() ),
'ServerTerminated': ( lambda self, request_data: self.ServerTerminated() ),
}


def __init__( self, solution_path, keep_logfiles, desired_omnisharp_port ):
self._logger = logging.getLogger( __name__ )
self._solution_path = solution_path
Expand All @@ -314,15 +345,6 @@ def __init__( self, solution_path, keep_logfiles, desired_omnisharp_port ):
self._desired_omnisharp_port = desired_omnisharp_port;


def Subcommand( self, command, arguments, request_data ):
command_lamba = CsharpSolutionCompleter.subcommands[ command ]
return command_lamba( self, request_data )


def DefinedSubcommands( self ):
return CsharpSolutionCompleter.subcommands.keys()


def CodeCheck( self, request_data ):
filename = request_data[ 'filepath' ]
if not filename:
Expand Down
Loading