Skip to content

Commit

Permalink
Add support for DocumentSymbol in document outline requests
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bstaletic committed Aug 17, 2024
1 parent 1026c83 commit 936a5b6
Showing 1 changed file with 46 additions and 3 deletions.
49 changes: 46 additions & 3 deletions ycmd/completers/language_server/language_server_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2655,10 +2655,10 @@ def GoToDocumentOutline( self, request_data ):

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

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

Check warning on line 2661 in ycmd/completers/language_server/language_server_completer.py

View check run for this annotation

Codecov / codecov/patch

ycmd/completers/language_server/language_server_completer.py#L2659-L2661

Added lines #L2659 - L2661 were not covered by tests

return _SymbolInfoListToGoTo( request_data, result )

Expand Down Expand Up @@ -3427,6 +3427,49 @@ def BuildGoToLocationFromSymbol( symbol ):
return locations


def _FlattenDocumentSymbolHierarchy( symbols ):
result = []
for s in symbols:
partial_results = [ s ]
if s.get( 'children' ):
partial_results.extend(

Check warning on line 3435 in ycmd/completers/language_server/language_server_completer.py

View check run for this annotation

Codecov / codecov/patch

ycmd/completers/language_server/language_server_completer.py#L3431-L3435

Added lines #L3431 - L3435 were not covered by tests
_FlattenDocumentSymbolHierarchy( s[ 'children' ] ) )
result.extend( partial_results )
return result

Check warning on line 3438 in ycmd/completers/language_server/language_server_completer.py

View check run for this annotation

Codecov / codecov/patch

ycmd/completers/language_server/language_server_completer.py#L3437-L3438

Added lines #L3437 - L3438 were not covered by tests


def _DocumentSymboListToGoTo( request_data, symbols ):
"""Convert a list of LSP DocumentSymbol into a YCM GoTo response"""

def BuildGoToLocationFromSymbol( symbol ):
symbol[ 'uri' ] = lsp.FilePathToUri( request_data[ 'filepath' ] )
location, line_value = _LspLocationToLocationAndDescription(

Check warning on line 3446 in ycmd/completers/language_server/language_server_completer.py

View check run for this annotation

Codecov / codecov/patch

ycmd/completers/language_server/language_server_completer.py#L3444-L3446

Added lines #L3444 - L3446 were not covered by tests
request_data,
symbol )

description = ( f'{ lsp.SYMBOL_KIND[ symbol[ "kind" ] ] }: '

Check warning on line 3450 in ycmd/completers/language_server/language_server_completer.py

View check run for this annotation

Codecov / codecov/patch

ycmd/completers/language_server/language_server_completer.py#L3450

Added line #L3450 was not covered by tests
f'{ symbol[ "name" ] }' )

goto = responses.BuildGoToResponseFromLocation( location,

Check warning on line 3453 in ycmd/completers/language_server/language_server_completer.py

View check run for this annotation

Codecov / codecov/patch

ycmd/completers/language_server/language_server_completer.py#L3453

Added line #L3453 was not covered by tests
description )
goto[ 'extra_data' ] = {

Check warning on line 3455 in ycmd/completers/language_server/language_server_completer.py

View check run for this annotation

Codecov / codecov/patch

ycmd/completers/language_server/language_server_completer.py#L3455

Added line #L3455 was not covered by tests
'kind': lsp.SYMBOL_KIND[ symbol[ 'kind' ] ],
'name': symbol[ 'name' ],
}
return goto

Check warning on line 3459 in ycmd/completers/language_server/language_server_completer.py

View check run for this annotation

Codecov / codecov/patch

ycmd/completers/language_server/language_server_completer.py#L3459

Added line #L3459 was not covered by tests

locations = [ BuildGoToLocationFromSymbol( s ) for s in

Check warning on line 3461 in ycmd/completers/language_server/language_server_completer.py

View check run for this annotation

Codecov / codecov/patch

ycmd/completers/language_server/language_server_completer.py#L3461

Added line #L3461 was not covered by tests
sorted( symbols,
key = lambda s: ( s[ 'kind' ], s[ 'name' ] ) ) ]

if not locations:
raise RuntimeError( "Symbol not found" )
elif len( locations ) == 1:
return locations[ 0 ]

Check warning on line 3468 in ycmd/completers/language_server/language_server_completer.py

View check run for this annotation

Codecov / codecov/patch

ycmd/completers/language_server/language_server_completer.py#L3465-L3468

Added lines #L3465 - L3468 were not covered by tests
else:
return locations

Check warning on line 3470 in ycmd/completers/language_server/language_server_completer.py

View check run for this annotation

Codecov / codecov/patch

ycmd/completers/language_server/language_server_completer.py#L3470

Added line #L3470 was not covered by tests


def _LspLocationToLocationAndDescription( request_data,
location,
range_property = 'range' ):
Expand Down

0 comments on commit 936a5b6

Please sign in to comment.