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

Tweaks to simplify code patterns (for ToddGrun) #76925

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ internal static EmitBaseline.MetadataSymbols GetOrCreateMetadataSymbols(EmitBase
internal static SynthesizedTypeMaps GetSynthesizedTypesFromMetadata(MetadataReader reader, MetadataDecoder metadataDecoder)
{
var anonymousTypes = ImmutableSegmentedDictionary.CreateBuilder<AnonymousTypeKey, AnonymousTypeValue>();
var anonymousDelegatesWithIndexedNames = new Dictionary<AnonymousDelegateWithIndexedNamePartialKey, ArrayBuilder<AnonymousTypeValue>>();
var anonymousDelegatesWithIndexedNames = PooledDictionary<AnonymousDelegateWithIndexedNamePartialKey, ArrayBuilder<AnonymousTypeValue>>.GetInstance();
var anonymousDelegates = ImmutableSegmentedDictionary.CreateBuilder<SynthesizedDelegateKey, SynthesizedDelegateValue>();

foreach (var handle in reader.TypeDefinitions)
Expand Down
13 changes: 10 additions & 3 deletions src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public static bool TryAdd<TKey, TValue>(
}
#endif

public static void AddPooled<K, V>(this IDictionary<K, ArrayBuilder<V>> dictionary, K key, V value)
public static void AddPooled<K, V>(this Dictionary<K, ArrayBuilder<V>> dictionary, K key, V value)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all callers passed a Dict. This avoids interface dispatch.

where K : notnull
{
if (!dictionary.TryGetValue(key, out var values))
Expand All @@ -88,15 +88,22 @@ public static void AddPooled<K, V>(this IDictionary<K, ArrayBuilder<V>> dictiona
values.Add(value);
}

public static ImmutableSegmentedDictionary<K, ImmutableArray<V>> ToImmutableSegmentedDictionaryAndFree<K, V>(this IReadOnlyDictionary<K, ArrayBuilder<V>> builder)
/// <summary>
/// Converts the passed in dictionary to an <see cref="ImmutableSegmentedDictionary{TKey, TValue}"/>, where all
/// the values in the passed builder will be converted to an <see cref="ImmutableArray{T}"/> using <see
/// cref="ArrayBuilder{T}.ToImmutableAndFree"/>. The <paramref name="dictionary"/> will be freed at the end of
/// this method as well, and should not be used afterwards.
/// </summary>
public static ImmutableSegmentedDictionary<K, ImmutableArray<V>> ToImmutableSegmentedDictionaryAndFree<K, V>(this PooledDictionary<K, ArrayBuilder<V>> dictionary)
where K : notnull
{
var result = ImmutableSegmentedDictionary.CreateBuilder<K, ImmutableArray<V>>();
foreach (var (key, values) in builder)
foreach (var (key, values) in dictionary)
{
result.Add(key, values.ToImmutableAndFree());
}

dictionary.Free();
return result.ToImmutable();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;

Expand All @@ -17,16 +18,25 @@ internal partial class AnalyzerDriver<TLanguageKindEnum> : AnalyzerDriver where
/// </summary>
private sealed class GroupedAnalyzerActions : IGroupedAnalyzerActions
{
public static readonly GroupedAnalyzerActions Empty = new GroupedAnalyzerActions(ImmutableArray<(DiagnosticAnalyzer, GroupedAnalyzerActionsForAnalyzer)>.Empty, AnalyzerActions.Empty);
public static readonly GroupedAnalyzerActions Empty = new GroupedAnalyzerActions(
ImmutableArray<(DiagnosticAnalyzer, GroupedAnalyzerActionsForAnalyzer)>.Empty,
ImmutableSegmentedDictionary<TLanguageKindEnum, ImmutableArray<DiagnosticAnalyzer>>.Empty,
AnalyzerActions.Empty);

private GroupedAnalyzerActions(ImmutableArray<(DiagnosticAnalyzer, GroupedAnalyzerActionsForAnalyzer)> groupedActionsAndAnalyzers, in AnalyzerActions analyzerActions)
private GroupedAnalyzerActions(
ImmutableArray<(DiagnosticAnalyzer, GroupedAnalyzerActionsForAnalyzer)> groupedActionsAndAnalyzers,
ImmutableSegmentedDictionary<TLanguageKindEnum, ImmutableArray<DiagnosticAnalyzer>> analyzersByKind,
in AnalyzerActions analyzerActions)
{
GroupedActionsByAnalyzer = groupedActionsAndAnalyzers;
AnalyzerActions = analyzerActions;
AnalyzersByKind = analyzersByKind;
}

public ImmutableArray<(DiagnosticAnalyzer analyzer, GroupedAnalyzerActionsForAnalyzer groupedActions)> GroupedActionsByAnalyzer { get; }

public ImmutableSegmentedDictionary<TLanguageKindEnum, ImmutableArray<DiagnosticAnalyzer>> AnalyzersByKind { get; }

public AnalyzerActions AnalyzerActions { get; }

public bool IsEmpty
Expand All @@ -48,7 +58,8 @@ public static GroupedAnalyzerActions Create(DiagnosticAnalyzer analyzer, in Anal

var groupedActions = new GroupedAnalyzerActionsForAnalyzer(analyzer, analyzerActions, analyzerActionsNeedFiltering: false);
var groupedActionsAndAnalyzers = ImmutableArray<(DiagnosticAnalyzer, GroupedAnalyzerActionsForAnalyzer)>.Empty.Add((analyzer, groupedActions));
return new GroupedAnalyzerActions(groupedActionsAndAnalyzers, in analyzerActions);
var analyzersByKind = CreateAnalyzersByKind(groupedActionsAndAnalyzers);
return new GroupedAnalyzerActions(groupedActionsAndAnalyzers, analyzersByKind, in analyzerActions);
}

public static GroupedAnalyzerActions Create(ImmutableArray<DiagnosticAnalyzer> analyzers, in AnalyzerActions analyzerActions)
Expand All @@ -58,7 +69,8 @@ public static GroupedAnalyzerActions Create(ImmutableArray<DiagnosticAnalyzer> a
var groups = analyzers.SelectAsArray(
(analyzer, analyzerActions) => (analyzer, new GroupedAnalyzerActionsForAnalyzer(analyzer, analyzerActions, analyzerActionsNeedFiltering: true)),
analyzerActions);
return new GroupedAnalyzerActions(groups, in analyzerActions);
var analyzersByKind = CreateAnalyzersByKind(groups);
return new GroupedAnalyzerActions(groups, analyzersByKind, in analyzerActions);
}

IGroupedAnalyzerActions IGroupedAnalyzerActions.Append(IGroupedAnalyzerActions igroupedAnalyzerActions)
Expand All @@ -74,7 +86,20 @@ IGroupedAnalyzerActions IGroupedAnalyzerActions.Append(IGroupedAnalyzerActions i

var newGroupedActions = GroupedActionsByAnalyzer.AddRange(groupedAnalyzerActions.GroupedActionsByAnalyzer);
var newAnalyzerActions = AnalyzerActions.Append(groupedAnalyzerActions.AnalyzerActions);
return new GroupedAnalyzerActions(newGroupedActions, newAnalyzerActions);
var analyzersByKind = CreateAnalyzersByKind(newGroupedActions);
return new GroupedAnalyzerActions(newGroupedActions, analyzersByKind, newAnalyzerActions);
}

private static ImmutableSegmentedDictionary<TLanguageKindEnum, ImmutableArray<DiagnosticAnalyzer>> CreateAnalyzersByKind(ImmutableArray<(DiagnosticAnalyzer, GroupedAnalyzerActionsForAnalyzer)> groupedActionsAndAnalyzers)
{
var analyzersByKind = PooledDictionary<TLanguageKindEnum, ArrayBuilder<DiagnosticAnalyzer>>.GetInstance();
foreach (var (analyzer, groupedActionsForAnalyzer) in groupedActionsAndAnalyzers)
{
foreach (var (kind, _) in groupedActionsForAnalyzer.NodeActionsByAnalyzerAndKind)
analyzersByKind.AddPooled(kind, analyzer);
}

return analyzersByKind.ToImmutableSegmentedDictionaryAndFree();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2611,10 +2611,26 @@ void executeNodeActions()

void executeNodeActionsByKind(ArrayBuilder<SyntaxNode> nodesToAnalyze, GroupedAnalyzerActions groupedActions, bool arePerSymbolActions)
{
if (groupedActions.GroupedActionsByAnalyzer.Length == 0)
{
return;
}

var analyzersForNodes = PooledHashSet<DiagnosticAnalyzer>.GetInstance();
foreach (var node in nodesToAnalyze)
{
if (groupedActions.AnalyzersByKind.TryGetValue(_getKind(node), out var analyzersForKind))
{
foreach (var analyzer in analyzersForKind)
{
analyzersForNodes.Add(analyzer);
}
}
}

foreach (var (analyzer, groupedActionsForAnalyzer) in groupedActions.GroupedActionsByAnalyzer)
{
var nodeActionsByKind = groupedActionsForAnalyzer.NodeActionsByAnalyzerAndKind;
if (nodeActionsByKind.IsEmpty || !analysisScope.Contains(analyzer))
if (!analyzersForNodes.Contains(analyzer) || !analysisScope.Contains(analyzer))
{
continue;
}
Expand Down Expand Up @@ -2642,6 +2658,8 @@ void executeNodeActionsByKind(ArrayBuilder<SyntaxNode> nodesToAnalyze, GroupedAn
}
}

analyzersForNodes.Free();

void executeSyntaxNodeActions(
DiagnosticAnalyzer analyzer,
GroupedAnalyzerActionsForAnalyzer groupedActionsForAnalyzer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -931,20 +931,10 @@ internal static ImmutableSegmentedDictionary<TLanguageKindEnum, ImmutableArray<S
foreach (var nodeAction in nodeActions)
{
foreach (var kind in nodeAction.Kinds)
{
if (!nodeActionsByKind.TryGetValue(kind, out var actionsForKind))
{
nodeActionsByKind.Add(kind, actionsForKind = ArrayBuilder<SyntaxNodeAnalyzerAction<TLanguageKindEnum>>.GetInstance());
}

actionsForKind.Add(nodeAction);
}
nodeActionsByKind.AddPooled(kind, nodeAction);
}

var tuples = nodeActionsByKind.Select(kvp => KeyValuePairUtil.Create(kvp.Key, kvp.Value.ToImmutableAndFree()));
var map = ImmutableSegmentedDictionary.CreateRange(tuples);
nodeActionsByKind.Free();
return map;
return nodeActionsByKind.ToImmutableSegmentedDictionaryAndFree();
}

/// <summary>
Expand Down Expand Up @@ -1030,20 +1020,10 @@ internal static ImmutableSegmentedDictionary<OperationKind, ImmutableArray<Opera
foreach (var operationAction in operationActions)
{
foreach (var kind in operationAction.Kinds)
{
if (!operationActionsByKind.TryGetValue(kind, out var actionsForKind))
{
operationActionsByKind.Add(kind, actionsForKind = ArrayBuilder<OperationAnalyzerAction>.GetInstance());
}

actionsForKind.Add(operationAction);
}
operationActionsByKind.AddPooled(kind, operationAction);
}

var tuples = operationActionsByKind.Select(kvp => KeyValuePairUtil.Create(kvp.Key, kvp.Value.ToImmutableAndFree()));
var map = ImmutableSegmentedDictionary.CreateRange(tuples);
operationActionsByKind.Free();
return map;
return operationActionsByKind.ToImmutableSegmentedDictionaryAndFree();
}

/// <summary>
Expand Down
Loading