來開發 Visual Studio Code SystemVerilog plugin 吧!開發紀錄(四)
在前一篇文章說到了,如何在 Visual Studio Code 中使用 programmatic language features,加入滑鼠游標移動到程式碼時顯示一些提示的功能,上一篇文章中我們透過在 plugin 初始化的時候,使用了 registerHoverProvider
顯示 "Hover Content"
的提示。然而,在官方的文件中並不建議這樣作,而是使用 Lanugage Server 將 plugin 跟程式碼解析的功能分開。
在這篇文章中,將會展示跟前一篇文章一樣的功能,但是改為用 Language Server 實做,使用到的主要參考資料是對新手還是很難用的 官方新手範例。
建立 Language Server 所需之檔案
要分離程式碼解析的功能,就是把程式碼解析這一個功能拆開,放到 Language Server 實做。為此,我們要新增一個 server/
的資料夾,這個資料夾將會作為一個 sub-project 來實做 Language Server,最低限度需要的檔案有這些:
1server/
2 |- src/
3 | |- server.ts
4 |- package.json
5 |- tsconfig.json
第一,在 tsconfig.json
要加上 "composite": true
的 flag。作為新手,我當然不知道這個功能是什麼,總之放上去編譯器才不會抱怨。
1{
2"compilerOptions": {
3 "composite": true
4},
5}
第二,package.json
的相依性要換成這兩個,這倒是很好理解。
1{
2"dependencies": {
3 "vscode-languageserver": "^7.0.0",
4 "vscode-languageserver-textdocument": "^1.0.1"
5}
6}
最後,現在的 project 的 tsconfig.json
要引入這行作為 sub-project。作到這步驟,我忽然像起來很久以前我朋友抱怨 JavaScript 的編譯管理功能比手寫 Makefile 還難用,我終於理解他在說什麼了。
1{ "references": [ { "path": "./server"} ] }
改寫原本之 Plugin
在原本的 plugin 中,我們用一個 callback 實做 hover 的功能:
1vscode.languages.registerHoverProvider('javascript', {
2 provideHover(document, position, token) {
3 return {
4 contents: ['Hover Content']
5 };
6 }
7});
現在,我們把這些程式碼都刪掉,改為啟動 Language Server 就好了,這段程式碼幾乎是從 官方新手範例 直接複製過來的,這個大概是官方新手範例最有用處的地方了……
1let serverModule = context.asAbsolutePath(
2 path.join('server', 'out', 'server.js')
3);
4let debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] };
5let serverOptions: ServerOptions = {
6 run: { module: serverModule, transport: TransportKind.ipc },
7 debug: {
8 module: serverModule,
9 transport: TransportKind.ipc,
10 options: debugOptions
11 }
12};
13let clientOptions: LanguageClientOptions = {
14 documentSelector: [{ scheme: 'file', language: 'systemverilog' }]
15};
16client = new LanguageClient(
17 'languageServerExample',
18 'Language Server Example',
19 serverOptions,
20 clientOptions
21);
22client.start();
實做 Language Server
官方新手範例提供的例子中相當的複雜,具有讀檔案、讀設定檔等等的強大功能,但是對於新手來說實在是不好懂。經過一番努力之後,我終於找出了,一個可動的 Language Server 最低限度需要寫的程式如下:
1const connection = createConnection(ProposedFeatures.all);
2const documents: TextDocuments<TextDocument> = new TextDocuments(TextDocument);
3connection.onInitialize(/* TODO */);
4connection.onHover(/* TODO */);
5documents.listen(connection);
6connection.listen();
裡面的 onInitialize()
跟 onHover()
是兩個 callbacks,聽名字也知道是「初始化」的時候跟「滑鼠游標移動到程式碼上面」的時候會作的事情。首先,先來看 onHover()
的內容,其程式碼跟前面不用 Language Server 的時候幾乎一樣。
1connection.onHover(
2 (_params: HoverParams): Hover => {
3 return {
4 contents: 'Hover',
5 };
6 }
7);
這邊想抱怨一下,關於 HoverParams
的文件,在網路上幾乎找不到,甚至也沒有太多 onHover()
裡面要用這個型別的文件。好在 TypeScript 是個強型別的程式語言,靠 Visual Studio Code 程式碼瀏覽的功能,多少能猜出要這樣寫……
onInitialize()
則是將範例的程式碼拿來簡化一下得來,這邊我還是要繼續抱怨,一開始這個 return 的設定裡面沒有 hoverProvider: true
這個選項,所以 hover 的功能一直沒有作用,我也是靠程式碼瀏覽的功能,猜出要這樣寫的。
1connection.onInitialize((_params: InitializeParams) => {
2 const result: InitializeResult = {
3 capabilities: {
4 textDocumentSync: TextDocumentSyncKind.Incremental,
5 hoverProvider: true,
6 workspace: {
7 workspaceFolders: {
8 supported: true
9 }
10 }
11 }
12 };
13 return result;
14});
完成之程式碼
本篇文章完成之 Github 連結在此 。
系列文連結
-
來開發 Visual Studio Code SystemVerilog plugin 吧!開發紀錄(一)
-
來開發 Visual Studio Code SystemVerilog plugin 吧!開發紀錄(二)
-
來開發 Visual Studio Code SystemVerilog plugin 吧!開發紀錄(三)
-
來開發 Visual Studio Code SystemVerilog plugin 吧!開發紀錄(四)
- 來開發 Visual Studio Code SystemVerilog plugin 吧!開發紀錄(一)
- 來開發 Visual Studio Code SystemVerilog plugin 吧!開發紀錄(二)
- 來開發 Visual Studio Code SystemVerilog plugin 吧!開發紀錄(三)
- 來開發 Visual Studio Code SystemVerilog plugin 吧!開發紀錄(四)