Skip to content

Commit

Permalink
chore: remove linq func allocations, add IsRefLikeType and `Nullabl…
Browse files Browse the repository at this point in the history
…eValue` check
  • Loading branch information
TimothyMakkison committed Jul 12, 2023
1 parent f6d8d34 commit 8443d3d
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 20 deletions.
23 changes: 16 additions & 7 deletions src/Riok.Mapperly/Descriptors/Enumerables/CollectionInfoBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ ITypeSymbol enumeratedType
typeInfo,
GetImplementedCollectionTypes(wellKnownTypes, type, typeInfo),
enumeratedType,
FindCountProperty(wellKnownTypes, symbolAccessor, type, typeInfo),
FindCountProperty(symbolAccessor, type, typeInfo),
HasValidAddMethod(wellKnownTypes, type, typeInfo),
collectionTypeInfo?.Immutable == true
);
Expand All @@ -115,11 +115,20 @@ ITypeSymbol enumeratedType
if (type is not ({ IsValueType: true, IsReadOnly: true } and INamedTypeSymbol { TypeArguments.Length: 1 } namedType))
return null;

// if the collection is Span<> or Memory<> etc, get the type symbol
// if the collection is a ref type the check for Span<> or ReadOnlySpanSpan<>
if (
SymbolEqualityComparer.Default.Equals(type.OriginalDefinition, types.Get(typeof(Span<>)))
|| SymbolEqualityComparer.Default.Equals(type.OriginalDefinition, types.Get(typeof(ReadOnlySpan<>)))
|| SymbolEqualityComparer.Default.Equals(type.OriginalDefinition, types.Get(typeof(Memory<>)))
namedType.IsRefLikeType
&& (
SymbolEqualityComparer.Default.Equals(type.OriginalDefinition, types.Get(typeof(Span<>)))
|| SymbolEqualityComparer.Default.Equals(type.OriginalDefinition, types.Get(typeof(ReadOnlySpan<>)))
)
)
{
return namedType.TypeArguments[0];
}
// Memory<> or ReadOnlyMemory<> etc, get the type symbol
if (
SymbolEqualityComparer.Default.Equals(type.OriginalDefinition, types.Get(typeof(Memory<>)))
|| SymbolEqualityComparer.Default.Equals(type.OriginalDefinition, types.Get(typeof(ReadOnlyMemory<>)))
)
{
Expand Down Expand Up @@ -149,7 +158,7 @@ or CollectionType.SortedSet
|| t.HasImplicitGenericImplementation(types.Get(typeof(ISet<>)), nameof(ISet<object>.Add));
}

private static string? FindCountProperty(WellKnownTypes types, SymbolAccessor symbolAccessor, ITypeSymbol t, CollectionType typeInfo)
private static string? FindCountProperty(SymbolAccessor symbolAccessor, ITypeSymbol t, CollectionType typeInfo)
{
if (typeInfo is CollectionType.IEnumerable)
return null;
Expand All @@ -170,7 +179,7 @@ or CollectionType.ReadOnlyMemory
var member = symbolAccessor
.GetAllAccessibleMappableMembers(t)
.FirstOrDefault(
x => x.Name is nameof(ICollection<object>.Count) or nameof(Array.Length) && x.Type.SpecialType == SpecialType.System_Int32
x => x.Type.SpecialType == SpecialType.System_Int32 && x.Name is nameof(ICollection<object>.Count) or nameof(Array.Length)
);
return member?.Name;
}
Expand Down
17 changes: 14 additions & 3 deletions src/Riok.Mapperly/Descriptors/SymbolAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,13 @@ internal IEnumerable<AttributeData> GetAttributes<T>(ISymbol symbol)
where T : Attribute
{
var attributeSymbol = _types.Get<T>();
return GetAttributesCore(symbol)
.Where(x => SymbolEqualityComparer.Default.Equals(x.AttributeClass?.ConstructedFrom ?? x.AttributeClass, attributeSymbol));
foreach (var attr in GetAttributesCore(symbol))
{
if (SymbolEqualityComparer.Default.Equals(attr.AttributeClass?.ConstructedFrom ?? attr.AttributeClass, attributeSymbol))
{
yield return attr;
}
}
}

internal bool HasAttribute<T>(ISymbol symbol)
Expand Down Expand Up @@ -67,7 +72,13 @@ internal IReadOnlyCollection<IMappableMember> GetAllAccessibleMappableMembers(IT

internal IEnumerable<IMappableMember> GetMappableMembers(ITypeSymbol symbol, string name, IEqualityComparer<string> comparer)
{
return GetAllAccessibleMappableMembers(symbol).Where(x => comparer.Equals(name, x.Name));
foreach (var member in GetAllAccessibleMappableMembers(symbol))
{
if (comparer.Equals(name, member.Name))
{
yield return member;
}
}
}

private IEnumerable<ISymbol> GetAllMembers(ITypeSymbol symbol, string name) => GetAllMembers(symbol).Where(x => name.Equals(x.Name));
Expand Down
7 changes: 1 addition & 6 deletions src/Riok.Mapperly/Helpers/NullableSymbolExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ namespace Riok.Mapperly.Helpers;

public static class NullableSymbolExtensions
{
private const string NullableGenericTypeName = "System.Nullable<T>";

internal static bool HasSameOrStricterNullability(this ITypeSymbol symbol, ITypeSymbol other)
{
return symbol.NullableAnnotation == NullableAnnotation.NotAnnotated
Expand Down Expand Up @@ -109,10 +107,7 @@ internal static bool IsNullable(this ITypeParameterSymbol typeParameter, Nullabl

private static ITypeSymbol? NonNullableValueType(this ITypeSymbol symbol)
{
if (
symbol is INamedTypeSymbol { IsValueType: true, IsGenericType: true } namedType
&& namedType.ConstructedFrom.ToDisplayString() == NullableGenericTypeName
)
if (symbol.IsValueType && symbol is INamedTypeSymbol { OriginalDefinition.SpecialType: SpecialType.System_Nullable_T } namedType)
return namedType.TypeArguments[0];
return null;
}
Expand Down
15 changes: 11 additions & 4 deletions src/Riok.Mapperly/Helpers/SymbolExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,17 @@ internal static bool ImplementsGeneric(
return true;
}

typedInterface = t.AllInterfaces.FirstOrDefault(
x => x.IsGenericType && SymbolEqualityComparer.Default.Equals(x.OriginalDefinition, genericInterfaceSymbol)
);
return typedInterface != null;
foreach (var typeSymbol in t.AllInterfaces)
{
if (typeSymbol.IsGenericType && SymbolEqualityComparer.Default.Equals(typeSymbol.OriginalDefinition, genericInterfaceSymbol))
{
typedInterface = typeSymbol;
return true;
}
}

typedInterface = null;
return false;
}

internal static bool ImplementsGeneric(
Expand Down

0 comments on commit 8443d3d

Please sign in to comment.