Gopls: パッシブ機能
このページでは、goplsの基本的なLSP機能のうち、「パッシブ」と表現できるものについて説明します。多くのエディタでは、特別な操作を必要とせずにソースファイルに関する情報を継続的に提供するためにこれらの機能を使用しているためです。
「コードレンズ」も参照してください。その一部は、ソースコードに追加情報でアノテーションを付け、パッシブ機能と見なすこともできます。
ホバー
LSPのtextDocument/hoverクエリは、カーソル下のコードに関する説明(名前、種類、型、値(定数の場合)、省略された宣言(型の場合)、ドキュメントコメント(もしあれば)、およびpkg.go.dev上のシンボルのドキュメントへのリンクなど)を返します。クライアントはプレーンテキストまたはMarkdownを要求できます。
選択に応じて、応答には追加情報が含まれる場合があります。たとえば、型にホバーすると、その宣言されたメソッドと、埋め込みフィールドから昇格されたすべてのメソッドが表示されます。
ドキュメントリンク: ドキュメントコメントは角括弧を使用して他のシンボルを参照できます。たとえば、[fmt.Printf]などです。これらのドキュメントリンクのいずれかにホバーすると、参照されているシンボルに関する情報が表示されます。
構造体サイズ/オフセット情報: 構造体型の宣言の場合、名前にホバーすると構造体のバイト単位のサイズが表示されます
また、各フィールド名にホバーすると、そのフィールドのサイズとオフセットが表示されます
この情報は、データ構造のレイアウトを最適化する場合や、各フィールドを不可解なバイトオフセットで参照するアセンブリファイルやスタックトレースを読み取る場合に役立つことがあります。
さらに、ホバーは以下を報告します
- 構造体のサイズクラス。これは、この型の単一オブジェクトに対してGoランタイムによって実際に割り当てられるバイト数です。
- 構造体フィールドの順序が最適ではないために無駄になったスペースの割合(この数値が20%以上の場合)
上記の構造体では、アラインメント規則により、2つのブールフィールド(1バイト)がそれぞれ完全なワード(8バイト)を占有する必要があり、(7 + 7) /(3 * 8)= 58%の無駄が発生します。2つのブールフィールドを一緒に配置すると、1ワード節約できます。(ほとんどの構造体では、簡潔さよりも明瞭さが重要であるため、プロファイリングによって非常に頻繁に割り当てられることが示されたデータ構造の場合にのみ、スペースを節約するためにフィールドを並べ替える必要があります。)
埋め込みディレクティブ: //go:embedディレクティブ内のファイル名パターン、たとえば*.htmlにホバーすると、ワイルドカードが展開されるファイル名のリストが表示されます。
リンク名ディレクティブ: //go:linknameディレクティブは、別のシンボルに対してリンカーレベルのエイリアスを作成します。ディレクティブにホバーすると、その別のシンボルに関する情報が表示されます。
Go 1.0以降に追加された標準ライブラリのシンボルに対するホバー情報には、そのシンボルが追加されたGoリリースが記載されています。
設定
hoverKind設定は、ドキュメントの詳細度を制御します。linkTarget設定は、GoパッケージリンクのベースURIを指定します。
注意点
- LSPの残念な制限として、現在
Hoverリクエストには位置のみが含まれ、選択は含まれません。これは、たとえば、より大きな式f(x).yのf(x)部分の型とメソッドに関する情報を要求することが不可能であることを意味します。この問題に対処してほしい場合は、microsoft/language-server-protocol#1466に賛成票を投じてください。
クライアントサポート
- VS Code: デフォルトで有効。カーソル付近のパネルにレンダリングされたMarkdownを表示します。
- Emacs + eglot: デフォルトで有効。エコーエリアに1行の概要を表示します。
- Vim + coc.nvim: ??
- CLI:
gopls definition file.go:#start-#endには、Hoverクエリからの情報が含まれます。
シグネチャヘルプ
LSPのtextDocument/signatureHelpクエリは、カーソルまたは選択範囲を囲む最も内側の関数呼び出しに関する情報(関数のシグネチャ、各パラメータの名前、型、ドキュメントなど)を返します。
クライアントは、この情報を提供して、ユーザーが関数呼び出しを読んだり編集したりする際に、各パラメータの目的と順序を思い出すのに役立ちます。
カーソルが関数またはメソッドを示す識別子内にある場合、呼び出しの括弧は必要ありません。たとえば、once.Do(initialize‸)でのシグネチャヘルプは、once.Doではなくinitializeについて説明します。
クライアントサポート
- VS Code: デフォルトで有効。IntelliSense設定では「パラメータヒント」とも呼ばれます。Hover情報と並んでシグネチャとドキュメントコメントを表示します。
- Emacs + eglot: デフォルトで有効。エコーエリアにシグネチャを表示します。
- Vim + coc.nvim: ??
- CLI:
gopls signature file.go:#start-#end
ドキュメントハイライト
LSPのtextDocument/documentHighlightクエリは、現在のカーソル位置または選択に基づいてハイライトされるべきソース範囲のセットを報告し、それらの関係を強調します。
以下の構文の各部分はセットを形成し、いずれかのメンバーを選択すると、goplsは完全なセットをハイライトします
- 同じシンボルを参照する各識別子(以下のスクリーンショットを参照)。
- 名前付きの結果変数と、
returnステートメントの対応するすべてのオペランド。 - 同じループの
for、break、continueトークン。 - 同じswitchステートメントの
switchとbreakトークン。 - 関数の
funcキーワードと、そのすべてのreturnステートメント。
たとえば、returnオペランドでもある識別子によって、これらの複数のルールが単一の選択によってアクティブ化される場合があります。
同じ識別子の異なる出現箇所は、特定の変数シンボルへの「読み取り」参照と「書き込み」参照を区別するために色分けされる場合があります。
クライアントサポート
- VS Code: デフォルトで有効。カーソルの移動またはシングルクリックでトリガーされます。(注:ダブルクリックは単純な構文に依存しないテキストマッチをアクティブにします。)
- Emacs + eglot: デフォルトで有効。カーソルの移動または選択でトリガーされます。
- Vim + coc.nvim: ??
- CLI:
gopls signature file.go:#start-#end
インレイヒント
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)を提供します。
例を含む完全なリストについては、インレイヒントを参照してください。
設定
hints設定は、必要なヒントのセットを示します。気が散るのを減らすため、デフォルト値は空です。ヒントを有効にするには、上記の一意の識別子をヒントマップに1つ以上追加します。たとえば"hints": {"parameterNames": true}
クライアントサポート
- VS Code:
hints構成値に加えて、VS Codeは、サポートされている各種類のインレイヒントに対してグラフィカルな構成メニュー(「設定を開く(UI)」で「Goインレイヒント」を検索)を提供します。 - Emacs + eglot: デフォルトで無効。
M-x eglot-inlay-hints-modeと、ここで説明されている構成が必要です。 - Vim + coc.nvim: ??
- CLI: 未サポート
セマンティックトークン
LSPのtextDocument/semanticTokensクエリは、現在のファイルまたはその一部のすべてのトークンに関する情報を報告します。クライアントは、この情報を使用して、たとえば、関数と型、定数と変数、またはライブラリ関数と組み込み関数の間の意味的な区別を伝える構文ハイライトを提供できます。
クライアントは、関心のある型と修飾子のセットを指定する必要があります。
Goplsは次のトークン型を報告します
"comment": コメント"function": 関数"keyword": キーワード"label": 制御ラベル(LSP標準型ではありません)"macro": テキスト/テンプレートトークン"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"
設定
semanticTokens設定は、goplsがセマンティックトークンリクエストに応答するかどうかを決定します。このオプションにより、クライアントが機能に対するクライアント側の制御を提供しない場合でも、ユーザーはセマンティックトークンを無効にできます。goplsのセマンティックトークンアルゴリズムは、型チェックに依存しており、これが目に見えるレイテンシを追加するため、現在この機能は構文ハイライトの遅延を避けるためにデフォルトで無効になっています。参照:https://go.dokyumento.jp/issue/#45313、https://go.dokyumento.jp/issue/#47465。- 実験的な
noSemanticStringおよびnoSemanticNumber設定は、一部のクライアントがこれらのトークンをよりカラフルにハイライトする場合があるため、サーバーが応答からstringおよびnumberの種類を除外するようにします。参照:https://go.dokyumento.jp/issue/45753。
クライアントサポート
- VS Code: セマンティックハイライトガイドを参照してください。
- Emacs + eglot: 未サポート。joaotavora/eglot#615を参照してください。
- Vim + coc.nvim: ??
- CLI:
gopls semtok file.go
折りたたみ範囲
LSPのtextDocument/foldingRangeクエリは、現在のファイル内で個別に折りたたみまたは展開できる領域のリストを報告します。たとえば、コードを調査する際に、長いコメントや関数を折りたたむと、より多くのコードが1つの画面に収まり、便利になる場合があります。
このプロトコルは、クライアントが、一致する括弧のペアのようなきめ細かい範囲を好むか、完全な行で構成される範囲のみを好むかを示すことを許可しています。
クライアントサポート
- VS Code: 左余白に表示されます。山形記号(
∨および>)を切り替えて、折りたたんだり展開したりします。 - Emacs + eglot: 未サポート。
- Vim + coc.nvim: ??
- CLI:
gopls folding_ranges file.go
ドキュメントリンク
LSPのtextDocument/documentLinkクエリは、現在のファイルのドキュメントコメントと文字列リテラルからURLをヒューリスティックに抽出し、クライアントがそれらをクリック可能なリンクとして表示できるようにします。
明示的なURLに加えて、goplsはインポート宣言の文字列リテラルも、インポートされたパッケージのpkg.go.devドキュメントへのリンクに変換します。
設定
importShortcut設定は、import宣言に対して返されるリンクの種類を決定します。linkTarget設定は、GoパッケージリンクのベースURIを指定します。
クライアントサポート
- VS Code: リンクにホバーすると、「リンクをたどる (cmd+click)」ポップアップが表示されます。
- Emacs + eglot: 現在は使用されていません。
- Vim + coc.nvim: ??
- CLI:
gopls links file.go
このドキュメントのソースファイルは、golang.org/x/tools/gopls/doc の下にあります。