I'm trying to develop a Language Server to a new language in VS Code and I'm using the Microsoft sample as reference (https://github.com/microsoft/vscode-extension-samples/tree/master/lsp-sample).
In their sample the autocompletion is done in this chunk of code:
connection.onCompletion(
(_textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => {
// The pass parameter contains the position of the text document in
// which code complete got requested. For the example we ignore this
// info and always provide the same completion items.
return [
{
label: 'TypeScript',
kind: CompletionItemKind.Text,
data: 1
},
{
label: 'JavaScript',
kind: CompletionItemKind.Text,
data: 2
}
];
}
);
As the comment says, it's a dumb autocompletion system, since it always provides the same suggestions.
I can see that there's an input parameter of type TextDocumentPositionParams
and this type has the following interface:
export interface TextDocumentPositionParams {
/**
* The text document.
*/
textDocument: TextDocumentIdentifier;
/**
* The position inside the text document.
*/
position: Position;
}
It has the cursor position and a TextDocumentIdentifier
but the last only has a uri property.
I want to create an intelligent autocomplete system, based on the type of the object of the word in the cursor position.
This sample is very limited and I'm kinda lost here. I guess I could read the file in the uri
property and based on the cursor position I could figure out which items I should suggest. But how about when the file is not saved? If I read the file I would read the data that is on disk, and not what is currently shown in the editor.
What's the best approach to do that?
The Language Server Protocol supports text synchronization, see TextDocumentSyncOptions
in ServerCapabilities
and the corresponding methods (textDocument/didChange
, didChange
, didClose
...). A Language Server will usually keep a copy of all open documents in memory.
The sample you linked actually makes use of this, but the synchronization itself is abstracted away into the TextDocuments
class from vscode-languageserver
. As a result server.ts
doesn't have to do much more than this:
let documents: TextDocuments = new TextDocuments();
[...]
documents.listen(connection);
You can then simply use documents.get(uri).getText()
to obtain the text shown in the editor.