Skip to content

Commit f0bee22

Browse files
committed
Preliminary type/call hierarchy support
1 parent 03b2c82 commit f0bee22

File tree

3 files changed

+107
-6
lines changed

3 files changed

+107
-6
lines changed

ycmd/__main__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,8 @@ def Main():
194194
args.stderr,
195195
args.keep_logfiles )
196196
atexit.register( handlers.ServerCleanup )
197+
from bottle import TemplatePlugin
198+
handlers.app.uninstall(TemplatePlugin)
197199
handlers.app.install( WatchdogPlugin( args.idle_suicide_seconds,
198200
args.check_interval_seconds ) )
199201
handlers.app.install( HmacPlugin( hmac_secret ) )

ycmd/completers/language_server/language_server_completer.py

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1785,6 +1785,18 @@ def GetSubcommandsMap( self ):
17851785
lambda self, request_data, args: self.GetType( request_data )
17861786
)
17871787

1788+
if ( self._server_capabilities and
1789+
_IsCapabilityProvided( self._server_capabilities,
1790+
'typeHierarchyProvider' ) ):
1791+
commands[ 'TypeHierarchy' ] = (
1792+
lambda self, request_data, args:
1793+
self.InitialHierarchy( request_data, [ 'type' ] )
1794+
)
1795+
commands[ 'ResolveTypeHierarchyItem' ] = (
1796+
lambda self, request_data, args:
1797+
self.Hierarchy( request_data, [ *args, 'type' ] )
1798+
)
1799+
17881800
if ( self._server_capabilities and
17891801
_IsCapabilityProvided( self._server_capabilities,
17901802
'callHierarchyProvider' ) ):
@@ -1796,6 +1808,14 @@ def GetSubcommandsMap( self ):
17961808
lambda self, request_data, args:
17971809
self.CallHierarchy( request_data, [ 'incoming' ] )
17981810
)
1811+
commands[ 'CallHierarchy' ] = (
1812+
lambda self, request_data, args:
1813+
self.InitialHierarchy( request_data, [ 'call' ] )
1814+
)
1815+
commands[ 'ResolveCallHierarchyItem' ] = (
1816+
lambda self, request_data, args:
1817+
self.Hierarchy( request_data, [ *args, 'call' ] )
1818+
)
17991819

18001820
commands.update( self.GetCustomSubcommands() )
18011821

@@ -2643,14 +2663,90 @@ def GoToDocumentOutline( self, request_data ):
26432663
return _SymbolInfoListToGoTo( request_data, result )
26442664

26452665

2666+
def InitialHierarchy( self, request_data, args ):
2667+
if not self.ServerIsReady():
2668+
raise RuntimeError( 'Server is initializing. Please wait.' )
2669+
2670+
kind = args[ 0 ]
2671+
2672+
self._UpdateServerWithFileContents( request_data )
2673+
request_id = self.GetConnection().NextRequestId()
2674+
message = lsp.PrepareHierarchy( request_id, request_data, kind.title() )
2675+
prepare_response = self.GetConnection().GetResponse(
2676+
request_id,
2677+
message,
2678+
REQUEST_TIMEOUT_COMMAND )
2679+
preparation_item = prepare_response.get( 'result' ) or []
2680+
if not preparation_item:
2681+
raise RuntimeError( f'No { kind } hierarchy found.' )
2682+
2683+
assert len( preparation_item ) == 1, (
2684+
'Not available: Multiple hierarchies were received, '
2685+
'this is not currently supported.' )
2686+
2687+
preparation_item[ 0 ][ 'locations' ] = [
2688+
responses.BuildGoToResponseFromLocation(
2689+
*_LspLocationToLocationAndDescription( request_data, location ) )
2690+
for location in preparation_item ]
2691+
preparation_item[ 0 ][ 'kind' ] = lsp.SYMBOL_KIND[ preparation_item[ 0 ][ 'kind' ] ]
2692+
return preparation_item
2693+
2694+
2695+
def Hierarchy( self, request_data, args ):
2696+
if not self.ServerIsReady():
2697+
raise RuntimeError( 'Server is initializing. Please wait.' )
2698+
2699+
preparation_item, direction, kind = args
2700+
2701+
# Remove ycmd things
2702+
if 'fromRanges' in preparation_item:
2703+
name_and_kind_key = 'to' if direction == 'outgoing' else 'from'
2704+
preparation_item = preparation_item[ name_and_kind_key ]
2705+
else:
2706+
del preparation_item[ 'locations' ]
2707+
preparation_item[ 'kind' ] = lsp.SYMBOL_KIND.index( preparation_item[ 'kind' ] )
2708+
2709+
if kind == 'call':
2710+
direction += 'Calls'
2711+
self._UpdateServerWithFileContents( request_data )
2712+
request_id = self.GetConnection().NextRequestId()
2713+
message = lsp.Hierarchy( request_id, kind, direction, preparation_item )
2714+
response = self.GetConnection().GetResponse( request_id,
2715+
message,
2716+
REQUEST_TIMEOUT_COMMAND )
2717+
2718+
result = response.get( 'result' )
2719+
if result:
2720+
for item in result:
2721+
if kind == 'call':
2722+
name_and_kind_key = 'to' if direction == 'outgoing' else 'from'
2723+
item[ 'kind' ] = lsp.SYMBOL_KIND[ item[ name_and_kind_key ][ 'kind' ] ]
2724+
item[ 'name' ] = item[ name_and_kind_key ][ 'name' ]
2725+
lsp_locations = [ {
2726+
'uri': item[ name_and_kind_key ][ 'uri' ],
2727+
'range': r }
2728+
for r in item[ 'fromRanges' ] ]
2729+
item[ 'locations' ] = [
2730+
responses.BuildGoToResponseFromLocation(
2731+
*_LspLocationToLocationAndDescription( request_data, location ) )
2732+
for location in lsp_locations ]
2733+
else:
2734+
item[ 'kind' ] = lsp.SYMBOL_KIND[ item[ 'kind' ] ]
2735+
item[ 'locations' ] = [
2736+
responses.BuildGoToResponseFromLocation(
2737+
*_LspLocationToLocationAndDescription( request_data, location ) )
2738+
for location in [ item ] ]
2739+
return result
2740+
raise RuntimeError( f'No { direction } { kind } found.' )
2741+
26462742

26472743
def CallHierarchy( self, request_data, args ):
26482744
if not self.ServerIsReady():
26492745
raise RuntimeError( 'Server is initializing. Please wait.' )
26502746

26512747
self._UpdateServerWithFileContents( request_data )
26522748
request_id = self.GetConnection().NextRequestId()
2653-
message = lsp.PrepareCallHierarchy( request_id, request_data )
2749+
message = lsp.PrepareHierarchy( request_id, request_data, 'Call' )
26542750
prepare_response = self.GetConnection().GetResponse(
26552751
request_id,
26562752
message,
@@ -2666,7 +2762,10 @@ def CallHierarchy( self, request_data, args ):
26662762
preparation_item = preparation_item[ 0 ]
26672763

26682764
request_id = self.GetConnection().NextRequestId()
2669-
message = lsp.CallHierarchy( request_id, args[ 0 ], preparation_item )
2765+
message = lsp.Hierarchy( request_id,
2766+
'call',
2767+
args[ 0 ] + 'Calls',
2768+
preparation_item )
26702769
response = self.GetConnection().GetResponse( request_id,
26712770
message,
26722771
REQUEST_TIMEOUT_COMMAND )

ycmd/completers/language_server/language_server_protocol.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -633,8 +633,8 @@ def Position( line_num, line_value, column_codepoint ):
633633
}
634634

635635

636-
def PrepareCallHierarchy( request_id, request_data ):
637-
return BuildRequest( request_id, 'textDocument/prepareCallHierarchy', {
636+
def PrepareHierarchy( request_id, request_data, kind ):
637+
return BuildRequest( request_id, f'textDocument/prepare{ kind }Hierarchy', {
638638
'textDocument': {
639639
'uri': FilePathToUri( request_data[ 'filepath' ] ),
640640
},
@@ -644,8 +644,8 @@ def PrepareCallHierarchy( request_id, request_data ):
644644
} )
645645

646646

647-
def CallHierarchy( request_id, direction, item ):
648-
return BuildRequest( request_id, f'callHierarchy/{ direction }Calls', {
647+
def Hierarchy( request_id, kind, direction, item ):
648+
return BuildRequest( request_id, f'{ kind }Hierarchy/{ direction }', {
649649
'item': item
650650
} )
651651

0 commit comments

Comments
 (0)