0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Rust重寫(xiě)的LSP:KCL IDE 插件的功能介紹與設(shè)計(jì)解析

jf_wN0SrCdH ? 來(lái)源:Rust語(yǔ)言中文社區(qū) ? 2023-05-11 09:39 ? 次閱讀

在上周,KCL 發(fā)布了 v0.4.6 版本,這個(gè)版本在語(yǔ)言、工具鏈、社區(qū)集成&擴(kuò)展支持等方面進(jìn)行了重點(diǎn)更新。本文包含 KCL IDE 插件的功能特性和 LSP 的介紹、KCL LSP Server 端的設(shè)計(jì)和實(shí)現(xiàn)以及未來(lái)的規(guī)劃和期望。

功能特性

在這次更新中,我們發(fā)布了全新的 KCL VS Code 插件,并且用 Rust 重寫(xiě)了 LSP 的 Server 端。我們提供了 IDE 中常用的代碼輔助功能,如高亮、跳轉(zhuǎn)、補(bǔ)全、Outline、懸停、錯(cuò)誤提示等。

  • 高亮

fa1a0f0e-ef67-11ed-90ce-dac502259ad0.png

  • 補(bǔ)全

fa23ddea-ef67-11ed-90ce-dac502259ad0.png

  • Outline

fa4dc182-ef67-11ed-90ce-dac502259ad0.png

  • 懸停 & 跳轉(zhuǎn)

fa700efe-ef67-11ed-90ce-dac502259ad0.png

  • 錯(cuò)誤/警告提示

fa7c9020-ef67-11ed-90ce-dac502259ad0.png

歡迎到 https://kcl-lang.io/docs/tools/Ide/vs-code/ 了解更多

什么是 LSP?

在這次更新中,我們基于 LSP 實(shí)現(xiàn)了以上能力。LSP 指的是 Language Server Protocol,它是由微軟在 2016 年推出的一種用于編程語(yǔ)言工具的協(xié)議。借用一張圖,很容易就可以理解 LSP。

fa96447a-ef67-11ed-90ce-dac502259ad0.pngLSP

通過(guò) LSP ,編輯器和 IDE 可以通過(guò) JSON-RPC 通信協(xié)議與后端運(yùn)行的語(yǔ)言服務(wù)器(Server 端)進(jìn)行通信。語(yǔ)言服務(wù)器可以提供代碼分析、自動(dòng)補(bǔ)全、語(yǔ)法高亮、定義跳轉(zhuǎn)等功能?;?LSP,開(kāi)發(fā)者可以在不同的編輯器和 IDE 之間遷移,使得語(yǔ)言工具的開(kāi)發(fā)從 M(語(yǔ)言數(shù)量) * N(編輯器/IDE數(shù)量) 降低為 M + N


為什么用Rust重寫(xiě)?

KCL 編譯器和其他工具最初由 Python 實(shí)現(xiàn),因?yàn)樾阅茉?,我們?Rust 語(yǔ)言重寫(xiě)了編譯器(性能提升 40 倍!我們用 Rust 重寫(xiě)了自己的項(xiàng)目)。在此之后,我們使用 Rust 逐步重寫(xiě)了 KCL 的其他工具,如測(cè)試工具、Format 工具等。在這次更新中,我們用 Rust 重寫(xiě)了 LSP Server 端,其主要考慮因素也是性能。

fa9fc9f0-ef67-11ed-90ce-dac502259ad0.png

過(guò)去,Python 版本的 Server 端在處理一些復(fù)雜的場(chǎng)景(編譯文件數(shù)量超過(guò)200個(gè))時(shí),處理一個(gè)跳轉(zhuǎn)的請(qǐng)求,Server 端從接收到請(qǐng)求到計(jì)算結(jié)果并響應(yīng),時(shí)間長(zhǎng)達(dá) 6 秒以上,幾乎是不可用狀態(tài)。由于 Server 端的實(shí)現(xiàn)主要基于語(yǔ)言編譯器前中端的詞法解析和語(yǔ)義分析,在我們使用 Rust 重寫(xiě)以后,這部分性能分別提升了 20 和 40 倍, 帶來(lái)的顯著結(jié)果就是 Server 端的響應(yīng)時(shí)間得到了巨大提升,對(duì)于同樣的場(chǎng)景,響應(yīng)時(shí)間縮短至 100 毫秒左右。而對(duì)于一些簡(jiǎn)單的場(chǎng)景,響應(yīng)時(shí)間只有幾毫秒,做到了用戶無(wú)感。

KCL LSP Server的設(shè)計(jì)與實(shí)現(xiàn)

KCL LSP Server 的設(shè)計(jì)如下圖所示:

fbda7824-ef67-11ed-90ce-dac502259ad0.png

主要流程可以分為幾個(gè)階段:

  1. 建立連接,初始化 LSP 能力。在 IDE 的 Client 端,打開(kāi)特定文件(KCL的 *.k)時(shí),IDE 會(huì)啟動(dòng)本地的 kcl_language_server 二進(jìn)制文件,啟動(dòng) Server 端。這個(gè)文件與 KCL 一起發(fā)布,并安裝在 KCL 的 bin 目錄下。Server 啟動(dòng)后會(huì)建立 standard IO 的 Connection,并等待 Client 發(fā)送的初始化請(qǐng)求。Server 端接收初始化請(qǐng)求后會(huì)定義 Server 端信息和能力,并返回給 Client,以此完成 LSP 的初始化連接。
  2. 建立連接后,Server 端會(huì)啟動(dòng)一個(gè)輪詢函數(shù),不斷接收來(lái)自 Client 的 LSP Message,例如 Notification(打開(kāi)/關(guān)閉/變更/刪除文件等)和 Request(跳轉(zhuǎn)、懸停等),以及來(lái)自 Server 端自身的 Task。并統(tǒng)一封裝成事件(Event)交給下一步處理。
  3. 對(duì)于各種事件,按照以下步驟處理:
///Handlesaneventfromoneofthemanysourcesthatthelanguageserversubscribesto.
fnhandle_event(&mutself,event:Event)->anyhow::Result<()>{
//1.Processtheincomingevent
matchevent{
Event::Task(task)=>self.handle_task(task)?,
Event::Lsp(msg)=>matchmsg{
lsp_server::Request(req)=>self.on_request(req,start_time)?,
lsp_server::Notification(not)=>self.on_notification(not)?,
_=>{}
},
};

//2.Processchanges
letstate_changed:bool=self.process_vfs_changes();

//3.HandleDiagnostics
ifstate_changed{
letmutsnapshot=self.snapshot();
lettask_sender=self.task_sender.clone();
//Spawnthediagnosticsinthethreadpool
self.thread_pool.execute(move||{
 handle_diagnostics(snapshot, task_sender)?;
});
}

Ok(())
}

3.1 任務(wù)分發(fā):根據(jù)任務(wù)類型,做函數(shù)分發(fā)。在子函數(shù)中,會(huì)進(jìn)一步基于 Request 或 Notification 的類型繼續(xù)分發(fā)到最終的處理函數(shù)中,如處理文件變更、處理跳轉(zhuǎn)請(qǐng)求等。這些函數(shù)會(huì)根據(jù)基于編譯器中前端編譯出的語(yǔ)義模型(AST,符號(hào)表,錯(cuò)誤信息等)做分析,計(jì)算生成對(duì)應(yīng)的 Response(如跳轉(zhuǎn)請(qǐng)求的目標(biāo)位置)。

3.2 處理變更:用戶在修改代碼或更改文件時(shí),會(huì)發(fā)送對(duì)應(yīng)的 Notification。在前一步的處理中,會(huì)將變更保存在虛擬文件系統(tǒng)(VFS)中。Server 端會(huì)根據(jù)新的源代碼,進(jìn)行重新編譯,保存新的語(yǔ)義模型,以供下一個(gè)請(qǐng)求做處理。

3.3 錯(cuò)誤處理:這里的錯(cuò)誤并非指 Server 端的運(yùn)行錯(cuò)誤,而是代碼編譯中的語(yǔ)法、語(yǔ)義錯(cuò)誤,編譯警告等。Client 端并沒(méi)有對(duì)應(yīng)的請(qǐng)求類型來(lái)請(qǐng)求這些錯(cuò)誤,而是由 Server 端主動(dòng)發(fā)送 Diagnostics。因此,在發(fā)生變更后,同步地將錯(cuò)誤信息更新至 Client 端。

遇到的問(wèn)題

1.為什么需要虛擬文件系統(tǒng)?

在最初的設(shè)計(jì)中,并沒(méi)有考慮使用虛擬文件系統(tǒng)。我們每次從文件系統(tǒng)中獲取源代碼,進(jìn)行編譯和分析。對(duì)于一些“靜態(tài)”的任務(wù),如跳轉(zhuǎn),可以在變更代碼后保存到文件系統(tǒng),然后再進(jìn)行跳轉(zhuǎn)的操作。配合到 VS Code 的自動(dòng)保存功能,體驗(yàn)上并沒(méi)有明顯的差距。但對(duì)于代碼補(bǔ)全這一功能,IDE 中輸入的補(bǔ)全trigger(如 “.”)會(huì)觸發(fā)文件變更的通知和代碼補(bǔ)全的請(qǐng)求,但對(duì)應(yīng)的代碼還未保存到文件系統(tǒng)中,編譯后的語(yǔ)義模型無(wú)法做對(duì)應(yīng)的分析。因此,我們借助 Rust Analyzer 對(duì)應(yīng)的 vfs 的create,在 Server 端引入了虛擬文件系統(tǒng),將編譯的入口從文件路徑變?yōu)榱?source code。Client 端輸入代碼后,文件變更的通知會(huì)先更新虛擬文件系統(tǒng),重新編譯文件,生成新的語(yǔ)義模型,然后再處理補(bǔ)全請(qǐng)求。

2. 如何處理不完整的代碼?

我們遇到的另一個(gè)比較大的問(wèn)題是如何處理不完整的代碼。同樣的,對(duì)于跳轉(zhuǎn)這類“靜態(tài)”的任務(wù),可以假定代碼是完整、正確的。但對(duì)于補(bǔ)全操作,如以下代碼,希望在輸入.后,補(bǔ)全字符串的函數(shù)。對(duì)于編譯流程,第二行實(shí)際上是不完整的代碼,無(wú)法編譯出正常的 AST 樹(shù)。

s:str="hellokcl"
len=s.

為此,我們?cè)?KCL 的編譯中實(shí)現(xiàn)了語(yǔ)法和語(yǔ)義上的多種錯(cuò)誤恢復(fù),保證編譯過(guò)程始終能產(chǎn)生完整的 AST 和符號(hào)表。在這個(gè)例子中,我們新增了一個(gè)表示空的 AST 節(jié)點(diǎn)作為占位符,使得第二行能夠生成完整的 AST。在處理補(bǔ)全的請(qǐng)求時(shí),會(huì)根據(jù) s 的類型和其他語(yǔ)義信息,補(bǔ)全函數(shù)名、schema attr 或 pkg 中定義的 schema 名。

Rust Analyzer architecture:

Architecture Invariant: parsing never fails, the parser produces (T, Vec) rather than Result.

總結(jié)與展望

KCL 的 IDE 插件目前已經(jīng)實(shí)現(xiàn)高亮、跳轉(zhuǎn)、補(bǔ)全、Outline、懸停、錯(cuò)誤提示等功能。這些功能提升了 KCL 用戶的開(kāi)發(fā)效率。然而,作為一款 IDE 插件,它的功能還不夠完整。在未來(lái)的開(kāi)發(fā)中,我們會(huì)繼續(xù)完善,未來(lái)的工作有以下幾個(gè)方向:

  1. 更多的語(yǔ)言能力:提供更多的功能,如代碼重構(gòu),錯(cuò)誤的quick fix,代碼 fmt等,進(jìn)一步完善功能,提升開(kāi)發(fā)效率
  2. 更多的 IDE 接入:目前,KCL 雖然提供了 LSP,只接入了 VS Code,未來(lái)會(huì)基于 LSP 的能力為 KCL 用戶提供更多選擇。
  3. AI 能力的集成:目前,ChatGPT 風(fēng)靡全網(wǎng),各行各業(yè)都在關(guān)注。我們也在探索 AI×KCL 的結(jié)合,提供更智能的研發(fā)體驗(yàn)。總之,我們會(huì)繼續(xù)完善和優(yōu)化 KCL 的 IDE 插件,讓它更加成熟和實(shí)用。為KCL用戶帶來(lái)更加方便和高效的開(kāi)發(fā)體驗(yàn)。

審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 編程語(yǔ)言
    +關(guān)注

    關(guān)注

    10

    文章

    1929

    瀏覽量

    34540
  • LSP
    LSP
    +關(guān)注

    關(guān)注

    0

    文章

    11

    瀏覽量

    9759
  • KCL
    KCL
    +關(guān)注

    關(guān)注

    0

    文章

    8

    瀏覽量

    4045

原文標(biāo)題:Rust 重寫(xiě)的 LSP:KCL IDE 插件的功能介紹與設(shè)計(jì)解析

文章出處:【微信號(hào):Rust語(yǔ)言中文社區(qū),微信公眾號(hào):Rust語(yǔ)言中文社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Eclipse IDE插件研發(fā)工程師

    、 基于Eclipse IDE進(jìn)行二次開(kāi)發(fā),將已有的工具鏈集成到Eclipse IDE中 。3、 根據(jù)需求開(kāi)發(fā)新的功能插件。4、 解決開(kāi)發(fā)過(guò)程中遇到的技術(shù)難點(diǎn)。崗位要求1、 計(jì)算機(jī)專業(yè)
    發(fā)表于 04-20 15:22

    IDE為S32 Design Studio安裝Lauterbach插件無(wú)法解析位置是為什么?

    我正在嘗試通過(guò)我的 IDE 為 S32 Design Studio 安裝 Lauterbach 插件無(wú)法解析位置。 ?
    發(fā)表于 06-08 06:01

    Rust代碼中加載靜態(tài)庫(kù)時(shí),出現(xiàn)錯(cuò)誤 ` rust-lld: error: undefined symbol: malloc `怎么解決?

    我正在 MCUXpresso IDE 中創(chuàng)建一個(gè)靜態(tài)庫(kù)。我正在使用 redlib 在我的代碼中導(dǎo)入 ` [i]stdlib.h`。它成功地構(gòu)建了一個(gè)靜態(tài)庫(kù)。但是,靜態(tài)庫(kù)中未定義一些標(biāo)準(zhǔn)庫(kù)函數(shù),例如
    發(fā)表于 06-09 08:44

    lsp_lsp是什么意思

    在多協(xié)議標(biāo)簽交換(MPLS)系統(tǒng)中,標(biāo)簽交換路徑(LSP)是指屬于特定“轉(zhuǎn)發(fā)等價(jià)類”(FEC)的分組所經(jīng)過(guò)的路徑,即處于同一層次的多個(gè)標(biāo)簽交換路由器(LSR)所形成的路徑。
    發(fā)表于 12-14 16:21 ?5.2w次閱讀

    jquery插件寫(xiě)法及用法(jQuery插件開(kāi)發(fā)全解析

    如今做web開(kāi)發(fā),jquery 幾乎是必不可少的,同時(shí)jquery插件也是不斷的被大家所熟知,以及運(yùn)用。最近在搞這個(gè)jquery插件,發(fā)現(xiàn)它的牛逼之處,所以講一講jQuery插件的寫(xiě)法、使用jQuery
    發(fā)表于 12-03 09:21 ?1w次閱讀
    jquery<b class='flag-5'>插件</b>寫(xiě)法及用法(jQuery<b class='flag-5'>插件</b>開(kāi)發(fā)全<b class='flag-5'>解析</b>)

    用于MPLAB X IDE代碼性能分析插件的工作原理和代碼性能分析參考

    MPLAB X IDE提供收集有關(guān)C代碼函數(shù)的函數(shù)級(jí)性能分析(Function Level Profiling, FLP)數(shù)據(jù)的功能。但是,該數(shù)據(jù)無(wú)法在未安裝MPLAB X IDE插件
    發(fā)表于 06-11 04:28 ?11次下載
    用于MPLAB X <b class='flag-5'>IDE</b>代碼性能分析<b class='flag-5'>插件</b>的工作原理和代碼性能分析參考

    微軟開(kāi)發(fā)基于Rust的新編程語(yǔ)言,將很快開(kāi)源

    此前,微軟表示正探索將Rust作為C和C++的安全替代方案,并且也對(duì)外展示了使用Rust重寫(xiě)Windows組件的體驗(yàn),根據(jù)微軟的說(shuō)法,Rust是一種從根本上考慮安全性的編程語(yǔ)言,他們將
    的頭像 發(fā)表于 12-03 10:36 ?3887次閱讀

    用于MPLABX IDE的代碼性能分析插件

    MPLAB X IDE提供收集有關(guān)C代碼函數(shù)的函數(shù)級(jí)性能分析(Function Level Profiling,F(xiàn)LP)數(shù)據(jù)的功能。但是,該數(shù)據(jù)無(wú)法在未安裝MPLAB X IDE插件
    發(fā)表于 05-12 10:38 ?15次下載

    Rust重寫(xiě)了自己的項(xiàng)目

    一年前,我們使用 Python 語(yǔ)言構(gòu)建了整個(gè) KCL 語(yǔ)言編譯器的實(shí)現(xiàn),雖然在一開(kāi)始的時(shí)候運(yùn)行良好,Python 簡(jiǎn)單易上手,生態(tài)豐富,團(tuán)隊(duì)的研發(fā)效率也很高,但是隨著代碼庫(kù)的擴(kuò)張和工程師人數(shù)的增加,代碼維護(hù)起來(lái)愈加困難。
    的頭像 發(fā)表于 02-02 16:45 ?1135次閱讀

    Cloudflare用Rust重寫(xiě)Nginx C模塊,構(gòu)建沒(méi)有Nginx的未來(lái)

    近日,Cloudflare 工程師介紹了如何使用 Rust 重寫(xiě)基于 C 語(yǔ)言的 Nginx 模塊。Cloudflare 工程師在博客寫(xiě)道,他們用 Rust 為 Cloudflare
    的頭像 發(fā)表于 03-08 09:36 ?683次閱讀

    Windows 11初嘗Rust,36000行內(nèi)核代碼已重寫(xiě)

    更早些時(shí)候,微軟用 Rust 重寫(xiě)了 DirectWrite Core 庫(kù)的概念驗(yàn)證,它是 Windows 的 DWrite 引擎的 Windows App SDK 實(shí)現(xiàn),用于文本分析、布局和渲染
    的頭像 發(fā)表于 05-19 16:39 ?983次閱讀
    Windows 11初嘗<b class='flag-5'>Rust</b>,36000行內(nèi)核代碼已<b class='flag-5'>重寫(xiě)</b>!

    用于Arduino IDE插件Blockly@rduino

    電子發(fā)燒友網(wǎng)站提供《用于Arduino IDE插件Blockly@rduino.zip》資料免費(fèi)下載
    發(fā)表于 06-20 11:27 ?2次下載
    用于Arduino <b class='flag-5'>IDE</b>的<b class='flag-5'>插件</b>Blockly@rduino

    Rust構(gòu)建QEMU插件的框架

    Cannonball 是一個(gè)用 Rust 構(gòu)建 QEMU 插件的框架!您可以在 C 語(yǔ)言的 QEMU TCG 插件中執(zhí)行的任何操作,都可以使用cannonball。編寫(xiě)以最小的開(kāi)銷和盡可能多的
    的頭像 發(fā)表于 07-21 16:57 ?842次閱讀

    JetBrains發(fā)布獨(dú)立Rust IDE:RustRover

    在推出 RustRover 之前,JetBrains 以插件形式在 IntelliJ IDEA 和 CLion 中支持 Rust 功能?,F(xiàn)在他們開(kāi)發(fā)多年的開(kāi)源插件已成為 RustRov
    的頭像 發(fā)表于 09-18 16:47 ?993次閱讀
    JetBrains發(fā)布獨(dú)立<b class='flag-5'>Rust</b> <b class='flag-5'>IDE</b>:RustRover

    一次Rust重寫(xiě)基礎(chǔ)軟件的實(shí)踐

    受到2022年“谷歌使用Rust重寫(xiě)Android系統(tǒng)且所有Rust代碼的內(nèi)存安全漏洞為零” [1] 的啟發(fā),最近筆者懷著濃厚的興趣也順應(yīng)Rust 的潮流,嘗試著將一款C語(yǔ)言開(kāi)發(fā)的基礎(chǔ)
    的頭像 發(fā)表于 01-25 11:21 ?578次閱讀