dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.99k stars 4.03k forks source link

Make MetadataDisplayFormat public #72844

Open tmat opened 6 months ago

tmat commented 6 months ago

Background and Motivation

After a compilation is emitted and the resulting image is loaded, we need to find a type in the loaded Assembly that corresponds to a source INamedTypeSymbol defined in the compilation.  

Proposed API

namespace Microsoft.CodeAnalysis;

public class SymbolDisplayFormat
{
+   SymbolDisplayFormat MetadataDisplayFormat { get; }
}

Implemented like so: https://github.com/dotnet/roslyn/blob/cf8b467a73d6f7d5ad96b12d1ba457bdc7109992/src/Compilers/Core/Portable/SourceGeneration/Nodes/SyntaxValueProvider_ForAttributeWithMetadataName.cs#L60-L61

Usage Examples

var qualifiedTypeName = typeSymbol.ToDisplayString(SymbolDisplayFormat.MetadataDisplayFormat);
var type = Assembly.GetType(qualifiedTypeName);

Alternative Designs

Risks

333fred commented 6 months ago

API Review

Conclusion: Needs work. Exposing a UsePlusForNestedTypes option seems reasonable by itself. A format would then need to be very precise as to what it supports and where.

tmat commented 6 months ago

My bad, I didn't notice that s_metadataDisplayFormat is only used by tests and is not the full implementation of fully qualified name.

The intention was to allow the code written in the usage example - that is, given a ITypeSymbol return a fully qualified metadata name in the format that System.Reflection parses to load a type. See https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/Reflection/TypeNameParser.cs.

This format is also used in ECMA-335 when serializing the value of System.Type for custom attribute blob. This is implemented by the compiler here: https://github.com/dotnet/roslyn/blob/main/src/Compilers/Core/Portable/PEWriter/TypeNameSerializer.cs

Examples:

typeof(X<int*[]>.Y<string>[,,]))
X`1+Y`1[[System.Int32*[], System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]][,,]
typeof(X<>.Y<>)
X`1+Y`1