iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0

在我完成 auto-conjure 和 Conjure Piglet Client 這兩個專案的期間,開發過程中,最讓我痛苦的事,莫過於缺少了跳轉定義這個功能。所以,第三個專案,我就決定來實作這個功能。而且,我考慮把它直接實做在 Conjure Fennel Client 裡,然後去對 Conjure 提交 Pull Request

問題概述

為了釐清到底該如何做出這個功能,我讓 LLM 解釋「編輯器的跳轉定義」通常怎麼實作。而 LLM 回答:

一個語言伺服器如何實現 "jump to definition" 呢?它會執行以下步驟:

  1. 程式碼解析 (Parsing):語言伺服器會讀取你的 Fennel 程式碼,並將其解析成一個抽象語法樹 (Abstract Syntax Tree, AST)。這個樹狀結構準確地表示了你的程式碼的結構和語義。
  1. 符號分析 (Symbol Analysis):在解析過程中,伺服器會識別出所有重要的符號(symbols),例如:變數 (variables), 函數 (functions), 宏 (macros), 鍵值對 (key-value pairs)。
  1. 定義與引用關聯 (Definition-Reference Linking):伺服器會建立一個映射表,將每個符號的使用位置與它的定義位置關聯起來。例如,當你在程式碼中呼叫 (my-function x) 時,伺服器會找到 (defn my-function ...) 的那一行,並將它們連結起來。
  1. 提供給編輯器:當你在編輯器中按下 "jump to definition" 的快捷鍵時,編輯器會向語言伺服器發送一個請求,告訴它:「用戶現在在檔案 A 的第 10 行第 5 列,請告訴我這裡的符號定義在哪裡。」
  1. 回傳結果:語言伺服器根據它的內部映射表,回傳定義的位置(檔案、行號、列號),然後編輯器會自動跳轉到該位置。

解題架構

考慮到此一功能的用戶就是我,所以軟體規格我來決定就可以了。而我決定讓功能盡可能地簡化,讓軟體早日上線。

我做了三個簡化:

  1. 我選擇使用 Tree-sitter 來解析程式碼,而不是 Fennel 自己的 parser 。這樣子,我的跳轉定義就無法處理 Macro 。但是,我認為,跳轉 Macro 的機率遠低於跳轉函數的機率,而 Tree-sitter 簡單得太多了。
  2. 我捨棄使用 Language Server Protocol ,直接實作在 Conjure 裡。這樣子也會簡單很多,只是我的這個功能就無法跨編輯器使用。
  3. 我捨棄『前置程式碼解析』,改成使用『即時程式碼解析』,而這又讓問題更簡單了一些。

它的運作方式如下:

  1. Conjure Fennel Client 收到「跳轉定義」的指令後,會觸發 def-str-util.search-and-jump 函數。
  2. search-and-jump 裡,它會用 Tree-sitter 來解析程式碼、並且進一步解析模組的檔案位置,最後找出要跳轉的位置。
  3. 跳轉。

小結

我在開發時,很多問題都會參考看看 LLM 怎麼說;而且,我喜歡把策略/執行分開問。

然而,在策略的層次,LLM 常常提供了標準解法,這並不意味著你的使用情境最適合標準解法,所以過度依賴 LLM 有時候可能反而走更遠的路。


上一篇
專案研討—CBOR
下一篇
專案研討—跳轉定義背後的 Tree-sitter
系列文
在 Neovim 中探索 Fennel 與函數式編程26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言