Searching code with Sourcegraph

Ben Hoyt

使用 Sourcegraph 搜尋程式碼

原文由 Ben Hoyt 發布,訂閱此部落格

Sourcegraph 是一款用於搜尋與瀏覽大型程式碼庫的工具。該工具提供多種搜尋方式,包括正規表示式搜尋,以及具備語言感知能力、相對較新的「結構化搜尋」。工具的開源核心具備程式碼搜尋、跳至定義以及其他「程式碼智慧」功能,能幫助開發者理解橫跨多個儲存庫的程式碼庫。Sourcegraph 的程式碼搜尋工具能在滑鼠懸停時顯示函式與方法的說明文件,並讓開發者快速跳至定義或找出特定識別字的所有參照。

Sourcegraph 伺服器主要以 Go 撰寫,核心以 Apache License 2.0 釋出;各種「企業版」擴充功能則採用專有授權。Sourcegraph 背後的公司每個月都會釋出新版本,其中最新版本(3.18)改善了對 C++ 的支援,而3.17 版本則帶來更快、更精準的程式碼搜尋,並支援 ANDOR 搜尋運算子。

程式碼搜尋

Sourcegraph 的主要功能是能夠橫跨一個或多個儲存庫搜尋程式碼。即使一次搜尋數百個儲存庫,結果通常也能在一兩秒內回傳。預設的查詢模式是字面搜尋,會完全按照字面比對"foo bar" 這樣的搜尋字串,包含引號在內。點擊搜尋列右側的 .* 圖示可切換為正規表示式搜尋,這兩種搜尋模式都支援區分大小寫的比對(點擊 Aa 圖示即可)。

[Sourcegraph 搜尋]

[] 圖示則會切換為「結構化搜尋」,這是由任職於 Sourcegraph 的 Rijnard van Tonder 為其 Comby 專案所打造的搜尋語法。結構化搜尋具備語言感知能力,在處理巢狀表示式與多行陳述式方面比正規表示式更為出色。結構化搜尋的查詢常用來找出潛在的錯誤或可簡化的程式碼,例如,針對以下內容的查詢

    fmt.Sprintf(":[str]")

這會找出開發者可以省去 fmt.Sprintf() 呼叫的地方——也就是當它只有單一參數且該參數僅為字串字面值時。

文件中有一份架構圖,展示了 Sourcegraph 安裝後會執行的各種處理程序。另有一份更詳細的「搜尋查詢的生命週期」說明。前端會先在查詢中尋找 repo: 過濾條件,以決定需要搜尋哪些儲存庫。伺服器將儲存庫清單與大多數其他 Sourcegraph 詮釋資料一併儲存在 PostgreSQL 資料庫中;Git 儲存庫則會以一般方式複製並儲存在檔案系統中。

接著,伺服器會判斷哪些儲存庫已建立索引(若查詢中指定了特定版本,則針對該版本判斷),以及哪些尚未建立索引:儲存庫的索引建立與已索引的搜尋,皆由以 Go 撰寫、基於 trigram 的程式碼搜尋函式庫 zoekt 處理。(對使用 trigram 搜尋程式碼感到好奇的讀者,或許會對 Go 技術負責人 Russ Cox 撰寫的相關文章感興趣)。

尚未建立索引的儲存庫版本,則由另一個獨立的「searcher」處理程序負責(可透過 Kubernetes 進行水平擴展)。它會從 Sourcegraph 的伺服器(即 gitserver)取得儲存庫的 zip 壓縮檔,並逐一遍歷其中的檔案,使用 Go 的 regexp 套件進行正規表示式搜尋的比對,或使用 Comby 函式庫進行結構化搜尋。預設情況下,僅會為儲存庫的預設分支建立索引,但 Sourcegraph 3.18 新增了為非預設分支建立索引的能力

程式碼智慧

Sourcegraph 的第二項主要功能是該公司所稱的「程式碼智慧」:能夠導向游標所在變數或函式的定義,或找出其所有參照。預設情況下,這些功能使用「基於搜尋的啟發式方法,而非將程式碼解析為 AST[抽象語法樹]」,但在我實際測試中,這些啟發式方法的準確度似乎相當高。該工具能毫無問題地找到 C、Python 和 Go 中的定義,甚至能找到 Python 中動態指派的定義(例如能夠跳至我在scandir 專案中被指派與重新指派的 scandir_python 名稱的定義)。

較近期,Sourcegraph 使用微軟的 Language Server Index Format(LSIF)實作了更精準的程式碼搜尋功能(相較於搜尋啟發式方法,改為使用特定語言的解析樹),這是一種以 JSON 為基礎、用於儲存語言工具的索引器所擷取資料的檔案格式。Sourcegraph 已自行撰寫或維護多個語言的 LSIF 索引器,包括 GoC/C++Python(皆採用 MIT 授權)。目前,Sourcegraph 中的 LSIF 支援為選用功能,根據文件所述:「它提供了快速且精準的程式碼智慧,但需要定期產生並上傳至你的 Sourcegraph 執行個體。」Sourcegraph 的建議是在每次提交時都產生並上傳 LSIF 資料,但開發者也可以設定定期任務,以較低的頻率進行索引。

程式碼智慧查詢可分為三種類型:懸停查詢(擷取與符號相關的說明文件以顯示為「懸停文字」)、跳至定義查詢,以及尋找參照查詢。若有精準的 LSIF 資訊可用,就會優先使用,否則 Sourcegraph 會退回使用基於 Ctags 與搜尋相結合的「模糊」結果。

開源嗎?

Sourcegraph 採用開放核心授權,但其交付方式有些不尋常:所有原始碼,包括專有程式碼,都放在同一個公開儲存庫中,但在 enterprise/web/src/enterprise/ 目錄下的程式碼適用 Sourcegraph Enterprise 授權,其餘程式碼則採用 Apache 授權。Sourcegraph 提供的預先建置 Docker 映像檔包含了企業版程式碼「以提供平順升級至 Sourcegraph Enterprise 的路徑」,但儲存庫中也提供了可用來建置完全開源映像檔的建置指令碼。企業版程式碼中包含一項檢查,會禁止超過十位使用者使用,但在開源建置版本中則不會包含該檢查。整體而言,開源版本的建置與安裝文件並不完善,其設定指令碼也可能缺少某些步驟——確實給人一種次等公民的感覺。

Sourcegraph(公司)營運著該系統的代管版本,讓任何人都能搜尋來自各程式碼代管平台的「熱門」公開儲存庫。目前不清楚「熱門」是如何定義的,也不確定此代管版本究竟索引了哪些儲存庫,但這個版本確實很好地展示了可用的功能。該公司的定價頁面列出了僅限企業版使用的功能,包括:Campaigns 多儲存庫重構工具、對多個程式碼代管平台的支援、客製化品牌、即時培訓課程等。

安裝設定

如其安裝文件所示,使用 docker-compose 方式安裝預先建置的 Sourcegraph 映像檔十分快速。只需幾分鐘就能啟動並執行,再花幾分鐘進行設定。由於我是在本機上執行,因此使用了 ngrok 通道來(暫時)提供一個支援 https 的對外網域(執行時並非必要,但若有提供,某些功能會運作得更好)。更為快速的單一指令 Docker 安裝方式也能正常運作,但我決定試試 docker-compose 選項:它看起來稍微更貼近實際情況,因為它被推薦用於中小型正式環境部署,而不僅僅是本地測試。對於更大規模、需高可用性的部署,Sourcegraph 建議在 Kubernetes 叢集上部署

設定過程幾乎不需要什麼配置:建立管理員使用者,並將系統指向程式碼代管平台(以我的情況來說,需要建立一個 GitHub 存取權杖,讓 Sourcegraph 能存取我在 GitHub 上的公開與私有儲存庫)。一旦加入存取權杖,Sourcegraph 就開始複製並索引這些儲存庫。幾分鐘後,就可以開始搜尋了。該系統針對自行託管進行了最佳化;推測該公司希望讓開發者能輕鬆為少數測試使用者完成設定(然後在超過十位使用者時再要求付費)。

其中一項可能會讓某些人卻步的「功能」,是 Sourcegraph 所稱的「pings」;預設情況下,該工具約每 30 分鐘會向 https://sourcegraph.com/.api/updates.com 發送一次 POST 請求「以協助我們的產品與客戶團隊」。這項「關鍵遙測」包含「初始站點安裝者的電子郵件地址」與「現有使用者帳號總數」,推測是為了讓公司能在達到十位使用者門檻時,嘗試聯繫安裝者以推銷其企業版方案。此功能只能透過修改原始碼來關閉(ping 的程式碼位於開源核心中,因此有人可以將這一行註解掉來移除它)。預設情況下,系統也會針對某些產品功能發送彙整後的使用資訊,但這可以透過設定 DisableNonCriticalTelemetry 配置變數來關閉。值得肯定的是,Sourcegraph 對其「ping 理念」相當坦率,並明確表示絕不會發送原始碼、檔案名稱或具體的搜尋查詢。

瀏覽器與編輯器整合

除了搜尋伺服器與網頁介面外,Sourcegraph 還為 Chrome 和 Firefox 提供了瀏覽器擴充功能,讓使用者在 GitHub 和 GitLab 等代管平台上瀏覽時也能使用其功能。舉例來說,當在 GitHub 上審查 pull request 時,安裝了 Sourcegraph 擴充功能的開發者可以快速跳至定義、尋找所有參照,或查看特定介面的實作。自 2019 年 6 月起,GitHub 也擁有類似功能,其使用自家的 semantic 函式庫,不過 Sourcegraph 的瀏覽器擴充功能似乎更為強大(例如,它能找到結構體欄位,而不僅僅是函式與方法)。Sourcegraph 的瀏覽器擴充功能會盡量讓開發者留在 github.com 上,但對於某些連結與定義,則會導向 Sourcegraph 執行個體的網址。

Sourcegraph 也為四款熱門編輯器(Visual Studio Code、Atom、IntelliJ 和 Sublime Text)提供了編輯器整合。這些外掛讓開發者能在 Sourcegraph 中開啟目前檔案,或使用 Sourcegraph 搜尋選取的文字(外掛會在瀏覽器中開啟結果)。這些瀏覽器擴充功能與編輯器外掛符合 Sourcegraph 的其中一項原則:「我們最終希望成為一個將開發者使用的所有工具串連起來的平台」。

總結

Sourcegraph 的開發過程也相當開放,針對即將到來的 3.193.20 版本設有追蹤議題,以及一份開發中的路線圖。除了針對核心(搜尋與程式碼智慧)規劃的諸多改進,例如達到「OpenGrok 對等」的水準之外,看來該公司也正在開發其雲端服務,而 Campaigns 功能也將迎來大幅改進。

Sourcegraph 看起來是一套設計良好的系統,頗具實用性,尤其適合大型程式碼庫與大型開發團隊。事實上,文件也暗示該工具可能不太適合小型團隊:「Sourcegraph 對處理較大型程式碼庫或團隊(15 位以上開發者)的開發者更有用。」有些人也可能因支援不足的開源建置版本與會回傳資訊的「pings」而卻步;不過,看起來仍有一些人堅持使用開源版本並成功讓它運作起來。

本文章由 muse-spark-1.2-contributor 進行翻譯

留言