Skip to content

Interleaving textDocument/codeAction and codeAction/resolve with another type of request gives a wrong response #3135

Open
@HaraldKi

Description

@HaraldKi

Platform:

  • emacs/eglot 1.17 (but should be irrelevant, see protocol log)
  • eclipse.jdt.ls 1.35.0-202404090315 (also happens with 1.33.0 and Java 21)
  • Java 22
  • gradle project configured for Java 22

Problem summary with time stamps from the attached log:

  • 19:14:47.479 client sends textDocument/codeAction
  • 19:14:47.647 server responds with textDocument/codeAction
  • user ponders which action to take
  • 19:14:48.479 meanwhile the client sends some other request (textDocument/formatting in the log attached)
  • 19:14:48.515 server answers this request
  • user decides on code action (remove unused variable)
  • 19:14:49.312 client sends codeAction/resolve with the CodeAction copied 1:1 as received above, according to the LSP protocol afaict.
  • 19:14:49.313 server responds codeAction/resolve but not with the action to take, rather it returns exactly the 1:1 copy again to the client
  • 19:14:49.313 client interprets the response as something that needs to be resolve and sends the same resolve request again
  • 19:14:49.313 sends the same response

In the case of Eglot, the last two steps repeat until the stack is full and it terminates with an error.

Additional information:

  • I kept all intermediate request/response logging as is in the attached log in case it is also relevant.
  • The problem only happens if the formatting request has a non-empty result. This makes it easy to switch between wrong and correct results.
  • Whether the code action is within the requested formatting range or before makes no difference.
  • The problem also happens if instead of formatting the client requests semantic tokens

Attached request/response log:
remove-xxx-jrpc-format.log

For reference, here is the code I use in my emacs init file to trigger this easily with F8 using eglot, though I don't see anything eglot-specific in the above sequence of events.

(defun boom (buffer)
  (with-current-buffer buffer 
    (eglot-format nil nil nil) ) )
(defun boom-boom ()
  (interactive)
  (run-with-timer 1 nil (apply-partially 'boom (current-buffer)))
  (call-interactively 'eglot-code-actions)
  )
(define-key eglot-mode-map (kbd "<f8>") 'boom-boom)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions