Skip to content

Commit

Permalink
address API review feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
adamsitnik committed Aug 2, 2024
1 parent 7d2d0d6 commit 9a0cd58
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 164 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ internal TypeName GetArrayTypeName(ArrayInfo arrayInfo)
// Custom offset arrays are not supported by design, so in our case it's always SZArray.
// That is why we don't call TypeName.MakeArrayTypeName(1) because it would create [*] instead of [] name.
return arrayInfo.Rank == 1
? elementTypeName.MakeArrayTypeName()
? elementTypeName.MakeSZArrayTypeName()
: elementTypeName.MakeArrayTypeName(arrayInfo.Rank);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ internal static void ThrowInvalidValue(object value)
internal static void ThrowInvalidReference()
=> throw new SerializationException(SR.Serialization_InvalidReference);

internal static void ThrowInvalidTypeName(string name)
=> throw new SerializationException(SR.Format(SR.Serialization_InvalidTypeName, name));

internal static void ThrowUnexpectedNullRecordCount()
=> throw new SerializationException(SR.Serialization_UnexpectedNullRecordCount);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ internal static class TypeNameHelpers
private static readonly TypeName?[] s_PrimitiveSZArrayTypeNames = new TypeName?[(int)UIntPtrPrimitiveType + 1];
private static AssemblyNameInfo? s_CoreLibAssemblyName;

internal static AssemblyNameInfo CoreLibAssemblyName
=> s_CoreLibAssemblyName ??= AssemblyNameInfo.Parse("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089".AsSpan());

internal static TypeName GetPrimitiveTypeName(PrimitiveType primitiveType)
{
Debug.Assert(primitiveType is not (PrimitiveType.None or PrimitiveType.Null));
Expand Down Expand Up @@ -50,7 +53,7 @@ internal static TypeName GetPrimitiveTypeName(PrimitiveType primitiveType)
_ => "System.UInt64",
};

s_PrimitiveTypeNames[(int)primitiveType] = typeName = TypeName.Parse(fullName.AsSpan()).WithCoreLibAssemblyName();
s_PrimitiveTypeNames[(int)primitiveType] = typeName = TypeName.CreateSimpleTypeName(fullName, assemblyName: CoreLibAssemblyName);
}
return typeName;
}
Expand All @@ -60,7 +63,7 @@ internal static TypeName GetPrimitiveSZArrayTypeName(PrimitiveType primitiveType
TypeName? typeName = s_PrimitiveSZArrayTypeNames[(int)primitiveType];
if (typeName is null)
{
s_PrimitiveSZArrayTypeNames[(int)primitiveType] = typeName = GetPrimitiveTypeName(primitiveType).MakeArrayTypeName();
s_PrimitiveSZArrayTypeNames[(int)primitiveType] = typeName = GetPrimitiveTypeName(primitiveType).MakeSZArrayTypeName();
}
return typeName;
}
Expand Down Expand Up @@ -128,7 +131,38 @@ internal static TypeName ParseSystemRecordTypeName(this string rawName, PayloadO
.WithCoreLibAssemblyName(); // We know it's a System Record, so we set the LibraryName to CoreLib

internal static TypeName WithCoreLibAssemblyName(this TypeName systemType)
=> systemType.WithAssemblyName(s_CoreLibAssemblyName ??= AssemblyNameInfo.Parse("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089".AsSpan()));
=> systemType.WithAssemblyName(CoreLibAssemblyName);

private static TypeName WithAssemblyName(this TypeName typeName, AssemblyNameInfo assemblyName)
{
if (!typeName.IsSimple)
{
if (typeName.IsArray)
{
TypeName newElementType = typeName.GetElementType().WithAssemblyName(assemblyName);

return typeName.IsSZArray
? newElementType.MakeSZArrayTypeName()
: newElementType.MakeArrayTypeName(typeName.GetArrayRank());
}
else if (typeName.IsConstructedGenericType)
{
TypeName newGenericTypeDefinition = typeName.GetGenericTypeDefinition().WithAssemblyName(assemblyName);

// We don't change the assembly name of generic arguments on purpose.
return newGenericTypeDefinition.MakeGenericTypeName(typeName.GetGenericArguments());
}
else
{
// BinaryFormatter can not serialize pointers or references.
ThrowHelper.ThrowInvalidTypeName(typeName.FullName);
}
}

TypeName? newDeclaringType = typeName.IsNested ? typeName.DeclaringType.WithAssemblyName(assemblyName) : null;

return TypeName.CreateSimpleTypeName(typeName.FullName, newDeclaringType, assemblyName);
}

private static TypeName ParseWithoutAssemblyName(string rawName, PayloadOptions payloadOptions)
{
Expand Down
6 changes: 6 additions & 0 deletions src/libraries/System.Formats.Nrbf/tests/TypeMatchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,12 @@ private static void Verify<T>(T input) where T : notnull

Assert.True(one.TypeNameMatches(typeof(T)));

Assert.Equal(typeof(T).GetTypeFullNameIncludingTypeForwards(), one.TypeName.FullName);
if (typeof(T) != typeof(TimeSpan)) // TimeSpan is missing type forwards
{
Assert.Equal(typeof(T).GetAssemblyNameIncludingTypeForwards(), one.TypeName.AssemblyName!.FullName);
}

foreach (Type type in PrimitiveTypes)
{
Assert.Equal(typeof(T) == type, one.TypeNameMatches(type));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2427,7 +2427,7 @@ public sealed partial class TypeName
internal TypeName() { }
public string AssemblyQualifiedName { get { throw null; } }
public AssemblyNameInfo? AssemblyName { get { throw null; } }
public System.Reflection.Metadata.TypeName? DeclaringType { get { throw null; } }
public System.Reflection.Metadata.TypeName DeclaringType { get { throw null; } }
public string FullName { get { throw null; } }
public bool IsArray { get { throw null; } }
public bool IsByRef { get { throw null; } }
Expand All @@ -2438,19 +2438,19 @@ internal TypeName() { }
public bool IsSZArray { get { throw null; } }
public bool IsVariableBoundArrayType { get { throw null; } }
public string Name { get { throw null; } }
public static System.Reflection.Metadata.TypeName CreateSimpleTypeName(string metadataName, System.Reflection.Metadata.TypeName? declaringType = null, AssemblyNameInfo? assemblyName = null) { throw null; }
public static System.Reflection.Metadata.TypeName Parse(System.ReadOnlySpan<char> typeName, System.Reflection.Metadata.TypeNameParseOptions? options = null) { throw null; }
public static bool TryParse(System.ReadOnlySpan<char> typeName, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Reflection.Metadata.TypeName? result, System.Reflection.Metadata.TypeNameParseOptions? options = null) { throw null; }
public int GetArrayRank() { throw null; }
public System.Collections.Immutable.ImmutableArray<System.Reflection.Metadata.TypeName> GetGenericArguments() { throw null; }
public System.Reflection.Metadata.TypeName GetGenericTypeDefinition() { throw null; }
public System.Reflection.Metadata.TypeName GetElementType() { throw null; }
public int GetNodeCount() { throw null; }
public System.Reflection.Metadata.TypeName MakeArrayTypeName() { throw null; }
public System.Reflection.Metadata.TypeName MakeSZArrayTypeName() { throw null; }
public System.Reflection.Metadata.TypeName MakeArrayTypeName(int rank) { throw null; }
public System.Reflection.Metadata.TypeName MakeByRefTypeName() { throw null; }
public System.Reflection.Metadata.TypeName MakeGenericTypeName(System.Collections.Immutable.ImmutableArray<System.Reflection.Metadata.TypeName> typeArguments) { throw null; }
public System.Reflection.Metadata.TypeName MakePointerTypeName() { throw null; }
public System.Reflection.Metadata.TypeName WithAssemblyName(AssemblyNameInfo assemblyName) { throw null; }
}
public sealed partial class TypeNameParseOptions
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,4 +435,7 @@
<data name="Arg_NotSimpleTypeName" xml:space="preserve">
<value>MakeGenericTypeName may only be called on a type name for which TypeName.IsSimple is true, for '{0}' it's not.</value>
</data>
<data name="Argument_EmptyString" xml:space="preserve">
<value>The value cannot be an empty string.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,41 @@ public int GetArrayRank()
#endif

#if SYSTEM_REFLECTION_METADATA
/// <summary>
/// Creates a new <see cref="TypeName" /> object that represents given name with provided assembly name.
/// </summary>
/// <param name="metadataName">Unescaped full name.</param>
/// <param name="declaringType">Declaring type name.</param>
/// <param name="assemblyName">Assembly name.</param>
/// <returns>Created simple name.</returns>
/// <exception cref="ArgumentNullException"><paramref name="metadataName"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">Provided type name was invalid. For example, it was empty or escaped.</exception>
public static TypeName CreateSimpleTypeName(string metadataName, TypeName? declaringType = null, AssemblyNameInfo? assemblyName = null)
{
#if NET
ArgumentNullException.ThrowIfNullOrEmpty(nameof(metadataName));
bool containsEscapeCharacter = metadataName.Contains(TypeNameParserHelpers.EscapeCharacter);
#else
if (string.IsNullOrEmpty(metadataName))
{
throw metadataName is null
? throw new ArgumentNullException(nameof(metadataName))
: throw new ArgumentException(SR.Argument_EmptyString, nameof(metadataName));
}
bool containsEscapeCharacter = metadataName.IndexOf(TypeNameParserHelpers.EscapeCharacter) >= 0;
#endif
if (containsEscapeCharacter)
{
throw new ArgumentException(SR.Argument_InvalidTypeName);
}

return new TypeName(fullName: metadataName,
assemblyName: assemblyName,
elementOrGenericType: null,
declaringType: declaringType,
genericTypeArguments: ImmutableArray<TypeName>.Empty);
}

/// <summary>
/// Returns a <see cref="TypeName" /> object representing a one-dimensional array
/// of the current type, with a lower bound of zero.
Expand All @@ -421,7 +456,7 @@ public int GetArrayRank()
/// A <see cref="TypeName" /> object representing a one-dimensional array
/// of the current type, with a lower bound of zero.
/// </returns>
public TypeName MakeArrayTypeName() => MakeElementTypeName(TypeNameParserHelpers.SZArray);
public TypeName MakeSZArrayTypeName() => MakeElementTypeName(TypeNameParserHelpers.SZArray);

/// <summary>
/// Returns a <see cref="TypeName" /> object representing an array of the current type,
Expand Down Expand Up @@ -465,40 +500,9 @@ public TypeName MakeArrayTypeName(int rank)
/// <exception cref="InvalidOperationException">The current type name is not simple.</exception>
public TypeName MakeGenericTypeName(ImmutableArray<TypeName> typeArguments)
=> IsSimple
? new TypeName(fullName: null, AssemblyName, elementOrGenericType: this, genericTypeArguments: typeArguments)
? new TypeName(fullName: null, AssemblyName, elementOrGenericType: this, declaringType: _declaringType, genericTypeArguments: typeArguments)
: throw new InvalidOperationException(SR.Format(SR.Arg_NotSimpleTypeName, FullName));

/// <summary>
/// Returns a <see cref="TypeName" /> object that represents the current type name with provided assembly name.
/// </summary>
/// <returns>
/// A <see cref="TypeName" /> object that represents the current type name with provided assembly name.
/// </returns>
public TypeName WithAssemblyName(AssemblyNameInfo? assemblyName)
=> WithAssemblyName(this, AssemblyName, assemblyName)!;

private static TypeName? WithAssemblyName(TypeName? typeName, AssemblyNameInfo? oldName, AssemblyNameInfo? newName)
{
if (typeName is null)
{
return null;
}
else if (!ReferenceEquals(typeName.AssemblyName, oldName))
{
return typeName; // There is nothing to update.
}

return new TypeName(
fullName: typeName._fullName,
newName,
elementOrGenericType: WithAssemblyName(typeName._elementOrGenericType, oldName, newName),
declaringType: WithAssemblyName(typeName._declaringType, oldName, newName),
// We don't update the assembly names of generic arguments on purpose!
genericTypeArguments: typeName._genericArguments,
rankOrModifier: typeName._rankOrModifier,
nestedNameLength: typeName._nestedNameLength);
}

private TypeName MakeElementTypeName(sbyte rankOrModifier)
=> new TypeName(
fullName: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal static class TypeNameParserHelpers
internal const sbyte SZArray = -1;
internal const sbyte Pointer = -2;
internal const sbyte ByRef = -3;
private const char EscapeCharacter = '\\';
internal const char EscapeCharacter = '\\';
#if NET8_0_OR_GREATER
private static readonly SearchValues<char> s_endOfFullTypeNameDelimitersSearchValues = SearchValues.Create("[]&*,+\\");
#endif
Expand Down
Loading

0 comments on commit 9a0cd58

Please sign in to comment.