Hata's Blog

goplsのソースコードの歩き方

本記事ではGoのLanguage Serverであるgoplsのソースコードを読む際に役立つであろう、プロジェクトのディレクトリ構成やアーキテクチャについて軽く紹介します。

goplsとは

goplsとは、オープンソースのGo言語のLanguage Serverです。Goで書かれています。 goplsは、VSCodeなどのエディタでGoの開発する際に、補完や定義ジャンプ、リファクタリングなどの機能を提供します。普段Goで開発されている方は、普段何気なく使っているのではないでしょうか。 goplsについては以下でも紹介しておりますので、合わせてご覧ください。

GoのLanguage Server Protocol実装、 「gopls」の自動補完の仕組みを学ぶGo Conference 2024の資料です ※13枚目に誤解を招く表現がありました。Golandのバックエンドはgoplsではなく独自のものです。
favicon of https://speakerdeck.com/shohata/gonolanguage-server-protocolshi-zhuang-gopls-nozi-dong-bu-wan-noshi-zu-miwoxue-buspeakerdeck.com
ogp of https://files.speakerdeck.com/presentations/8cba039186a644158679fd86e4bca3f9/slide_0.jpg?30528649

ソースコードへのアクセス

goplsのソースコードはGitで取得できます。

GitHub - golang/tools: [mirror] Go Tools[mirror] Go Tools. Contribute to golang/tools development by creating an account on GitHub.
favicon of https://github.com/golang/toolsgithub.com
ogp of https://opengraph.githubassets.com/83bf1a069470350b99572a75912a246c650693a2aa3d89c352b34644ccd11079/golang/tools

機能へのアクセスの仕方

goplsは「定義ジャンプ」や「補完」など、Language Serverが提供する機能を一通り実装しています。

それぞれの機能ごとに、各機能の簡単な紹介、クライアントのサポート状況、既存の問題点などがドキュメントにまとめています。 たとえばフォーマットやシンボルの変換機能を提供するtransfomationについては以下のページに記載があります。 https://github.com/golang/tools/blob/master/gopls/doc/features/transformation.md#formatting

以下のインデックスページにそれぞれの機能ごとに概要がまとめられているので、まずはここから、自分の調べたい機能について調べてみるのが良いでしょう。

https://github.com/golang/tools/blob/master/gopls/doc/features/README.md

なお、機能によってはTODOになっているものもあります(例:補完機能)。

アーキテクチャ・設計

調べたい機能についての概要がわかったら、次にその機能がどのように実装されているかを調べていきます。 ソースコードを読んでいくにあたって、まず全体像を把握しておかないとどこから読んでいけばいいのかわかりません。

以下の図は、Goのimportの依存関係に基づいたコンポーネント群の関係が示されています(gopls公式より拝借)。

img

最下層は、LSP(Language Server Protocol)のリクエストとレスポンスの型を定義するパッケージが配置されています。 その上の層には、RPC に関連するパッケージ(lsprpc や server)、Goの関連ファイル(golang、mod、work、template など)に関連するパッケージが配置されています。

https://github.com/golang/tools/blob/master/gopls/doc/design/implementation.md

上記のドキュメントには、先ほどの図を含めたgoplsの設計について詳しく記載されています。こちらを参考にしながら、ソースコードを読んでいくと理解が深まるでしょう。

探検の始め方

大枠について理解したところで、ソースコードの探検を始めていきましょう。

さきほどの図は、主要コンポーネントを完全なリストではないので詳細は省かれていますが、主要機能(例:定義ジャンプ、補完、フォーマット)のコアとなる処理は、internal/golang/に配置されています。

手っ取り早く機能のコアロジックから追っていきたい場合

このディレクトリから該当の機能と対応したファイルを探し、読み始めると良いでしょう。 ちなみに補完処理に関しては複雑な機能のため、さらにcompletionパッケージに分かれています。

サーバーのエントリーポイントから追っていきたい場合

goplsはLauguage Server、つまりサーバーなので、クライアントからのリクエストを受け取り、それに対してレスポンスを返すという基本的な機能を持っています。普段、Web APIを開発している方は、Serverパッケージから読み始めると理解しやすいです。 https://github.com/golang/tools/blob/master/gopls/internal/protocol/tsserver.go#L168 あたりにリクエストハンドラが実装されているので、調べたい機能のケースから追っていくと追いやすいです。

探検道具

設計ドキュメント

各機能ごとではなく、全体の設計について知りたい場合は以下のドキュメントが参考になります。goplsが目標としていること、逆に目標としていないこと、アーキテクチャ決定などが記載されています。 また、goplsはコミュニティ開発者作のツール群を統合したものであるため、統合前のツールへアクセスできるリンクも記載されています。

https://github.com/golang/tools/blob/master/gopls/doc/design/design.md

Github Copilot Chat

goplsのコードリーディングでは、VSCode限定になってしまいますが、Github Copilot Chatがおすすめです。goplsの全体やファイルのコンテキストを読み取って質問しながら進めることで、格段に効率的なコードリーディングができます。

まとめ

本記事ではgoplsのソースコードを読む際に役立つであろう、プロジェクトのパッケージ構成やアーキテクチャについて軽く紹介しました。goplsについての解説記事はまだまだ少ないので、この記事がgoplsのソースコードを読みとくきっかけになれば幸いです。

x(Twitter)にポスト
Profile
Shoki Hata

決済領域のソフトウェアエンジニア。週末はコーヒー豆を焙煎しています。