iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🧐

[Unity] Enabling C# Standard Library IntelliSense Hints in Rider and VS Code

に公開
Update History

Fixed an issue where it didn't work properly on environments other than Windows + Unity 6!

The familiar issue in Unity projects with Visual Studio / VS Code where hints for the C# standard library are not displayed.

👇 This is a Unity editor extension to solve this problem.

You will no longer need to open your browser to check the differences between things like FileMode Create, CreateNew, and Truncate — those options you only use occasionally and kind of understand, but not quite.

Contains Quite Important Information

The XML documentation for C# BCL IntelliSense is quite extensive. For libraries created before Nullable Reference Types (NRT) existed, important supplemental information is often provided in the API comments.

This one returns XElement rather than XElement?, so even with #nullable enable, no null warning is issued. And if it's not found, it throws an NRE at runtime.

Other examples include Path.GetTempFileName(), which is a method named "FileName" but returns a full path, or Path.GetTempPath(), which has a DirectorySeparatorChar appended to the end (!). You'll be able to check these subtle specifications of early APIs right within your IDE.

Execution Results / Supported Environments

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

VS Code

Since it doesn't use any tricks other than brute force, it works in VS Code too!

👇

Rider (macOS)

Rider inherently shows hints even in Unity projects, but using ApiDocumentationCollector enriches (?) the content.

Note: Attributes added uniquely by Rider, such as Pure, will be preserved.

While Visual Studio and VS Code do not display exception tags even if they exist, Rider seems to display them. It's helpful not to have to guess based on the exception type!

From this 👉 👇 To this

By the way, the Pure attribute seems to be self-declared. It seems the code will compile even if there are side effects.

  • Note: In recent versions of VS, a note appears regardless of whether it's a pure function, asking if it's okay to discard the LINQ return value.

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

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

As a minor detail, GetTempPath has a quirky specification where DirectorySeparatorChar is appended to the end, but this is not documented. Therefore, even for Rider, it's worth updating using ApiDocumentationCollector.

C# API Documentation for IDE

To load the documentation into your IDE, install ApiDocumentationCollector and execute the process from Unity's main menu.

Installation

Perform this via the Unity Package Manager (UPM).

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

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

Usage

Items will be added to the Unity main menu, so select your desired language and execute.

Select from the menu 👉 👇 Select execution mode from the dialog
Promotion → Escalation is more common
  • Yes, Download and Execute
    • After downloading, displays the following privilege escalation dialog and automatically executes the copy task.
  • Yes, but Download Only
    • Only performs downloading and batch command generation.
  • Cancel
    • Cancels the operation.

You need to execute this for each version of the Unity Editor, and it requires approximately 250 500 MB of disk space, which is larger than the assemblies themselves.

Additionally, about 300 MB of space is required for the NuGet package download cache shared across all Unity versions.

Privilege Escalation Dialog

Since files need to be copied to the system drive, a privilege escalation dialog will be displayed after downloading.

macOS Windows (Image)

Generated Batch Commands

This is a list of copy commands from NugetClient.TempFolderPath.

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

On macOS, it looks like the following. It also performs chmod +x automatically.

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

Multi-language Support

If translation data for the specified language is not found, it falls back to the default language (English).

Chinese

German

French

Korean

NugetClient

A small NuGet client is included.

  • HttpClient
    • Allows you to set a custom client.
  • TryGetPackageUrl(string, string? out string)
    • Retrieves the download URL from a package name.
  • TryDownloadPackageFile(string, out string)
    • Downloads a ZIP file from the specified URL.
  • Timeout
    • Sets the default network timeout. This does not apply to the following asynchronous methods.
  • TryGetPackageUrlAsync(string, string?, CancellationToken)
    • Retrieves the download URL from a package name. Returns null on failure.
  • TryGetAvailableVersionAsync(string, CancellationToken)
    • Retrieves all versions of a package. Returns null on failure.
  • TryDownloadPackageFileAsync(string, CancellationToken)
    • Attempts to save the ZIP file to the cache folder. Returns null on failure.
  • TryDownloadPackageAsync(string, CancellationToken)
    • Attempts to download the ZIP data. Returns null on failure.

Dependency resolution is not supported. Since the ZIP doesn't contain anything like package.json, it seems necessary to handle it using the 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

There was also an official C# SDK.

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

Conclusion

Miscellaneous Talk

(I'm writing this based on my general understanding without deep research)

.NET Standard was released either before or just after it became open-source, so it is (was) distributed as a common monolithic library.

  • For example, core functions are in mscorlib.dll (the classic 8+3 filename lol), netstandard.dll, etc.

Recent versions of Unity include System.Threading.Tasks.dll and System.Reactive.*.dll (!), but these might just be performing type forwarding to the assemblies mentioned above, or maybe not. (Since it was a transitional period, the progress varies by library and type.)

Visual Studio loads the XML file of the "assembly where the type is actually defined," so this needs to be handled properly. While ApiDocumentationCollector performs some checks, it doesn't go as far as tracking which file a type is forwarded to or removing unnecessary types from the XML, which makes the files a bit large.

That's all. Thank you for your time.

Discussion