Architecture of LSPServer
Overview
LSPServer is an implementation of Language Server Protocol for Wolfram Language code.
The server process that is launched by clients is a regular Wolfram kernel.
StdIO
stdin and stdout are used to communicate with the client.
The server kernel has a background thread that blocks reading stdin.
There are functions for checking if there is any traffic and this allows a very simple main loop in the server:
While[True,
TryQueue["StdIO"];
ProcessScheduledJobs[];
If[empty[$ContentQueue],
Pause[0.1];
Continue[]
];
content = $ContentQueue[[1]];
$ContentQueue = Rest[$ContentQueue];
contents = LSPEvaluate[content];
writeLSPResult["StdIO", sock, contents];
]
$ContentQueue
is a list of messages waiting to be processed.
Messages
Messages like testDocument/color
are expanded into multiple messages:
{
textDocument/concreteParse,
textDocument/aggregateParse,
textDocument/abstractParse,
textDocument/colorFencepost
}
and these are what are placed in the queue.
textDocument/colorFencepost
is where the actual work gets done.
Expanding messages has benefits: If a file closed, then the queue of all messages is cleared, so there is no unnecessary work done.
By sequencing like this, then the implementation of textDocument/colorFencepost
can assume that the AST is already present.
This simplifies implementation of textDocument/colorFencepost
.
Jobs can be scheduled for the future, such as waiting to display implicit tokens.
$OpenFilesMap
$OpenFilesMap
is a global association that contains entries for each file that is currently open.
The key is the URI of the file and the value is an entry that has this structure:
<|
"Text" -> ...,
"CST" -> ...,
"CSTTabs" -> ...,
"Agg" -> ...,
"AggTabs" -> ...,
"AST" -> ...,
"ScopingData" -> ...,
"LastChange" -> ...,
"ScheduledJobs" -> { Function[{entry}, {methods, toRemove}]... },
"SuppressedRegions" -> ...,
"CSTLints" -> ...,
"AggLints" -> ...,
"ASTLints" -> ...,
"ScopingLints" -> ...
|>