-
-
Notifications
You must be signed in to change notification settings - Fork 391
Handle LSP Initialize request synchronously #1750
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The LSP spec. has strong restrictions around what messages are allowed in between the Initialize request and response. Handling the message synchronously goes a long way towards satisfying those invariants.
@@ -43,7 +44,12 @@ requestHandler m k = LSP.requestHandler m $ \RequestMessage{_method,_id,_params} | |||
trace x = otTracedHandler "Request" (show _method) $ \sp -> do | |||
traceWithSpan sp _params | |||
x | |||
writeChan chan $ ReactorRequest (SomeLspId _id) (trace $ LSP.runLspT env $ resp' =<< k ide _params) (LSP.runLspT env . resp' . Left) | |||
item = case _method of | |||
SInitialize -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is dead code - handleInit
is the actual initialize request handler. lsp
will never actually call a InitializeRequest
handler defined the regular way since initialize is special. Instead it defines its own handler, into which custom logic can be inserted using doInitialize
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case it sounds like InitializeRequest
is already being handled synchronously, is that right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
I've also been confused by the out of order progress messages and something non-obvious is going on. It might even be a bug in lsp-test.
I did try to investigate the ghcide code path and I couldn't figure out how it was possible for us to send progress messages before the initialize response.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second part seems easy to explain: we call shakeOpen
inside the doInitialize
handler, shakeOpen
will evaluate the rules and call kick
, and kick
may trigger progress reporting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I thought shakeOpen
was only initializing state.
Will this cause progress begin/end messages to be generated, but they won't make it back to the client until after the initialise response returns? If they arrive later, what will happen? What about messages which are allowed during initialise, like logging - are they going to be delayed too? |
Turns out this change won't make any difference, since the It's not obvious to me how to block progress reporting during initialise, since we call |
We already have a flag to say we want testing messages. How about making that a mode. ProgressAlways (testing), ProgressSometimes (normal), ProgressNever (init). |
Maybe that could work, but I'm not sure how all the data dependencies will work out. We already use We need the result of The only way to find out is by prototyping the change both in |
Usually we would use the |
The easiest thing would be to change |
My understanding is the flow is initialize request/response, where we are super limited. Then we get initialized. Why not move all our initialisation to initialized, and just stick with the minimum reporting of capabilities back? Then we wouldn't call the kick or anything. Even if we did do a shakeOpen, I don't see why we need to do a shakeRun inside it, but I'm super unclear about the flow there. |
Right, we could move some of the initialization to the
|
The LSP spec. has strong restrictions around what messages are allowed
in between the Initialize request and response. Handling the message
synchronously goes a long way towards satisfying those invariants.