LSP簡介
LSP
的全稱是Language Server Protocol
,是微軟推出的一項標準化協議,旨在用來統一開發工具與Language Server
之前的通訊。它支援語言的自動補全、定義跳轉、檢視定義、檢視引用、lint、語法高亮
等等,但具體實現要看各種語言的LS支援是否完善。在這之前,各種IDE都需要自己實現一套類似的東西,顯得比較重複。藉助於LSP
,開發工具只要按規則接入該協議,便可以享受到各種語言提供的服務。
目前支援的語言
彙總在這裡,下圖只截出了部分,維護者有民間組織,微軟,還有正牌。比如對swift的支援就是Apple維護的sourcekit-lsp。
LSP如何工作
官網上有段介紹LSP是如何工作的。
client和server之前使用JSONRPC
進行通訊,採用request-response
的方式,如下圖。
主要步驟:
- 使用者開啟文件,client傳送
textDocument/didOpen
通知,告訴伺服器。這時檔案內容儲存在記憶體中。 - 使用者編輯文件,client傳送
textDocument/didChange
通知,然後server會發回textDocument/publishDiagnostics
通知,會分析出error和warning。client根據這些error和warning進行對應的UI顯示。 - 使用者執行跳轉到符號定義,client發起
textDocument/definition
請求,server返回相關的位置資訊。 - 使用者關閉文件,client傳送
textDocument/didClose
通知,檔案內容更新到磁碟。
下面來看下具體的request和response,以textDocument/definition
來舉例。
request:
其主要引數是method
,params
。params會帶上當前的檔案資訊,要查詢定義的符號資訊(第幾行,第幾個字元)
{
"jsonrpc": "2.0",
"id" : 1,
"method": "textDocument/definition",
"params": {
"textDocument": {
"uri": "file:///p%3A/mseng/VSCode/Playgrounds/cpp/use.cpp"
},
"position": {
"line": 3,
"character": 12
}
}
}
複製程式碼
response: 響應包括符號定義的檔案位置,符號的起始和終止位置。
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"uri": "file:///p%3A/mseng/VSCode/Playgrounds/cpp/provide.cpp",
"range": {
"start": {
"line": 0,
"character": 4
},
"end": {
"line": 0,
"character": 11
}
}
}
}
複製程式碼
LSP定義
LSP中定義了很多method
,用來區分不同事件。包括請求和通知。
如initialize
,是client發給server的第一個請求。
Shutdown
,關閉請求。
textDocument/definition
,檢視符號定義的請求。
...
其詳細定義文件在這裡。
VSCode中安裝swift LSP
眾所周知,VSCode是一款功能強大的編輯器,其提供了非常豐富的外掛來支援各種語言的開發,並且它是眾多編輯器中率先支援LSP
的。
Swift For LSP
還在早期開發的階段,因此並沒有提供安裝包或者外掛。所以目前我們只能手動下載安裝。步驟如下:
安裝XCode
這步應該可以略過。
安裝VSCode
這步應該也可以略過。
安裝最新swift toolChain
到Swift.org下載最新的主幹包,安裝好之後,到XCode->Preferences->Components選擇剛安裝的toolchain。或者這裡不選擇,在vscode中設定toolchain的路徑。
安裝node和npm
由於VSCode的外掛都是用js/ts來寫的,所以需要js的執行環境。推薦直接下載安裝包來安裝。
驗證是否裝好了,可以執行以下命令
nmp --version
複製程式碼
編譯並安裝SourceKit-LSP
clone倉庫:
git clone https://github.com/apple/sourcekit-lsp.git
複製程式碼
跳轉到sourcekit-lsp目錄:
cd sourcekit-lsp
複製程式碼
編譯:
swift build
複製程式碼
編譯成功後,會在.build/debug
找到二進位制檔案。我們將其移到/usr/local/bin
目錄下,以便可以直接使用。
mv .build/debug/sourcekit-lsp /usr/local/bin
複製程式碼
這個命令會啟動lsp的程式。
sourcekit-lsp
複製程式碼
安裝SourceKit-LSP外掛
該外掛的作用是讓VSCode
與SourceKit-LSP
之間可以進行通訊。
- 進入到sourceKit-lsp下面的
Editors/vscode/
目錄
cd Editors/vscode/
複製程式碼
- 執行
npm run createDevPackage
npm run createDevPackage
複製程式碼
如果在這步遇到npm ERR! 404 Not Found: flatmap-stream@0.1.1
的問題,可以嘗試刪除lock檔案,清除快取試試。
rm package-lock.json
npm cache clean --force
複製程式碼
- 安裝
sourcekit-lsp-vscode-dev.vsix
code --install-extension out/sourcekit-lsp-vscode-dev.vsix
複製程式碼
首先要在VSCode中安裝code
命令,cmd+shift+p
,輸入shell command
,然後安裝code命令。如圖所示。
重啟VSCode。
- 配置sourcekit-lsp
使用快捷鍵cmd,
(或者preference-->settings),進入settings
頁面,搜尋sourcekit-lsp
,ToolChain Path
中填入之前下載安裝的toolchain路徑。比如我的是/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2018-11-25-a.xctoolchain
。
以上就配置完成了。
最後,開啟一個swift的xcode工程,滑鼠停留在關鍵字上,會展示出具體的定義。如下圖。
將設定中的Trace Server開啟,設定成message
,可以看到請求/響應/通知資訊;設定成verbose
,會更加詳細,具體欄位以及內容。其中請求是有id編號的,通知沒有。
- 開啟工程時,log如下。會依次傳送
initialize
,initialized
,textDocument/didOpen
。window/logMessage
是server發過來的通知。
[Trace - 3:00:00 PM] Sending request 'initialize - (0)'.
[Trace - 3:00:00 PM] Received notification 'window/logMessage'.
could not open compilation database for /Users/liusilan/Documents/workspace/my/LeetCode/countSegments noEntry
[Trace - 3:00:00 PM] Received notification 'window/logMessage'.
failed to open IndexStoreDB: indexstoredb_index_create error: index store path does not exist: /Users/liusilan/Documents/workspace/my/LeetCode/countSegments/.build/debug/index/store
[Trace - 3:00:00 PM] Received response 'initialize - (0)' in 234ms.
[Trace - 3:00:00 PM] Sending notification 'initialized'.
[Trace - 3:00:00 PM] Sending notification 'textDocument/didOpen'.
[Trace - 3:00:00 PM] Received notification 'textDocument/publishDiagnostics'.
[Trace - 3:00:01 PM] Received notification 'textDocument/publishDiagnostics'.
複製程式碼
- 在進行編輯時,log如下。傳送
textDocument/didChange
,server會返回textDocument/publishDiagnostics
。
[Trace - 2:58:57 PM] Sending notification 'textDocument/didChange'.
[Trace - 2:58:57 PM] Received notification 'textDocument/publishDiagnostics'.
[Trace - 2:58:57 PM] Received notification 'textDocument/publishDiagnostics'.
複製程式碼
- 滑鼠停留時,會傳送
textDocument/hover
。
[Trace - 2:53:43 PM] Sending request 'textDocument/hover - (3)'.
[Trace - 2:53:43 PM] Received response 'textDocument/hover - (3)' in 3ms.
複製程式碼
- 游標點在某行時,會傳送
textDocument/documentHighlight
。
[Trace - 2:55:07 PM] Sending request 'textDocument/documentHighlight - (22)'.
[Trace - 2:55:07 PM] Received response 'textDocument/documentHighlight - (22)' in 2ms.
複製程式碼
- 按住cmd鍵,檢視符號定義時,會傳送
textDocument/definition
。
[Trace - 2:55:40 PM] Sending request 'textDocument/definition - (43)'.
[Trace - 2:55:40 PM] Received response 'textDocument/definition - (43)' in 8ms.
複製程式碼
關於versbose列印的資訊,大家可以嘗試設定看看。
另外,SouceKit-LSP
也是支援Sublime Text
的,具體配置可以參照sublime-text配置。
Suorcekit-LSP支援的特性
目前,因為它還在早期開發中,支援的功能還不是很多,相信以後會越來越完善。
Feature | Status | Notes |
---|---|---|
Swift | ✅ | |
C/C++/ObjC | ❌ | clangd is not available in the recommended toolchain. You can try out C/C++/ObjC support by building clangd from source and putting it in PATH . |
Code completion | ✅ | |
Quick Help (Hover) | ✅ | |
Diagnostics | ✅ | |
Fix-its | ❌ | |
Jump to Definition | ✅ | |
Find References | ✅ | |
Background Indexing | ❌ | Build project to update the index using Indexing While Building |
Workspace Symbols | ❌ | |
Refactoring | ❌ | |
Formatting | ❌ | |
Folding | ❌ | |
Syntax Highlighting | ❌ | Not currently part of LSP. |
Document Symbols | ❌ |
VSCode除錯swift
除錯在開發過程中是必不可少的,之前總是生成xcodeproj
,然後在xcode
中進行除錯,總歸有些不太方便。
在VSCode中
除錯swift
也挺簡單的,步驟如下:
-
安裝外掛CoreLLDB
-
配置launch.json
在外掛安裝完成之後,開啟swift工程,按F5
,會出現配置彈框,如下。
點選Open launch.json
進行配置,具體配置如下:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
// Running executables
{
"type": "lldb",
"request": "launch",
"name": "Run your Executable",
"program": "${workspaceFolder}/.build/debug/xxx",
"args": [],
"cwd": "${workspaceFolder}",
"preLaunchTask": "swift-build"
}
]
}
複製程式碼
注意將"program": "${workspaceFolder}/.build/debug/xxx",
中的xxx
改成自己工程可執行檔案的名字。
- 配置task.json
launch.json
配置好後,繼續按F5
,此時會出現配置task的彈窗,如下圖。
點選Configure Task
進行配置,如下:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
// compile your SPM project
{
"label": "swift-build",
"type": "shell",
"command": "swift build"
},
// compile your SPM tests
{
"label": "swift-build-tests",
"type": "process",
"command": "swift",
"group": "build",
"args": [
"build",
"--build-tests"
]
}]
}
複製程式碼
至此,全部配置完成。按F5
開始除錯,如果仍然出現彈窗,則說明某個地方沒配置好,需對比下上面的配置。
最後就可以愉快的除錯了。