Prefer to Using LSP Configurations
Though tinymist doesn't refuse to keep state in your disk, it actually doesn't have any data to write to disk yet. All customized behaviors (user settings) are passed to the server by LSP configurations. This is a good practice to keep the server state clean and simple.
Handling Compiler Input Events
The compilation triggers many side effects, but the behavior of compiler actor is still easy to predicate. This is achieved by accepting all compile inputs by events.
Let us take reading files from physical file system as example of processing compile inputs, as shown in FigureĀ 1. The upper access models take precedence over the lower access models. The memory access model is updated sequentially by LspActor
receiving source change notifications, assigned with logical ticks
. The notify access model is also updated in same way by NotifyActor
. When there is an absent access, the system access model initiates the request for the file system directly. The read contents from fs are assigned with logical access time
.
The problem is to ensure that the compiler can read the content correctly from access models at the time.
If there is an only active input source in a small time window, we can know the problem is solved, as the logical ticks
and
keep increasing, enforced by actors. For example, if there is only LspActor
active at the small time window, the memory access model receives the source changes in the order of
, i.e. the sequential order of receiving notifications. The cases of two rest access models is more complicated, but are also ensured that compiler reads content in order of
.
Otherwise, the two input sources are both active in a small time window on a same file. However, this indicates that, the file is in already the memory access model at most time. Since the precedence, the compiler reads content in order of at the time.
The only bad case can happen is that: When the two input sources are both active in a small time window on a same file:
- first
LspActor
removes the file from the memory access model, then compiler doesn't read content from file system in time . - first
NotifyActor
inserts the file from the inotify thread, then the LSP client (editor) overlays an older content in time .
This is handled by tinymist by some tricks.
Record and Replay
Tinymist can record these input events with assigned the logic ticks. By replaying the events, tinymist can reproduce the server state for debugging. This technique is learned from the well-known LSP, clangd, and the well known emulator, QEMU.