Skip to content

Commit

Permalink
WIP: Allow capabilities to be set to enable snippets only where needed
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben Jackson committed Jan 10, 2020
1 parent 5289137 commit dc4b5d9
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 11 deletions.
17 changes: 12 additions & 5 deletions ycmd/completers/language_server/language_server_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1283,12 +1283,18 @@ def GetSettings( self, module, request_data ):


def _GetSettingsFromExtraConf( self, request_data ):
self._settings = self.DefaultSettings( request_data )
ls = self.DefaultSettings( request_data )
# In case no module is found
self._settings = {
'ls': ls
}

module = extra_conf_store.ModuleForSourceFile( request_data[ 'filepath' ] )
if module:
settings = self.GetSettings( module, request_data )
self._settings.update( settings.get( 'ls', {} ) )
self._settings = self.GetSettings( module, request_data )
ls.update( self._settings.get( 'ls', {} ) )
self._settings[ 'ls' ] = ls

# Only return the dir if it was found in the paths; we don't want to use
# the path of the global extra conf as a project root dir.
if not extra_conf_store.IsGlobalExtraConfModule( module ):
Expand Down Expand Up @@ -1706,7 +1712,8 @@ def _SendInitialize( self, request_data, extra_conf_dir ):
# clear how/where that is specified.
msg = lsp.Initialize( request_id,
self._project_directory,
self._settings )
self._settings.get( 'ls', {} ),
self._settings.get( 'capabilities', {} ) )

def response_handler( response, message ):
if message is None:
Expand Down Expand Up @@ -1819,7 +1826,7 @@ def _HandleInitializeInPollThread( self, response ):
# configuration should be send in response to a workspace/configuration
# request?
self.GetConnection().SendNotification(
lsp.DidChangeConfiguration( self._settings ) )
lsp.DidChangeConfiguration( self._settings.get( 'ls', {} ) ) )

# Notify the other threads that we have completed the initialize exchange.
self._initialize_response = None
Expand Down
17 changes: 12 additions & 5 deletions ycmd/completers/language_server/language_server_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
unquote,
url2pathname,
urlparse,
urljoin )
urljoin,
UpdateDict )


Error = collections.namedtuple( 'RequestError', [ 'code', 'reason' ] )
Expand Down Expand Up @@ -233,16 +234,22 @@ def BuildResponse( request, parameters ):
return _BuildMessageData( message )


def Initialize( request_id, project_directory, settings ):
def Initialize( request_id,
project_directory,
settings,
capabilities ):
"""Build the Language Server initialize request"""

return BuildRequest( request_id, 'initialize', {
'processId': os.getpid(),
'rootPath': project_directory,
'rootUri': FilePathToUri( project_directory ),
'initializationOptions': settings,
'capabilities': {
'workspace': { 'applyEdit': True, 'documentChanges': True },
'capabilities': UpdateDict( {
'workspace': {
'applyEdit': True,
'documentChanges': True,
},
'textDocument': {
'codeAction': {
'codeActionLiteralSupport': {
Expand Down Expand Up @@ -288,7 +295,7 @@ def Initialize( request_id, project_directory, settings ):
},
},
},
},
}, capabilities ),
} )


Expand Down
50 changes: 49 additions & 1 deletion ycmd/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@
# Not installing aliases from python-future; it's unreliable and slow.
from builtins import * # noqa

from future.utils import PY2, native
try:
import collections.abc as collections_abc
except ImportError:
import collections as collections_abc

from future.utils import PY2, native, iteritems
import copy
import json
import logging
Expand Down Expand Up @@ -673,3 +678,46 @@ def GetClangResourceDir():


CLANG_RESOURCE_DIR = GetClangResourceDir()


def UpdateDict( target, override ):
"""Apply the updates in |override| to the dict |target|. This is like
dict.update, but recursive. i.e. if the existing element is a dict, then
override elements of the sub-dict rather than wholesale replacing.
e.g.
UpdateDict(
{
'outer': { 'inner': { 'key': 'oldValue', 'existingKey': True } }
},
{
'outer': { 'inner': { 'key': 'newValue' } },
'newKey': { 'newDict': True },
}
)
yields:
{
outer: {
inner: {
key: 'newValue',
exitingKey: True
}
},
newKey: { newDict: True }
}
"""

for key, value in iteritems( override ):
current_value = target.get( key )
if not isinstance( current_value, collections_abc.Mapping ):
target[ key ] = value
elif isinstance( value, collections_abc.Mapping ):
target[ key ] = UpdateDict( current_value, value )
else:
target[ key ] = value

return target

0 comments on commit dc4b5d9

Please sign in to comment.