跳至內容

以程式碼圖搜尋程式碼

本指南說明如何把程式庫納入程式碼圖,然後用它來回答你在重構之前真正會問的問題:有什麼依賴這個?

程式碼圖是一個符號與邊的資料庫,透過 tree-sitter 解析你已註冊的檢出而建立。它的工具面向代理——你需要透過詢問代理來使用它們。

程式碼圖會索引 Dart、JavaScript、TypeScript、TSX、PHP、Python、Rust、Zig、C、C++、Go、Java、Ruby、C#、Swift、Kotlin、R、Assembly、MATLAB 與 Ada。任何其他語言的檔案都不會被解析,所以不會出現在 search_code、code_symbol、code_callers、code_callees 或 code_impact 中。

還有兩件事會影響哪些內容會被索引:

  • 在 git 工作樹中,列舉會交由 git ls-files --cached --others --exclude-standard 決定,因此每個 .gitignore、巢狀忽略檔案、.git/info/exclude 以及全域排除檔案都會被遵循。這正是讓 node_modules 與建置輸出不會進入程式碼圖的原因。
  • 產生的 Dart 則一律會被捨棄。產生的檔案通常都已提交,所以單靠 git 並不會排除它們,而它們在每次執行程式碼產生時都會變動。

註冊檢出會觸發 RepoAdded,自動為它啟動 index_code 管線。參見將程式庫加入工作區。

如要手動重新索引:

  1. 開啟 設定 → 工作區 → 程式庫。
  2. 在程式庫那一列上按 索引程式碼 按鈕。
  3. 執行期間,按鈕會顯示已完成檔案數對總數,並附有取消控制項。完成後,它會變成一個帶有符號數量的勾號。

程式碼圖按工作區、程式庫與檢出分割:已連結的檢出是一個分割區,而每個空間 worktree 各有自己的分割區(以其隔離程式庫 id 為鍵)。

有兩個節流機制值得了解,因為它們能解釋一段看起來像當機的等待:

  • 檔案監看器在主機上一次只允許一次索引執行——第二個檢出必須等待。index_code 管線另外還限制每個工作區只能執行一次,所以同一個工作區中的兩個程式庫會排隊;不同工作區則可並行索引。索引器本身會序列化同一個檢出的兩次執行,因此管線啟動與監看器掃描不會重複解析它。
  • 屬於休眠空間(過去一週沒有任何訊息)的 worktree 既不會被監看,也不會被索引。已連結的檢出仍會被監看。略過決定會在五分鐘後重新檢查,因此重新活躍起來的空間會被重新納入。

請代理搜尋。工具是 search_code,它同時需要工作區與程式庫:

search_code(workspace_id: "...", repo_id: "...", query: "authentication middleware")

程式庫 id 來自 list_repos。選用的 mode 引數可為 keyword、semantic 或 hybrid,預設為 hybrid——在名稱、簽章與文件註解上套用 BM25,並與向量相似度融合。

每個結果會帶有符號的 id、名稱、完整限定名稱、種類、檔案路徑、起始與結束行,以及它的簽章(若有的話)。id 就是你餵給本頁其他每個工具的識別代碼。

當你知道確切名稱時,改為直接查詢:

code_symbol(workspace_id: "...", repo_id: "...", name: "MyClass")

兩者都接受來自搜尋結果的 symbol_id,以及選用的 limit(預設 50):

code_callers(workspace_id: "...", symbol_id: "...")
code_callees(workspace_id: "...", symbol_id: "...")

code_callers 會傳回有邊指向此符號的那些符號;code_callees 則傳回它所依賴的符號。

這正是整頁存在的理由:

code_impact(workspace_id: "...", symbol_id: "...", depth: 3)

它會計算反向依賴半徑:也就是沿著 calls、extends 與 implements 邊,直接或間接依賴該符號的所有東西(匯入、mixin 與泛型參照會儲存在圖中,但這裏不會走訪)。depth 是最大跳躍次數,介於 1 與 6 之間,預設為 2。

結果有三個欄位:

  • root——你所查詢的符號
  • impacted——可觸及的集合,包括深度為 0 的根,每個都帶有相對於根的 depth
  • edgeCount——走訪過程中跨越了多少條邊,是一個計數,而非邊本身

在重新命名或變更簽章之前先執行它,並把受影響清單交給代理作為其範圍。

結果會對照呼叫者自己的工作副本核對

標題為「結果會對照呼叫者自己的工作副本核對」的章節

若呼叫者是代理,空間 id 會自動注入,結果會對照該空間的工作副本核對。若某個符號的檔案已不存在於呼叫者的樹中,該符號會被省略,回應會帶有 staleOmitted 計數,以及一則說明這些符號的索引已過期的備註。

這就是為何你和代理對同一個查詢會得到不同答案,也是為何某個空間中的代理會與另一個空間中的代理得到不同答案。同一個空間中每則對話共用那一個 worktree。核對會以失敗放行的方式處理:寧可給出過期的答案,也不要空白的答案。

當你想要某項變更的影響半徑時,請代理執行 code_impact(或 review_studio.blastRadius)。參見審查運算。

符號與事實會在寫入時嵌入,而且只有在裝置上已安裝嵌入模型時才會這樣做。在此之前,mode: "semantic" 以及 hybrid 的語意部分沒有任何東西可供比對,搜尋實際上只靠關鍵字。

請在建立索引之前,於 設定 → 伺服器 → 診斷與私隱 → 語意搜尋 安裝模型。符號會在其檔案被匯入時取得向量。

另請注意,任何重新建置伺服器二進位檔的動作都會重新預備語法 dylib 並改變其 mtime,這會令每個索引檢查點失效,並在下次執行時迫使對每個檢出完整重新走訪一次。它會重新計算雜湊,但不會重新擷取未變更的檔案。

符號種類: 函式、方法、類別、欄位、列舉、建構子、getter、setter、typedef、擴充、mixin、變數。

邊的種類: calls、imports、extends、implements、mixes in、references。

這些工具的標準簽章位於 MCP 工具。