自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Code Review效率低?來試試智能語法服務(wù)

開發(fā) 開發(fā)工具
在人工代碼評審(Code Review,CR)中,對于純文本形式的代碼瀏覽不可避免地將耗費大量的時間,影響CR的效率。那么有沒有更智能的方法?

 ????在人工代碼評審(Code Review,CR)中,對于純文本形式的代碼瀏覽不可避免地將耗費大量的時間,影響CR的效率。那么有沒有更智能的方法?阿里云云效代碼智能語法服務(wù)基于云端備份的快速代碼導(dǎo)航服務(wù),無須本地克隆即可在頁面體驗熟悉的定義引用快速查看跳轉(zhuǎn)功能,可大幅提升代碼評審的效率和質(zhì)量。本文分享相關(guān)的技術(shù)原理與實現(xiàn)方法。

一 前言

代碼文本不是簡單的二維平面結(jié)構(gòu),看懂一段代碼需要反復(fù)地通過定義與引用的跳轉(zhuǎn),才能將代碼深層次的邏輯和片段影響范圍理解透徹。純文本形式的代碼瀏覽是網(wǎng)頁端代碼評審的最大痛點之一,朱熹老先生常說“心不在此,則眼不看仔細,心眼既不專一,卻只漫浪誦讀,決不能記,記亦不能久也?!贝a文本扁平式地漫浪誦讀只能達到眼到、口到的境界,如果你是一個認真負責(zé)的代碼評審者,阿里云云效代碼智能語法服務(wù)一定是幫助你充分理解代碼變更,超越眼口,到達“心到”境界的功能。心既到矣,眼口豈不到乎?

那么什么是代碼智能語法服務(wù)呢?語法服務(wù)提供了基于云端備份的快速代碼導(dǎo)航服務(wù),無須本地克隆即可在頁面體驗熟悉的定義引用快速查看跳轉(zhuǎn)功能,大幅提升代碼評審的效率和質(zhì)量。

二 技術(shù)基礎(chǔ)

阿里云云效代碼智能語法服務(wù)的底層技術(shù)是LSIF(Language Server Index Format),它是一種持久化語言的索引的圖存儲格式,通過圖的格式,表示了“代碼文檔”-> “語法智能結(jié)果”之間的事件關(guān)系。

在LSIF之前,LSP(Language Server Protocol)定義了編碼語言與各類終端代碼編輯器之前的交互協(xié)議。原先開發(fā)者需要為每一款編輯器都定義適配一種語法分析服務(wù)應(yīng)用,那么M個語言要在M個代碼編輯器中使用的話需要MxN個應(yīng)用。而有了LSP的出現(xiàn),開發(fā)者在解析代碼語法時只需要遵循LSP協(xié)議格式,實現(xiàn)代碼補全、定義展示、代碼診斷等接口,就只需要開發(fā)M+N個應(yīng)用。

??

??

 

然而代碼分析往往需要耗費大量的時間和資源,當(dāng)用戶請求某個語法服務(wù)(如查看定義),后端需要克隆代碼,下載依賴包,解析語法,構(gòu)建索引(類比一下IntelliJ Idea初始化工程的場景),編輯器場景用戶已經(jīng)習(xí)慣于這樣的方式,等待幾分鐘或許問題不大。但CR場景或者輕量級的代碼瀏覽場景,這種方式就顯得時效性比較低了,幾分鐘后或許用戶已經(jīng)完成了代碼瀏覽,而且缺少持久化的存儲會導(dǎo)致資源過度消耗。于是,LSIF就在這樣的背景下應(yīng)運而生,秉承用空間換時間的思想,提前計算好語法分析結(jié)果以特定的索引格式存儲在云上,從而快速響應(yīng)不同用戶的多次請求。

援引官方示例來簡單介紹下LSIF,如下方代碼:

// this is a sample classpublic class Sample {}

假定只有一種交互,當(dāng)鼠標(biāo)移動到Sample的類名上,就會出現(xiàn)“this is a sample class”的注釋信息。用LSIF的圖就可以如下描述。

??

??

 

一個sample文件,包含了一個range信息,這個range關(guān)聯(lián)了一個hoverResult。含義是該文件的某個位置范圍內(nèi),觸發(fā)hover事件的話,就給出hoverResult存儲的結(jié)果。

如果用Json文件描述這張圖的存儲,就可以得到如下結(jié)果:

{ id: 1, type: "vertex", label: "document", uri: "file:///abc/sample.java", languageId: "java" }{ id: 2, type: "vertex", label: "range", start: { line: 0, character: 13}, end: { line: 0, character: 18 } }{ id: 3, type: "edge", label: "contains", outV: 1, inVs: [2] }{ id: 4, type: "vertex", label: "hoverResult", result: {["this is a sample class"]} }{ id: 5, type: "edge", label: "textDocument/hover", outV: 2, inV: 4 }

實際一個工程的LSIF圖會非常復(fù)雜,經(jīng)常會包含幾十萬個節(jié)點。感興趣的同學(xué)可以參考LSIF具體描述[1]。

三 實現(xiàn)方式

阿里云云效的語法服務(wù)架構(gòu)圖主要分為兩部分:

基于事件觸發(fā)的索引構(gòu)建過程

基于用戶請求的語法服務(wù)響應(yīng)

??

??

 

1 索引構(gòu)建

用戶對代碼的瀏覽場景主要集中在代碼評審和主干分支的代碼瀏覽,所以我們目前主要支持兩種場景的語法服務(wù)。語法服務(wù)接收來自代碼平臺的事件消息,如代碼推送事件,評審的創(chuàng)建、更新、合并、關(guān)閉、重新開啟事件,來觸發(fā)語法服務(wù)構(gòu)建。

我們的構(gòu)建工作流調(diào)度主要基于阿里巴巴開源的分布式調(diào)度框架tbschedule,該系統(tǒng)會通過zookeeper維護一個任務(wù)集群,通過zookeeper做節(jié)點管理和任務(wù)分發(fā),不重復(fù)不遺漏地快速處理調(diào)度任務(wù)。

針對不同語言,我們只需要實現(xiàn)一次從源代碼到LSIF格式的轉(zhuǎn)換,就能將其應(yīng)用在多種場景。多種代碼語言代碼語言都會被解析成統(tǒng)一的LSIF格式文件。

針對阿里巴巴內(nèi)部主要的Java語言,我們利用開源Java代碼解析工具Spoon[2]將Java源代碼分析為AST(抽象語法樹),然后捕捉定義和引用、定義與注釋之間的關(guān)聯(lián),將坐標(biāo)信息、注釋內(nèi)容,文本類型,所屬文件等信息聚合,輸出為統(tǒng)一的LSIF的Json格式。

開發(fā)期間修復(fù)并適配了一些lsif-java的問題,如位置范圍信息錯亂,召回多種遺漏的高亮詞類型,適配非Maven倉庫的索引構(gòu)建。同時還修復(fù)了Spoon關(guān)于無法正確解析注釋中的部分注解的問題,PR已被Spoon社區(qū)接受合并[3]。

生成lsif.json文件后,由于這個Json文件較大,直接由前端加載并響應(yīng)請求不太合理,后期增量生成與維護難度也很大,所以我們還需要一步:將lsif.json轉(zhuǎn)化為結(jié)構(gòu)化數(shù)據(jù),從而按需響應(yīng)用戶查詢請求。lsif的圖存儲格式讓人自然地聯(lián)想到用圖數(shù)據(jù)結(jié)構(gòu)存儲,圖查詢的速度也比較快,然而由于索引變化迭代較快,頻繁更換的ID導(dǎo)致圖存儲難以適配增量方案,不同代碼庫不同語言的索引數(shù)據(jù)很難在一張圖中結(jié)構(gòu)化,參考了社區(qū)的相關(guān)實踐,考慮到成本和性能,因為ES天然地適合大規(guī)模的數(shù)據(jù)存儲和索引,我們最后選擇了用ES(Elasticsearch)做結(jié)構(gòu)化數(shù)據(jù)存儲。

我們將這種結(jié)構(gòu)化的數(shù)據(jù)上傳到ES,然后語法服務(wù)后端服務(wù)器會基于用戶的語法請求,構(gòu)造ES請求Query,查詢定義、引用或注釋信息,將其拼裝返回。

對于分支,我們會持續(xù)更新和保留最新版本的索引數(shù)據(jù);對于代碼評審,我們會構(gòu)建源分支的每次Push版本和源目標(biāo)分支的merge-base版本的索引。

索引構(gòu)建的另外一個難點是增量計算。如上文所述,語法服務(wù)索引構(gòu)建對資源的要求非常高,而現(xiàn)實中代碼庫不可避免地會存在頻繁提交的現(xiàn)象。如此引申出了兩個優(yōu)化點:

利用增量的方式減少存儲內(nèi)容的變更,加快索引構(gòu)建速度。

利用分布式時序鎖減少頻繁請求帶來的壓力。

增量方案

每次分支索引構(gòu)建成功,我們都會在數(shù)據(jù)庫中記錄分支對應(yīng)的版本號,當(dāng)該分支有了一次新的提交后,在生成lsif.json后,系統(tǒng)會比較兩個分支的Diff,獲取到變更文件和變更類型,通過變更文件來進一步提取索引受到影響的文件(引用或定義的坐標(biāo)信息變更),分析出所有受影響的文件和對應(yīng)的ES增刪操作后,完成增量索引上傳。這個增量的過程平均能減少45%的分支構(gòu)建時間。

??

??

 

時序鎖管理

根據(jù)庫大小的區(qū)別,LSIF的索引構(gòu)建時間為10秒至數(shù)分鐘不等,而用戶對同一個代碼倉庫的提交操作峰值可能會達到每分鐘近百次,即使我們采用了增量技術(shù)也很難滿足高頻的構(gòu)建請求,并且提交事件觸達和調(diào)度任務(wù)執(zhí)行無法保證精準(zhǔn)的時序性。綜上所述,我們需要一個分布式時序鎖來保證任務(wù)調(diào)度的順序和盡量減少重復(fù)調(diào)度。

當(dāng)同一代碼庫的不同推動消息紛涌而至,Redis維護的分布式鎖會做如下判斷:若該庫當(dāng)前沒有正在運行的任務(wù),將任務(wù)置于隊首,立即運行;若已有一個正在執(zhí)行的任務(wù),比較新來的Push消息是否是最新的,若是,則加入隊尾;當(dāng)隊伍已有兩個成員時,則將任務(wù)丟棄,因為每次執(zhí)行任務(wù)時,系統(tǒng)都會克隆分支代碼,基于最新的版本構(gòu)建索引,如此就避免了多少次Push就需要執(zhí)行多少次索引構(gòu)建的可能性??紤]到線程意外退出的情況,隊首會每隔5秒鐘全局發(fā)送心跳,當(dāng)隊尾或新來的任務(wù)監(jiān)聽到心跳超時,則會將隊首的任務(wù)放棄并執(zhí)行新的任務(wù)。

??

??

 

2 語法服務(wù)響應(yīng)

如前言的示例,用戶在使用語法服務(wù)時,主要有以下三個請求:

每次打開文件獲取所有的可點擊高亮詞

點擊高亮詞獲取對應(yīng)的定義與引用列表

點擊定義和引用實現(xiàn)跳轉(zhuǎn)

針對第一個請求,系統(tǒng)會構(gòu)造基于文件路徑的過濾條件構(gòu)造ES的Query請求,將當(dāng)前文件的所有高亮詞坐標(biāo)信息發(fā)送給前端,避免了前端做語法分詞,沒有構(gòu)建好的文件自然也不會在頁面上被高亮出來。另外,為了避免超大文件對ES的壓力,前端會做分批動態(tài)加載。

針對第二個請求,我們在獲取定義與引用列表的過程中,不光要得到文件名和位置信息,還需要將對應(yīng)的代碼內(nèi)容展示出來,方便用戶理解。為了實現(xiàn)這個效果,我們新增了批量獲取文件片段的接口。

對于第三個請求,同一個文件內(nèi)的跳轉(zhuǎn)會自動高亮到對應(yīng)的代碼行,不同文件間的跳轉(zhuǎn)會新開頁面并跳轉(zhuǎn)。

語法服務(wù)響應(yīng)和語法索引構(gòu)建是完全異步的,互不影響,支持獨立的資源擴縮。

3 索引清理

語法服務(wù)的索引大小約是代碼文件內(nèi)容的數(shù)倍,比較消耗存儲資源。所以針對用戶通常的使用習(xí)慣和場景,制定了一系列索引清理任務(wù)來避免資源過度的損耗。

當(dāng)代碼評審合并或刪除時,當(dāng)分支刪除時,系統(tǒng)會開始執(zhí)行索引清理任務(wù),釋放索引資源。

四 語法服務(wù)展望

缺少符號跳轉(zhuǎn)長久以來一直是頁面上代碼閱讀的痛點之一,各種語法協(xié)議和技術(shù)層出不窮,如LSIF、Kythe、SARIF、UAST、Tree-sitter,ctags,全球技術(shù)人都在為更智能的代碼分析,更好的代碼體驗,更高的代碼質(zhì)量做努力。云效語法服務(wù)后續(xù)也會逐漸加快語法構(gòu)建速度,支持更多的代碼語言,滿足更多的語法場景,提升用戶的代碼瀏覽體驗。

相關(guān)鏈接

[1]https://microsoft.github.io/language-server-protocol/specifications/lsif/0.4.0/specification/

[2]http://spoon.gforge.inria.fr/

[3]https://github.com/INRIA/spoon/pull/3513

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2023-10-11 16:33:37

2024-04-18 08:11:57

R 樹空間索引技術(shù)R-tree

2024-01-10 08:33:15

R 樹R-tree圖形編輯器

2018-08-16 15:11:47

Code ReviewPPT代碼

2020-07-10 12:06:28

WebpackBundleless瀏覽器

2015-11-17 16:11:07

Code Review

2022-10-27 10:33:48

敏捷開發(fā)開發(fā)

2020-08-25 08:03:59

測試Sharness結(jié)構(gòu)

2016-09-23 18:32:42

iTunesIOS 10蘋果

2020-12-02 08:31:47

Elasticsear

2020-11-04 16:34:45

單元測試技術(shù)

2012-07-05 09:45:02

代碼審查

2013-10-24 09:43:58

代碼代碼審查

2022-06-17 11:10:43

PandasPolarsPython

2021-08-09 06:57:41

CodeReview流程

2021-04-25 09:19:22

騰訊Code Reviewleader

2009-08-05 09:59:40

Code Review代碼審查工具

2015-01-23 10:45:23

2020-05-27 11:25:48

開發(fā)技能代碼

2014-04-15 13:16:00

Code Review
點贊
收藏

51CTO技術(shù)棧公眾號