|
| 1 | +# Dispatch architecture |
| 2 | +``` |
| 3 | + Message from |
| 4 | + client |
| 5 | + + + + |
| 6 | + | | | |
| 7 | + | +-----v-----+ | |
| 8 | + | | | | |
| 9 | + <-------+IdeRequest<----+ Reactor +------->GhcRequest+-------> |
| 10 | + | | | | |
| 11 | + | +-----------+ | |
| 12 | + | | |
| 13 | + | | |
| 14 | +IdeM IdeGhcM +--------+ |
| 15 | + | +----->IdeResponseDeferred | | | |
| 16 | + | | + +---------> | |
| 17 | + | | | | | ghc | |
| 18 | + | + | | | mod | |
| 19 | + +------->IdeResponse | Triggers<----+ <---------+ | |
| 20 | + | + ^ | | | | | | |
| 21 | + | | | +---v-------v--+ | | | | |
| 22 | + | | | | | + | +--------+ |
| 23 | + | | +-----------+ RequestQueue | cacheModule<---+ |
| 24 | + | | | | | |
| 25 | + | | +--------------+ | |
| 26 | + | | | |
| 27 | + | | +----------------------------------------------+ |
| 28 | + | v v | |
| 29 | + | IdeResult | |
| 30 | + | + + | |
| 31 | + | v | | |
| 32 | + | IdeResultFail | | |
| 33 | + | v | |
| 34 | + | IdeResultOk | |
| 35 | + | + | |
| 36 | + | v | |
| 37 | + | RequestCallback | |
| 38 | + v + v |
| 39 | + v |
| 40 | + Possibly respond to |
| 41 | + client if needed |
| 42 | +``` |
| 43 | + |
| 44 | +## Reactor |
| 45 | +Any notifications, requests or response messages from the client are handled |
| 46 | +through the `Reactor` which lives inside `LspStdio.hs`. It routes these messages |
| 47 | +to call the appropriate plugins by making `PluginRequest`s, and then responds |
| 48 | +to the client if needed. `PluginRequest`s come in 2 flavours: `IdeRequest` |
| 49 | +and `GhcRequest`, which take place on 2 different threads. |
| 50 | + |
| 51 | +## Threads |
| 52 | +The 2 threads are represented by 2 monads: `IdeM` and `IdeGhcM`. |
| 53 | + |
| 54 | +`IdeM` should be used for anything that does not require immediate access |
| 55 | +to ghc-mod, since `IdeGhcM` is used mainly for typechecking modules and is |
| 56 | +the most constrained resource. |
| 57 | + |
| 58 | +## Responses |
| 59 | +If you are on `IdeM` and need access to a cached module, consider using an |
| 60 | +`IdeResponseDeferred`. You can provide it with a `FilePath` to a module you |
| 61 | +want, and your callback will be called with the module whenever `IdeGhcM` |
| 62 | +has loaded it. |
| 63 | +It is advised that you do not return an `IdeResponseDeferred` directly though, |
| 64 | +and instead use one of the `withCachedModule` or `withCachedModuleAndData` |
| 65 | +helper functions instead. |
| 66 | + |
| 67 | +## Results |
| 68 | +An `IdeResponse` will eventually return an `IdeResult` at the end of the day, |
| 69 | +which will hand back data to the Reactor. `IdeGhcM` skips the response part |
| 70 | +and returns an `IdeResult` directly since it will never need to be deferred. |
0 commit comments