diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
index fdd395fe520a0..a37abf7a0c116 100644
--- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -192,7 +192,7 @@
-
+
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs
index 6f74dde91fe7e..c95e1630a04a1 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs
@@ -270,12 +270,12 @@ internal static unsafe MarshalAsAttribute GetMarshalAs(ConstArray nativeType, Ru
: Text.Encoding.UTF8.GetString(MemoryMarshal.CreateReadOnlySpanFromNullTerminated(marshalCookieRaw));
RuntimeType? safeArrayUserDefinedType = string.IsNullOrEmpty(safeArrayUserDefinedTypeName) ? null :
- TypeNameParser.GetTypeReferencedByCustomAttribute(safeArrayUserDefinedTypeName, scope);
+ TypeNameResolver.GetTypeReferencedByCustomAttribute(safeArrayUserDefinedTypeName, scope);
RuntimeType? marshalTypeRef = null;
try
{
- marshalTypeRef = marshalTypeName is null ? null : TypeNameParser.GetTypeReferencedByCustomAttribute(marshalTypeName, scope);
+ marshalTypeRef = marshalTypeName is null ? null : TypeNameResolver.GetTypeReferencedByCustomAttribute(marshalTypeName, scope);
}
catch (TypeLoadException)
{
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs
index 53f2690948df4..3af48057a870e 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs
@@ -249,7 +249,7 @@ private static partial void GetTypeCoreIgnoreCase(QCallAssembly assembly,
{
ArgumentException.ThrowIfNullOrEmpty(name);
- return TypeNameParser.GetType(name, topLevelAssembly: this,
+ return TypeNameResolver.GetType(name, topLevelAssembly: this,
throwOnError: throwOnError, ignoreCase: ignoreCase);
}
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs
index 38663e57cde24..e00b0b1854a36 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs
@@ -543,7 +543,7 @@ private static object EncodedValueToRawValue(PrimitiveValue val, CustomAttribute
}
private static RuntimeType ResolveType(RuntimeModule scope, string typeName)
{
- RuntimeType type = TypeNameParser.GetTypeReferencedByCustomAttribute(typeName, scope);
+ RuntimeType type = TypeNameResolver.GetTypeReferencedByCustomAttribute(typeName, scope);
Debug.Assert(type is not null);
return type;
}
@@ -899,7 +899,7 @@ private static CustomAttributeType ParseCustomAttributeType(ref CustomAttributeD
throw new BadImageFormatException();
}
- enumType = TypeNameParser.GetTypeReferencedByCustomAttribute(enumTypeMaybe, module);
+ enumType = TypeNameResolver.GetTypeReferencedByCustomAttribute(enumTypeMaybe, module);
if (!enumType.IsEnum)
{
throw new BadImageFormatException();
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs
index 4e9a4dffeb209..43760e17b4d98 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs
@@ -403,7 +403,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont
{
ArgumentException.ThrowIfNullOrEmpty(className);
- return TypeNameParser.GetType(className, topLevelAssembly: Assembly,
+ return TypeNameResolver.GetType(className, topLevelAssembly: Assembly,
throwOnError: throwOnError, ignoreCase: ignoreCase);
}
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameParser.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.CoreCLR.cs
similarity index 89%
rename from src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameParser.CoreCLR.cs
rename to src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.CoreCLR.cs
index 35fa0b5718e38..78e2422b34104 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameParser.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.CoreCLR.cs
@@ -4,6 +4,7 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
+using System.Reflection.Metadata;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
@@ -11,7 +12,7 @@
namespace System.Reflection
{
- internal partial struct TypeNameParser
+ internal partial struct TypeNameResolver
{
private Func? _assemblyResolver;
private Func? _typeResolver;
@@ -55,13 +56,13 @@ internal partial struct TypeNameParser
return null;
}
- Metadata.TypeName? parsed = Metadata.TypeNameParser.Parse(typeName, throwOnError: throwOnError);
+ TypeName? parsed = TypeNameParser.Parse(typeName, throwOnError);
if (parsed is null)
{
return null;
}
- return new TypeNameParser()
+ return new TypeNameResolver()
{
_assemblyResolver = assemblyResolver,
_typeResolver = typeResolver,
@@ -79,7 +80,7 @@ internal partial struct TypeNameParser
bool ignoreCase,
Assembly topLevelAssembly)
{
- Metadata.TypeName? parsed = Metadata.TypeNameParser.Parse(typeName, throwOnError);
+ TypeName? parsed = TypeNameParser.Parse(typeName, throwOnError);
if (parsed is null)
{
@@ -90,7 +91,7 @@ internal partial struct TypeNameParser
return throwOnError ? throw new ArgumentException(SR.Argument_AssemblyGetTypeCannotSpecifyAssembly) : null;
}
- return new TypeNameParser()
+ return new TypeNameResolver()
{
_throwOnError = throwOnError,
_ignoreCase = ignoreCase,
@@ -110,8 +111,8 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName,
RuntimeAssembly requestingAssembly = scope.GetRuntimeAssembly();
- Metadata.TypeName parsed = Metadata.TypeName.Parse(typeName);
- RuntimeType? type = (RuntimeType?)new TypeNameParser()
+ TypeName parsed = TypeName.Parse(typeName);
+ RuntimeType? type = (RuntimeType?)new TypeNameResolver()
{
_throwOnError = true,
_suppressContextualReflectionContext = true,
@@ -140,13 +141,13 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName,
return null;
}
- Metadata.TypeName? parsed = Metadata.TypeNameParser.Parse(typeName, throwOnError);
+ TypeName? parsed = TypeNameParser.Parse(typeName, throwOnError);
if (parsed is null)
{
return null;
}
- RuntimeType? type = (RuntimeType?)new TypeNameParser()
+ RuntimeType? type = (RuntimeType?)new TypeNameResolver()
{
_requestingAssembly = requestingAssembly,
_throwOnError = throwOnError,
@@ -181,11 +182,10 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName,
}
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
- Justification = "TypeNameParser.GetType is marked as RequiresUnreferencedCode.")]
+ Justification = "TypeNameResolver.GetType is marked as RequiresUnreferencedCode.")]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern",
- Justification = "TypeNameParser.GetType is marked as RequiresUnreferencedCode.")]
- private Type? GetType(string escapedTypeName, // For nested types, it's Name. For other types it's FullName
- ReadOnlySpan nestedTypeNames, Metadata.TypeName parsedName)
+ Justification = "TypeNameResolver.GetType is marked as RequiresUnreferencedCode.")]
+ private Type? GetType(string escapedTypeName, ReadOnlySpan nestedTypeNames, TypeName parsedName)
{
Assembly? assembly;
@@ -230,12 +230,12 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName,
}
return null;
}
- return GetTypeFromDefaultAssemblies(UnescapeTypeName(escapedTypeName), nestedTypeNames, parsedName);
+ return GetTypeFromDefaultAssemblies(TypeNameHelpers.Unescape(escapedTypeName), nestedTypeNames, parsedName);
}
if (assembly is RuntimeAssembly runtimeAssembly)
{
- string unescapedTypeName = UnescapeTypeName(escapedTypeName);
+ string unescapedTypeName = TypeNameHelpers.Unescape(escapedTypeName);
// Compat: Non-extensible parser allows ambiguous matches with ignore case lookup
if (!_extensibleParser || !_ignoreCase)
{
@@ -268,7 +268,7 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName,
if (_throwOnError)
{
throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType,
- nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : escapedTypeName));
+ nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : TypeNameHelpers.Unescape(escapedTypeName)));
}
return null;
}
@@ -277,7 +277,7 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName,
return type;
}
- private Type? GetTypeFromDefaultAssemblies(string typeName, ReadOnlySpan nestedTypeNames, Metadata.TypeName parsedName)
+ private Type? GetTypeFromDefaultAssemblies(string typeName, ReadOnlySpan nestedTypeNames, TypeName parsedName)
{
RuntimeAssembly? requestingAssembly = (RuntimeAssembly?)_requestingAssembly;
if (requestingAssembly is not null)
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs
index 81caecb09c99a..8707db0cf7f6f 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs
@@ -16,7 +16,7 @@ public abstract partial class Type : MemberInfo, IReflect
public static Type? GetType(string typeName, bool throwOnError, bool ignoreCase)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TypeNameParser.GetType(typeName, Assembly.GetExecutingAssembly(ref stackMark),
+ return TypeNameResolver.GetType(typeName, Assembly.GetExecutingAssembly(ref stackMark),
throwOnError: throwOnError, ignoreCase: ignoreCase);
}
@@ -25,7 +25,7 @@ public abstract partial class Type : MemberInfo, IReflect
public static Type? GetType(string typeName, bool throwOnError)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TypeNameParser.GetType(typeName, Assembly.GetExecutingAssembly(ref stackMark),
+ return TypeNameResolver.GetType(typeName, Assembly.GetExecutingAssembly(ref stackMark),
throwOnError: throwOnError);
}
@@ -34,7 +34,7 @@ public abstract partial class Type : MemberInfo, IReflect
public static Type? GetType(string typeName)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TypeNameParser.GetType(typeName, Assembly.GetExecutingAssembly(ref stackMark));
+ return TypeNameResolver.GetType(typeName, Assembly.GetExecutingAssembly(ref stackMark));
}
[RequiresUnreferencedCode("The type might be removed")]
@@ -45,7 +45,7 @@ public abstract partial class Type : MemberInfo, IReflect
Func? typeResolver)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver,
+ return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver,
((assemblyResolver != null) && (typeResolver != null)) ? null : Assembly.GetExecutingAssembly(ref stackMark));
}
@@ -58,7 +58,7 @@ public abstract partial class Type : MemberInfo, IReflect
bool throwOnError)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver,
+ return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver,
((assemblyResolver != null) && (typeResolver != null)) ? null : Assembly.GetExecutingAssembly(ref stackMark),
throwOnError: throwOnError);
}
@@ -73,7 +73,7 @@ public abstract partial class Type : MemberInfo, IReflect
bool ignoreCase)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver,
+ return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver,
((assemblyResolver != null) && (typeResolver != null)) ? null : Assembly.GetExecutingAssembly(ref stackMark),
throwOnError: throwOnError, ignoreCase: ignoreCase);
}
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/ReflectionHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/ReflectionHelpers.cs
index 1defad0d10f95..dbdc93b93bac7 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/ReflectionHelpers.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/ReflectionHelpers.cs
@@ -17,14 +17,14 @@ internal static class ReflectionHelpers
// a default assembly name.
public static Type GetType(string typeName, string callingAssemblyName, bool throwOnError, bool ignoreCase)
{
- return TypeNameParser.GetType(typeName, throwOnError: throwOnError, ignoreCase: ignoreCase, defaultAssemblyName: callingAssemblyName);
+ return TypeNameResolver.GetType(typeName, throwOnError: throwOnError, ignoreCase: ignoreCase, defaultAssemblyName: callingAssemblyName);
}
// This entry is used to implement Type.GetType()'s ability to detect the calling assembly and use it as
// a default assembly name.
public static Type ExtensibleGetType(string typeName, string callingAssemblyName, Func assemblyResolver, Func? typeResolver, bool throwOnError, bool ignoreCase)
{
- return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, throwOnError: throwOnError, ignoreCase: ignoreCase, defaultAssemblyName: callingAssemblyName);
+ return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver, throwOnError: throwOnError, ignoreCase: ignoreCase, defaultAssemblyName: callingAssemblyName);
}
// This supports Assembly.GetExecutingAssembly() intrinsic expansion in the compiler
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
index c7bfa7ff2215e..faf1eb8fc3de1 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
@@ -493,7 +493,7 @@
-
+
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs
index 9fb1ebe030827..99292670fa8aa 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs
@@ -68,7 +68,7 @@ public sealed override Type GetType(string name, bool throwOnError, bool ignoreC
{
ArgumentException.ThrowIfNullOrEmpty(name);
- return TypeNameParser.GetType(name,
+ return TypeNameResolver.GetType(name,
throwOnError: throwOnError,
ignoreCase: ignoreCase,
topLevelAssembly: this);
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameParser.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.NativeAot.cs
similarity index 92%
rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameParser.NativeAot.cs
rename to src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.NativeAot.cs
index 2149003ddcfb4..51129f0fda74d 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameParser.NativeAot.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.NativeAot.cs
@@ -3,15 +3,16 @@
using System.Diagnostics.CodeAnalysis;
using System.IO;
+using System.Reflection.Metadata;
using System.Reflection.Runtime.Assemblies;
using System.Reflection.Runtime.General;
namespace System.Reflection
{
//
- // Parser for type names passed to GetType() apis.
+ // Resolver for type names passed to GetType() apis.
//
- internal partial struct TypeNameParser
+ internal partial struct TypeNameResolver
{
private Func? _assemblyResolver;
private Func? _typeResolver;
@@ -51,13 +52,13 @@ internal partial struct TypeNameParser
return null;
}
- Metadata.TypeName? parsed = Metadata.TypeNameParser.Parse(typeName, throwOnError);
+ TypeName? parsed = TypeNameParser.Parse(typeName, throwOnError);
if (parsed is null)
{
return null;
}
- return new TypeNameParser()
+ return new TypeNameResolver()
{
_assemblyResolver = assemblyResolver,
_typeResolver = typeResolver,
@@ -74,7 +75,7 @@ internal partial struct TypeNameParser
bool ignoreCase,
Assembly topLevelAssembly)
{
- Metadata.TypeName? parsed = Metadata.TypeNameParser.Parse(typeName, throwOnError);
+ TypeName? parsed = TypeNameParser.Parse(typeName, throwOnError);
if (parsed is null)
{
@@ -85,7 +86,7 @@ internal partial struct TypeNameParser
return throwOnError ? throw new ArgumentException(SR.Argument_AssemblyGetTypeCannotSpecifyAssembly) : null;
}
- return new TypeNameParser()
+ return new TypeNameResolver()
{
_throwOnError = throwOnError,
_ignoreCase = ignoreCase,
@@ -117,7 +118,7 @@ internal partial struct TypeNameParser
Justification = "GetType APIs are marked as RequiresUnreferencedCode.")]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern",
Justification = "GetType APIs are marked as RequiresUnreferencedCode.")]
- private Type? GetType(string escapedTypeName, ReadOnlySpan nestedTypeNames, Metadata.TypeName parsedName)
+ private Type? GetType(string escapedTypeName, ReadOnlySpan nestedTypeNames, TypeName parsedName)
{
Assembly? assembly;
@@ -156,7 +157,7 @@ internal partial struct TypeNameParser
{
if (assembly is RuntimeAssemblyInfo runtimeAssembly)
{
- type = runtimeAssembly.GetTypeCore(UnescapeTypeName(escapedTypeName), throwOnError: _throwOnError, ignoreCase: _ignoreCase);
+ type = runtimeAssembly.GetTypeCore(TypeNameHelpers.Unescape(escapedTypeName), throwOnError: _throwOnError, ignoreCase: _ignoreCase);
}
else
{
@@ -171,7 +172,7 @@ internal partial struct TypeNameParser
}
else
{
- string? unescapedTypeName = UnescapeTypeName(escapedTypeName);
+ string? unescapedTypeName = TypeNameHelpers.Unescape(escapedTypeName);
RuntimeAssemblyInfo? defaultAssembly = null;
if (_defaultAssemblyName != null)
@@ -233,7 +234,7 @@ internal partial struct TypeNameParser
if (_throwOnError)
{
throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType,
- nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : escapedTypeName));
+ nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : TypeNameHelpers.Unescape(escapedTypeName)));
}
return null;
}
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.NativeAot.cs
index 7db1728b3128e..d5b3c54e1fc27 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.NativeAot.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.NativeAot.cs
@@ -95,7 +95,7 @@ internal string FormatTypeNameForReflection()
[RequiresUnreferencedCode("The type might be removed")]
public static Type GetType(string typeName, bool throwOnError, bool ignoreCase)
{
- return TypeNameParser.GetType(typeName, throwOnError: throwOnError, ignoreCase: ignoreCase);
+ return TypeNameResolver.GetType(typeName, throwOnError: throwOnError, ignoreCase: ignoreCase);
}
[Intrinsic]
@@ -108,7 +108,7 @@ public static Type GetType(string typeName, bool throwOnError, bool ignoreCase)
[RequiresUnreferencedCode("The type might be removed")]
public static Type GetType(string typeName, Func? assemblyResolver, Func? typeResolver, bool throwOnError, bool ignoreCase)
{
- return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, throwOnError: throwOnError, ignoreCase: ignoreCase);
+ return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver, throwOnError: throwOnError, ignoreCase: ignoreCase);
}
}
}
diff --git a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs
index 33a86023ced27..cda882d7b730f 100644
--- a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs
@@ -2,16 +2,19 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Diagnostics;
using System.Reflection.Metadata;
using Internal.TypeSystem;
-#nullable disable
-
namespace Internal.TypeSystem
{
public static class CustomAttributeTypeNameParser
{
+ private static readonly TypeNameParseOptions s_typeNameParseOptions = new() { MaxNodes = int.MaxValue };
+
///
/// Parses the string '' and returns the type corresponding to the parsed type name.
/// The type name string should be in the 'SerString' format as defined by the ECMA-335 standard.
@@ -19,105 +22,170 @@ public static class CustomAttributeTypeNameParser
///
public static TypeDesc GetTypeByCustomAttributeTypeName(this ModuleDesc module, string name, bool throwIfNotFound = true,
Func canonResolver = null)
- {
- return System.Reflection.TypeNameParser.ResolveType(module, name, throwIfNotFound, canonResolver);
- }
- }
-}
-
-namespace System.Reflection
-{
- internal partial struct TypeNameParser
- {
- private static readonly TypeNameParseOptions s_typeNameParseOptions = new() { MaxNodes = int.MaxValue };
-
- private ModuleDesc _module;
- private bool _throwIfNotFound;
- private Func _canonResolver;
-
- public static TypeDesc ResolveType(ModuleDesc module, string name, bool throwIfNotFound,
- Func canonResolver)
{
if (!TypeName.TryParse(name.AsSpan(), out TypeName parsed, s_typeNameParseOptions))
- {
ThrowHelper.ThrowTypeLoadException(name, module);
- }
- return new TypeNameParser()
+ return new TypeNameResolver()
{
+ _context = module.Context,
_module = module,
_throwIfNotFound = throwIfNotFound,
_canonResolver = canonResolver
- }.Resolve(parsed)?.Value;
+ }.Resolve(parsed);
}
- private sealed class Type
+ public static TypeDesc GetTypeByCustomAttributeTypeNameForDataFlow(string name, ModuleDesc callingModule,
+ TypeSystemContext context, List referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary)
{
- public Type(TypeDesc type) => Value = type;
- public TypeDesc Value { get; }
+ typeWasNotFoundInAssemblyNorBaseLibrary = false;
- public Type MakeArrayType() => new Type(Value.MakeArrayType());
- public Type MakeArrayType(int rank) => new Type(Value.MakeArrayType(rank));
- public Type MakePointerType() => new Type(Value.MakePointerType());
- public Type MakeByRefType() => new Type(Value.MakeByRefType());
+ if (!TypeName.TryParse(name.AsSpan(), out TypeName parsed, s_typeNameParseOptions))
+ return null;
- public Type MakeGenericType(Type[] typeArguments)
+ TypeNameResolver resolver = new()
{
- TypeDesc[] instantiation = new TypeDesc[typeArguments.Length];
- for (int i = 0; i < typeArguments.Length; i++)
- instantiation[i] = typeArguments[i].Value;
- return new Type(((MetadataType)Value).MakeInstantiatedType(instantiation));
- }
+ _context = context,
+ _module = callingModule,
+ _referencedModules = referencedModules
+ };
+
+ TypeDesc type = resolver.Resolve(parsed);
+
+ typeWasNotFoundInAssemblyNorBaseLibrary = resolver._typeWasNotFoundInAssemblyNorBaseLibrary;
+ return type;
}
- private Type GetType(string typeName, ReadOnlySpan nestedTypeNames, TypeName parsedName)
+ private struct TypeNameResolver
{
- ModuleDesc module = (parsedName.AssemblyName == null) ? _module :
- _module.Context.ResolveAssembly(parsedName.AssemblyName.ToAssemblyName(), throwIfNotFound: _throwIfNotFound);
+ internal TypeSystemContext _context;
+ internal ModuleDesc _module;
+ internal bool _throwIfNotFound;
+ internal Func _canonResolver;
+
+ internal List _referencedModules;
+ internal bool _typeWasNotFoundInAssemblyNorBaseLibrary;
- if (_canonResolver != null && nestedTypeNames.IsEmpty)
+ internal TypeDesc Resolve(TypeName typeName)
{
- MetadataType canonType = _canonResolver(module, typeName);
- if (canonType != null)
- return new Type(canonType);
+ if (typeName.IsSimple)
+ {
+ return GetSimpleType(typeName);
+ }
+
+ if (typeName.IsConstructedGenericType)
+ {
+ return GetGenericType(typeName);
+ }
+
+ if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef)
+ {
+ TypeDesc type = Resolve(typeName.GetElementType());
+ if (type == null)
+ return null;
+
+ if (typeName.IsArray)
+ return typeName.IsSZArray ? type.MakeArrayType() : type.MakeArrayType(rank: typeName.GetArrayRank());
+
+ if (typeName.IsPointer)
+ return type.MakePointerType();
+
+ if (typeName.IsByRef)
+ return type.MakeByRefType();
+ }
+
+ Debug.Fail("Expected to be unreachable");
+ return null;
}
- if (module != null)
+ private TypeDesc GetSimpleType(TypeName typeName)
{
- Type type = GetTypeCore(module, typeName, nestedTypeNames);
- if (type != null)
- return type;
+ TypeName topLevelTypeName = typeName;
+ while (topLevelTypeName.IsNested)
+ {
+ topLevelTypeName = topLevelTypeName.DeclaringType;
+ }
+
+ ModuleDesc module = _module;
+ if (topLevelTypeName.AssemblyName != null)
+ {
+ module = _context.ResolveAssembly(typeName.AssemblyName.ToAssemblyName(), throwIfNotFound: _throwIfNotFound);
+ if (module == null)
+ return null;
+ }
+
+ if (module != null)
+ {
+ TypeDesc type = GetSimpleTypeFromModule(typeName, module);
+ if (type != null)
+ {
+ _referencedModules?.Add(module);
+ return type;
+ }
+ }
+
+ // If it didn't resolve and wasn't assembly-qualified, we also try core library
+ if (topLevelTypeName.AssemblyName == null)
+ {
+ if (module != _context.SystemModule)
+ {
+ TypeDesc type = GetSimpleTypeFromModule(typeName, _context.SystemModule);
+ if (type != null)
+ {
+ _referencedModules?.Add(_context.SystemModule);
+ return type;
+ }
+ }
+
+ _typeWasNotFoundInAssemblyNorBaseLibrary = true;
+ }
+
+ if (_throwIfNotFound)
+ ThrowHelper.ThrowTypeLoadException(typeName.FullName, module);
+ return null;
}
- // If it didn't resolve and wasn't assembly-qualified, we also try core library
- if (parsedName.AssemblyName == null)
+ private TypeDesc GetSimpleTypeFromModule(TypeName typeName, ModuleDesc module)
{
- Type type = GetTypeCore(module.Context.SystemModule, typeName, nestedTypeNames);
- if (type != null)
- return type;
+ if (typeName.IsNested)
+ {
+ TypeDesc type = GetSimpleTypeFromModule(typeName.DeclaringType, module);
+ if (type == null)
+ return null;
+ return ((MetadataType)type).GetNestedType(TypeNameHelpers.Unescape(typeName.Name));
+ }
+
+ string fullName = TypeNameHelpers.Unescape(typeName.FullName);
+
+ if (_canonResolver != null)
+ {
+ MetadataType canonType = _canonResolver(module, fullName);
+ if (canonType != null)
+ return canonType;
+ }
+
+ (string typeNamespace, string name) = TypeNameHelpers.Split(fullName);
+
+ return module.GetType(typeNamespace, name, throwIfNotFound: false);
}
- if (_throwIfNotFound)
- ThrowHelper.ThrowTypeLoadException(parsedName.FullName, module);
- return null;
- }
-
- private static Type GetTypeCore(ModuleDesc module, string typeName, ReadOnlySpan nestedTypeNames)
- {
- (string typeNamespace, string name) = SplitFullTypeName(typeName);
-
- MetadataType type = module.GetType(typeNamespace, name, throwIfNotFound: false);
- if (type == null)
- return null;
-
- for (int i = 0; i < nestedTypeNames.Length; i++)
+ private TypeDesc GetGenericType(TypeName typeName)
{
- type = type.GetNestedType(nestedTypeNames[i]);
- if (type == null)
+ TypeDesc typeDefinition = Resolve(typeName.GetGenericTypeDefinition());
+ if (typeDefinition == null)
return null;
- }
- return new Type(type);
+ ImmutableArray typeArguments = typeName.GetGenericArguments();
+ TypeDesc[] instantiation = new TypeDesc[typeArguments.Length];
+ for (int i = 0; i < typeArguments.Length; i++)
+ {
+ TypeDesc type = Resolve(typeArguments[i]);
+ if (type == null)
+ return null;
+ instantiation[i] = type;
+ }
+ return ((MetadataType)typeDefinition).MakeInstantiatedType(instantiation);
+ }
}
}
}
diff --git a/src/coreclr/tools/ILVerification/ILVerification.projitems b/src/coreclr/tools/ILVerification/ILVerification.projitems
index c0f3644b1ab34..fc02753d60104 100644
--- a/src/coreclr/tools/ILVerification/ILVerification.projitems
+++ b/src/coreclr/tools/ILVerification/ILVerification.projitems
@@ -66,21 +66,12 @@
Utilities\CustomAttributeTypeNameParser.cs
-
- System\Diagnostics\CodeAnalysis\UnconditionalSuppressMessageAttribute.cs
-
-
- System\Diagnostics\CodeAnalysis\NullableAttributes.cs
-
-
- Utilities\CustomAttributeTypeNameParser.Helpers
+
+ Utilities\TypeNameHelpers.cs
Utilities\ValueStringBuilder.cs
-
- Utilities\ValueStringBuilder.AppendSpanFormattable.cs
-
Utilities\LockFreeReaderHashtable.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs
index 279418b2fac3c..f297a7cb73927 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs
@@ -88,7 +88,7 @@ internal bool TryResolveTypeNameAndMark(string typeName, in DiagnosticContext di
ModuleDesc? callingModule = (diagnosticContext.Origin.MemberDefinition.GetOwningType() as MetadataType)?.Module;
List referencedModules = new();
- TypeDesc foundType = System.Reflection.TypeNameParser.ResolveType(typeName, callingModule, diagnosticContext.Origin.MemberDefinition!.Context,
+ TypeDesc foundType = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeNameForDataFlow(typeName, callingModule, diagnosticContext.Origin.MemberDefinition!.Context,
referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary);
if (foundType == null)
{
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs
deleted file mode 100644
index 278b6c4735afc..0000000000000
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeNameParser.Dataflow.cs
+++ /dev/null
@@ -1,117 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Generic;
-using System.Reflection.Metadata;
-using Internal.TypeSystem;
-
-namespace System.Reflection
-{
- internal partial struct TypeNameParser
- {
- private static readonly TypeNameParseOptions s_typeNameParseOptions = new() { MaxNodes = int.MaxValue };
-
- private TypeSystemContext _context;
- private ModuleDesc _callingModule;
- private List _referencedModules;
- private bool _typeWasNotFoundInAssemblyNorBaseLibrary;
-
- public static TypeDesc ResolveType(string name, ModuleDesc callingModule,
- TypeSystemContext context, List referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary)
- {
- if (!TypeName.TryParse(name, out TypeName parsed, s_typeNameParseOptions))
- {
- typeWasNotFoundInAssemblyNorBaseLibrary = false;
- return null;
- }
-
- var parser = new TypeNameParser()
- {
- _context = context,
- _callingModule = callingModule,
- _referencedModules = referencedModules
- };
-
- TypeDesc result = parser.Resolve(parsed)?.Value;
-
- typeWasNotFoundInAssemblyNorBaseLibrary = parser._typeWasNotFoundInAssemblyNorBaseLibrary;
- return result;
- }
-
- private sealed class Type
- {
- public Type(TypeDesc type) => Value = type;
- public TypeDesc Value { get; }
-
- public Type MakeArrayType() => new Type(Value.MakeArrayType());
- public Type MakeArrayType(int rank) => new Type(Value.MakeArrayType(rank));
- public Type MakePointerType() => new Type(Value.MakePointerType());
- public Type MakeByRefType() => new Type(Value.MakeByRefType());
-
- public Type MakeGenericType(Type[] typeArguments)
- {
- TypeDesc[] instantiation = new TypeDesc[typeArguments.Length];
- for (int i = 0; i < typeArguments.Length; i++)
- instantiation[i] = typeArguments[i].Value;
- return new Type(((MetadataType)Value).MakeInstantiatedType(instantiation));
- }
- }
-
- private Type GetType(string typeName, ReadOnlySpan nestedTypeNames, TypeName parsedName)
- {
- ModuleDesc module;
-
- if (parsedName.AssemblyName != null)
- {
- module = _context.ResolveAssembly(parsedName.AssemblyName.ToAssemblyName(), throwIfNotFound: false);
- }
- else
- {
- module = _callingModule;
- }
-
- if (module != null)
- {
- Type type = GetTypeCore(module, typeName, nestedTypeNames);
- if (type != null)
- {
- _referencedModules?.Add(module);
- return type;
- }
- }
-
- // If it didn't resolve and wasn't assembly-qualified, we also try core library
- if (parsedName.AssemblyName == null)
- {
- Type type = GetTypeCore(_context.SystemModule, typeName, nestedTypeNames);
- if (type != null)
- {
- _referencedModules?.Add(_context.SystemModule);
- return type;
- }
-
- _typeWasNotFoundInAssemblyNorBaseLibrary = true;
- }
-
- return null;
- }
-
- private static Type GetTypeCore(ModuleDesc module, string typeName, ReadOnlySpan nestedTypeNames)
- {
- (string typeNamespace, string name) = SplitFullTypeName(typeName);
-
- MetadataType type = module.GetType(typeNamespace, name, throwIfNotFound: false);
- if (type == null)
- return null;
-
- for (int i = 0; i < nestedTypeNames.Length; i++)
- {
- type = type.GetNestedType(nestedTypeNames[i]);
- if (type == null)
- return null;
- }
-
- return new Type(type);
- }
- }
-}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj
index a895dbe1726fa..eb9db7165be26 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj
@@ -396,9 +396,8 @@
-
-
- Compiler\Dataflow\TypeNameParser.Helpers.cs
+
+ Utilities\TypeNameHelpers.cs
Utilities\ValueStringBuilder.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem/ILCompiler.TypeSystem.csproj b/src/coreclr/tools/aot/ILCompiler.TypeSystem/ILCompiler.TypeSystem.csproj
index 1a5db3b44445d..d287e10e97d5f 100644
--- a/src/coreclr/tools/aot/ILCompiler.TypeSystem/ILCompiler.TypeSystem.csproj
+++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem/ILCompiler.TypeSystem.csproj
@@ -198,8 +198,8 @@
Utilities\CustomAttributeTypeNameParser.cs
-
- Utilities\CustomAttributeTypeNameParser.Helpers
+
+ Utilities\TypeNameHelpers.cs
Utilities\ValueStringBuilder.cs
diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h
index 2f9049aea8d71..081325545827e 100644
--- a/src/coreclr/vm/corelib.h
+++ b/src/coreclr/vm/corelib.h
@@ -337,8 +337,8 @@ DEFINE_METHOD(RT_TYPE_HANDLE, ALLOCATECOMOBJECT, AllocateComObject,
#endif
DEFINE_FIELD(RT_TYPE_HANDLE, M_TYPE, m_type)
-DEFINE_CLASS(TYPE_NAME_PARSER, Reflection, TypeNameParser)
-DEFINE_METHOD(TYPE_NAME_PARSER, GET_TYPE_HELPER, GetTypeHelper, SM_Type_CharPtr_RuntimeAssembly_Bool_Bool_RetRuntimeType)
+DEFINE_CLASS(TYPE_NAME_RESOLVER, Reflection, TypeNameResolver)
+DEFINE_METHOD(TYPE_NAME_RESOLVER, GET_TYPE_HELPER, GetTypeHelper, SM_Type_CharPtr_RuntimeAssembly_Bool_Bool_RetRuntimeType)
DEFINE_CLASS_U(Reflection, RtFieldInfo, NoClass)
DEFINE_FIELD_U(m_fieldHandle, ReflectFieldObject, m_pFD)
diff --git a/src/coreclr/vm/typeparse.cpp b/src/coreclr/vm/typeparse.cpp
index 3f6acfafdf471..5a9947042928c 100644
--- a/src/coreclr/vm/typeparse.cpp
+++ b/src/coreclr/vm/typeparse.cpp
@@ -31,7 +31,7 @@ static TypeHandle GetTypeHelper(LPCWSTR szTypeName, Assembly* pRequestingAssembl
OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
- PREPARE_NONVIRTUAL_CALLSITE(METHOD__TYPE_NAME_PARSER__GET_TYPE_HELPER);
+ PREPARE_NONVIRTUAL_CALLSITE(METHOD__TYPE_NAME_RESOLVER__GET_TYPE_HELPER);
DECLARE_ARGHOLDER_ARRAY(args, 4);
args[ARGNUM_0] = PTR_TO_ARGHOLDER(szTypeName);
args[ARGNUM_1] = OBJECTREF_TO_ARGHOLDER(objRequestingAssembly);
diff --git a/src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs b/src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs
index b4fbdca1e9091..41598ddc5310c 100644
--- a/src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs
+++ b/src/libraries/Common/src/System/Reflection/AssemblyNameFormatter.cs
@@ -6,8 +6,6 @@
using System.Globalization;
using System.Text;
-#nullable enable
-
namespace System.Reflection
{
internal static class AssemblyNameFormatter
diff --git a/src/libraries/Common/src/System/Reflection/AssemblyNameParser.cs b/src/libraries/Common/src/System/Reflection/AssemblyNameParser.cs
index bfd91d781a4ec..1c9f55d4087f7 100644
--- a/src/libraries/Common/src/System/Reflection/AssemblyNameParser.cs
+++ b/src/libraries/Common/src/System/Reflection/AssemblyNameParser.cs
@@ -8,8 +8,6 @@
using System.Runtime.CompilerServices;
using System.Text;
-#nullable enable
-
namespace System.Reflection
{
///
diff --git a/src/libraries/Common/src/System/Reflection/Metadata/AssemblyNameInfo.cs b/src/libraries/Common/src/System/Reflection/Metadata/AssemblyNameInfo.cs
index cb4de9467f660..35e12bdd81527 100644
--- a/src/libraries/Common/src/System/Reflection/Metadata/AssemblyNameInfo.cs
+++ b/src/libraries/Common/src/System/Reflection/Metadata/AssemblyNameInfo.cs
@@ -1,8 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-#nullable enable
-
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text;
diff --git a/src/libraries/Common/src/System/Reflection/Metadata/TypeName.cs b/src/libraries/Common/src/System/Reflection/Metadata/TypeName.cs
index 1464f0248280b..3f1ea8394393c 100644
--- a/src/libraries/Common/src/System/Reflection/Metadata/TypeName.cs
+++ b/src/libraries/Common/src/System/Reflection/Metadata/TypeName.cs
@@ -1,8 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-#nullable enable
-
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
@@ -390,7 +388,7 @@ public int GetArrayRank()
///
public
#if SYSTEM_PRIVATE_CORELIB
- IReadOnlyList GetGenericArguments() => _genericArguments is null ? Array.Empty() : _genericArguments;
+ ReadOnlySpan GetGenericArguments() => CollectionsMarshal.AsSpan(_genericArguments);
#else
ImmutableArray GetGenericArguments() => _genericArguments;
#endif
diff --git a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameHelpers.cs b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameHelpers.cs
new file mode 100644
index 0000000000000..f43a04fadfd59
--- /dev/null
+++ b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameHelpers.cs
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection.Metadata;
+using System.Text;
+
+namespace System.Reflection.Metadata
+{
+ internal static class TypeNameHelpers
+ {
+ private const char EscapeCharacter = '\\';
+
+ ///
+ /// Removes escape characters from the string (if there were any found).
+ ///
+ internal static string Unescape(string name)
+ {
+ int indexOfEscapeCharacter = name.IndexOf(EscapeCharacter);
+ if (indexOfEscapeCharacter < 0)
+ {
+ return name;
+ }
+
+ return Unescape(name, indexOfEscapeCharacter);
+
+ static string Unescape(string name, int indexOfEscapeCharacter)
+ {
+ // this code path is executed very rarely (IL Emit or pure IL with chars not allowed in C# or F#)
+ var sb = new ValueStringBuilder(stackalloc char[64]);
+ sb.EnsureCapacity(name.Length);
+ sb.Append(name.AsSpan(0, indexOfEscapeCharacter));
+
+ for (int i = indexOfEscapeCharacter; i < name.Length;)
+ {
+ char c = name[i++];
+
+ if (c != EscapeCharacter)
+ {
+ sb.Append(c);
+ }
+ else if (i < name.Length && name[i] == EscapeCharacter) // escaped escape character ;)
+ {
+ sb.Append(c);
+ // Consume the escaped escape character, it's important for edge cases
+ // like escaped escape character followed by another escaped char (example: "\\\\\\+")
+ i++;
+ }
+ }
+
+ return sb.ToString();
+ }
+ }
+
+ internal static (string typeNamespace, string name) Split(string typeName)
+ {
+ string typeNamespace, name;
+
+ // Matches algorithm from ns::FindSep in src\coreclr\utilcode\namespaceutil.cpp
+ // This could result in the type name beginning with a '.' character.
+ int separator = typeName.LastIndexOf('.');
+ if (separator <= 0)
+ {
+ typeNamespace = "";
+ name = typeName;
+ }
+ else
+ {
+ if (typeName[separator - 1] == '.')
+ separator--;
+ typeNamespace = typeName.Substring(0, separator);
+ name = typeName.Substring(separator + 1);
+ }
+
+ return (typeNamespace, name);
+ }
+ }
+}
diff --git a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParser.cs b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParser.cs
index dcba442054a5d..5a5bbe04a0c18 100644
--- a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParser.cs
+++ b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParser.cs
@@ -10,8 +10,6 @@
using static System.Reflection.Metadata.TypeNameParserHelpers;
-#nullable enable
-
namespace System.Reflection.Metadata
{
[DebuggerDisplay("{_inputString}")]
diff --git a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserHelpers.cs b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserHelpers.cs
index 1cdc5e230ad96..2fa33ea1dfe3b 100644
--- a/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserHelpers.cs
+++ b/src/libraries/Common/src/System/Reflection/Metadata/TypeNameParserHelpers.cs
@@ -7,8 +7,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Text;
-#nullable enable
-
namespace System.Reflection.Metadata
{
internal static class TypeNameParserHelpers
diff --git a/src/libraries/Common/src/System/Reflection/TypeNameParser.Helpers.cs b/src/libraries/Common/src/System/Reflection/TypeNameParser.Helpers.cs
deleted file mode 100644
index 84ef2137fb095..0000000000000
--- a/src/libraries/Common/src/System/Reflection/TypeNameParser.Helpers.cs
+++ /dev/null
@@ -1,214 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Reflection.Metadata;
-using System.Text;
-
-#nullable enable
-
-#if SYSTEM_PRIVATE_CORELIB
-namespace System.Reflection.Metadata
-{
- internal struct TypeNameParseOptions
- {
- public TypeNameParseOptions() { }
-#pragma warning disable CA1822 // Mark members as static
- // CoreLib does not enforce any limits
- public bool IsMaxDepthExceeded(int _) => false;
- public int MaxNodes
- {
- get
- {
- Debug.Fail("Expected to be unreachable");
- return 0;
- }
- }
-#pragma warning restore CA1822
- }
-}
-#endif
-
-namespace System.Reflection
-{
- internal partial struct TypeNameParser
- {
-#if !MONO // Mono never needs unescaped names
- private const char EscapeCharacter = '\\';
-
- ///
- /// Removes escape characters from the string (if there were any found).
- ///
- private static string UnescapeTypeName(string name)
- {
- int indexOfEscapeCharacter = name.IndexOf(EscapeCharacter);
- if (indexOfEscapeCharacter < 0)
- {
- return name;
- }
-
- return Unescape(name, indexOfEscapeCharacter);
-
- static string Unescape(string name, int indexOfEscapeCharacter)
- {
- // this code path is executed very rarely (IL Emit or pure IL with chars not allowed in C# or F#)
- var sb = new ValueStringBuilder(stackalloc char[64]);
- sb.EnsureCapacity(name.Length);
- sb.Append(name.AsSpan(0, indexOfEscapeCharacter));
-
- for (int i = indexOfEscapeCharacter; i < name.Length;)
- {
- char c = name[i++];
-
- if (c != EscapeCharacter)
- {
- sb.Append(c);
- }
- else if (i < name.Length && name[i] == EscapeCharacter) // escaped escape character ;)
- {
- sb.Append(c);
- // Consume the escaped escape character, it's important for edge cases
- // like escaped escape character followed by another escaped char (example: "\\\\\\+")
- i++;
- }
- }
-
- return sb.ToString();
- }
- }
-#endif
-
- private static (string typeNamespace, string name) SplitFullTypeName(string typeName)
- {
- string typeNamespace, name;
-
- // Matches algorithm from ns::FindSep in src\coreclr\utilcode\namespaceutil.cpp
- // This could result in the type name beginning with a '.' character.
- int separator = typeName.LastIndexOf('.');
- if (separator <= 0)
- {
- typeNamespace = "";
- name = typeName;
- }
- else
- {
- if (typeName[separator - 1] == '.')
- separator--;
- typeNamespace = typeName.Substring(0, separator);
- name = typeName.Substring(separator + 1);
- }
-
- return (typeNamespace, name);
- }
-
- [UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresDynamicCode",
- Justification = "Used to implement resolving types from strings.")]
- private Type? Resolve(TypeName typeName)
- {
- if (typeName.IsNested)
- {
- TypeName? current = typeName;
- int nestingDepth = 0;
- while (current is not null && current.IsNested)
- {
- nestingDepth++;
- current = current.DeclaringType;
- }
-
- // We're performing real type resolution, it is assumed that the caller has already validated the correctness
- // of this TypeName object against their own policies, so there is no need for this method to perform any further checks.
- string[] nestedTypeNames = new string[nestingDepth];
- current = typeName;
- while (current is not null && current.IsNested)
- {
-#if MONO
- nestedTypeNames[--nestingDepth] = current.Name;
-#else // CLR, NativeAOT and tools require unescaped nested type names
- nestedTypeNames[--nestingDepth] = UnescapeTypeName(current.Name);
-#endif
- current = current.DeclaringType;
- }
-#if SYSTEM_PRIVATE_CORELIB
- string nonNestedParentName = current!.FullName;
-#else // the tools require unescaped names
- string nonNestedParentName = UnescapeTypeName(current!.FullName);
-#endif
- Type? type = GetType(nonNestedParentName, nestedTypeNames, typeName);
- return type is null || !typeName.IsConstructedGenericType ? type : MakeGenericType(type, typeName);
- }
- else if (typeName.IsConstructedGenericType)
- {
- Type? type = Resolve(typeName.GetGenericTypeDefinition());
- return type is null ? null : MakeGenericType(type, typeName);
- }
- else if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef)
- {
- Type? type = Resolve(typeName.GetElementType());
- if (type is null)
- {
- return null;
- }
-
- if (typeName.IsByRef)
- {
- return type.MakeByRefType();
- }
- else if (typeName.IsPointer)
- {
- return type.MakePointerType();
- }
- else if (typeName.IsSZArray)
- {
- return type.MakeArrayType();
- }
- else
- {
- Debug.Assert(typeName.IsVariableBoundArrayType);
-
- return type.MakeArrayType(rank: typeName.GetArrayRank());
- }
- }
- else
- {
- Debug.Assert(typeName.IsSimple);
-
- Type? type = GetType(
-#if SYSTEM_PRIVATE_CORELIB
- typeName.FullName,
-#else // the tools require unescaped names
- UnescapeTypeName(typeName.FullName),
-#endif
- nestedTypeNames: ReadOnlySpan.Empty, typeName);
-
- return type;
- }
- }
-
- [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern",
- Justification = "Used to implement resolving types from strings.")]
- [UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresDynamicCode",
- Justification = "Used to implement resolving types from strings.")]
- private Type? MakeGenericType(Type type, TypeName typeName)
- {
- var genericArgs = typeName.GetGenericArguments();
-#if SYSTEM_PRIVATE_CORELIB
- int size = genericArgs.Count;
-#else
- int size = genericArgs.Length;
-#endif
- Type[] genericTypes = new Type[size];
- for (int i = 0; i < size; i++)
- {
- Type? genericArg = Resolve(genericArgs[i]);
- if (genericArg is null)
- {
- return null;
- }
- genericTypes[i] = genericArg;
- }
-
- return type.MakeGenericType(genericTypes);
- }
- }
-}
diff --git a/src/libraries/Common/src/System/Text/ValueStringBuilder.AppendSpanFormattable.cs b/src/libraries/Common/src/System/Text/ValueStringBuilder.AppendSpanFormattable.cs
index 3e9cf2c56d3ea..04e9fcbdb5524 100644
--- a/src/libraries/Common/src/System/Text/ValueStringBuilder.AppendSpanFormattable.cs
+++ b/src/libraries/Common/src/System/Text/ValueStringBuilder.AppendSpanFormattable.cs
@@ -1,8 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-#nullable enable
-
namespace System.Text
{
internal ref partial struct ValueStringBuilder
diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
index f1b61a1ea67c4..99e354aa32d3a 100644
--- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
+++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
@@ -778,6 +778,7 @@
+
@@ -1475,9 +1476,6 @@
Common\System\IO\PathInternal.CaseSensitivity.cs
-
- Common\System\Reflection\TypeNameParser.Helpers
-
Common\System\Reflection\AssemblyNameParser.cs
@@ -1490,6 +1488,9 @@
Common\System\Reflection\Metadata\TypeName.cs
+
+ Common\System\Reflection\Metadata\TypeNameHelpers.cs
+
Common\System\Reflection\Metadata\TypeNameParser.cs
diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs
index 5ee6c949bc97e..2d82ed0c0e7f5 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs
@@ -1,8 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-#nullable enable
-
namespace System.Diagnostics.CodeAnalysis
{
///
diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.cs
new file mode 100644
index 0000000000000..9e36505b390ea
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.cs
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection.Metadata;
+using System.Text;
+
+namespace System.Reflection.Metadata
+{
+ internal struct TypeNameParseOptions
+ {
+ public TypeNameParseOptions() { }
+#pragma warning disable CA1822 // Mark members as static
+ // CoreLib does not enforce any limits
+ public bool IsMaxDepthExceeded(int _) => false;
+ public int MaxNodes
+ {
+ get
+ {
+ Debug.Fail("Expected to be unreachable");
+ return 0;
+ }
+ }
+#pragma warning restore CA1822
+ }
+}
+
+namespace System.Reflection
+{
+ internal partial struct TypeNameResolver
+ {
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresDynamicCode",
+ Justification = "Used to implement resolving types from strings.")]
+ private Type? Resolve(TypeName typeName)
+ {
+ if (typeName.IsSimple)
+ {
+ return GetSimpleType(typeName);
+ }
+ else if (typeName.IsConstructedGenericType)
+ {
+ return GetGenericType(typeName);
+ }
+ else if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef)
+ {
+ Type? type = Resolve(typeName.GetElementType());
+ if (type is null)
+ return null;
+
+ if (typeName.IsArray)
+ {
+ return typeName.IsSZArray ? type.MakeArrayType() : type.MakeArrayType(rank: typeName.GetArrayRank());
+ }
+ if (typeName.IsByRef)
+ {
+ return type.MakeByRefType();
+ }
+ else if (typeName.IsPointer)
+ {
+ return type.MakePointerType();
+ }
+ }
+
+ Debug.Fail("Expected to be unreachable");
+ return null;
+ }
+
+ private Type? GetSimpleType(TypeName typeName)
+ {
+ if (typeName.IsNested)
+ {
+ TypeName current = typeName;
+ int nestingDepth = 0;
+ do
+ {
+ nestingDepth++;
+ current = current.DeclaringType!;
+ }
+ while (current.IsNested);
+
+ string[] nestedTypeNames = new string[nestingDepth];
+ current = typeName;
+ while (current.IsNested)
+ {
+ nestedTypeNames[--nestingDepth] = TypeNameHelpers.Unescape(current.Name);
+ current = current.DeclaringType!;
+ }
+
+ return GetType(current.FullName, nestedTypeNames, typeName);
+ }
+ else
+ {
+ return GetType(typeName.FullName, default, typeName);
+ }
+
+ }
+
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern",
+ Justification = "Used to implement resolving types from strings.")]
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresDynamicCode",
+ Justification = "Used to implement resolving types from strings.")]
+ private Type? GetGenericType(TypeName typeName)
+ {
+ Type? type = Resolve(typeName.GetGenericTypeDefinition());
+ if (type is null)
+ return null;
+
+ ReadOnlySpan genericArgs = typeName.GetGenericArguments();
+ Type[] genericTypes = new Type[genericArgs.Length];
+ for (int i = 0; i < genericArgs.Length; i++)
+ {
+ Type? genericArg = Resolve(genericArgs[i]);
+ if (genericArg is null)
+ return null;
+ genericTypes[i] = genericArg;
+ }
+
+ return type.MakeGenericType(genericTypes);
+ }
+ }
+}
diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
index 076fc42815c65..9137c694aa4ab 100644
--- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -235,7 +235,7 @@
-
+
diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameParser.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.Mono.cs
similarity index 91%
rename from src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameParser.Mono.cs
rename to src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.Mono.cs
index 22a7361d9814e..ef5d63ec28074 100644
--- a/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameParser.Mono.cs
+++ b/src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.Mono.cs
@@ -4,6 +4,7 @@
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
+using System.Reflection.Metadata;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;
using System.Text;
@@ -11,7 +12,7 @@
namespace System.Reflection
{
- internal unsafe ref partial struct TypeNameParser
+ internal unsafe ref partial struct TypeNameResolver
{
private Func? _assemblyResolver;
private Func? _typeResolver;
@@ -39,13 +40,13 @@ internal unsafe ref partial struct TypeNameParser
return null;
}
- Metadata.TypeName? parsed = Metadata.TypeNameParser.Parse(typeName, throwOnError: throwOnError);
+ TypeName? parsed = TypeNameParser.Parse(typeName, throwOnError);
if (parsed is null)
{
return null;
}
- return new TypeNameParser()
+ return new TypeNameResolver()
{
_assemblyResolver = assemblyResolver,
_typeResolver = typeResolver,
@@ -92,10 +93,10 @@ internal unsafe ref partial struct TypeNameParser
}
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern",
- Justification = "TypeNameParser.GetType is marked as RequiresUnreferencedCode.")]
+ Justification = "TypeNameResolver.GetType is marked as RequiresUnreferencedCode.")]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
- Justification = "TypeNameParser.GetType is marked as RequiresUnreferencedCode.")]
- private Type? GetType(string escapedTypeName, ReadOnlySpan nestedTypeNames, Metadata.TypeName parsedName)
+ Justification = "TypeNameResolver.GetType is marked as RequiresUnreferencedCode.")]
+ private Type? GetType(string escapedTypeName, ReadOnlySpan nestedTypeNames, TypeName parsedName)
{
Assembly? assembly = (parsedName.AssemblyName is not null) ? ResolveAssembly(parsedName.AssemblyName.ToAssemblyName()) : null;
@@ -150,7 +151,7 @@ internal unsafe ref partial struct TypeNameParser
if (_throwOnError)
{
throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType,
- nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : escapedTypeName));
+ nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : TypeNameHelpers.Unescape(escapedTypeName)));
}
return null;
}
diff --git a/src/mono/System.Private.CoreLib/src/System/Type.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Type.Mono.cs
index 851cc8f92c551..3fc4f6082c9b2 100644
--- a/src/mono/System.Private.CoreLib/src/System/Type.Mono.cs
+++ b/src/mono/System.Private.CoreLib/src/System/Type.Mono.cs
@@ -76,7 +76,7 @@ internal IntPtr GetUnderlyingNativeHandle()
[RequiresUnreferencedCode("The type might be removed")]
private static Type? GetType(string typeName, Func? assemblyResolver, Func? typeResolver, bool throwOnError, bool ignoreCase, ref StackCrawlMark stackMark)
{
- return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark);
+ return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark);
}
public static Type? GetTypeFromHandle(RuntimeTypeHandle handle)