Skip to content

Commit 77d333a

Browse files
committed
Add support for DocumentSymbol in document outline requests
We are intentionally not advertising the capability. We do want a flat response, so receiving a DocumentSymbol is a pessimisation. Not advertising the capability means that conforming servers take the faster code path and the likes of OmniSharp, that assume capabilities, still work. Yes, it's messy, but so is LSP.
1 parent 1026c83 commit 77d333a

File tree

1 file changed

+47
-3
lines changed

1 file changed

+47
-3
lines changed

ycmd/completers/language_server/language_server_completer.py

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2655,10 +2655,10 @@ def GoToDocumentOutline( self, request_data ):
26552655

26562656
result = response.get( 'result' ) or []
26572657

2658-
# We should only receive SymbolInformation (not DocumentSymbol)
26592658
if any( 'range' in s for s in result ):
2660-
raise ValueError(
2661-
"Invalid server response; DocumentSymbol not supported" )
2659+
LOGGER.debug( 'Hierarchical DocumentSymbol not supported.' )
2660+
result = _FlattenDocumentSymbolHierarchy( result )
2661+
return _DocumentSymboListToGoTo( request_data, result )
26622662

26632663
return _SymbolInfoListToGoTo( request_data, result )
26642664

@@ -3427,6 +3427,50 @@ def BuildGoToLocationFromSymbol( symbol ):
34273427
return locations
34283428

34293429

3430+
def _FlattenDocumentSymbolHierarchy( symbols ):
3431+
result = []
3432+
for s in symbols:
3433+
partial_results = [ s ]
3434+
if s.get( 'children' ):
3435+
partial_results.extend(
3436+
_FlattenDocumentSymbolHierarchy( s[ 'children' ] ) )
3437+
result.extend( partial_results )
3438+
return result
3439+
3440+
3441+
def _DocumentSymboListToGoTo( request_data, symbols ):
3442+
"""Convert a list of LSP DocumentSymbol into a YCM GoTo response"""
3443+
3444+
print(1)
3445+
def BuildGoToLocationFromSymbol( symbol ):
3446+
symbol[ 'uri' ] = lsp.FilePathToUri( request_data[ 'filepath' ] )
3447+
location, line_value = _LspLocationToLocationAndDescription(
3448+
request_data,
3449+
symbol )
3450+
3451+
description = ( f'{ lsp.SYMBOL_KIND[ symbol[ "kind" ] ] }: '
3452+
f'{ symbol[ "name" ] }' )
3453+
3454+
goto = responses.BuildGoToResponseFromLocation( location,
3455+
description )
3456+
goto[ 'extra_data' ] = {
3457+
'kind': lsp.SYMBOL_KIND[ symbol[ 'kind' ] ],
3458+
'name': symbol[ 'name' ],
3459+
}
3460+
return goto
3461+
3462+
locations = [ BuildGoToLocationFromSymbol( s ) for s in
3463+
sorted( symbols,
3464+
key = lambda s: ( s[ 'kind' ], s[ 'name' ] ) ) ]
3465+
3466+
if not locations:
3467+
raise RuntimeError( "Symbol not found" )
3468+
elif len( locations ) == 1:
3469+
return locations[ 0 ]
3470+
else:
3471+
return locations
3472+
3473+
34303474
def _LspLocationToLocationAndDescription( request_data,
34313475
location,
34323476
range_property = 'range' ):

0 commit comments

Comments
 (0)