Skip to content

Commit 8f7e64a

Browse files
authored
Merge pull request #38 from Yeah69/perf/lazy-currently-considered-types
Perf/lazy currently considered types
2 parents 877354b + 9f354f3 commit 8f7e64a

18 files changed

Lines changed: 518 additions & 372 deletions

File tree

.github/workflows/main.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ jobs:
1818
steps:
1919
- uses: actions/checkout@main
2020
- name: Setup .NET Core
21-
uses: actions/setup-dotnet@v3.2.0
21+
uses: actions/setup-dotnet@v5.2.0
2222
with:
23-
dotnet-version: 8.0.406
23+
dotnet-version: 10.0.202
2424
- run: set DOTNET_CLI_TELEMETRY_OPTOUT=1
2525
- name: Install dependencies
2626
run: dotnet restore .\MrMeeseeks.DIE.sln

Main/Configuration/CheckTypeProperties.cs

Lines changed: 51 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ internal abstract class CheckTypeProperties : ICheckTypeProperties
8686
private readonly ITypeParameterUtility _typeParameterUtility;
8787
private readonly WellKnownTypes _wellKnownTypes;
8888

89-
private readonly Dictionary<INamedTypeSymbol, IDictionary<ITypeSymbol, ISet<object>>> _typeToKeyToValue = new();
90-
private readonly Dictionary<INamedTypeSymbol, int> _decorationToOrdinal;
89+
private readonly Dictionary<INamedTypeSymbol, IDictionary<ITypeSymbol, ISet<object>>> _typeToKeyToValue = new(CustomSymbolEqualityComparer.Default);
9190

9291
internal CheckTypeProperties(
9392
ICurrentlyConsideredTypes currentlyConsideredTypes,
@@ -139,23 +138,6 @@ internal CheckTypeProperties(
139138
implementationType.OriginalDefinition,
140139
new Dictionary<ITypeSymbol, ISet<object>>{{keyType, new HashSet<object>{keyValue}}});
141140
}
142-
143-
_decorationToOrdinal = currentlyConsideredTypes.DecoratorTypes
144-
.SelectMany(d => d.GetAttributes().Select(a => (d, a)))
145-
.Select(t =>
146-
{
147-
var (decorator, attribute) = t;
148-
if (!currentlyConsideredTypes.DecorationOrdinalAttributeTypes.Any(a =>
149-
CustomSymbolEqualityComparer.Default.Equals(a, attribute.AttributeClass)))
150-
return ((INamedTypeSymbol DecorationImplementationType, int Ordinal)?)null;
151-
return (
152-
DecorationImplementationType: decorator,
153-
Ordinal: attribute.ConstructorArguments[0].Value is int ordinal ? ordinal : 0);
154-
})
155-
.Where(t => t is not null)
156-
.Select(t => t ?? throw new ImpossibleDieException())
157-
.Concat(currentlyConsideredTypes.DecorationOrdinalChoices)
158-
.ToDictionary(t => t.DecorationImplementationType, t => t.Ordinal);
159141
}
160142

161143
public DisposalType ShouldDisposalBeManaged(INamedTypeSymbol implementationType)
@@ -167,41 +149,43 @@ public DisposalType ShouldDisposalBeManaged(INamedTypeSymbol implementationType)
167149

168150
if (_wellKnownTypes.IAsyncDisposable is not null
169151
&& implementationType.OriginalDefinitionIfUnbound().AllInterfaces.Contains(_wellKnownTypes.IAsyncDisposable)
170-
&& !_currentlyConsideredTypes.AsyncTransientTypes.Contains(implementationType.UnboundIfGeneric()))
152+
&& !_currentlyConsideredTypes.IsAsyncTransient(implementationType.UnboundIfGeneric()))
171153
ret |= DisposalType.Async;
172154

173155
if (implementationType.OriginalDefinitionIfUnbound().AllInterfaces.Contains(_wellKnownTypes.IDisposable)
174-
&& !_currentlyConsideredTypes.SyncTransientTypes.Contains(implementationType.UnboundIfGeneric()))
156+
&& !_currentlyConsideredTypes.IsSyncTransient(implementationType.UnboundIfGeneric()))
175157
ret |= DisposalType.Sync;
176158

177159
return ret;
178160
}
179161

180162
public ScopeLevel ShouldBeScopeRoot(INamedTypeSymbol implementationType)
181163
{
182-
if (_currentlyConsideredTypes.TransientScopeRootTypes.Contains(implementationType.UnboundIfGeneric()))
164+
if (_currentlyConsideredTypes.IsTransientScopeRoot(implementationType.UnboundIfGeneric()))
183165
return ScopeLevel.TransientScope;
184-
if (_currentlyConsideredTypes.ScopeRootTypes.Contains(implementationType.UnboundIfGeneric()))
166+
if (_currentlyConsideredTypes.IsScopeRoot(implementationType.UnboundIfGeneric()))
185167
return ScopeLevel.Scope;
186168
return ScopeLevel.None;
187169
}
188170

189-
public bool ShouldBeComposite(INamedTypeSymbol interfaceType) => _currentlyConsideredTypes.InterfaceToComposite.ContainsKey(interfaceType.UnboundIfGeneric());
171+
public bool ShouldBeComposite(INamedTypeSymbol interfaceType) => _currentlyConsideredTypes.HasComposite(interfaceType);
190172
public ScopeLevel GetScopeLevelFor(INamedTypeSymbol implementationType)
191173
{
192174
var unbound = implementationType.UnboundIfGeneric();
193-
if (_currentlyConsideredTypes.ContainerInstanceTypes.Contains(unbound))
175+
if (_currentlyConsideredTypes.IsContainerInstance(unbound))
194176
return ScopeLevel.Container;
195-
if (_currentlyConsideredTypes.TransientScopeInstanceTypes.Contains(unbound))
177+
if (_currentlyConsideredTypes.IsTransientScopeInstance(unbound))
196178
return ScopeLevel.TransientScope;
197-
if (_currentlyConsideredTypes.ScopeInstanceTypes.Contains(unbound))
179+
if (_currentlyConsideredTypes.IsScopeInstance(unbound))
198180
return ScopeLevel.Scope;
199181
return ScopeLevel.None;
200182
}
201183

202184
public INamedTypeSymbol? GetCompositeFor(INamedTypeSymbol interfaceType)
203185
{
204-
var compositeImplementation = _currentlyConsideredTypes.InterfaceToComposite[interfaceType.UnboundIfGeneric()];
186+
var compositeImplementation = _currentlyConsideredTypes.GetCompositeFor(interfaceType);
187+
if (compositeImplementation is null)
188+
return null;
205189
var implementations = GetClosedImplementations(
206190
interfaceType,
207191
[compositeImplementation],
@@ -243,7 +227,7 @@ when implementationType.InstanceConstructors.SingleOrDefault(c => c.Parameters.L
243227
};
244228
}
245229

246-
public bool ShouldBeDecorated(INamedTypeSymbol interfaceType) => _currentlyConsideredTypes.InterfaceToDecorators.ContainsKey(interfaceType.UnboundIfGeneric());
230+
public bool ShouldBeDecorated(INamedTypeSymbol interfaceType) => _currentlyConsideredTypes.HasDecorators(interfaceType);
247231

248232
public IReadOnlyList<INamedTypeSymbol> GetDecorationSequenceFor(INamedTypeSymbol interfaceType,
249233
INamedTypeSymbol implementationType)
@@ -264,10 +248,10 @@ public IReadOnlyList<INamedTypeSymbol> GetDecorationSequenceFor(INamedTypeSymbol
264248
found = true;
265249
}
266250
}
267-
268-
if (!found && _currentlyConsideredTypes.InterfaceToDecorators.TryGetValue(interfaceType.UnboundIfGeneric(), out var allDecorators))
251+
var allDecorators = _currentlyConsideredTypes.GetDecoratorsFor(interfaceType);
252+
if (!found && allDecorators.Length > 0)
269253
sequence = allDecorators
270-
.OrderBy(d => _decorationToOrdinal.TryGetValue(d, out var ordinal) ? ordinal : 0);
254+
.OrderBy(d => _currentlyConsideredTypes.GetDecorationOrdinal(d));
271255

272256
return sequence
273257
.Select(imp =>
@@ -287,8 +271,7 @@ public IReadOnlyList<INamedTypeSymbol> GetDecorationSequenceFor(INamedTypeSymbol
287271
.ToList();
288272
}
289273

290-
public INamedTypeSymbol? MapToSingleFittingImplementation(INamedTypeSymbol type,
291-
InjectionKey? injectionKey)
274+
public INamedTypeSymbol? MapToSingleFittingImplementation(INamedTypeSymbol type, InjectionKey? injectionKey)
292275
{
293276
var choice =
294277
_currentlyConsideredTypes.ImplementationChoices.TryGetValue(type.UnboundIfGeneric(), out var choice0)
@@ -317,8 +300,8 @@ public IReadOnlyList<INamedTypeSymbol> GetDecorationSequenceFor(INamedTypeSymbol
317300

318301
if (type is { TypeKind: not TypeKind.Interface, IsAbstract: false, IsStatic: false })
319302
{
320-
if (_currentlyConsideredTypes.DecoratorTypes.Contains(type) ||
321-
_currentlyConsideredTypes.CompositeTypes.Contains(type))
303+
if (_currentlyConsideredTypes.IsDecorator(type) ||
304+
_currentlyConsideredTypes.IsComposite(type))
322305
// if concrete type is decorator or composite then just shortcut
323306
return type;
324307
var possibleConcreteTypeImplementations = FilterByInjectionKey(
@@ -335,24 +318,22 @@ public IReadOnlyList<INamedTypeSymbol> GetDecorationSequenceFor(INamedTypeSymbol
335318
return list.Count == 1 ? list[0] : null;
336319
}
337320

338-
var possibleImplementations = _currentlyConsideredTypes.ImplementationMap.TryGetValue(type.UnboundIfGeneric(), out var implementations)
339-
? FilterByInjectionKey(
321+
var implementations = _currentlyConsideredTypes.GetAllImplementingTypes(type);
322+
var possibleImplementations = FilterByInjectionKey(
340323
GetClosedImplementations(
341324
type,
342325
[..implementations],
343326
true,
344327
false,
345328
false),
346-
injectionKey)
347-
: [];
329+
injectionKey);
348330

349331
var list2 = possibleImplementations.Take(2).ToList();
350332

351333
return list2.Count == 1 ? list2[0] : null;
352334
}
353335

354-
public IReadOnlyList<INamedTypeSymbol> MapToImplementations(INamedTypeSymbol typeSymbol,
355-
InjectionKey? injectionKey)
336+
public IReadOnlyList<INamedTypeSymbol> MapToImplementations(INamedTypeSymbol typeSymbol, InjectionKey? injectionKey)
356337
{
357338
if (_currentlyConsideredTypes
358339
.ImplementationCollectionChoices
@@ -368,17 +349,15 @@ public IReadOnlyList<INamedTypeSymbol> MapToImplementations(INamedTypeSymbol typ
368349
injectionKey).ToList();
369350
}
370351

371-
return _currentlyConsideredTypes.ImplementationMap.TryGetValue(typeSymbol.UnboundIfGeneric(),
372-
out var implementations)
373-
? FilterByInjectionKey(
352+
return FilterByInjectionKey(
374353
GetClosedImplementations(
375354
typeSymbol,
376-
[..implementations],
355+
[.._currentlyConsideredTypes.GetAllImplementingTypes(typeSymbol.UnboundIfGeneric())],
377356
false,
378357
false,
379358
false),
380-
injectionKey).ToList()
381-
: Array.Empty<INamedTypeSymbol>();
359+
injectionKey)
360+
.ToList();
382361
}
383362

384363
private IEnumerable<INamedTypeSymbol> FilterByInjectionKey(
@@ -424,15 +403,15 @@ private IEnumerable<INamedTypeSymbol> GetClosedImplementations(
424403
var unboundImplementation = implementation.UnboundIfGeneric();
425404
var originalImplementation = implementation.OriginalDefinitionIfUnbound();
426405

427-
var isCompositeImplementation = _currentlyConsideredTypes.CompositeTypes.Contains(unboundImplementation);
406+
var isCompositeImplementation = _currentlyConsideredTypes.IsComposite(unboundImplementation);
428407
if (chooseComposite && !isCompositeImplementation || !chooseComposite && isCompositeImplementation)
429408
continue;
430-
var isDecoratorImplementation = _currentlyConsideredTypes.DecoratorTypes.Contains(unboundImplementation);
409+
var isDecoratorImplementation = _currentlyConsideredTypes.IsDecorator(unboundImplementation);
431410
if (chooseDecorator && !isDecoratorImplementation || !chooseDecorator && isDecoratorImplementation)
432411
continue;
433412
if (!chooseComposite
434413
&& !chooseDecorator
435-
&& !_currentlyConsideredTypes.AllConsideredImplementations.Contains(unboundImplementation))
414+
&& !_currentlyConsideredTypes.ImplementationConsidered(unboundImplementation))
436415
continue;
437416
if (!implementation.IsGenericType)
438417
{
@@ -559,21 +538,27 @@ IImmutableSet<INamedTypeSymbol> GetSubstitutes(
559538

560539
public (INamedTypeSymbol Type, IMethodSymbol Initializer)? GetInitializerFor(INamedTypeSymbol implementationType)
561540
{
562-
if (_currentlyConsideredTypes.ImplementationToInitializer.TryGetValue(implementationType.UnboundIfGeneric(), out var tuple))
563-
{
564-
var abstractionType = implementationType
565-
.AllDerivedTypesAndSelf()
566-
.FirstOrDefault(t => CustomSymbolEqualityComparer.Default.Equals(t.UnboundIfGeneric(), tuple.Item1.UnboundIfGeneric()));
567-
568-
var initializerMethod = implementationType
569-
.AllDerivedTypesAndSelf()
570-
.SelectMany(t => t.GetMembers(tuple.Item2.Name))
571-
.OfType<IMethodSymbol>()
572-
.FirstOrDefault(m => CustomSymbolEqualityComparer.Default.Equals(m.OriginalDefinition, tuple.Item2.OriginalDefinition));
573-
574-
return abstractionType is not null && initializerMethod is not null ? (abstractionType, initializerMethod) : null;
575-
}
576-
return null;
541+
var initializerInfo = _currentlyConsideredTypes.GetInitializerFor(implementationType);
542+
if (initializerInfo is null)
543+
return null;
544+
545+
var (abstractionType, initializerMethodDef) = initializerInfo.Value;
546+
547+
var concreteAbstractionType = implementationType
548+
.AllDerivedTypesAndSelf()
549+
.FirstOrDefault(t => CustomSymbolEqualityComparer.Default.Equals(
550+
t.UnboundIfGeneric(), abstractionType.UnboundIfGeneric()));
551+
552+
var initializerMethod = implementationType
553+
.AllDerivedTypesAndSelf()
554+
.SelectMany(t => t.GetMembers(initializerMethodDef.Name))
555+
.OfType<IMethodSymbol>()
556+
.FirstOrDefault(m => CustomSymbolEqualityComparer.Default.Equals(
557+
m.OriginalDefinition, initializerMethodDef.OriginalDefinition));
558+
559+
return concreteAbstractionType is not null && initializerMethod is not null
560+
? (concreteAbstractionType, initializerMethod)
561+
: null;
577562
}
578563

579564
public IReadOnlyList<IPropertySymbol>? GetPropertyChoicesFor(INamedTypeSymbol implementationType)

0 commit comments

Comments
 (0)