🧐

【Unity】C# 標準ライブラリにもヒントが表示されるようにする【Rider / VS Code】

に公開
更新履歴

Windows + Unity 6 以外で上手く行かない問題に対処!

Unity プロジェクト + Visual Studio / VS Code でお馴染みの C# 標準ライブラリのヒントが表示されない問題。

👇 この問題を解決するための Unity エディター拡張です。

たまにしか使わない FileMode Create CreateNew Truncate のような、分かるようで分からん奴の違いって何だっけ? って時にブラウザを開かなくて良くなります。

結構重要な情報が含まれている

C# BCL の IntelliSense 用の XML ドキュメントはかなり充実していて、Null 許容参照型(NRT: Nullable Reference Types)がまだ無かった頃に作られたライブラリなんかは API コメントで重要な補足が行われていたりします。

コイツは XElement? ではなく XElement を返すので #nullable enable していてもヌル警告が出ません。そして見つからなかった場合は実行時に NRE を投げます。

他にも Path.GetTempFileName() はファイル名ってメソッドだけどフルパスを返すとか、Path.GetTempPath() は末尾には DirectorySeparatorChar が付与されている(!)とか、初期に作られた API の微妙な仕様が IDE 上で確認できるようになります。

実行結果/対応環境

  • Unity 2021.3 ... Unity 6
  • Windows / macOS
  • Visual Studio / Rider / VS Code

VS Code

力技以外のトリックは使っていないので VS Code でも動きます!

👇

Rider(macOS)

Rider はもともと Unity プロジェクトでもヒントが表示されますが、ApiDocumentationCollector を使うと内容が拡充(?)されます。

※ Rider が独自に追加した Pure のような属性は引き継がれた状態になります。

Visual Studio や VS Code では例外タグの内容が存在しても表示されませんが Rider だと表示されるようです。例外の型からエスパーしなくて良いのは助かりますね!

これが 👉 👇 こうなる

ちなみに Pure 属性は自己申告制みたいですね? 副作用があってもコンパイルは通るようです。

※ 最近の VS だと純粋関数とか関係なく LINQ の戻り値破棄して大丈夫そ? って注釈が出る

https://www.jetbrains.com/help/rider/Reference__Code_Annotation_Attributes.html#PureAttribute

https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.contracts.pureattribute

重箱の隅ですが、GetTempPath は末尾に DirectorySeparatorChar が付くっていうクソ仕様があるのにその旨記載されていなかったりするので、元々表示される Rider でも ApiDocumentationCollector を使って更新するのはアリです。

C# API Documentation for IDE

IDE にドキュメントを読み込むには ApiDocumentationCollector をインストールして、Unity のメインメニューから処理を実行します。

インストール

Unity パッケージマネージャー(UPM)から行います。

https://github.com/sator-imaging/Unity-Fundamentals.git

https://github.com/sator-imaging/Unity-Fundamentals

使い方

Unity のメインメニューに項目が追加されるので使用言語を選択して実行します。

メニューから選んで 👉 👇 ダイアログから実行モードを選択
Promotion → Escalation の方が一般的
  • Yes, Download and Execute
    • ダウンロードを行った後、以下の権限昇格ダイアログを表示し自動でコピータスクを実行します。
  • Yes, but Download Only
    • ダウンロードとバッチコマンドの生成のみを行います。
  • Cancel
    • キャンセルします。

Unity エディターのバージョンごとに実行する必要があり、アセンブリー本体より重い 250 500 MB 程度のディスク容量が必要になります。

また、全 Unity バージョンで共有する nuget パッケージのダウンロードキャッシュに 300 MB 程度の容量が必要になります。

権限昇格ダイアログ

システムドライブにファイルをコピーする必要があるため、ダウンロード後に権限昇格ダイアログが表示されます。

macOS Windows(イメージ)

生成されるバッチコマンド

NugetClient.TempFolderPath から copy するコマンドの羅列です。

pushd "..."
copy "Accessibility.xml"              "...Data\UnityReferenceAssemblies\unity-4.8-api\Accessibility.xml"
copy "i18n.XML"                       "...Data\UnityReferenceAssemblies\unity-4.8-api\i18n.XML"
copy "Microsoft.Build.Engine.xml"     "...Data\UnityReferenceAssemblies\unity-4.8-api\Microsoft.Build.Engine.xml"
copy "Microsoft.Build.Framework.xml"  "...Data\UnityReferenceAssemblies\unity-4.8-api\Microsoft.Build.Framework.xml"
..
.
timeout /nobreak -1

macOS は以下のような感じ。chmod +x も自動で行います。

#!/bin/sh
pushd "..."
cp "..." "..."
..
.
exit

多言語対応

指定した言語の翻訳データが見つからなかった場合は既定の言語(英語)にフォールバックします。

中国語

ドイツ語

フランス語

韓国語

NugetClient

ちょっとした nuget クライアントが付属しています。

  • HttpClient
    • 独自のクライアントを設定できます。
  • TryGetPackageUrl(string, string? out string)
    • パッケージ名からダウンロード URL を取得します。
  • TryDownloadPackageFile(string, out string)
    • 指定した URL から ZIP ファイルをダウンロードします。
  • Timeout
    • 既定のネットワークタイムアウトを設定します。以下の非同期メソッドには適用されません。
  • TryGetPackageUrlAsync(string, string?, CancellationToken)
    • パッケージ名からダウンロード URL を取得します。失敗した場合はヌルを返します。
  • TryGetAvailableVersionAsync(string, CancellationToken)
    • パッケージのすべてのバージョンを取得します。失敗した場合はヌルを返します。
  • TryDownloadPackageFileAsync(string, CancellationToken)
    • ZIP ファイルのキャッシュフォルダーへの保存を試みます。失敗した場合はヌルを返します。
  • TryDownloadPackageAsync(string, CancellationToken)
    • ZIP データのダウンロードを試みます。失敗した場合はヌルを返します。

依存関係の解決には対応していません。Zip に package.json 的なモノは含まれていないので、REST API で上手いことやる必要があるようです。

https://learn.microsoft.com/en-us/nuget/api/registration-base-url-resource#registration-page

https://learn.microsoft.com/ja-jp/nuget/api/registration-base-url-resource#package-dependency-group

C# SDK(公式)もあったようです。

https://learn.microsoft.com/en-us/nuget/reference/nuget-client-sdk

おわりに

四方山話

(何も調べずにそれっぽいことを書いています)

.NET Standard はオープンソース化される前、または OSS になった直後にリリースされたものなので、よくあるモノシリックなライブラリーとして配布されています。(いました)

※ 例えばコア機能は mscorlib.dll(8+3文字w)や netstandard.dll 等々

最近の Unity には System.Threading.Tasks.dllSystem.Reactive.*.dll(!)なんかが付属していますが、これらは上記アセンブリへタイプフォワーディングするだけのモノになっていたり、なっていなかったりします。(過渡期だったのでライブラリ/型ごとに進行状況がバラバラ)

Visual Studio は「実際に型が定義されているアセンブリ」の XML ファイルを読み込むため、そこら辺上手いことやる必要があります。ApiDocumentationCollector はある程度のチェックはしていますが、どのファイルに転送されるかだったり不要な型を XML から取り除くことまではやっていないので、ちょっとファイルが重くなっています。

以上です。お疲れ様でした。

Discussion