Message from
client
+ + +
| | |
| +-----v-----+ |
| | | |
<-------+IdeRequest<----+ Reactor +------->GhcRequest+------->
| | | |
| +-----------+ |
| |
| |
IdeM IdeGhcM +--------+
| +----->IdeResponseDeferred | | |
plugins <--+ | + +---------> |
| | | | | | ghc |
+-------> + | | | mod |
+------->IdeResponse | Triggers<----+ <---------+ |
| + ^ | | | | | |
| | | +---v-------v--+ | | | |
| | | | | + | +--------+
| | +-----------+ RequestQueue | cacheModule<---+
| | | | |
| | +--------------+ |
| | |
| | +----------------------------------------------+
| v v |
| IdeResult |
| + + |
| v | |
| IdeResultFail | |
| v |
| IdeResultOk |
| + |
| v |
| RequestCallback |
v + v
v
Possibly respond to
client if needed
Any notifications, requests or response messages from the client are handled
through the Reactor which lives inside LspStdio.hs. It routes these messages
to call the appropriate plugins by making PluginRequests, and then responds
to the client if needed. PluginRequests come in 2 flavours: IdeRequest
and GhcRequest, which take place on 2 different threads.
The 2 threads are represented by 2 monads: IdeM and IdeGhcM.
IdeM should be used for anything that does not require immediate access
to ghc-mod, since IdeGhcM is used mainly for typechecking modules and is
the most constrained resource.
To get onto the threads, send an IReq or GReq to the dispatcher with
makeRequest inside LspStdio.hs:reactor.
If you are on IdeM and need access to a cached module, consider using an
IdeResponseDeferred. You can provide it with a FilePath to a module you
want, and your callback will be called with the module whenever IdeGhcM
has loaded it.
It is advised that you do not return an IdeResponseDeferred directly though,
and instead use one of the withCachedModule or withCachedModuleAndData
helper functions instead.
An IdeResponse will eventually return an IdeResult at the end of the day,
which will hand back data to the Reactor. IdeGhcM skips the response part
and returns an IdeResult directly since it will never need to be deferred.