Gopls: 設計
未来からのメモ
以下は、2018 年から 2019 年にかけての様々な情報源から集約された gopls の元の設計ドキュメントです。それ以来、以下に挙げられた機能はすべて、他の多くの機能とともに実装されています。最初の 2 つの目標は達成されました。gopls は LSP の完全な実装であり、VS Code Go や他の多くのエディタのデフォルトのバックエンドです。3 番目の目標は部分的にしか実現されていません。gopls は多くの機能を得ましたが、このドキュメントで使われている意味での拡張性はありません。gopls を拡張する唯一の方法は gopls を変更することです。4 番目の目標は達成されていません。一部の著名な企業は Bazel で gopls を使用できていますが、そのエクスペリエンスは劣悪であり、Go コマンドは公式にサポートされている唯一のビルドシステムです。
一方で、明示的な非目標のうち 2 つは再考されました。1 つは軽微なものです。構文ハイライトは、セマンティックトークンによって LSP でサポートされるようになりました。もう 1 つは主要なものです。gopls の人気が高まるにつれて、そのメモリフットプリントが問題であることが明らかになりました。開発者ワークスペースのサイズは、一般的な開発環境 (特にコンテナ化された開発) で利用可能な RAM よりも速く増加していました。Gopls は現在、ディスク上のインデックスとインメモリキャッシュのハイブリッドを使用しており、詳細はスケーラビリティに関するブログ投稿で詳しく説明されています。
注目すべきは、このドキュメントが困難を予測する上で先見の明があったことです。Gopls は、その基盤となる標準ライブラリパッケージに対して確かに苦戦し、そのユーザーエクスペリエンスは依然として LSP によって制限されています。しかし、小規模なチームにもかかわらず、これらの決定は gopls が進化する Go 言語 (すなわちジェネリクス) に追随し、多くの新しいテキストエディタと統合するのに役立ったため、標準ライブラリと LSP に固執することが正しいアプローチでした。
Gopls の開発は、4 年以上経った今でも、シンプルさ、信頼性、拡張性に重点を置いて継続されています。新しいオプトインのGo テレメトリーは、Github の問題だけでは達成できなかった、リリースにおけるより高い安定性の基準を達成するのに役立つでしょう。さらに、テレメトリーにより、優先度の高い機能に集中し、コードベースに負担をかけている歴史的な回避策を廃止できるようになります。より高い速度で、改善されたリファクタリング、静的解析、そして未来がもたらすものについて、コミュニティと協力することを楽しみにしています。
- Rob Findley (rfindley@google.com)、2023 年
目標
goplsは Go プログラマが使用する主要なエディタのデフォルトのバックエンドとなり、Go チームによって完全にサポートされるべきです。goplsは、LSP 仕様に記載されているように、LSP の完全な実装となり、その機能の可能な限り多くを標準化します。goplsはクリーンで拡張性のあるものとなり、将来的に追加機能を包含し、Go ツールが再びクラス最高のツールとなることを可能にします。goplsは代替のビルドシステムとファイルレイアウトをサポートし、あらゆる環境で Go 開発をよりシンプルで強力なものにします。
コンテキスト
Go には開発者のエクスペリエンスを向上させる優れた便利なコマンドラインツールが多数ありますが、これらのツールを IDE と統合することは課題となり得ることが明らかになりました。
これらのツールのサポートは、コミュニティメンバーの厚意に頼っていましたが、言語、ツールチェーン、環境が変化するにつれて、時に大きなサポート負担を強いられてきました。その結果、多くのツールが動作しなくなったり、サポートの問題を抱えたり、フォークや代替品によって混乱を招いたり、本来あるべきほど優れたエクスペリエンスを提供できなくなったりしました。さらなる問題と詳細については、以下の「既存のソリューション」セクションを参照してください。
これは時々使用するツールであれば問題ありませんが、コア IDE 機能にとっては容認できません。オートコンプリート、定義へのジャンプ、フォーマット、およびその他のそのような機能は、Go 開発の鍵となるため、常に機能する必要があります。
Go チームは、あらゆるビルドシステムで機能するエディタバックエンドを作成します。また、各ツールが呼び出しごとに個別に型チェッカーを実行する必要がなくなり、代わりに長時間実行されるプロセスが存在し、定義、補完、診断、およびその他の機能間でデータを共有できるため、Go ツールのレイテンシも改善できるでしょう。
これらのツールの所有権を取得し、gopls の形でパッケージ化することで、Go チームは Go 開発のエクスペリエンスが Go ユーザーにとって不必要に複雑にならないようにします。1 つのエディタバックエンドを持つことは、Go 開発者、Go チーム、Go エディタプラグインのメンテナの生活を簡素化します。
詳細な背景については、Rebecca の素晴らしい GopherCon の基調講演トークとスライドを参照してください。
非目標
-
コマンドライン速度
gopls にはコマンドラインモードがありますが、コマンドの応答性ではなく長時間実行に最適化されるため、CI システムなどのツールには適さない場合があります。そのような場合は、整合性のために同じ基盤ライブラリを使用する代替ツールが必要になります。
-
低メモリ環境
非常に低いレイテンシで大規模なプロジェクトをうまく処理するために、gopls は多くの情報をメモリに保持します。開発者は通常、十分な RAM を持つシステムで作業していると想定されており、これは問題にならないでしょう。一般的に、これは既存の IDE ソリューション (IntelliJ など) の大きなメモリ使用量によって裏付けられています。
-
構文ハイライト
現在、この機能を別のバイナリに委譲するエディタはなく、標準的な方法もありません。
既存のソリューション
Go チームは毎年、開発者に言語のエクスペリエンスについて尋ねる調査を実施しています。
その質問の 1 つに「エディタについてどう感じますか?」というものがあります。
その回答は非常に否定的なものでした。いくつかの分類された引用
- セットアップ
- 「インストールと設定が難しい」
- 「ドキュメントが不十分」
- パフォーマンス
- 「パフォーマンスが非常に悪い」
- 「大規模プロジェクトではかなり遅い」
- 信頼性
- 「機能がある日は動作するが、次の日には動作しない」
- 「ツールが新しい言語機能で更新されない」
各エディタには独自のプラグインがあり、様々なツールを呼び出しますが、その多くは新しい Go リリースで壊れたり、メンテナンスされなくなったりしています。
個々のツールはそれぞれ、コードとそのすべての推移的な依存関係を理解する作業を行う必要があります。
各機能は異なるツールであり、コマンドラインのパターン、入力の受け入れ方と出力の解析方法、ソースコードの場所の指定方法が異なります。VSCode は、既存の機能セットをサポートするために 24 種類のコマンドラインツールをインストールしましたが、その多くには設定するためのオプションやフォークがあります。すべてのエディタでモジュールに移行する必要があったツールのセットを見ると、63 個の別々のツールがありました。
これらのツールはすべてコードを理解する必要があり、そのために同じ標準ライブラリを使用しています。これらのライブラリはこのような種類のツールに最適化されていますが、それでもこれだけの量のコードを処理するには多くの時間がかかります。ツールのほとんどは 100ms 以内に結果を返すことができません。開発者がエディタで入力すると、これらの機能の複数がアクティブになる必要があり、これはコストを一度だけでなく何度も支払っていることを意味します。全体的な効果は、遅く感じる編集体験と、有効になっていないか、あるいは非常にゆっくりと結果が表示されるため、到着しても役に立たない機能です。これはコードベースのサイズとともに増加する問題であり、時間の経過とともに悪化しており、企業が Go をより主要なタスクに使用するにつれて対処している大規模なコードベースの種類にとっては特に悪い問題です。
要件
完全な機能セット
gopls が成功と見なされるためには、以下で議論されている完全な機能セットを実装する必要があります。これは、ユーザーが置き換えられるツールと同等の生産性を感じるために必要な機能セットです。以前の実装のすべての機能が含まれているわけではありません。ほとんど使用されない機能 (guru のポインタ分析など) は削除し、簡単に適合せず、回避策を講じる必要がある機能 (保存フック/リンターの置き換えなど) もあります。
同等かそれ以上のエクスペリエンス
これらのすべての機能について、ユーザーエクスペリエンスは、すべてのエディタで現在利用可能なものと同等またはそれを超えるものでなければなりません。これは言うのは簡単ですが、検証したり測定したりするのは難しいことです。可能な測定の多くは、エクスペリエンスを捉えることができません。
たとえば、定義へのジャンプ呼び出しのレイテンシを測定しようとすると、古い godef ツールからの結果はかなり一貫していました。gopls の実装からのレイテンシの範囲ははるかに広くなる可能性があります。最高のものは桁違いに速く、最悪のものはわずかに悪いかもしれません。これは、gopls がはるかに多くの作業を行おうとしますが、呼び出し間でキャッシュできるためです。
あるいは、補完呼び出しの場合、遅くなるかもしれませんが、より良い最初のマッチを生成するため、ユーザーがより頻繁にそれを受け入れ、全体的に優れたエクスペリエンスにつながる可能性があります。
ほとんどの場合、これはユーザーレポートに頼る必要があります。エクスペリエンスが改善されていないためユーザーが切り替えを拒否している場合、明らかに未完成です。切り替えているがほとんどの人が不満を言っている場合、切り替えを魅力的にするのに十分なほど改善された領域がある一方で、悪くなった領域が他にもある可能性があります。ほとんどの人が切り替えていて、沈黙しているか肯定的な場合、おそらく完了しています。ツールを作成する際には、ユーザーがすべてです。
貢献者の強固なコミュニティ
gopls が解決しようとしている問題の範囲と規模は、コア Go チームにとって手に負えないものです。すべてを実現するには、強力なコミュニティが必要になります。
これは、コードが貢献しやすく、多くの開発者が並行して作業しやすいものでなければならないことを意味します。機能は適切に疎結合され、徹底的なテストストーリーを持っている必要があります。
ユーザーの許容範囲内のレイテンシ
ユーザーアクションの許容可能なレイテンシについて多くの研究が行われています。
gopls に影響する主な結果は、継続的なユーザーアクションに直接応答するフィードバックは、知覚できないように 100ms 未満である必要があり、200ms を超えるものはユーザーを苛立たせるということです。これは一般的に、開発者が入力する際に発生するすべてのものについて、目標が 100ms 未満である必要があることを意味します。gopls がこの期限を満たせないケースは常にあり、そのような場合にユーザーエクスペリエンスを許容できるようにする方法が必要ですが、一般的にこの期限の目的は基本的なアーキテクチャ設計を知らせることであり、長期的にはこの目標を理論的に達成できないソリューションは間違った答えです。
設定が簡単
開発者は非常にこだわりがあり、コーディング体験に対する欲求も大きく異なります。gopls は、それらの欲求を満たすために、かなりの柔軟性をサポートする必要があります。ただし、設定なしのデフォルト設定は、ほとんどのユーザーにとって最高のエクスペリエンスである必要があり、可能な場合は、クライアントが gopls との通信を変更することなく、処理に関する選択を簡単に行えるように、機能は設定なしで柔軟である必要があります。
困難
データ量
- 小
- 中
- 大
- 企業のモノレポ:はるかに大規模
大量のコードを解析して型チェックすることは非常にコストがかかり、変換された形式は多くのスペースを使用します。gopls は開発者が入力するたびにこの情報を更新し続ける必要があるため、メモリ使用量と速度のバランスをとるために、変換された形式をキャッシュする方法を非常に慎重に管理する必要があります。
キャッシュの無効化
型チェックの基本的な操作単位はパッケージですが、エディタの基本的な操作単位はファイルです。gopls はファイルをパッケージに効率的にマッピングできる必要があり、ファイルが変更されたときにどのパッケージを更新する必要があるか (およびそれに推移的に依存する他のパッケージも) を認識できるようにする必要があります。これは、ファイルのコンテンツを変更すると、それが属すると見なされるパッケージが変更される可能性がある (パッケージ宣言やビルドタグの変更によって) という事実、ファイルが複数のパッケージに含まれる可能性があるという事実、およびエディタを使用せずにファイルが変更される可能性があり、その場合、変更が通知されないという事実によって、特に困難になります。
不適切なコア機能
Go の基本ライブラリ (例: go/token、go/ast、go/types) はすべて、コンパイラのようなアプリケーション向けに設計されています。これらはメモリ使用量よりもスループットを重視する傾向があり、プログラム終了時に成長して破棄されることを意図した構造を持ち、処理するソースにエラーがあっても動作し続けるようには設計されていません。また、増分変更を行う機能もありません。
これらのライブラリで長時間実行されるサービスをうまく動作させることは非常に大きな課題ですが、新しいライブラリを作成することははるかに多くの作業であり、両方のライブラリセットを維持する必要があるため、長期的にかなりのコストが発生します。現時点では、動作するツールをユーザーの手に届けることがより重要です。長期的には、この決定を再検討する必要があるかもしれません。新しい低レベルライブラリが、機能を前進させ続ける唯一の方法となるかもしれません。
ビルドシステムの機能
gopls はビルドシステムに依存しないことになっていますが、ファイルがパッケージにどのようにマッピングされるかを検出するためにビルドシステムを使用する必要があります。そうしようとすると、機能が同じであっても、コスト (時間、CPU、メモリ) が大きく異なり、ユーザーエクスペリエンスに大きく影響する可能性があります。これらの違いを最小限に抑えるか隠すために、gopls がビルドシステムとどのように相互作用するかを設計することは困難です。
ビルドタグ
Go のビルドタグシステムは非常に強力で、多くのユースケースがあります。ソースファイルは、アクティブなタグのセットに対して強力なブール論理を使用して、それ自体を除外できます。しかし、これはコマンドラインでアクティブなタグのセットを指定するように設計されており、ライブラリはすべて一度に 1 つの有効な組み合わせにのみ対応するように設計されています。また、有効な組み合わせのセットを導き出す方法もありません。
ファイルを型チェックするには、同じパッケージ内の他のすべてのファイルの知識が必要であり、そのファイルのセットはビルドタグによって変更されます。パッケージのエクスポートされた識別子のセットも、どのファイルがパッケージに含まれているか、したがってそのビルドタグによって影響を受けます。
これは、ビルドタグ制御のないファイルやパッケージであっても、考慮すべきビルドタグのセットを知らなければ正しい結果を生成できないことを意味します。このため、ファイルを表示する際に有用な結果を生成することは非常に困難です。
LSP でサポートされていない機能
既存の LSP プロトコルに簡単には適合しないが、できるようになると良いことがいくつかあります。例えば、制御フロー情報の表示、自動構造体タグ、複雑なリファクタリングなどです。
各機能は慎重に検討し、LSP への変更を提案するか、すべてのエディタプラグインで使いやすいプロトコルへの gopls 固有の拡張機能を追加する必要があります。
これらを最初から避けるために、コア LSP 機能のみが実装されます。これらはベースライン要件を満たすのに十分だからです。しかし、潜在的な機能はコアアーキテクチャで考慮に入れておく必要があります。
配布
ユーザーが適切なバージョンの gopls を使用していることを確認することは問題になるでしょう。各エディタプラグインは、独自のやり方でツールをインストールする可能性が高く、システム全体にインストールすることを選択するものもあれば、独自のコピーを保持するものもあるでしょう。
これはまったく新しいツールであるため、急速に変化するでしょう。ユーザーが古いバージョンを使用していることを知らされていない場合、すでに修正済みの問題を経験することになり、これは彼らにとってより悪いことであり、その後おそらく問題を報告することになり、gopls チームの時間を無駄にすることになります。gopls が最新であるかどうかをチェックするメカニズムと、最新バージョンをインストールするための推奨される方法が必要です。
ユーザーの問題のデバッグ
gopls は本質的に、開発者のマシン上で非常に状態を持つ長時間実行されるサーバーです。その基本的な操作は、ユーザーの環境からローカルビルドキャッシュの内容まで、多くのものに影響されます。操作するデータは、多くの場合、共有できない機密コードベースです。これらすべてが、ユーザーが有用なバグを報告したり、最小限の再現を作成したりすることを困難にします。
ユーザーが可能な情報を簡単に報告できる方法と、状態全体を必要とせずに問題を再現しようとする方法が必要です。これは回帰テストを作成するためにも必要です。
基本的な設計上の決定
ツール設計の残りの大部分に影響を与え、ユーザーエクスペリエンスに影響する基本的なトレードオフを行う、いくつかの根本的なアーキテクチャ上の決定があります。
プロセス寿命: エディタによって管理される
大規模なコードベースを完全に型チェックし、レイテンシ要件内で分析することは実現不可能であり、既存のソリューションの主要な問題の1つです。計算された情報がディスクにキャッシュされたとしても、アナライザーと型チェッカーを実行すると、依存関係グラフ内のすべてのファイルの完全な AST が必要になるため、これは依然として当てはまります。理論的には改善可能ですが、既存の解析および型チェックライブラリを大幅に書き直す必要があり、現時点では実現不可能です。
これは、gopls が長時間実行されるプロセスであり、結果をメモリにキャッシュして事前計算することで、リクエストが到着したときに回答をはるかに高速に生成できる必要があることを意味します。
ユーザーのマシン上でデーモンとして実行することもできますが、デーモンの管理には多くの問題があります。長期的にはそれが正しい選択である可能性が高く、基本的なアーキテクチャ設計ではそれを許容すべきですが、当初は、起動したエディタと同じ期間持続し、簡単に再起動できるプロセスを持つことになります。
キャッシュ: メモリ内
永続的なディスクキャッシュは維持するのに非常にコストがかかり、多くの追加の問題を解決する必要があります。必要な情報の構築は、リクエストに必要なレイテンシと比較するとコストがかかりますが、エディタの起動時間と比較するとかなり軽微であるため、gopls が再起動されたときに情報を再構築することは許容されると予想されます。
これにより得られる利点は、gopls が再起動間でステートレスになることで、問題が発生したり、状態が混乱したりした場合でも、単純な再起動で問題が解決することが多いということです。また、ユーザーが問題を報告する際に、ディスク上のキャッシュの全状態が問題の診断と再現に必要ないことも意味します。
通信: stdin/stdout JSON
LSP 仕様は通常使用される JSON メッセージを定義していますが、それらのメッセージがどのように送信されるかを定義していません。また、JSON を使用しない LSP の実装もあります (例えば、プロトコルバッファはオプションです)。
gopls の制約は、すべてのエディタのすべてのオペレーティングシステムに簡単に統合できなければならないこと、および大規模な外部依存関係を持たないことです。
JSON は Go の標準ライブラリの一部であり、LSP のネイティブ言語でもあるため、最も理にかなっています。圧倒的に最もサポートされている通信メカニズムはプロセスの標準入力と出力であり、一般的なクライアント実装はすべてこのモードでJSON rpc 2を使用する方法を持っています。Go にはこのプロトコルの完全で依存関係の少ない実装はありませんでしたが、JSON ライブラリの上のかなり小さなプロトコルであり、中程度の労力で実装でき、とにかく一般的に有用なライブラリとなるでしょう。
将来的には、分離されたクライアントサーバーモードで実行されることが予想されるため、最初から stdin/stdout の代わりにソケットを使用できる方法で記述することが、それが可能であることを確認するための最良の方法でした。また、エディタの外で gopls サーバーを手動で実行して監視/デバッグできることは、デバッグの大きな助けにもなりました。
他のツールを実行する: いいえ
機能
gopls が包括的な IDE ソリューションとなるために公開する必要がある機能のセットがあります。以下は、既存のソリューションと LSP へのマッピング方法とともに、最小限の機能セットです。
内省
内省機能は、開発者が作業中にコードに関する情報を伝えます。変更を加えたり示唆したりすることはありません。
| Diagnostics | コンパイルエラーや lint エラーを含むコードの静的解析結果 |
|---|---|
| 必要 | 完全な go/analysis の実行。完全な AST、型、SSA 情報が必要。 |
| LSP | textDocument/publishDiagnostics |
| 以前 | go build、go vet、golint、errcheck、staticcheck |
| これは、コンパイラやチェッカーをシェルで実行する必要なく、迅速なターンアラウンドを可能にする最も重要な IDE 機能の 1 つです。IDE の問題リスト、ガターマーカー、波線の下線などに利用されることがよくあります。 ユーザーが実行されるチェックのセットをカスタマイズできるようにするために、できればメインの LSP バイナリを再コンパイルする必要なく、いくつか複雑な設計作業を行う必要があります。 |
| ホバー | カーソル下のコードに関する情報。 |
|---|---|
| 必要 | ファイルおよびすべての依存関係の AST および型情報 |
| LSP | textDocument/hover |
| 以前 | godoc、gogetdoc |
| コードを読んでいるときに、コンパイラには既知だがコードからは常に明らかではない情報を表示するために使用されます。例えば、識別子の型やドキュメントを返す場合があります。 |
| シグネチャヘルプ | 関数パラメータ情報とドキュメント |
|---|---|
| 必要 | ファイルおよびすべての依存関係の AST および型情報 |
| LSP | textDocument/signatureHelp |
| 以前 | gogetdoc |
| 関数呼び出しがコードに入力されているときに、開発者が正しく呼び出すことができるように、その呼び出しのパラメータを知ることは役立ちます。 |
ナビゲーション
ナビゲーション機能は、開発者がコードベース内を簡単に見つけられるように設計されています。
| 定義 | 識別子を選択し、その識別子が定義されたコードにジャンプします。 |
|---|---|
| 必要 | ファイルおよびすべての依存関係の完全な型情報 |
| LSP | textDocument/declaration |
textDocument/definition |
|
textDocument/typeDefinition |
|
| 以前 | godef |
| シンボルが定義されている場所をエディタに開くように要求することは、利用可能な IDE 内で最も一般的に使用されるコードナビゲーションツールの 1 つです。特に、慣れないコードベースを探索する際に非常に価値があります。 コンパイラの出力の制限により、このタスクにバイナリデータを使用することはできません (具体的には、列情報がわからないため)。したがって、ソースから解析する必要があります。 |
| 実装 | インターフェースを実装する型を報告します |
|---|---|
| 必要 | 完全なワークスペースの型知識 |
| LSP | textDocument/implementation |
| 以前 | impl |
| この機能は大規模なコードベースへのスケーリングが難しく、正しく実装するには検討が必要です。それまでの間は、より限定的な形式で実装することも可能かもしれません。 |
| ドキュメントシンボル | 現在のファイル内のトップレベルシンボルのセットを提供します。 |
|---|---|
| 必要 | 現在のファイルのみの AST |
| LSP | textDocument/documentSymbol |
| 以前 | go-outline、go-symbols |
| アウトラインモードなどを駆動するために使用されます。 |
| 参考文献 | カーソル下のシンボルへのすべての参照を検索します。 |
|---|---|
| 必要 | 逆推移閉包の AST および型情報 |
| LSP | textDocument/references |
| 以前 | guru |
| これには、現在のファイルが属する可能性のあるすべてのパッケージに依存する可能性のあるすべてのパッケージの知識が必要です。過去には、これはグローバルな知識によって実装されていましたが、これはスケーラブルではありません。あるいは、「スコープ」を指定することによって実装されていましたが、これはユーザーを混乱させ、ツールを使用しなくなるほどでした。gopls は長期的にはより強力なソリューションが必要になる可能性がありますが、最初はスコープを自動的に制限することで許容できる結果が得られるかもしれません。これはおそらく、既知であればモジュール、そうでなければ何らかの合理的な親ディレクトリになるでしょう。 |
| 折りたたみ | ブロックの論理的な階層を報告します |
|---|---|
| 必要 | 現在のファイルのみの AST |
| LSP | textDocument/foldingRange |
| 以前 | go-outline |
| これは通常、エディタで展開および折りたたみ動作を提供するために使用されます。 |
| 選択 | カーソル周辺の論理的な選択領域を報告します |
|---|---|
| 必要 | 現在のファイルのみの AST |
| LSP | textDocument/selectionRange |
| 以前 | guru |
| 選択範囲の拡大などのエディタ機能で使用されます。 |
編集支援
これらの機能は、リファクタリング機能を含む、ユーザーのためのコードへの編集を提案または適用します。リファクタリングには多くの潜在的なユースケースがあります。リファクタリングは、Go ツールが潜在的に非常に強力になる可能性があるが、これまでそうではなかった分野の 1 つであり、したがって開発者エクスペリエンスを向上させる大きな可能性があります。しかし、人々が必要とするリファクタリングの種類や、それをどのように表現すべきかについて、まだ明確な理解はなく、この点に関して LSP プロトコルには弱点があります。これは、それがより研究プロジェクトになる可能性が高いことを意味します。
| フォーマット | ファイルのフォーマットを修正します |
|---|---|
| 必要 | 現在のファイルの AST |
| LSP | textDocument/formatting |
textDocument/rangeFormatting |
|
textDocument/onTypeFormatting |
|
| 以前 | gofmt、goimports、goreturns |
| 標準のフォーマットパッケージを使用します。 現在の制限は、不正な形式のコードでは機能しないことです。不正な AST のフォーマットを許可するか、AST を有効なモードに強制するために、フォーマッタに非常に慎重な変更が必要になるかもしれません。これらの変更は、範囲モードとファイルモードも改善しますが、onTypeFormatting には基本的に不可欠です。 |
| インポート | 使用されているシンボルに合わせてインポートブロックを自動的に書き換えます。 |
|---|---|
| 必要 | 現在のファイルの AST と、すべての候補パッケージの完全なシンボル知識。 |
| LSP | textDocument/codeAction |
| 以前 | goimports、goreturns |
| これには、まだ使用されていないパッケージの知識と、それらのパッケージを名前で検索する機能が必要です。 また、検出したすべてのパッケージのエクスポートされたシンボル情報も必要です。 標準の imports パッケージを使用して実装する必要がありますが、一部の相互作用では、ファイル全体を書き換えるだけでなく、よりきめ細かい API を公開する必要があるかもしれません。 |
| オートコンプリート | 現在入力中のエンティティを補完する候補を提示します。 |
|---|---|
| 必要 | ファイルおよびすべての依存関係の AST および型情報 また、すべてのパッケージの完全なエクスポートされたシンボル知識も必要です。 |
| LSP | textDocument/completion |
completionItem/resolve |
|
| 以前 | gocode |
| オートコンプリートは最も複雑な機能の 1 つであり、より多くの情報を知っているほど提案が改善されます。たとえば、まだインポートされていないパッケージでも、公開シンボルがあればオートコンプリートできます。作成しているプログラムの種類を知っていれば、オプションの提案を改善できます。通常どのように関数を呼び出すかを知っていれば、より良い引数を提案できます。一般的なコードパターンを知っていれば、パターン全体を提案できます。特定のタスクを持ち、そのタスクが完了すれば機能も完了する他の多くの機能とは異なり、オートコンプリートは決して完成しません。候補とそれらの順位付けの両方をバランスさせ、改善することは、今後長い間研究課題となるでしょう。 |
| 名前変更 | 識別子の名前を変更します |
|---|---|
| 必要 | 逆推移閉包の AST および型情報 |
| LSP | textDocument/rename |
textDocument/prepareRename |
|
| 以前 | golang.org/x/tools/cmd/gorename |
| これは、参照の検索と同じ情報を使用し、同じ問題と制限をすべて抱えています。提案される変更が誤った結果を許容しないため、若干悪化します。パッケージのパブリック API を変更するために使用することも危険です。 |
| 提案された修正 | コードを変更するために手動または自動で承認できる提案 |
|---|---|
| 必要 | 完全な go/analysis の実行。完全な AST、型、SSA 情報が必要。 |
| LSP | textDocument/codeAction |
| 以前 | N/A |
| これは新しい go/analysis エンジンによって強化された真新しい機能であり、膨大な量の自動リファクタリングを可能にするはずです。 |
このドキュメントのソースファイルは、golang.org/x/tools/gopls/doc の下にあります。