Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: common linq loop allocations, add small optimisations #555

Merged
merged 1 commit into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -21,7 +21,7 @@
if (TypeFullName != null)
return types.TryGet(TypeFullName);

throw new InvalidOperationException("One type needs to be set for each collection type");

Check warning on line 24 in src/Riok.Mapperly/Descriptors/Enumerables/CollectionInfoBuilder.cs

View check run for this annotation

Codecov / codecov/patch

src/Riok.Mapperly/Descriptors/Enumerables/CollectionInfoBuilder.cs#L24

Added line #L24 was not covered by tests
}
}

Expand Down Expand Up @@ -100,7 +100,7 @@
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,18 +115,27 @@
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<>)))
)
{
return namedType.TypeArguments[0];
}

return null;

Check warning on line 138 in src/Riok.Mapperly/Descriptors/Enumerables/CollectionInfoBuilder.cs

View check run for this annotation

Codecov / codecov/patch

src/Riok.Mapperly/Descriptors/Enumerables/CollectionInfoBuilder.cs#L138

Added line #L138 was not covered by tests
}

private static bool HasValidAddMethod(WellKnownTypes types, ITypeSymbol t, CollectionType typeInfo)
Expand All @@ -149,7 +158,7 @@
|| 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 @@
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 All @@ -187,7 +196,7 @@
foreach (var typeInfo in _collectionTypeInfos)
{
if (typeInfo.GetTypeSymbol(types) is not { } typeSymbol)
continue;

Check warning on line 199 in src/Riok.Mapperly/Descriptors/Enumerables/CollectionInfoBuilder.cs

View check run for this annotation

Codecov / codecov/patch

src/Riok.Mapperly/Descriptors/Enumerables/CollectionInfoBuilder.cs#L199

Added line #L199 was not covered by tests

if (SymbolEqualityComparer.Default.Equals(type.OriginalDefinition, typeSymbol))
return typeInfo;
Expand Down Expand Up @@ -335,7 +344,7 @@
foreach (var typeInfo in _collectionTypeInfos)
{
if (typeInfo.GetTypeSymbol(types) is not { } typeSymbol)
continue;

Check warning on line 347 in src/Riok.Mapperly/Descriptors/Enumerables/CollectionInfoBuilder.cs

View check run for this annotation

Codecov / codecov/patch

src/Riok.Mapperly/Descriptors/Enumerables/CollectionInfoBuilder.cs#L347

Added line #L347 was not covered by tests

if (type.ImplementsGeneric(typeSymbol, out _))
{
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 @@
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 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;
}

Check warning on line 80 in src/Riok.Mapperly/Descriptors/SymbolAccessor.cs

View check run for this annotation

Codecov / codecov/patch

src/Riok.Mapperly/Descriptors/SymbolAccessor.cs#L80

Added line #L80 was not covered by tests
}
}

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
Loading