Gopls:被動特性

本頁介紹了 gopls 的基本 LSP 特性,這些特性可以被描述為“被動的”,因為許多編輯器會持續使用它們來提供有關原始碼檔案的資訊,而無需採取任何特殊操作。

另請參閱 程式碼提示,其中一些會用額外資訊註解您的原始碼,因此也可以被視為被動特性。

懸停 (Hover)

LSP 的 textDocument/hover 查詢會返回游標下程式碼的描述,例如其名稱、種類、型別、值(對於常量)、縮略宣告(對於型別)、文件註釋(如果存在),以及指向 pkg.go.dev 上符號文件的連結。客戶端可以請求純文字或 Markdown 格式。

根據選定內容,響應可能包含額外資訊。例如,懸停在型別上會顯示其宣告的方法,以及從嵌入欄位中提升的任何方法。

文件連結:文件註釋可以使用方括號引用其他符號,例如 [fmt.Printf]。懸停在其中一個 文件連結 上會顯示有關被引用符號的資訊。

結構體大小/偏移量資訊:對於結構體型別的宣告,懸停在名稱上會顯示結構體的位元組大小

懸停在每個欄位名稱上會顯示該欄位的大小和偏移量

這些資訊在最佳化資料結構的佈局、或在閱讀引用每個欄位的彙編檔案或堆疊跟蹤(其中按模糊的位元組偏移量引用欄位)時可能很有用。

此外,懸停還會報告

  • 結構體的 size class,即 Go 執行時為該型別單個物件實際分配的位元組數;以及
  • 由於結構體欄位排序不佳而浪費的空間百分比,如果該數值為 20% 或更高

在上面的結構體中,對齊規則要求兩個布林欄位(1 位元組)各自佔用一個完整的字(8 位元組),導致 (7 + 7) / (3 * 8) = 58% 的浪費。將兩個布林值放在一起可以節省一個字。(在大多數結構體中,清晰度比緊湊性更重要,因此您應該僅在效能分析顯示分配非常頻繁的資料結構中才重新排序欄位以節省空間。)

嵌入指令:懸停在 //go:embed 指令中的檔名模式(例如 *.html)會顯示萬用字元展開到的檔名列表。

Linkname 指令//go:linkname 指令為另一個符號建立連結器級別的別名。懸停在指令上會顯示其他符號的資訊。

對於 Go 1.0 之後新增到標準庫的符號,懸停資訊會顯示新增該符號的 Go 版本。

設定 (Settings)

  • hoverKind 設定控制文件的詳細程度。
  • linkTarget 設定指定 Go 包連結的基礎 URI。

注意事項 (Caveats)

  • LSP 的一個不幸限制是,Hover 請求當前只包含一個位置,而不包含選定範圍。這意味著無法請求有關較大表達式 f(x).yf(x) 部分的型別和方法的資訊。如果您希望看到這個問題得到解決,請為您在 microsoft/language-server-protocol#1466 上點贊。

客戶端支援 (Client support)

  • VS Code:預設啟用。在游標附近顯示渲染的 Markdown 面板。
  • Emacs + eglot:預設啟用。在回顯區顯示單行摘要。
  • Vim + coc.nvim: ??
  • CLIgopls definition file.go:#start-#end 包含來自 Hover 查詢的資訊。

簽名幫助 (Signature Help)

LSP 的 textDocument/signatureHelp 查詢會返回包含游標或選定範圍的最內層函式呼叫資訊,包括函式的簽名以及每個引數的名稱、型別和文件。

客戶端可以提供此資訊,以幫助使用者在閱讀或編輯函式呼叫時記住每個引數的目的及其順序。

如果游標位於表示函式或方法的識別符號內,則不需要呼叫括號。例如,在 once.Do(initialize‸) 中進行簽名幫助會描述 initialize,而不是 once.Do

客戶端支援 (Client support)

  • VS Code:預設啟用。在 IntelliSense 設定中也稱為“引數提示”。與 Hover 資訊一起顯示簽名和文件註釋。
  • Emacs + eglot:預設啟用。在回顯區顯示簽名。
  • Vim + coc.nvim: ??
  • CLIgopls signature file.go:#start-#end

文件高亮 (Document Highlight)

LSP 的 textDocument/documentHighlight 查詢會報告一組應根據當前游標位置或選定範圍進行高亮的源範圍,以強調它們之間的關係。

以下語法部分的每一部分都形成一個集合,因此如果您選擇其中任何一個成員,gopls 都會高亮整個集合:

  • 引用同一符號的每個識別符號(如下面的截圖所示);
  • 一個命名結果變數及其所有對應的 return 語句的運算元;
  • 同一迴圈的 forbreakcontinue 關鍵字;
  • 同一 switch 語句的 switchbreak 關鍵字;
  • 函式的 func 關鍵字及其所有 return 語句。

一個選擇可能啟用以上多條規則,例如,透過一個既是識別符號又是 return 運算元的識別符號。

同一識別符號的不同出現可能被著色,以區分對給定變數符號的“讀取”和“寫入”引用。

客戶端支援 (Client support)

  • VS Code:預設啟用。透過游標移動或單擊觸發。(注意:雙擊會啟用簡單的、不考慮語法的文字匹配。)
  • Emacs + eglot:預設啟用。透過游標移動或選定範圍觸發。
  • Vim + coc.nvim: ??
  • CLIgopls signature file.go:#start-#end

插入提示 (Inlay Hint)

LSP 的 textDocument/inlayHint 查詢會返回一組註釋,這些註釋將被插入到當前檔案中,以揭示隱式資訊。

示例

  • 在函式呼叫 f(1, 2) 中,提示會提供引數的名稱(parameterNames),如上圖所示。
  • 在呼叫泛型函式時,提示會提供型別引數(functionTypeParameters)。
  • 在賦值 x, y = 1, 2 中,提示會提供變數的型別(assignVariableTypes)。
  • 在結構體字面量(如 Point2D{1, 2})中,提示會提供欄位名稱(compositeLiteralFields)。
  • 在巢狀的複合字面量 T{{...}} 中,提示會提供內部字面量 {...} 的型別(compositeLiteralTypes)。
  • for k, v := range x {} 迴圈中,提示會提供變數 k 和 v 的型別(rangeVariableTypes)。
  • 對於常量表達式(可能使用 iota),提示會提供其計算值(constantValues)。

有關完整列表和示例,請參閱 插入提示

設定 (Settings)

  • hints 設定指示所需的提示集。為減少干擾,其預設值為空。要啟用提示,請將上面一個或多個識別符號新增到 hints 對映中。例如:
    "hints": {"parameterNames": true}
    

客戶端支援 (Client support)

  • VS Code:除了 hints 配置值外,VS Code 還提供了一個圖形化配置選單(“Preferences: Open Settings (UI)” 然後搜尋“Go Inlay Hints”),用於配置每種支援的插入提示型別。
  • Emacs + eglot:預設停用。需要 M-x eglot-inlay-hints-mode 以及 此處描述的配置。
  • Vim + coc.nvim: ??
  • CLI:不支援

語義令牌 (Semantic Tokens)

LSP 的 textDocument/semanticTokens 查詢會報告當前檔案或其一部分中所有令牌的資訊。客戶端可以使用這些資訊來提供語法高亮,以傳達例如函式與型別、常量與變數、或庫函式與內建函式之間的語義區別。

客戶端必須指定其感興趣的型別和修飾符集合。

Gopls 報告以下令牌型別:

  • "comment":註釋
  • "function":函式
  • "keyword":關鍵字
  • "label":控制標籤(非 LSP 標準型別)
  • "macro":text/template 令牌
  • "method":方法
  • "namespace":匯入的包名
  • "number":數字字面量
  • "operator":運算子
  • "parameter":引數變數
  • "string":字串字面量
  • "type":型別名稱(以及其他用途)
  • "typeParameter":型別引數
  • "variable":變數或常量(參見 readonly 修飾符)

Gopls 還報告以下標準修飾符:

  • "defaultLibrary":預宣告的符號
  • "definition":符號的宣告識別符號
  • "readonly":用於常量

以及這些非標準修飾符,每個代表該符號型別的頂層建構函式:

  • "array"
  • "bool"
  • "chan"
  • "interface"
  • "map"
  • "number"
  • "pointer"
  • "signature"
  • "slice"
  • "string"
  • "struct"

設定 (Settings)

客戶端支援 (Client Support)

  • VS Code:請參閱 語義高亮指南
  • Emacs + eglot:不支援;請參閱 joaotavora/eglot#615。
  • Vim + coc.nvim: ??
  • CLIgopls semtok file.go

摺疊範圍 (Folding Range)

LSP 的 textDocument/foldingRange 查詢會報告當前檔案中可以獨立摺疊或展開的區域列表。例如,在研究某些程式碼時,摺疊大型註釋或函式可能很方便,這樣可以在單個螢幕上顯示更多內容。

該協議 允許 客戶端指示它們更偏好細粒度範圍(如匹配的括號對),還是僅限完整行組成的範圍。

客戶端支援 (Client support)

  • VS Code:顯示在左邊距。透過切換箭頭(>)來摺疊或展開。
  • Emacs + eglot:不支援。
  • Vim + coc.nvim: ??
  • CLIgopls folding_ranges file.go

LSP 的 textDocument/documentLink 查詢使用啟發式方法從當前檔案中的文件註釋和字串字面量中提取 URL,以便客戶端可以將它們顯示為可點選連結。

除了顯式 URL 之外,gopls 還會將 import 宣告中的字串字面量轉換為指向已匯入包的 pkg.go.dev 文件的連結。

設定 (Settings)

  • importShortcut 設定決定為 import 宣告返回哪種型別的連結。
  • linkTarget 設定指定 Go 包連結的基礎 URI。

客戶端支援 (Client support)

  • VS Code:懸停在連結上會顯示“Follow link (cmd+click)”彈出視窗。
  • Emacs + eglot:目前未使用。
  • Vim + coc.nvim: ??
  • CLIgopls links file.go

本文件的原始碼可以在 golang.org/x/tools/gopls/doc 下找到。