Skip to content

Commit

Permalink
Account for one of the multiple GoTo handlers throwing an exception
Browse files Browse the repository at this point in the history
The GoTo subcommand might have multiple LSP handlers associated with it.
Mostly, it is `textDocument/definition` and `textDocument/declaration`.

Normally, we cycle through handlers until one of two things happens:

1. The handler returns more than one location.
2. The handler returns a single location, but that doese not contain the
   cursor.

This breaks if any of the handlers throws an exception. When that
happens, we immediately propagate the error, instead of trying the next
handler. However, we can not simply swallow exceptions, because there's
a possibility for all handlers to throw. Or some throws and some return
zero locations.

Current idea:

1. Do not throw as soon as a handler reports zero locations.
2. If the current handler returns more than a single location, replace
   previous result with the current one.
3. If there's more than one location or the single location does not
   contain cursor, break out of the loop - we have valid results.
   Otherwise, move to the next handler.
4. After exiting the handler loop, if the results are falsey, *now*
   throw an exception.
  • Loading branch information
bstaletic committed Jan 14, 2024
1 parent 5926c35 commit 47e3431
Showing 1 changed file with 12 additions and 11 deletions.
23 changes: 12 additions & 11 deletions ycmd/completers/language_server/language_server_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2527,9 +2527,7 @@ def _GoToRequest( self, request_data, handler ):
except ResponseFailedException:
result = None

if not result:
raise RuntimeError( 'Cannot jump to location' )
if not isinstance( result, list ):
if result and not isinstance( result, list ):
return [ result ]
return result

Expand All @@ -2544,15 +2542,18 @@ def GoTo( self, request_data, handlers ):

self._UpdateServerWithFileContents( request_data )

if len( handlers ) == 1:
result = self._GoToRequest( request_data, handlers[ 0 ] )
else:
for handler in handlers:
result = self._GoToRequest( request_data, handler )
if len( result ) > 1 or not _CursorInsideLocation( request_data,
result[ 0 ] ):
break
result = []
for handler in handlers:
new_result = self._GoToRequest( request_data, handler )
if new_result:
result = new_result
if len( result ) > 1 or ( result and
not _CursorInsideLocation( request_data,
result[ 0 ] ) ):
break

if not result:
raise RuntimeError( 'Cannot jump to location' )
return _LocationListToGoTo( request_data, result )


Expand Down

0 comments on commit 47e3431

Please sign in to comment.