VSCode使用LSP進行Swift開發

summer_liu_liu發表於2018-11-27

LSP簡介

LSP的全稱是Language Server Protocol,是微軟推出的一項標準化協議,旨在用來統一開發工具與Language Server之前的通訊。它支援語言的自動補全、定義跳轉、檢視定義、檢視引用、lint、語法高亮等等,但具體實現要看各種語言的LS支援是否完善。在這之前,各種IDE都需要自己實現一套類似的東西,顯得比較重複。藉助於LSP,開發工具只要按規則接入該協議,便可以享受到各種語言提供的服務。

目前支援的語言彙總在這裡,下圖只截出了部分,維護者有民間組織,微軟,還有正牌。比如對swift的支援就是Apple維護的sourcekit-lsp

image.png

LSP如何工作

官網上有段介紹LSP是如何工作的。

client和server之前使用JSONRPC進行通訊,採用request-response的方式,如下圖。

image.png

主要步驟:

  1. 使用者開啟文件,client傳送textDocument/didOpen通知,告訴伺服器。這時檔案內容儲存在記憶體中。
  2. 使用者編輯文件,client傳送textDocument/didChange通知,然後server會發回textDocument/publishDiagnostics通知,會分析出error和warning。client根據這些error和warning進行對應的UI顯示。
  3. 使用者執行跳轉到符號定義,client發起textDocument/definition請求,server返回相關的位置資訊。
  4. 使用者關閉文件,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的路徑。

image.png

安裝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外掛

該外掛的作用是讓VSCodeSourceKit-LSP之間可以進行通訊。

  1. 進入到sourceKit-lsp下面的Editors/vscode/目錄
cd Editors/vscode/
複製程式碼
  1. 執行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
複製程式碼
  1. 安裝sourcekit-lsp-vscode-dev.vsix
code --install-extension out/sourcekit-lsp-vscode-dev.vsix
複製程式碼

首先要在VSCode中安裝code命令,cmd+shift+p,輸入shell command,然後安裝code命令。如圖所示。

image.png

重啟VSCode。

  1. 配置sourcekit-lsp

使用快捷鍵cmd,(或者preference-->settings),進入settings頁面,搜尋sourcekit-lspToolChain Path中填入之前下載安裝的toolchain路徑。比如我的是/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2018-11-25-a.xctoolchain

image.png

以上就配置完成了。

最後,開啟一個swift的xcode工程,滑鼠停留在關鍵字上,會展示出具體的定義。如下圖。

image.png

將設定中的Trace Server開啟,設定成message,可以看到請求/響應/通知資訊;設定成verbose,會更加詳細,具體欄位以及內容。其中請求是有id編號的,通知沒有。

  • 開啟工程時,log如下。會依次傳送initializeinitializedtextDocument/didOpenwindow/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也挺簡單的,步驟如下:

  1. 安裝外掛CoreLLDB

    QQ20190108-4.png

  2. 配置launch.json

在外掛安裝完成之後,開啟swift工程,按F5,會出現配置彈框,如下。

VSCode使用LSP進行Swift開發

點選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改成自己工程可執行檔案的名字。

  1. 配置task.json

launch.json配置好後,繼續按F5,此時會出現配置task的彈窗,如下圖。

QQ20190108-2.png

點選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開始除錯,如果仍然出現彈窗,則說明某個地方沒配置好,需對比下上面的配置。

最後就可以愉快的除錯了。

QQ20190108-3.png

相關文章