vscode插件快餐教程(5) - 代碼補全
上節我們介紹了lsp的基本架構和協定的三次握手。
下面我們先學習一個最簡單的功能協定:給vscode發送一條通知。
LSP視窗消息
在LSP協定中,跟視窗相關的協定有三條:
- window/ShowMessage Notification
- window/showMessage Request
- window/logMessage Notification
我們可以使用Connection.window.sendxxxMessage函數來向用戶端發送消息。
根據消息程度的不同,分為Information, Warning和Error三個級别。
舉個例子,我們可以在onInitialized,也就是用戶端與服務端三次握手一切就緒之後,向用戶端發一個消息。
connection.onInitialized(() => {
connection.window.showInformationMessage('Hello World! form server side');
});
顯示結果如下:

代碼補全
我們用視窗通知熱熱身,測試一下鍊路通不通。下面我們就直奔我們最感興趣的主題之一:代碼補全。
代碼補全的形式其實也很簡單,輸入是一個TextDocumentPositionParams,輸出是一個CompletionItem的數組,這個函數注冊到connection.onCompletion中:
connection.onCompletion(
(_textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => {});
代碼補全中用到的主要資料結構如下圖所示:
其中kind屬性由一個枚舉定義:
大家不要被吓到,我們通過一個簡單的例子看一下,其實基本實作方法還是很簡單的:
connection.onCompletion(
(_textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => {
connection.console.log('[xulun]Position:' + _textDocumentPosition.textDocument);
return [
{
label: 'TextView',
kind: CompletionItemKind.Text,
data: 1
},
{
label: 'Button',
kind: CompletionItemKind.Text,
data: 2
},
{
label: 'ListView',
kind: CompletionItemKind.Text,
data: 3
}
];
}
)
補全的詳細資訊
除了補全資訊textDocument/completion之外,lsp還支援completionItem/resolve請求,輸入和輸出都是CompletionItem,傳回進一步的資訊。
通過connection.onCompletionResolve方法可以注冊對于completionItem/resolve請求的支援:
connection.onCompletionResolve(
(item: CompletionItem): CompletionItem => {
if (item.data === 1) {
item.detail = 'TextView';
item.documentation = 'TextView documentation';
} else if (item.data === 2) {
item.detail = 'Button';
item.documentation = 'JavaScript documentation';
} else if (item.data === 3) {
item.detail = 'ListView';
item.documentation = 'ListView documentation';
}
return item;
}
)
運作效果如下:
使用參數中的補全位置資訊
輸入參數中會帶有發出補全申請的位置資訊,我們可以根據這個資訊來控制補全的資訊。
我們以一個例子來說明下:
connection.onCompletion(
(_textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => {
return [
{
label: 'TextView' + _textDocumentPosition.position.character,
kind: CompletionItemKind.Text,
data: 1
},
{
label: 'Button' + _textDocumentPosition.position.line,
kind: CompletionItemKind.Text,
data: 2
},
{
label: 'ListView',
kind: CompletionItemKind.Text,
data: 3
}
];
}
)
我們此時不光補全一個控件名,還将目前的行号或列号增加其中。
下面是補全Button的運作情況,會增加目前的行号到補全資訊中,我們在934行觸發補全,于是補全提示的資訊變成Button933: