From 5190cd52fa213b3e5d3cfa4b1f7814f2956d822a Mon Sep 17 00:00:00 2001 From: Todd Grunke Date: Thu, 23 Jan 2025 15:10:08 -0800 Subject: [PATCH 01/49] WIP: Reduce CPU costs under AnalyzerExecutor.ExecuteSyntaxNodeActions In the scrolling speedometer test, the Roslyn CodeAnalysis process shows about 25% of CPU spent in this method. Of that, a surprising amount of it (11.2%) is spent in ImmutableSegmentedDictionary.TryGetValue. Debugging through this code, it appears this is because that is called O(m x n) times where m is the number of nodes to analyze and n is the number of items in groupedActions.GroupedActionsByAnalyzer. Instead, add a hook into GroupedAnalyzerActions to allow a mapping of kind -> analyzers. This can be used by executeNodeActionsByKind to get a much quicker way to determine whether the analyzer can contribute for the node in question. Only publishing this early so Cyrus can take a peek, as I still need to do a bit of debugging around these changes. Once Cyrus and I think the changes have merit, I will create a test insertion and publish the speedometer results once those are available. Only if all that goes well will I promote this PR out of draft mode. --- .../AnalyzerDriver.GroupedAnalyzerActions.cs | 49 +++++++++++++++++-- .../DiagnosticAnalyzer/AnalyzerDriver.cs | 17 ++++++- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs index 04132ae8fafbe..ed47f5f6b17d1 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs @@ -17,16 +17,25 @@ internal partial class AnalyzerDriver : AnalyzerDriver where /// 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, + ImmutableDictionary>.Empty, + AnalyzerActions.Empty); - private GroupedAnalyzerActions(ImmutableArray<(DiagnosticAnalyzer, GroupedAnalyzerActionsForAnalyzer)> groupedActionsAndAnalyzers, in AnalyzerActions analyzerActions) + private GroupedAnalyzerActions( + ImmutableArray<(DiagnosticAnalyzer, GroupedAnalyzerActionsForAnalyzer)> groupedActionsAndAnalyzers, + ImmutableDictionary> analyzersByKind, + in AnalyzerActions analyzerActions) { GroupedActionsByAnalyzer = groupedActionsAndAnalyzers; AnalyzerActions = analyzerActions; + AnalyzersByKind = analyzersByKind; } public ImmutableArray<(DiagnosticAnalyzer analyzer, GroupedAnalyzerActionsForAnalyzer groupedActions)> GroupedActionsByAnalyzer { get; } + public ImmutableDictionary> AnalyzersByKind { get; } + public AnalyzerActions AnalyzerActions { get; } public bool IsEmpty @@ -48,7 +57,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 analyzers, in AnalyzerActions analyzerActions) @@ -58,7 +68,8 @@ public static GroupedAnalyzerActions Create(ImmutableArray 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) @@ -74,7 +85,35 @@ 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 ImmutableDictionary> CreateAnalyzersByKind(ImmutableArray<(DiagnosticAnalyzer, GroupedAnalyzerActionsForAnalyzer)> groupedActionsAndAnalyzers) + { + var analyzersByKind = PooledDictionary>.GetInstance(); + foreach (var (analyzer, groupedActionsForAnalyzer) in groupedActionsAndAnalyzers) + { + foreach (var (kind, _) in groupedActionsForAnalyzer.NodeActionsByAnalyzerAndKind) + { + if (!analyzersByKind.TryGetValue(kind, out var builder)) + { + builder = ArrayBuilder.GetInstance(); + analyzersByKind.Add(kind, builder); + } + builder.Add(analyzer); + } + } + + // Essentially an inline of PooledBuilderExtensions.ToImmutableMultiDictionaryAndFree + var result = ImmutableDictionary.CreateBuilder>(); + foreach (var (key, items) in analyzersByKind) + { + result.Add(key, items.ToImmutableAndFree()); + } + + analyzersByKind.Free(); + return result.ToImmutable(); } } } diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs index f3f942d2d1cfc..00cdb183fe943 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs @@ -2611,10 +2611,21 @@ void executeNodeActions() void executeNodeActionsByKind(ArrayBuilder nodesToAnalyze, GroupedAnalyzerActions groupedActions, bool arePerSymbolActions) { + var analyzersForNodes = PooledHashSet.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; } @@ -2642,6 +2653,8 @@ void executeNodeActionsByKind(ArrayBuilder nodesToAnalyze, GroupedAn } } + analyzersForNodes.Free(); + void executeSyntaxNodeActions( DiagnosticAnalyzer analyzer, GroupedAnalyzerActionsForAnalyzer groupedActionsForAnalyzer, From 841bcbc108dca727a4f4e69d1e2a1e0bf89bfa6c Mon Sep 17 00:00:00 2001 From: Todd Grunke Date: Thu, 23 Jan 2025 17:21:30 -0800 Subject: [PATCH 02/49] Use some existing helpers to create a dictionary with ImmutableArray values. --- .../AnalyzerDriver.GroupedAnalyzerActions.cs | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs index ed47f5f6b17d1..807eda886d926 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs @@ -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; @@ -19,12 +20,12 @@ private sealed class GroupedAnalyzerActions : IGroupedAnalyzerActions { public static readonly GroupedAnalyzerActions Empty = new GroupedAnalyzerActions( ImmutableArray<(DiagnosticAnalyzer, GroupedAnalyzerActionsForAnalyzer)>.Empty, - ImmutableDictionary>.Empty, + ImmutableSegmentedDictionary>.Empty, AnalyzerActions.Empty); private GroupedAnalyzerActions( ImmutableArray<(DiagnosticAnalyzer, GroupedAnalyzerActionsForAnalyzer)> groupedActionsAndAnalyzers, - ImmutableDictionary> analyzersByKind, + ImmutableSegmentedDictionary> analyzersByKind, in AnalyzerActions analyzerActions) { GroupedActionsByAnalyzer = groupedActionsAndAnalyzers; @@ -34,7 +35,7 @@ private GroupedAnalyzerActions( public ImmutableArray<(DiagnosticAnalyzer analyzer, GroupedAnalyzerActionsForAnalyzer groupedActions)> GroupedActionsByAnalyzer { get; } - public ImmutableDictionary> AnalyzersByKind { get; } + public ImmutableSegmentedDictionary> AnalyzersByKind { get; } public AnalyzerActions AnalyzerActions { get; } @@ -89,31 +90,21 @@ IGroupedAnalyzerActions IGroupedAnalyzerActions.Append(IGroupedAnalyzerActions i return new GroupedAnalyzerActions(newGroupedActions, analyzersByKind, newAnalyzerActions); } - private static ImmutableDictionary> CreateAnalyzersByKind(ImmutableArray<(DiagnosticAnalyzer, GroupedAnalyzerActionsForAnalyzer)> groupedActionsAndAnalyzers) + private static ImmutableSegmentedDictionary> CreateAnalyzersByKind(ImmutableArray<(DiagnosticAnalyzer, GroupedAnalyzerActionsForAnalyzer)> groupedActionsAndAnalyzers) { var analyzersByKind = PooledDictionary>.GetInstance(); foreach (var (analyzer, groupedActionsForAnalyzer) in groupedActionsAndAnalyzers) { foreach (var (kind, _) in groupedActionsForAnalyzer.NodeActionsByAnalyzerAndKind) { - if (!analyzersByKind.TryGetValue(kind, out var builder)) - { - builder = ArrayBuilder.GetInstance(); - analyzersByKind.Add(kind, builder); - } - builder.Add(analyzer); + analyzersByKind.AddPooled(kind, analyzer); } } - // Essentially an inline of PooledBuilderExtensions.ToImmutableMultiDictionaryAndFree - var result = ImmutableDictionary.CreateBuilder>(); - foreach (var (key, items) in analyzersByKind) - { - result.Add(key, items.ToImmutableAndFree()); - } - + var result = analyzersByKind.ToImmutableSegmentedDictionaryAndFree(); analyzersByKind.Free(); - return result.ToImmutable(); + + return result; } } } From ec95ec4b5fd914287cdc925c63af1d64b3b751f1 Mon Sep 17 00:00:00 2001 From: Todd Grunke Date: Fri, 24 Jan 2025 06:47:47 -0800 Subject: [PATCH 03/49] Early return to avoid the added array walk when not necessary --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs index 00cdb183fe943..fa01b2f7f0e9f 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs @@ -2611,6 +2611,11 @@ void executeNodeActions() void executeNodeActionsByKind(ArrayBuilder nodesToAnalyze, GroupedAnalyzerActions groupedActions, bool arePerSymbolActions) { + if (groupedActions.GroupedActionsByAnalyzer.Length == 0) + { + return; + } + var analyzersForNodes = PooledHashSet.GetInstance(); foreach (var node in nodesToAnalyze) { From 072f4c75fbf3dd59d5c83753c041b90b683ab426 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 11:36:48 -0800 Subject: [PATCH 04/49] Fix abuse of generics in analyzer driver --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 146 +++++++++--------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 17eeeb262d9b7..3416e2e61fe39 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -701,9 +701,41 @@ public void ExecuteCodeBlockActions( where TLanguageKindEnum : struct { ExecuteBlockActionsCore, CodeBlockAnalyzerAction, SyntaxNodeAnalyzerAction, SyntaxNode, TLanguageKindEnum>( - codeBlockStartActions, codeBlockActions, codeBlockEndActions, analyzer, - declaredNode, declaredSymbol, executableCodeBlocks, (codeBlocks) => codeBlocks.SelectMany( - cb => + codeBlockStartActions, + codeBlockActions, + codeBlockEndActions, + analyzer, + declaredNode, + declaredSymbol, + executableCodeBlocks, + semanticModel, + filterSpan, + isGeneratedCode, + addActions: (startAction, codeBlockEndActions, syntaxNodeActions) => + { + var codeBlockScope = new HostCodeBlockStartAnalysisScope(startAction.Analyzer); + var blockStartContext = new AnalyzerCodeBlockStartAnalysisContext( + codeBlockScope, declaredNode, declaredSymbol, semanticModel, AnalyzerOptions, filterSpan, isGeneratedCode, cancellationToken); + + // Catch Exception from the start action. + ExecuteAndCatchIfThrows( + startAction.Analyzer, + static data => + { + data.action(data.context); + data.blockEndActions?.AddAll(data.scope.CodeBlockEndActions); + data.syntaxNodeActions?.AddRange(data.scope.SyntaxNodeActions); + }, + (action: startAction.Action, context: blockStartContext, scope: codeBlockScope, blockEndActions: codeBlockEndActions, syntaxNodeActions), + new AnalysisContextInfo(Compilation, declaredSymbol, declaredNode), + cancellationToken); + }, + executeActions: (syntaxNodeActions, diagReporter, isSupportedDiagnostic) => + { + Debug.Assert(getKind != null); + + var executableNodeActionsByKind = GetNodeActionsByKind(syntaxNodeActions); + var syntaxNodesToAnalyze = executableCodeBlocks.SelectMany(cb => { var filter = semanticModel.GetSyntaxNodesToAnalyzeFilter(cb, declaredSymbol); @@ -715,8 +747,11 @@ public void ExecuteCodeBlockActions( { return cb.DescendantNodesAndSelf(); } - }), - semanticModel, getKind, filterSpan, isGeneratedCode, cancellationToken); + }); + + ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions: codeBlockStartActions.Any(), cancellationToken); + }, + cancellationToken); } /// @@ -738,8 +773,35 @@ public void ExecuteOperationBlockActions( { ExecuteBlockActionsCore( operationBlockStartActions, operationBlockActions, operationBlockEndActions, analyzer, - declaredNode, declaredSymbol, operationBlocks, (blocks) => operations, semanticModel, - getKind: null, filterSpan, isGeneratedCode, cancellationToken); + declaredNode, declaredSymbol, operationBlocks, semanticModel, + filterSpan, isGeneratedCode, + addActions: (startAction, operationBlockEndActions, operationActions) => + { + var operationBlockScope = new HostOperationBlockStartAnalysisScope(startAction.Analyzer); + var operationStartContext = new AnalyzerOperationBlockStartAnalysisContext( + operationBlockScope, operationBlocks, declaredSymbol, semanticModel.Compilation, AnalyzerOptions, + GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); + + // Catch Exception from the start action. + ExecuteAndCatchIfThrows( + startAction.Analyzer, + static data => + { + data.action(data.context); + data.blockEndActions?.AddAll(data.scope.OperationBlockEndActions); + data.operationActions?.AddRange(data.scope.OperationActions); + }, + (action: startAction.Action, context: operationStartContext, scope: operationBlockScope, blockEndActions: operationBlockEndActions, operationActions), + new AnalysisContextInfo(Compilation, declaredSymbol), + cancellationToken); + }, + executeActions: (operationActions, diagReporter, isSupportedDiagnostic) => + { + var operationActionsByKind = GetOperationActionsByKind(operationActions); + var operationsToAnalyze = operations; + ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions: operationBlockStartActions.Any(), cancellationToken); + }, + cancellationToken); } private void ExecuteBlockActionsCore( @@ -750,11 +812,11 @@ private void ExecuteBlockActionsCore executableBlocks, - Func, IEnumerable> getNodesToAnalyze, SemanticModel semanticModel, - Func? getKind, TextSpan? filterSpan, bool isGeneratedCode, + Action, ArrayBuilder> addActions, + Action, AnalyzerDiagnosticReporter, Func> executeActions, CancellationToken cancellationToken) where TLanguageKindEnum : struct where TBlockStartAction : AnalyzerAction @@ -778,8 +840,6 @@ private void ExecuteBlockActionsCore.GetInstance(); var blockActions = PooledHashSet.GetInstance(); var executableNodeActions = ArrayBuilder.GetInstance(); - var syntaxNodeActions = executableNodeActions as ArrayBuilder>; - var operationActions = executableNodeActions as ArrayBuilder; ImmutableArray operationBlocks = executableBlocks[0] is IOperation ? (ImmutableArray)(object)executableBlocks : ImmutableArray.Empty; // Include the code block actions. @@ -792,73 +852,13 @@ private void ExecuteBlockActionsCore codeBlockStartAction) - { - var codeBlockEndActions = blockEndActions as PooledHashSet; - var codeBlockScope = new HostCodeBlockStartAnalysisScope(startAction.Analyzer); - var blockStartContext = new AnalyzerCodeBlockStartAnalysisContext( - codeBlockScope, declaredNode, declaredSymbol, semanticModel, AnalyzerOptions, filterSpan, isGeneratedCode, cancellationToken); - - // Catch Exception from the start action. - ExecuteAndCatchIfThrows( - startAction.Analyzer, - data => - { - data.action(data.context); - data.blockEndActions?.AddAll(data.scope.CodeBlockEndActions); - data.syntaxNodeActions?.AddRange(data.scope.SyntaxNodeActions); - }, - (action: codeBlockStartAction.Action, context: blockStartContext, scope: codeBlockScope, blockEndActions: codeBlockEndActions, syntaxNodeActions), - new AnalysisContextInfo(Compilation, declaredSymbol, declaredNode), - cancellationToken); - } - else - { - if (startAction is OperationBlockStartAnalyzerAction operationBlockStartAction) - { - var operationBlockEndActions = blockEndActions as PooledHashSet; - var operationBlockScope = new HostOperationBlockStartAnalysisScope(startAction.Analyzer); - var operationStartContext = new AnalyzerOperationBlockStartAnalysisContext( - operationBlockScope, operationBlocks, declaredSymbol, semanticModel.Compilation, AnalyzerOptions, - GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); - - // Catch Exception from the start action. - ExecuteAndCatchIfThrows( - startAction.Analyzer, - data => - { - data.action(data.context); - data.blockEndActions?.AddAll(data.scope.OperationBlockEndActions); - data.operationActions?.AddRange(data.scope.OperationActions); - }, - (action: operationBlockStartAction.Action, context: operationStartContext, scope: operationBlockScope, blockEndActions: operationBlockEndActions, operationActions: operationActions), - new AnalysisContextInfo(Compilation, declaredSymbol), - cancellationToken); - } - } - } + addActions(startAction, blockEndActions, executableNodeActions); using var _ = PooledDelegates.GetPooledFunction((d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), (self: this, analyzer), out Func isSupportedDiagnostic); // Execute stateful executable node analyzers, if any. if (executableNodeActions.Any()) - { - if (syntaxNodeActions != null) - { - Debug.Assert(getKind != null); - - var executableNodeActionsByKind = GetNodeActionsByKind(syntaxNodeActions); - var syntaxNodesToAnalyze = (IEnumerable)getNodesToAnalyze(executableBlocks); - ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); - } - else if (operationActions != null) - { - var operationActionsByKind = GetOperationActionsByKind(operationActions); - var operationsToAnalyze = (IEnumerable)getNodesToAnalyze(executableBlocks); - ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); - } - } + executeActions(executableNodeActions, diagReporter, isSupportedDiagnostic); executableNodeActions.Free(); From f038a00ab1cea2d9d710eb3e2a99a41a40c71b52 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 11:38:42 -0800 Subject: [PATCH 05/49] Add asserts --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 3416e2e61fe39..92ff8865b9706 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -700,6 +700,7 @@ public void ExecuteCodeBlockActions( CancellationToken cancellationToken) where TLanguageKindEnum : struct { + Debug.Assert(!executableCodeBlocks.IsEmpty); ExecuteBlockActionsCore, CodeBlockAnalyzerAction, SyntaxNodeAnalyzerAction, SyntaxNode, TLanguageKindEnum>( codeBlockStartActions, codeBlockActions, @@ -771,6 +772,7 @@ public void ExecuteOperationBlockActions( bool isGeneratedCode, CancellationToken cancellationToken) { + Debug.Assert(!operationBlocks.IsEmpty); ExecuteBlockActionsCore( operationBlockStartActions, operationBlockActions, operationBlockEndActions, analyzer, declaredNode, declaredSymbol, operationBlocks, semanticModel, From 24cbdacdb11d32584506168f36b8008147e09853 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 11:39:32 -0800 Subject: [PATCH 06/49] Remove type checking --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 92ff8865b9706..450d2592bd058 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -708,7 +708,7 @@ public void ExecuteCodeBlockActions( analyzer, declaredNode, declaredSymbol, - executableCodeBlocks, + operationBlocks: ImmutableArray.Empty, semanticModel, filterSpan, isGeneratedCode, @@ -813,7 +813,7 @@ private void ExecuteBlockActionsCore executableBlocks, + ImmutableArray operationBlocks, SemanticModel semanticModel, TextSpan? filterSpan, bool isGeneratedCode, @@ -829,7 +829,6 @@ private void ExecuteBlockActionsCore.GetInstance(); var blockActions = PooledHashSet.GetInstance(); var executableNodeActions = ArrayBuilder.GetInstance(); - ImmutableArray operationBlocks = executableBlocks[0] is IOperation ? (ImmutableArray)(object)executableBlocks : ImmutableArray.Empty; // Include the code block actions. blockActions.AddAll(actions); From 1639264b2de1045ecee9b320adec6ac5217d04cc Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 11:45:48 -0800 Subject: [PATCH 07/49] in progress --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 450d2592bd058..c7246602068ed 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -773,19 +773,20 @@ public void ExecuteOperationBlockActions( CancellationToken cancellationToken) { Debug.Assert(!operationBlocks.IsEmpty); - ExecuteBlockActionsCore( + ExecuteBlockActionsCore( operationBlockStartActions, operationBlockActions, operationBlockEndActions, analyzer, declaredNode, declaredSymbol, operationBlocks, semanticModel, filterSpan, isGeneratedCode, - addActions: (startAction, operationBlockEndActions, operationActions) => + addActions: static (startAction, operationBlockEndActions, operationActions, args, cancellationToken) => { + var (@this, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; var operationBlockScope = new HostOperationBlockStartAnalysisScope(startAction.Analyzer); var operationStartContext = new AnalyzerOperationBlockStartAnalysisContext( - operationBlockScope, operationBlocks, declaredSymbol, semanticModel.Compilation, AnalyzerOptions, - GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); + operationBlockScope, operationBlocks, declaredSymbol, semanticModel.Compilation, @this.AnalyzerOptions, + @this.GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); // Catch Exception from the start action. - ExecuteAndCatchIfThrows( + @this.ExecuteAndCatchIfThrows( startAction.Analyzer, static data => { @@ -794,19 +795,21 @@ public void ExecuteOperationBlockActions( data.operationActions?.AddRange(data.scope.OperationActions); }, (action: startAction.Action, context: operationStartContext, scope: operationBlockScope, blockEndActions: operationBlockEndActions, operationActions), - new AnalysisContextInfo(Compilation, declaredSymbol), + new AnalysisContextInfo(@this.Compilation, declaredSymbol), cancellationToken); }, - executeActions: (operationActions, diagReporter, isSupportedDiagnostic) => + executeActions: static (operationActions, diagReporter, isSupportedDiagnostic, args, cancellationToken) => { - var operationActionsByKind = GetOperationActionsByKind(operationActions); + var (@this, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; + var operationActionsByKind = @this.GetOperationActionsByKind(operationActions); var operationsToAnalyze = operations; - ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions: operationBlockStartActions.Any(), cancellationToken); + @this.ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions: operationBlockStartActions.Any(), cancellationToken); }, + args: (@this: this, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode), cancellationToken); } - private void ExecuteBlockActionsCore( + private void ExecuteBlockActionsCore( IEnumerable startActions, IEnumerable actions, IEnumerable endActions, @@ -817,13 +820,14 @@ private void ExecuteBlockActionsCore, ArrayBuilder> addActions, - Action, AnalyzerDiagnosticReporter, Func> executeActions, + Action, ArrayBuilder, TArgs, CancellationToken> addActions, + Action, AnalyzerDiagnosticReporter, Func, TArgs, CancellationToken> executeActions, + TArgs args, CancellationToken cancellationToken) - where TLanguageKindEnum : struct - where TBlockStartAction : AnalyzerAction - where TBlockAction : AnalyzerAction - where TNodeAction : AnalyzerAction + where TBlockStartAction : AnalyzerAction + where TBlockAction : AnalyzerAction + where TNodeAction : AnalyzerAction + where TArgs : struct { Debug.Assert(declaredNode != null); Debug.Assert(declaredSymbol != null); @@ -852,13 +856,13 @@ private void ExecuteBlockActionsCore arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), (self: this, analyzer), out Func isSupportedDiagnostic); // Execute stateful executable node analyzers, if any. if (executableNodeActions.Any()) - executeActions(executableNodeActions, diagReporter, isSupportedDiagnostic); + executeActions(executableNodeActions, diagReporter, isSupportedDiagnostic, args, cancellationToken); executableNodeActions.Free(); From c4aa312ae3a49edfeadb020ba0f42b416358be4b Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 11:49:13 -0800 Subject: [PATCH 08/49] pass args --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index c7246602068ed..1f56be5a7cdf1 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -701,7 +701,7 @@ public void ExecuteCodeBlockActions( where TLanguageKindEnum : struct { Debug.Assert(!executableCodeBlocks.IsEmpty); - ExecuteBlockActionsCore, CodeBlockAnalyzerAction, SyntaxNodeAnalyzerAction, SyntaxNode, TLanguageKindEnum>( + ExecuteBlockActionsCore( codeBlockStartActions, codeBlockActions, codeBlockEndActions, @@ -712,14 +712,16 @@ public void ExecuteCodeBlockActions( semanticModel, filterSpan, isGeneratedCode, - addActions: (startAction, codeBlockEndActions, syntaxNodeActions) => + addActions: static (startAction, codeBlockEndActions, syntaxNodeActions, args, cancellationToken) => { + var (@this, codeBlockStartActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode) = args; + var codeBlockScope = new HostCodeBlockStartAnalysisScope(startAction.Analyzer); var blockStartContext = new AnalyzerCodeBlockStartAnalysisContext( - codeBlockScope, declaredNode, declaredSymbol, semanticModel, AnalyzerOptions, filterSpan, isGeneratedCode, cancellationToken); + codeBlockScope, declaredNode, declaredSymbol, semanticModel, @this.AnalyzerOptions, filterSpan, isGeneratedCode, cancellationToken); // Catch Exception from the start action. - ExecuteAndCatchIfThrows( + @this.ExecuteAndCatchIfThrows( startAction.Analyzer, static data => { @@ -728,14 +730,16 @@ public void ExecuteCodeBlockActions( data.syntaxNodeActions?.AddRange(data.scope.SyntaxNodeActions); }, (action: startAction.Action, context: blockStartContext, scope: codeBlockScope, blockEndActions: codeBlockEndActions, syntaxNodeActions), - new AnalysisContextInfo(Compilation, declaredSymbol, declaredNode), + new AnalysisContextInfo(@this.Compilation, declaredSymbol, declaredNode), cancellationToken); }, - executeActions: (syntaxNodeActions, diagReporter, isSupportedDiagnostic) => + executeActions: static (syntaxNodeActions, diagReporter, isSupportedDiagnostic, args, cancellationToken) => { + var (@this, codeBlockStartActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode) = args; + Debug.Assert(getKind != null); - var executableNodeActionsByKind = GetNodeActionsByKind(syntaxNodeActions); + var executableNodeActionsByKind = @this.GetNodeActionsByKind(syntaxNodeActions); var syntaxNodesToAnalyze = executableCodeBlocks.SelectMany(cb => { var filter = semanticModel.GetSyntaxNodesToAnalyzeFilter(cb, declaredSymbol); @@ -750,8 +754,9 @@ public void ExecuteCodeBlockActions( } }); - ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions: codeBlockStartActions.Any(), cancellationToken); + @this.ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions: codeBlockStartActions.Any(), cancellationToken); }, + args: (@this: this, codeBlockStartActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode), cancellationToken); } @@ -779,7 +784,7 @@ public void ExecuteOperationBlockActions( filterSpan, isGeneratedCode, addActions: static (startAction, operationBlockEndActions, operationActions, args, cancellationToken) => { - var (@this, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; + var (@this, operationBlockStartActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; var operationBlockScope = new HostOperationBlockStartAnalysisScope(startAction.Analyzer); var operationStartContext = new AnalyzerOperationBlockStartAnalysisContext( operationBlockScope, operationBlocks, declaredSymbol, semanticModel.Compilation, @this.AnalyzerOptions, @@ -800,12 +805,12 @@ public void ExecuteOperationBlockActions( }, executeActions: static (operationActions, diagReporter, isSupportedDiagnostic, args, cancellationToken) => { - var (@this, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; + var (@this, operationBlockStartActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; var operationActionsByKind = @this.GetOperationActionsByKind(operationActions); var operationsToAnalyze = operations; @this.ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions: operationBlockStartActions.Any(), cancellationToken); }, - args: (@this: this, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode), + args: (@this: this, operationBlockStartActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode), cancellationToken); } From 4fc71a85384af88be69516f94d1062492897018c Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 11:54:09 -0800 Subject: [PATCH 09/49] Make inference work --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 1f56be5a7cdf1..8aa528914921f 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -701,6 +701,7 @@ public void ExecuteCodeBlockActions( where TLanguageKindEnum : struct { Debug.Assert(!executableCodeBlocks.IsEmpty); + var executableNodeActions = ArrayBuilder>.GetInstance(); ExecuteBlockActionsCore( codeBlockStartActions, codeBlockActions, @@ -712,6 +713,7 @@ public void ExecuteCodeBlockActions( semanticModel, filterSpan, isGeneratedCode, + executableNodeActions, addActions: static (startAction, codeBlockEndActions, syntaxNodeActions, args, cancellationToken) => { var (@this, codeBlockStartActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode) = args; @@ -739,19 +741,14 @@ public void ExecuteCodeBlockActions( Debug.Assert(getKind != null); - var executableNodeActionsByKind = @this.GetNodeActionsByKind(syntaxNodeActions); + var executableNodeActionsByKind = GetNodeActionsByKind(syntaxNodeActions); var syntaxNodesToAnalyze = executableCodeBlocks.SelectMany(cb => { var filter = semanticModel.GetSyntaxNodesToAnalyzeFilter(cb, declaredSymbol); - if (filter is object) - { - return cb.DescendantNodesAndSelf(descendIntoChildren: filter).Where(filter); - } - else - { - return cb.DescendantNodesAndSelf(); - } + return filter is not null + ? cb.DescendantNodesAndSelf(descendIntoChildren: filter).Where(filter) + : cb.DescendantNodesAndSelf(); }); @this.ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions: codeBlockStartActions.Any(), cancellationToken); @@ -778,10 +775,20 @@ public void ExecuteOperationBlockActions( CancellationToken cancellationToken) { Debug.Assert(!operationBlocks.IsEmpty); + + var executableNodeActions = ArrayBuilder.GetInstance(); ExecuteBlockActionsCore( - operationBlockStartActions, operationBlockActions, operationBlockEndActions, analyzer, - declaredNode, declaredSymbol, operationBlocks, semanticModel, - filterSpan, isGeneratedCode, + operationBlockStartActions, + operationBlockActions, + operationBlockEndActions, + analyzer, + declaredNode, + declaredSymbol, + operationBlocks, + semanticModel, + filterSpan, + isGeneratedCode, + executableNodeActions, addActions: static (startAction, operationBlockEndActions, operationActions, args, cancellationToken) => { var (@this, operationBlockStartActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; @@ -805,16 +812,17 @@ public void ExecuteOperationBlockActions( }, executeActions: static (operationActions, diagReporter, isSupportedDiagnostic, args, cancellationToken) => { - var (@this, operationBlockStartActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; - var operationActionsByKind = @this.GetOperationActionsByKind(operationActions); + var (@this, operationBlockStartActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; + var operationActionsByKind = GetOperationActionsByKind(operationActions); var operationsToAnalyze = operations; @this.ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions: operationBlockStartActions.Any(), cancellationToken); }, args: (@this: this, operationBlockStartActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode), cancellationToken); + executableNodeActions.Free(); } - private void ExecuteBlockActionsCore( + private void ExecuteBlockActionsCore( IEnumerable startActions, IEnumerable actions, IEnumerable endActions, @@ -825,6 +833,7 @@ private void ExecuteBlockActionsCore executableNodeActions, Action, ArrayBuilder, TArgs, CancellationToken> addActions, Action, AnalyzerDiagnosticReporter, Func, TArgs, CancellationToken> executeActions, TArgs args, @@ -849,7 +858,6 @@ private void ExecuteBlockActionsCore.GetInstance(); var blockActions = PooledHashSet.GetInstance(); - var executableNodeActions = ArrayBuilder.GetInstance(); // Include the code block actions. blockActions.AddAll(actions); @@ -869,8 +877,6 @@ private void ExecuteBlockActionsCore Date: Fri, 24 Jan 2025 11:54:21 -0800 Subject: [PATCH 10/49] Free --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 8aa528914921f..9ee0eb6d21cfe 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -755,6 +755,7 @@ public void ExecuteCodeBlockActions( }, args: (@this: this, codeBlockStartActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode), cancellationToken); + executableNodeActions.Free(); } /// From dcf23443ee43e1c15703b12a0fb2b878a89bf972 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 11:55:52 -0800 Subject: [PATCH 11/49] pass immutable arrays --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 9ee0eb6d21cfe..c5389c18c4ffb 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -686,9 +686,9 @@ private void ExecuteOperationAction( /// Execute code block actions for the given analyzer for the given declaration. /// public void ExecuteCodeBlockActions( - IEnumerable> codeBlockStartActions, - IEnumerable codeBlockActions, - IEnumerable codeBlockEndActions, + ImmutableArray> codeBlockStartActions, + ImmutableArray codeBlockActions, + ImmutableArray codeBlockEndActions, DiagnosticAnalyzer analyzer, SyntaxNode declaredNode, ISymbol declaredSymbol, @@ -762,9 +762,9 @@ public void ExecuteCodeBlockActions( /// Execute operation block actions for the given analyzer for the given declaration. /// public void ExecuteOperationBlockActions( - IEnumerable operationBlockStartActions, - IEnumerable operationBlockActions, - IEnumerable operationBlockEndActions, + ImmutableArray operationBlockStartActions, + ImmutableArray operationBlockActions, + ImmutableArray operationBlockEndActions, DiagnosticAnalyzer analyzer, SyntaxNode declaredNode, ISymbol declaredSymbol, @@ -824,9 +824,9 @@ public void ExecuteOperationBlockActions( } private void ExecuteBlockActionsCore( - IEnumerable startActions, - IEnumerable actions, - IEnumerable endActions, + ImmutableArray startActions, + ImmutableArray actions, + ImmutableArray endActions, DiagnosticAnalyzer analyzer, SyntaxNode declaredNode, ISymbol declaredSymbol, From 85fd6fa8d90eb7d89a0a47bb00560ed08fd74a7c Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 11:57:13 -0800 Subject: [PATCH 12/49] Indentation --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index c5389c18c4ffb..953d5f51f74b2 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -824,21 +824,21 @@ public void ExecuteOperationBlockActions( } private void ExecuteBlockActionsCore( - ImmutableArray startActions, - ImmutableArray actions, - ImmutableArray endActions, - DiagnosticAnalyzer analyzer, - SyntaxNode declaredNode, - ISymbol declaredSymbol, - ImmutableArray operationBlocks, - SemanticModel semanticModel, - TextSpan? filterSpan, - bool isGeneratedCode, - ArrayBuilder executableNodeActions, - Action, ArrayBuilder, TArgs, CancellationToken> addActions, - Action, AnalyzerDiagnosticReporter, Func, TArgs, CancellationToken> executeActions, - TArgs args, - CancellationToken cancellationToken) + ImmutableArray startActions, + ImmutableArray actions, + ImmutableArray endActions, + DiagnosticAnalyzer analyzer, + SyntaxNode declaredNode, + ISymbol declaredSymbol, + ImmutableArray operationBlocks, + SemanticModel semanticModel, + TextSpan? filterSpan, + bool isGeneratedCode, + ArrayBuilder executableNodeActions, + Action, ArrayBuilder, TArgs, CancellationToken> addActions, + Action, AnalyzerDiagnosticReporter, Func, TArgs, CancellationToken> executeActions, + TArgs args, + CancellationToken cancellationToken) where TBlockStartAction : AnalyzerAction where TBlockAction : AnalyzerAction where TNodeAction : AnalyzerAction From cf94f86d4eecfc2cc06daf8ab4e41d49969114ce Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 12:10:50 -0800 Subject: [PATCH 13/49] Strong typing --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs | 4 ++-- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs index f3f942d2d1cfc..fc3d1279112c5 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs @@ -2764,7 +2764,7 @@ void executeOperationsActionsByKind(ImmutableArray operationsToAnaly } } - void executeOperationsBlockActions(ImmutableArray operationBlocksToAnalyze, ImmutableArray operationsToAnalyze, IEnumerable codeBlockActions) + void executeOperationsBlockActions(ImmutableArray operationBlocksToAnalyze, ImmutableArray operationsToAnalyze, ArrayBuilder codeBlockActions) { if (!shouldExecuteOperationBlockActions) { @@ -2792,7 +2792,7 @@ void executeOperationsBlockActions(ImmutableArray operationBlocksToA } } - void executeCodeBlockActions(ImmutableArray executableCodeBlocks, IEnumerable codeBlockActions) + void executeCodeBlockActions(ImmutableArray executableCodeBlocks, ArrayBuilder codeBlockActions) { if (executableCodeBlocks.IsEmpty || !shouldExecuteCodeBlockActions) { diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 953d5f51f74b2..129a34a250394 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -967,7 +967,7 @@ internal static ImmutableSegmentedDictionary public void ExecuteSyntaxNodeActions( - IEnumerable nodesToAnalyze, + ArrayBuilder nodesToAnalyze, ImmutableSegmentedDictionary>> nodeActionsByKind, DiagnosticAnalyzer analyzer, SemanticModel model, @@ -1070,7 +1070,7 @@ internal static ImmutableSegmentedDictionary public void ExecuteOperationActions( - IEnumerable operationsToAnalyze, + ImmutableArray operationsToAnalyze, ImmutableSegmentedDictionary> operationActionsByKind, DiagnosticAnalyzer analyzer, SemanticModel model, @@ -1095,7 +1095,7 @@ public void ExecuteOperationActions( } private void ExecuteOperationActions( - IEnumerable operationsToAnalyze, + ImmutableArray operationsToAnalyze, ImmutableSegmentedDictionary> operationActionsByKind, DiagnosticAnalyzer analyzer, ISymbol containingSymbol, From cbbda7c3c5b438bb5ce09a6872fca19b6de2295e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:05:29 -0800 Subject: [PATCH 14/49] move freeing up --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 129a34a250394..702ce5249652e 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -882,10 +882,12 @@ private void ExecuteBlockActionsCore( - PooledHashSet blockActions, + HashSet blockActions, SyntaxNode declaredNode, ISymbol declaredSymbol, DiagnosticAnalyzer analyzer, @@ -933,8 +935,6 @@ private void ExecuteBlockActions( } } } - - blockActions.Free(); } internal static ImmutableSegmentedDictionary>> GetNodeActionsByKind( From 20a090c94820a42c2331f095af7103f40380da61 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:12:36 -0800 Subject: [PATCH 15/49] Remove ?. it's not necessary --- .../Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 702ce5249652e..cb0c6961dde1a 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -728,8 +728,8 @@ public void ExecuteCodeBlockActions( static data => { data.action(data.context); - data.blockEndActions?.AddAll(data.scope.CodeBlockEndActions); - data.syntaxNodeActions?.AddRange(data.scope.SyntaxNodeActions); + data.blockEndActions.AddAll(data.scope.CodeBlockEndActions); + data.syntaxNodeActions.AddRange(data.scope.SyntaxNodeActions); }, (action: startAction.Action, context: blockStartContext, scope: codeBlockScope, blockEndActions: codeBlockEndActions, syntaxNodeActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol, declaredNode), @@ -804,8 +804,8 @@ public void ExecuteOperationBlockActions( static data => { data.action(data.context); - data.blockEndActions?.AddAll(data.scope.OperationBlockEndActions); - data.operationActions?.AddRange(data.scope.OperationActions); + data.blockEndActions.AddAll(data.scope.OperationBlockEndActions); + data.operationActions.AddRange(data.scope.OperationActions); }, (action: startAction.Action, context: operationStartContext, scope: operationBlockScope, blockEndActions: operationBlockEndActions, operationActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol), @@ -835,7 +835,7 @@ private void ExecuteBlockActionsCore executableNodeActions, - Action, ArrayBuilder, TArgs, CancellationToken> addActions, + Action, ArrayBuilder, TArgs, CancellationToken> addActions, Action, AnalyzerDiagnosticReporter, Func, TArgs, CancellationToken> executeActions, TArgs args, CancellationToken cancellationToken) From bb29f7c5498ba16cd5968db5e5f02a6dcaf1a9b2 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:13:54 -0800 Subject: [PATCH 16/49] remove tuple renqaming --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index cb0c6961dde1a..4476abd5833c8 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -803,11 +803,11 @@ public void ExecuteOperationBlockActions( startAction.Analyzer, static data => { - data.action(data.context); - data.blockEndActions.AddAll(data.scope.OperationBlockEndActions); - data.operationActions.AddRange(data.scope.OperationActions); + data.action(data.operationStartContext); + data.operationBlockEndActions.AddAll(data.operationBlockScope.OperationBlockEndActions); + data.operationActions.AddRange(data.operationBlockScope.OperationActions); }, - (action: startAction.Action, context: operationStartContext, scope: operationBlockScope, blockEndActions: operationBlockEndActions, operationActions), + (action: startAction.Action, operationStartContext, operationBlockScope, operationBlockEndActions, operationActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol), cancellationToken); }, From e1dc124d62e836a91ad65967571c90f0fb8a6a5e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:14:23 -0800 Subject: [PATCH 17/49] remove tuple renqaming --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 4476abd5833c8..777269f9357c7 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -727,11 +727,11 @@ public void ExecuteCodeBlockActions( startAction.Analyzer, static data => { - data.action(data.context); - data.blockEndActions.AddAll(data.scope.CodeBlockEndActions); - data.syntaxNodeActions.AddRange(data.scope.SyntaxNodeActions); + data.action(data.blockStartContext); + data.codeBlockEndActions.AddAll(data.codeBlockScope.CodeBlockEndActions); + data.syntaxNodeActions.AddRange(data.codeBlockScope.SyntaxNodeActions); }, - (action: startAction.Action, context: blockStartContext, scope: codeBlockScope, blockEndActions: codeBlockEndActions, syntaxNodeActions), + (action: startAction.Action, blockStartContext, codeBlockScope, codeBlockEndActions, syntaxNodeActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol, declaredNode), cancellationToken); }, From ef6a2e03411aa7ae9aa4e9674a8bd44b18539ff9 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:14:55 -0800 Subject: [PATCH 18/49] remove tuple renqaming --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 777269f9357c7..4615ad77d4db2 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -727,11 +727,11 @@ public void ExecuteCodeBlockActions( startAction.Analyzer, static data => { - data.action(data.blockStartContext); + data.startAction.Action(data.blockStartContext); data.codeBlockEndActions.AddAll(data.codeBlockScope.CodeBlockEndActions); data.syntaxNodeActions.AddRange(data.codeBlockScope.SyntaxNodeActions); }, - (action: startAction.Action, blockStartContext, codeBlockScope, codeBlockEndActions, syntaxNodeActions), + (startAction, blockStartContext, codeBlockScope, codeBlockEndActions, syntaxNodeActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol, declaredNode), cancellationToken); }, @@ -803,11 +803,11 @@ public void ExecuteOperationBlockActions( startAction.Analyzer, static data => { - data.action(data.operationStartContext); + data.startAction.Action(data.operationStartContext); data.operationBlockEndActions.AddAll(data.operationBlockScope.OperationBlockEndActions); data.operationActions.AddRange(data.operationBlockScope.OperationActions); }, - (action: startAction.Action, operationStartContext, operationBlockScope, operationBlockEndActions, operationActions), + (startAction, operationStartContext, operationBlockScope, operationBlockEndActions, operationActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol), cancellationToken); }, From 296cd65d2b8ff00c5cb952060539f6f05feda6fc Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:16:15 -0800 Subject: [PATCH 19/49] remove tuple renqaming --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 4615ad77d4db2..e8ff23c311ebc 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -725,13 +725,14 @@ public void ExecuteCodeBlockActions( // Catch Exception from the start action. @this.ExecuteAndCatchIfThrows( startAction.Analyzer, - static data => + static args => { - data.startAction.Action(data.blockStartContext); - data.codeBlockEndActions.AddAll(data.codeBlockScope.CodeBlockEndActions); - data.syntaxNodeActions.AddRange(data.codeBlockScope.SyntaxNodeActions); + var (startAction, blockStartContext, codeBlockScope, codeBlockEndActions, syntaxNodeActions) = args; + startAction.Action(blockStartContext); + codeBlockEndActions.AddAll(codeBlockScope.CodeBlockEndActions); + syntaxNodeActions.AddRange(codeBlockScope.SyntaxNodeActions); }, - (startAction, blockStartContext, codeBlockScope, codeBlockEndActions, syntaxNodeActions), + argument: (startAction, blockStartContext, codeBlockScope, codeBlockEndActions, syntaxNodeActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol, declaredNode), cancellationToken); }, @@ -753,7 +754,7 @@ public void ExecuteCodeBlockActions( @this.ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions: codeBlockStartActions.Any(), cancellationToken); }, - args: (@this: this, codeBlockStartActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode), + argument: (@this: this, codeBlockStartActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode), cancellationToken); executableNodeActions.Free(); } @@ -801,13 +802,14 @@ public void ExecuteOperationBlockActions( // Catch Exception from the start action. @this.ExecuteAndCatchIfThrows( startAction.Analyzer, - static data => + static args => { - data.startAction.Action(data.operationStartContext); - data.operationBlockEndActions.AddAll(data.operationBlockScope.OperationBlockEndActions); - data.operationActions.AddRange(data.operationBlockScope.OperationActions); + var (startAction, operationStartContext, operationBlockScope, operationBlockEndActions, operationActions) = args; + startAction.Action(operationStartContext); + operationBlockEndActions.AddAll(operationBlockScope.OperationBlockEndActions); + operationActions.AddRange(operationBlockScope.OperationActions); }, - (startAction, operationStartContext, operationBlockScope, operationBlockEndActions, operationActions), + argument: (startAction, operationStartContext, operationBlockScope, operationBlockEndActions, operationActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol), cancellationToken); }, @@ -818,7 +820,7 @@ public void ExecuteOperationBlockActions( var operationsToAnalyze = operations; @this.ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions: operationBlockStartActions.Any(), cancellationToken); }, - args: (@this: this, operationBlockStartActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode), + argument: (@this: this, operationBlockStartActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode), cancellationToken); executableNodeActions.Free(); } @@ -837,7 +839,7 @@ private void ExecuteBlockActionsCore executableNodeActions, Action, ArrayBuilder, TArgs, CancellationToken> addActions, Action, AnalyzerDiagnosticReporter, Func, TArgs, CancellationToken> executeActions, - TArgs args, + TArgs argument, CancellationToken cancellationToken) where TBlockStartAction : AnalyzerAction where TBlockAction : AnalyzerAction @@ -870,13 +872,13 @@ private void ExecuteBlockActionsCore arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), (self: this, analyzer), out Func isSupportedDiagnostic); // Execute stateful executable node analyzers, if any. if (executableNodeActions.Any()) - executeActions(executableNodeActions, diagReporter, isSupportedDiagnostic, args, cancellationToken); + executeActions(executableNodeActions, diagReporter, isSupportedDiagnostic, argument, cancellationToken); ExecuteBlockActions(blockActions, declaredNode, declaredSymbol, analyzer, semanticModel, operationBlocks, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); ExecuteBlockActions(blockEndActions, declaredNode, declaredSymbol, analyzer, semanticModel, operationBlocks, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); From 6cbfa812a658a1388355ccf601918f70bc7bff52 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:20:25 -0800 Subject: [PATCH 20/49] Consistent naming --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index e8ff23c311ebc..3a760d6c2d3bd 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -686,9 +686,9 @@ private void ExecuteOperationAction( /// Execute code block actions for the given analyzer for the given declaration. /// public void ExecuteCodeBlockActions( - ImmutableArray> codeBlockStartActions, - ImmutableArray codeBlockActions, - ImmutableArray codeBlockEndActions, + ImmutableArray> startActions, + ImmutableArray actions, + ImmutableArray endActions, DiagnosticAnalyzer analyzer, SyntaxNode declaredNode, ISymbol declaredSymbol, @@ -703,9 +703,9 @@ public void ExecuteCodeBlockActions( Debug.Assert(!executableCodeBlocks.IsEmpty); var executableNodeActions = ArrayBuilder>.GetInstance(); ExecuteBlockActionsCore( - codeBlockStartActions, - codeBlockActions, - codeBlockEndActions, + startActions, + actions, + endActions, analyzer, declaredNode, declaredSymbol, @@ -714,9 +714,9 @@ public void ExecuteCodeBlockActions( filterSpan, isGeneratedCode, executableNodeActions, - addActions: static (startAction, codeBlockEndActions, syntaxNodeActions, args, cancellationToken) => + addActions: static (startAction, endActions, syntaxNodeActions, args, cancellationToken) => { - var (@this, codeBlockStartActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode) = args; + var (@this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode) = args; var codeBlockScope = new HostCodeBlockStartAnalysisScope(startAction.Analyzer); var blockStartContext = new AnalyzerCodeBlockStartAnalysisContext( @@ -727,18 +727,18 @@ public void ExecuteCodeBlockActions( startAction.Analyzer, static args => { - var (startAction, blockStartContext, codeBlockScope, codeBlockEndActions, syntaxNodeActions) = args; + var (startAction, blockStartContext, codeBlockScope, endActions, syntaxNodeActions) = args; startAction.Action(blockStartContext); - codeBlockEndActions.AddAll(codeBlockScope.CodeBlockEndActions); + endActions.AddAll(codeBlockScope.CodeBlockEndActions); syntaxNodeActions.AddRange(codeBlockScope.SyntaxNodeActions); }, - argument: (startAction, blockStartContext, codeBlockScope, codeBlockEndActions, syntaxNodeActions), + argument: (startAction, blockStartContext, codeBlockScope, endActions, syntaxNodeActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol, declaredNode), cancellationToken); }, executeActions: static (syntaxNodeActions, diagReporter, isSupportedDiagnostic, args, cancellationToken) => { - var (@this, codeBlockStartActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode) = args; + var (@this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode) = args; Debug.Assert(getKind != null); @@ -752,9 +752,9 @@ public void ExecuteCodeBlockActions( : cb.DescendantNodesAndSelf(); }); - @this.ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions: codeBlockStartActions.Any(), cancellationToken); + @this.ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); }, - argument: (@this: this, codeBlockStartActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode), + argument: (@this: this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode), cancellationToken); executableNodeActions.Free(); } @@ -763,9 +763,9 @@ public void ExecuteCodeBlockActions( /// Execute operation block actions for the given analyzer for the given declaration. /// public void ExecuteOperationBlockActions( - ImmutableArray operationBlockStartActions, - ImmutableArray operationBlockActions, - ImmutableArray operationBlockEndActions, + ImmutableArray startActions, + ImmutableArray actions, + ImmutableArray endActions, DiagnosticAnalyzer analyzer, SyntaxNode declaredNode, ISymbol declaredSymbol, @@ -780,9 +780,9 @@ public void ExecuteOperationBlockActions( var executableNodeActions = ArrayBuilder.GetInstance(); ExecuteBlockActionsCore( - operationBlockStartActions, - operationBlockActions, - operationBlockEndActions, + startActions, + actions, + endActions, analyzer, declaredNode, declaredSymbol, @@ -791,9 +791,9 @@ public void ExecuteOperationBlockActions( filterSpan, isGeneratedCode, executableNodeActions, - addActions: static (startAction, operationBlockEndActions, operationActions, args, cancellationToken) => + addActions: static (startAction, endActions, operationActions, args, cancellationToken) => { - var (@this, operationBlockStartActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; + var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; var operationBlockScope = new HostOperationBlockStartAnalysisScope(startAction.Analyzer); var operationStartContext = new AnalyzerOperationBlockStartAnalysisContext( operationBlockScope, operationBlocks, declaredSymbol, semanticModel.Compilation, @this.AnalyzerOptions, @@ -804,23 +804,23 @@ public void ExecuteOperationBlockActions( startAction.Analyzer, static args => { - var (startAction, operationStartContext, operationBlockScope, operationBlockEndActions, operationActions) = args; + var (startAction, operationStartContext, operationBlockScope, endActions, operationActions) = args; startAction.Action(operationStartContext); - operationBlockEndActions.AddAll(operationBlockScope.OperationBlockEndActions); + endActions.AddAll(operationBlockScope.OperationBlockEndActions); operationActions.AddRange(operationBlockScope.OperationActions); }, - argument: (startAction, operationStartContext, operationBlockScope, operationBlockEndActions, operationActions), + argument: (startAction, operationStartContext, operationBlockScope, endActions, operationActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol), cancellationToken); }, executeActions: static (operationActions, diagReporter, isSupportedDiagnostic, args, cancellationToken) => { - var (@this, operationBlockStartActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; + var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; var operationActionsByKind = GetOperationActionsByKind(operationActions); var operationsToAnalyze = operations; - @this.ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions: operationBlockStartActions.Any(), cancellationToken); + @this.ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); }, - argument: (@this: this, operationBlockStartActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode), + argument: (@this: this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode), cancellationToken); executableNodeActions.Free(); } From 0d3c7f68295e04801d5a39d2c66c832f2777e49d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:23:38 -0800 Subject: [PATCH 21/49] No need to pass temp buffer through --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 55 +++++++++---------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 3a760d6c2d3bd..cf6e575951dc6 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -701,7 +701,7 @@ public void ExecuteCodeBlockActions( where TLanguageKindEnum : struct { Debug.Assert(!executableCodeBlocks.IsEmpty); - var executableNodeActions = ArrayBuilder>.GetInstance(); + var ephemeralActions = ArrayBuilder>.GetInstance(); ExecuteBlockActionsCore( startActions, actions, @@ -713,10 +713,9 @@ public void ExecuteCodeBlockActions( semanticModel, filterSpan, isGeneratedCode, - executableNodeActions, - addActions: static (startAction, endActions, syntaxNodeActions, args, cancellationToken) => + addActions: static (startAction, endActions, args, cancellationToken) => { - var (@this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode) = args; + var (@this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode, ephemeralActions) = args; var codeBlockScope = new HostCodeBlockStartAnalysisScope(startAction.Analyzer); var blockStartContext = new AnalyzerCodeBlockStartAnalysisContext( @@ -732,17 +731,17 @@ public void ExecuteCodeBlockActions( endActions.AddAll(codeBlockScope.CodeBlockEndActions); syntaxNodeActions.AddRange(codeBlockScope.SyntaxNodeActions); }, - argument: (startAction, blockStartContext, codeBlockScope, endActions, syntaxNodeActions), + argument: (startAction, blockStartContext, codeBlockScope, endActions, ephemeralActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol, declaredNode), cancellationToken); }, - executeActions: static (syntaxNodeActions, diagReporter, isSupportedDiagnostic, args, cancellationToken) => + executeActions: static (diagReporter, isSupportedDiagnostic, args, cancellationToken) => { - var (@this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode) = args; + var (@this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode, ephemeralActions) = args; Debug.Assert(getKind != null); - var executableNodeActionsByKind = GetNodeActionsByKind(syntaxNodeActions); + var executableNodeActionsByKind = GetNodeActionsByKind(ephemeralActions); var syntaxNodesToAnalyze = executableCodeBlocks.SelectMany(cb => { var filter = semanticModel.GetSyntaxNodesToAnalyzeFilter(cb, declaredSymbol); @@ -754,9 +753,9 @@ public void ExecuteCodeBlockActions( @this.ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); }, - argument: (@this: this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode), + argument: (@this: this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode, ephemeralActions), cancellationToken); - executableNodeActions.Free(); + ephemeralActions.Free(); } /// @@ -778,7 +777,7 @@ public void ExecuteOperationBlockActions( { Debug.Assert(!operationBlocks.IsEmpty); - var executableNodeActions = ArrayBuilder.GetInstance(); + var ephemeralActions = ArrayBuilder.GetInstance(); ExecuteBlockActionsCore( startActions, actions, @@ -790,10 +789,9 @@ public void ExecuteOperationBlockActions( semanticModel, filterSpan, isGeneratedCode, - executableNodeActions, - addActions: static (startAction, endActions, operationActions, args, cancellationToken) => + addActions: static (startAction, endActions, args, cancellationToken) => { - var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; + var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions) = args; var operationBlockScope = new HostOperationBlockStartAnalysisScope(startAction.Analyzer); var operationStartContext = new AnalyzerOperationBlockStartAnalysisContext( operationBlockScope, operationBlocks, declaredSymbol, semanticModel.Compilation, @this.AnalyzerOptions, @@ -804,28 +802,28 @@ public void ExecuteOperationBlockActions( startAction.Analyzer, static args => { - var (startAction, operationStartContext, operationBlockScope, endActions, operationActions) = args; + var (startAction, operationStartContext, operationBlockScope, endActions, ephemeralActions) = args; startAction.Action(operationStartContext); endActions.AddAll(operationBlockScope.OperationBlockEndActions); - operationActions.AddRange(operationBlockScope.OperationActions); + ephemeralActions.AddRange(operationBlockScope.OperationActions); }, - argument: (startAction, operationStartContext, operationBlockScope, endActions, operationActions), + argument: (startAction, operationStartContext, operationBlockScope, endActions, ephemeralActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol), cancellationToken); }, - executeActions: static (operationActions, diagReporter, isSupportedDiagnostic, args, cancellationToken) => + executeActions: static (diagReporter, isSupportedDiagnostic, args, cancellationToken) => { - var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode) = args; - var operationActionsByKind = GetOperationActionsByKind(operationActions); + var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions) = args; + var operationActionsByKind = GetOperationActionsByKind(ephemeralActions); var operationsToAnalyze = operations; @this.ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); }, - argument: (@this: this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode), + argument: (@this: this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions), cancellationToken); - executableNodeActions.Free(); + ephemeralActions.Free(); } - private void ExecuteBlockActionsCore( + private void ExecuteBlockActionsCore( ImmutableArray startActions, ImmutableArray actions, ImmutableArray endActions, @@ -836,14 +834,12 @@ private void ExecuteBlockActionsCore executableNodeActions, - Action, ArrayBuilder, TArgs, CancellationToken> addActions, - Action, AnalyzerDiagnosticReporter, Func, TArgs, CancellationToken> executeActions, + Action, TArgs, CancellationToken> addActions, + Action, TArgs, CancellationToken> executeActions, TArgs argument, CancellationToken cancellationToken) where TBlockStartAction : AnalyzerAction where TBlockAction : AnalyzerAction - where TNodeAction : AnalyzerAction where TArgs : struct { Debug.Assert(declaredNode != null); @@ -872,13 +868,12 @@ private void ExecuteBlockActionsCore arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), (self: this, analyzer), out Func isSupportedDiagnostic); // Execute stateful executable node analyzers, if any. - if (executableNodeActions.Any()) - executeActions(executableNodeActions, diagReporter, isSupportedDiagnostic, argument, cancellationToken); + executeActions(diagReporter, isSupportedDiagnostic, argument, cancellationToken); ExecuteBlockActions(blockActions, declaredNode, declaredSymbol, analyzer, semanticModel, operationBlocks, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); ExecuteBlockActions(blockEndActions, declaredNode, declaredSymbol, analyzer, semanticModel, operationBlocks, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); From 77372b3165004ebbeee341f591497887669f7407 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:26:47 -0800 Subject: [PATCH 22/49] Name arguments --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index cf6e575951dc6..90c9b2462450a 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -902,34 +902,29 @@ private void ExecuteBlockActions( foreach (var blockAction in blockActions) { - var codeBlockAction = blockAction as CodeBlockAnalyzerAction; - if (codeBlockAction != null) + if (blockAction is CodeBlockAnalyzerAction codeBlockAction) { var context = new CodeBlockAnalysisContext(declaredNode, declaredSymbol, semanticModel, AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); ExecuteAndCatchIfThrows( codeBlockAction.Analyzer, - data => data.action(data.context), - (action: codeBlockAction.Action, context: context), + static data => data.action(data.context), + argument: (action: codeBlockAction.Action, context), new AnalysisContextInfo(Compilation, declaredSymbol, declaredNode), cancellationToken); } - else + else if (blockAction is OperationBlockAnalyzerAction operationBlockAction) { - var operationBlockAction = blockAction as OperationBlockAnalyzerAction; - if (operationBlockAction != null) - { - var context = new OperationBlockAnalysisContext(operationBlocks, declaredSymbol, semanticModel.Compilation, - AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); - - ExecuteAndCatchIfThrows( - operationBlockAction.Analyzer, - data => data.action(data.context), - (action: operationBlockAction.Action, context), - new AnalysisContextInfo(Compilation, declaredSymbol), - cancellationToken); - } + var context = new OperationBlockAnalysisContext(operationBlocks, declaredSymbol, semanticModel.Compilation, + AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); + + ExecuteAndCatchIfThrows( + operationBlockAction.Analyzer, + static data => data.action(data.context), + argument: (action: operationBlockAction.Action, context), + new AnalysisContextInfo(Compilation, declaredSymbol), + cancellationToken); } } } From 794fdc99fe47e4ad731109f2c2d9187a781da319 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:37:32 -0800 Subject: [PATCH 23/49] Use array builder consistently --- ...river.GroupedAnalyzerActionsForAnalyzer.cs | 26 ++++++++++++++----- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 2 +- .../DiagnosticStartAnalysisScope.cs | 16 +++++++----- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs index aa67d28c38cd7..5c0d7060a6901 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Linq; using Microsoft.CodeAnalysis.Collections; +using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis.Diagnostics { @@ -46,6 +47,16 @@ private static void VerifyActions(in ImmutableArray(in ArrayBuilder actions, DiagnosticAnalyzer analyzer) + where TAnalyzerAction : AnalyzerAction + { + foreach (var action in actions) + { + Debug.Assert(action.Analyzer == analyzer); + } + } + private ImmutableArray GetFilteredActions(in ImmutableArray actions) where TAnalyzerAction : AnalyzerAction => GetFilteredActions(actions, _analyzer, _analyzerActionsNeedFiltering); @@ -70,13 +81,16 @@ public ImmutableSegmentedDictionary(_analyzer) : - AnalyzerActions.GetSyntaxNodeActions(); + var nodeActions = ArrayBuilder>.GetInstance(); + if (_analyzerActionsNeedFiltering) + AnalyzerActions.AddSyntaxNodeActions(_analyzer, nodeActions); + else + AnalyzerActions.AddSyntaxNodeActions(nodeActions); + VerifyActions(nodeActions, _analyzer); - var analyzerActionsByKind = !nodeActions.IsEmpty ? - AnalyzerExecutor.GetNodeActionsByKind(nodeActions) : - ImmutableSegmentedDictionary>>.Empty; + var analyzerActionsByKind = !nodeActions.IsEmpty + ? AnalyzerExecutor.GetNodeActionsByKind(nodeActions) + : ImmutableSegmentedDictionary>>.Empty; RoslynImmutableInterlocked.InterlockedInitialize(ref _lazyNodeActionsByKind, analyzerActionsByKind); } diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 90c9b2462450a..e474c87fdab0e 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -930,7 +930,7 @@ private void ExecuteBlockActions( } internal static ImmutableSegmentedDictionary>> GetNodeActionsByKind( - IEnumerable> nodeActions) + ArrayBuilder> nodeActions) where TLanguageKindEnum : struct { Debug.Assert(nodeActions != null && nodeActions.Any()); diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/DiagnosticStartAnalysisScope.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/DiagnosticStartAnalysisScope.cs index fb6dcccfdfd45..ba5874c3d1d0a 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/DiagnosticStartAnalysisScope.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/DiagnosticStartAnalysisScope.cs @@ -820,14 +820,20 @@ internal readonly ImmutableArray return _codeBlockStartActions.OfType>().ToImmutableArray(); } - internal readonly ImmutableArray> GetSyntaxNodeActions() where TLanguageKindEnum : struct + internal readonly void AddSyntaxNodeActions( + ArrayBuilder> builder) where TLanguageKindEnum : struct { - return _syntaxNodeActions.OfType>().ToImmutableArray(); + foreach (var action in _syntaxNodeActions) + { + if (action is SyntaxNodeAnalyzerAction stronglyTypedAction) + builder.Add(stronglyTypedAction); + } } - internal readonly ImmutableArray> GetSyntaxNodeActions(DiagnosticAnalyzer analyzer) where TLanguageKindEnum : struct + internal readonly void AddSyntaxNodeActions( + DiagnosticAnalyzer analyzer, + ArrayBuilder> builder) where TLanguageKindEnum : struct { - var builder = ArrayBuilder>.GetInstance(); foreach (var action in _syntaxNodeActions) { if (action.Analyzer == analyzer && @@ -836,8 +842,6 @@ internal readonly ImmutableArray> Ge builder.Add(syntaxNodeAction); } } - - return builder.ToImmutableAndFree(); } internal readonly ImmutableArray OperationBlockActions From 1a6ce21bfd23524d993d4812a8ddee7a2e8bb13a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:37:48 -0800 Subject: [PATCH 24/49] free actions --- .../AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs index 5c0d7060a6901..8ee9bebdf3cf2 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs @@ -92,6 +92,8 @@ public ImmutableSegmentedDictionary>>.Empty; RoslynImmutableInterlocked.InterlockedInitialize(ref _lazyNodeActionsByKind, analyzerActionsByKind); + + nodeActions.Free(); } return _lazyNodeActionsByKind; From de90dff096d30b046dddd7c3a5fa6bd02f0c69d8 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:44:04 -0800 Subject: [PATCH 25/49] more pooling --- ...river.GroupedAnalyzerActionsForAnalyzer.cs | 42 ++++++++++++------- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 3 +- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs index 8ee9bebdf3cf2..5e5a07c1f27e0 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs @@ -57,22 +57,33 @@ private static void VerifyActions(in ArrayBuilder GetFilteredActions(in ImmutableArray actions) + private void AddFilteredActions( + ImmutableArray actions, + ArrayBuilder builder) where TAnalyzerAction : AnalyzerAction - => GetFilteredActions(actions, _analyzer, _analyzerActionsNeedFiltering); + { + AddFilteredActions(actions, _analyzer, _analyzerActionsNeedFiltering, builder); + } - private static ImmutableArray GetFilteredActions( + private static void AddFilteredActions( in ImmutableArray actions, DiagnosticAnalyzer analyzer, - bool analyzerActionsNeedFiltering) + bool analyzerActionsNeedFiltering, + ArrayBuilder builder) where TAnalyzerAction : AnalyzerAction { if (!analyzerActionsNeedFiltering) { - return actions; + builder.AddRange(actions); + } + else + { + foreach (var action in actions) + { + if (action.Analyzer == analyzer) + builder.Add(action); + } } - - return actions.WhereAsArray((action, analyzer) => action.Analyzer == analyzer, analyzer); } public ImmutableSegmentedDictionary>> NodeActionsByAnalyzerAndKind @@ -106,12 +117,14 @@ public ImmutableSegmentedDictionary.GetInstance(); + AddFilteredActions(AnalyzerActions.OperationActions, operationActions); VerifyActions(operationActions, _analyzer); - var analyzerActionsByKind = operationActions.Any() ? - AnalyzerExecutor.GetOperationActionsByKind(operationActions) : - ImmutableSegmentedDictionary>.Empty; + var analyzerActionsByKind = operationActions.Any() + ? AnalyzerExecutor.GetOperationActionsByKind(operationActions) + : ImmutableSegmentedDictionary>.Empty; RoslynImmutableInterlocked.InterlockedInitialize(ref _lazyOperationActionsByKind, analyzerActionsByKind); + operationActions.Free(); } return _lazyOperationActionsByKind; @@ -160,9 +173,10 @@ private static ImmutableArray GetExecutableCodeActions( { if (lazyCodeBlockActions.IsDefault) { - codeBlockActions = GetFilteredActions(codeBlockActions, analyzer, analyzerActionsNeedFiltering); - VerifyActions(codeBlockActions, analyzer); - ImmutableInterlocked.InterlockedInitialize(ref lazyCodeBlockActions, codeBlockActions); + var finalActions = ArrayBuilder.GetInstance(); + AddFilteredActions(codeBlockActions, analyzer, analyzerActionsNeedFiltering, finalActions); + VerifyActions(finalActions, analyzer); + ImmutableInterlocked.InterlockedInitialize(ref lazyCodeBlockActions, finalActions.ToImmutableAndFree()); } return lazyCodeBlockActions; diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index e474c87fdab0e..466659b7ffb91 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -1030,7 +1030,8 @@ private void ExecuteSyntaxNodeActions( } } - internal static ImmutableSegmentedDictionary> GetOperationActionsByKind(IEnumerable operationActions) + internal static ImmutableSegmentedDictionary> GetOperationActionsByKind( + ArrayBuilder operationActions) { Debug.Assert(operationActions.Any()); From 4aeb957ad52b809f3b3399613a3466cf510dd8a3 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:45:36 -0800 Subject: [PATCH 26/49] more pooling --- ...zerDriver.GroupedAnalyzerActionsForAnalyzer.cs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs index 5e5a07c1f27e0..5f3af03d4f299 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs @@ -37,16 +37,6 @@ public GroupedAnalyzerActionsForAnalyzer(DiagnosticAnalyzer analyzer, in Analyze public AnalyzerActions AnalyzerActions { get; } - [Conditional("DEBUG")] - private static void VerifyActions(in ImmutableArray actions, DiagnosticAnalyzer analyzer) - where TAnalyzerAction : AnalyzerAction - { - foreach (var action in actions) - { - Debug.Assert(action.Analyzer == analyzer); - } - } - [Conditional("DEBUG")] private static void VerifyActions(in ArrayBuilder actions, DiagnosticAnalyzer analyzer) where TAnalyzerAction : AnalyzerAction @@ -137,9 +127,10 @@ private ImmutableArray> CodeBloc { if (_lazyCodeBlockStartActions.IsDefault) { - var codeBlockActions = GetFilteredActions(AnalyzerActions.GetCodeBlockStartActions()); + var codeBlockActions = ArrayBuilder>.GetInstance(); + AddFilteredActions(AnalyzerActions.GetCodeBlockStartActions(), codeBlockActions); VerifyActions(codeBlockActions, _analyzer); - ImmutableInterlocked.InterlockedInitialize(ref _lazyCodeBlockStartActions, codeBlockActions); + ImmutableInterlocked.InterlockedInitialize(ref _lazyCodeBlockStartActions, codeBlockActions.ToImmutableAndFree()); } return _lazyCodeBlockStartActions; From 79caa86932951fd06a1f5fae7b5d4aeb6fe441fc Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:48:30 -0800 Subject: [PATCH 27/49] Push to common location --- ...river.GroupedAnalyzerActionsForAnalyzer.cs | 8 +--- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 38 +++++++++++-------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs index 5f3af03d4f299..ac20ac6cb64fe 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs @@ -89,9 +89,7 @@ public ImmutableSegmentedDictionary>>.Empty; + var analyzerActionsByKind = AnalyzerExecutor.GetNodeActionsByKind(nodeActions); RoslynImmutableInterlocked.InterlockedInitialize(ref _lazyNodeActionsByKind, analyzerActionsByKind); nodeActions.Free(); @@ -110,9 +108,7 @@ public ImmutableSegmentedDictionary.GetInstance(); AddFilteredActions(AnalyzerActions.OperationActions, operationActions); VerifyActions(operationActions, _analyzer); - var analyzerActionsByKind = operationActions.Any() - ? AnalyzerExecutor.GetOperationActionsByKind(operationActions) - : ImmutableSegmentedDictionary>.Empty; + var analyzerActionsByKind = AnalyzerExecutor.GetOperationActionsByKind(operationActions); RoslynImmutableInterlocked.InterlockedInitialize(ref _lazyOperationActionsByKind, analyzerActionsByKind); operationActions.Free(); } diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 466659b7ffb91..aea69ed9150c5 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -738,20 +738,21 @@ public void ExecuteCodeBlockActions( executeActions: static (diagReporter, isSupportedDiagnostic, args, cancellationToken) => { var (@this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode, ephemeralActions) = args; - - Debug.Assert(getKind != null); - - var executableNodeActionsByKind = GetNodeActionsByKind(ephemeralActions); - var syntaxNodesToAnalyze = executableCodeBlocks.SelectMany(cb => + if (ephemeralActions.Any()) { - var filter = semanticModel.GetSyntaxNodesToAnalyzeFilter(cb, declaredSymbol); + Debug.Assert(getKind != null); + var executableNodeActionsByKind = GetNodeActionsByKind(ephemeralActions); + var syntaxNodesToAnalyze = executableCodeBlocks.SelectMany(cb => + { + var filter = semanticModel.GetSyntaxNodesToAnalyzeFilter(cb, declaredSymbol); - return filter is not null - ? cb.DescendantNodesAndSelf(descendIntoChildren: filter).Where(filter) - : cb.DescendantNodesAndSelf(); - }); + return filter is not null + ? cb.DescendantNodesAndSelf(descendIntoChildren: filter).Where(filter) + : cb.DescendantNodesAndSelf(); + }); - @this.ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); + @this.ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); + } }, argument: (@this: this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode, ephemeralActions), cancellationToken); @@ -814,9 +815,12 @@ public void ExecuteOperationBlockActions( executeActions: static (diagReporter, isSupportedDiagnostic, args, cancellationToken) => { var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions) = args; - var operationActionsByKind = GetOperationActionsByKind(ephemeralActions); - var operationsToAnalyze = operations; - @this.ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); + if (ephemeralActions.Any()) + { + var operationActionsByKind = GetOperationActionsByKind(ephemeralActions); + var operationsToAnalyze = operations; + @this.ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); + } }, argument: (@this: this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions), cancellationToken); @@ -933,7 +937,8 @@ internal static ImmutableSegmentedDictionary> nodeActions) where TLanguageKindEnum : struct { - Debug.Assert(nodeActions != null && nodeActions.Any()); + if (nodeActions.IsEmpty) + return ImmutableSegmentedDictionary>>.Empty; var nodeActionsByKind = PooledDictionary>>.GetInstance(); foreach (var nodeAction in nodeActions) @@ -1033,7 +1038,8 @@ private void ExecuteSyntaxNodeActions( internal static ImmutableSegmentedDictionary> GetOperationActionsByKind( ArrayBuilder operationActions) { - Debug.Assert(operationActions.Any()); + if (operationActions.IsEmpty) + return ImmutableSegmentedDictionary>.Empty; var operationActionsByKind = PooledDictionary>.GetInstance(); foreach (var operationAction in operationActions) From 67bbe7a240c35dc62ec39cf7aa3659507b679185 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:48:58 -0800 Subject: [PATCH 28/49] No linq --- .../AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs index ac20ac6cb64fe..da9f21744240b 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs @@ -4,7 +4,6 @@ using System.Collections.Immutable; using System.Diagnostics; -using System.Linq; using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.PooledObjects; From 916168620cbd2e09d0be8606969cab70245bc0a5 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:49:30 -0800 Subject: [PATCH 29/49] No in --- .../AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs index da9f21744240b..c60c65d449108 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs @@ -37,7 +37,7 @@ public GroupedAnalyzerActionsForAnalyzer(DiagnosticAnalyzer analyzer, in Analyze public AnalyzerActions AnalyzerActions { get; } [Conditional("DEBUG")] - private static void VerifyActions(in ArrayBuilder actions, DiagnosticAnalyzer analyzer) + private static void VerifyActions(ArrayBuilder actions, DiagnosticAnalyzer analyzer) where TAnalyzerAction : AnalyzerAction { foreach (var action in actions) From e6ba1dd8b4301d03efeab823d88b4018bc1c2351 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:52:25 -0800 Subject: [PATCH 30/49] Use array builder --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index aea69ed9150c5..2bbb8f52f70f0 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -740,18 +740,28 @@ public void ExecuteCodeBlockActions( var (@this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode, ephemeralActions) = args; if (ephemeralActions.Any()) { - Debug.Assert(getKind != null); var executableNodeActionsByKind = GetNodeActionsByKind(ephemeralActions); - var syntaxNodesToAnalyze = executableCodeBlocks.SelectMany(cb => - { - var filter = semanticModel.GetSyntaxNodesToAnalyzeFilter(cb, declaredSymbol); + var syntaxNodesToAnalyze = ArrayBuilder.GetInstance(); - return filter is not null - ? cb.DescendantNodesAndSelf(descendIntoChildren: filter).Where(filter) - : cb.DescendantNodesAndSelf(); - }); + foreach (var block in executableCodeBlocks) + { + var filter = semanticModel.GetSyntaxNodesToAnalyzeFilter(block, declaredSymbol); + if (filter is not null) + { + foreach (var descendantNode in block.DescendantNodesAndSelf(descendIntoChildren: filter)) + { + if (filter(descendantNode)) + syntaxNodesToAnalyze.Add(descendantNode); + } + } + else + { + syntaxNodesToAnalyze.AddRange(block.DescendantNodesAndSelf()); + } + } @this.ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); + syntaxNodesToAnalyze.Free(); } }, argument: (@this: this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode, ephemeralActions), @@ -991,7 +1001,7 @@ public void ExecuteSyntaxNodeActions( } private void ExecuteSyntaxNodeActions( - IEnumerable nodesToAnalyze, + ArrayBuilder nodesToAnalyze, ImmutableSegmentedDictionary>> nodeActionsByKind, DiagnosticAnalyzer analyzer, ISymbol containingSymbol, From f1043221437e54b572cf6e74c28966236c74181d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 14:55:34 -0800 Subject: [PATCH 31/49] docs --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 2bbb8f52f70f0..10cf32bc97025 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -701,6 +701,8 @@ public void ExecuteCodeBlockActions( where TLanguageKindEnum : struct { Debug.Assert(!executableCodeBlocks.IsEmpty); + + // The actions we discover in 'addActions' and then execute in 'executeActions'. var ephemeralActions = ArrayBuilder>.GetInstance(); ExecuteBlockActionsCore( startActions, @@ -788,6 +790,7 @@ public void ExecuteOperationBlockActions( { Debug.Assert(!operationBlocks.IsEmpty); + // The actions we discover in 'addActions' and then execute in 'executeActions'. var ephemeralActions = ArrayBuilder.GetInstance(); ExecuteBlockActionsCore( startActions, From d32f3a72a23ee43b81f8f7979ae2a176dc369f92 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 16:25:57 -0800 Subject: [PATCH 32/49] Consistency --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 10cf32bc97025..71b6a15ed71f4 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -719,21 +719,21 @@ public void ExecuteCodeBlockActions( { var (@this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode, ephemeralActions) = args; - var codeBlockScope = new HostCodeBlockStartAnalysisScope(startAction.Analyzer); - var blockStartContext = new AnalyzerCodeBlockStartAnalysisContext( - codeBlockScope, declaredNode, declaredSymbol, semanticModel, @this.AnalyzerOptions, filterSpan, isGeneratedCode, cancellationToken); + var scope = new HostCodeBlockStartAnalysisScope(startAction.Analyzer); + var startContext = new AnalyzerCodeBlockStartAnalysisContext( + scope, declaredNode, declaredSymbol, semanticModel, @this.AnalyzerOptions, filterSpan, isGeneratedCode, cancellationToken); // Catch Exception from the start action. @this.ExecuteAndCatchIfThrows( startAction.Analyzer, static args => { - var (startAction, blockStartContext, codeBlockScope, endActions, syntaxNodeActions) = args; - startAction.Action(blockStartContext); - endActions.AddAll(codeBlockScope.CodeBlockEndActions); - syntaxNodeActions.AddRange(codeBlockScope.SyntaxNodeActions); + var (startAction, startContext, scope, endActions, syntaxNodeActions) = args; + startAction.Action(startContext); + endActions.AddAll(scope.CodeBlockEndActions); + syntaxNodeActions.AddRange(scope.SyntaxNodeActions); }, - argument: (startAction, blockStartContext, codeBlockScope, endActions, ephemeralActions), + argument: (startAction, startContext, scope, endActions, ephemeralActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol, declaredNode), cancellationToken); }, @@ -762,7 +762,12 @@ public void ExecuteCodeBlockActions( } } - @this.ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); + @this.ExecuteSyntaxNodeActions( + syntaxNodesToAnalyze, executableNodeActionsByKind, + analyzer, declaredSymbol, semanticModel, getKind, diagReporter, + isSupportedDiagnostic, filterSpan, isGeneratedCode, + hasCodeBlockStartOrSymbolStartActions: startActions.Any(), + cancellationToken); syntaxNodesToAnalyze.Free(); } }, @@ -806,9 +811,9 @@ public void ExecuteOperationBlockActions( addActions: static (startAction, endActions, args, cancellationToken) => { var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions) = args; - var operationBlockScope = new HostOperationBlockStartAnalysisScope(startAction.Analyzer); - var operationStartContext = new AnalyzerOperationBlockStartAnalysisContext( - operationBlockScope, operationBlocks, declaredSymbol, semanticModel.Compilation, @this.AnalyzerOptions, + var scope = new HostOperationBlockStartAnalysisScope(startAction.Analyzer); + var startContext = new AnalyzerOperationBlockStartAnalysisContext( + scope, operationBlocks, declaredSymbol, semanticModel.Compilation, @this.AnalyzerOptions, @this.GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); // Catch Exception from the start action. @@ -816,12 +821,12 @@ public void ExecuteOperationBlockActions( startAction.Analyzer, static args => { - var (startAction, operationStartContext, operationBlockScope, endActions, ephemeralActions) = args; - startAction.Action(operationStartContext); - endActions.AddAll(operationBlockScope.OperationBlockEndActions); - ephemeralActions.AddRange(operationBlockScope.OperationActions); + var (startAction, startContext, scope, endActions, ephemeralActions) = args; + startAction.Action(startContext); + endActions.AddAll(scope.OperationBlockEndActions); + ephemeralActions.AddRange(scope.OperationActions); }, - argument: (startAction, operationStartContext, operationBlockScope, endActions, ephemeralActions), + argument: (startAction, startContext, scope, endActions, ephemeralActions), new AnalysisContextInfo(@this.Compilation, declaredSymbol), cancellationToken); }, @@ -830,9 +835,12 @@ public void ExecuteOperationBlockActions( var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions) = args; if (ephemeralActions.Any()) { - var operationActionsByKind = GetOperationActionsByKind(ephemeralActions); - var operationsToAnalyze = operations; - @this.ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); + @this.ExecuteOperationActions( + operations, GetOperationActionsByKind(ephemeralActions), + analyzer, declaredSymbol, semanticModel, diagReporter, + isSupportedDiagnostic, filterSpan, isGeneratedCode, + hasOperationBlockStartOrSymbolStartActions: startActions.Any(), + cancellationToken); } }, argument: (@this: this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions), From bf0770d803263946163731287ad0ffb46414accf Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 16:30:31 -0800 Subject: [PATCH 33/49] simplify --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 24 ++++--------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 71b6a15ed71f4..896a15a6cae37 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -965,18 +965,10 @@ internal static ImmutableSegmentedDictionary>.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); + var map = nodeActionsByKind.ToImmutableSegmentedDictionaryAndFree(); nodeActionsByKind.Free(); return map; } @@ -1066,18 +1058,10 @@ internal static ImmutableSegmentedDictionary.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); + var map = operationActionsByKind.ToImmutableSegmentedDictionaryAndFree(); operationActionsByKind.Free(); return map; } From ba4c5b7dc6cab267e50dea179deef30667d7e5d0 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 16:30:55 -0800 Subject: [PATCH 34/49] Avoid allocs --- .../Portable/Collections/DictionaryExtensions.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs b/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs index cb74f75739217..5e3d92ed3503c 100644 --- a/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs @@ -99,5 +99,17 @@ public static ImmutableSegmentedDictionary> ToImmutableSegm return result.ToImmutable(); } + + public static ImmutableSegmentedDictionary> ToImmutableSegmentedDictionaryAndFree(this Dictionary> builder) + where K : notnull + { + var result = ImmutableSegmentedDictionary.CreateBuilder>(); + foreach (var (key, values) in builder) + { + result.Add(key, values.ToImmutableAndFree()); + } + + return result.ToImmutable(); + } } } From fcb8fe25260b98ab651f5ed3d10c380dd12276cf Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 16:31:28 -0800 Subject: [PATCH 35/49] Remove old code --- .../Portable/Collections/DictionaryExtensions.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs b/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs index 5e3d92ed3503c..82c37aeae890e 100644 --- a/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs @@ -88,18 +88,6 @@ public static void AddPooled(this IDictionary> dictiona values.Add(value); } - public static ImmutableSegmentedDictionary> ToImmutableSegmentedDictionaryAndFree(this IReadOnlyDictionary> builder) - where K : notnull - { - var result = ImmutableSegmentedDictionary.CreateBuilder>(); - foreach (var (key, values) in builder) - { - result.Add(key, values.ToImmutableAndFree()); - } - - return result.ToImmutable(); - } - public static ImmutableSegmentedDictionary> ToImmutableSegmentedDictionaryAndFree(this Dictionary> builder) where K : notnull { From b382cb0c9e3389ac38430f93b9d7d842d46bc313 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 16:32:10 -0800 Subject: [PATCH 36/49] Avoid interface dispatch --- src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs b/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs index 82c37aeae890e..ff221f3610bc3 100644 --- a/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs @@ -76,7 +76,7 @@ public static bool TryAdd( } #endif - public static void AddPooled(this IDictionary> dictionary, K key, V value) + public static void AddPooled(this Dictionary> dictionary, K key, V value) where K : notnull { if (!dictionary.TryGetValue(key, out var values)) From 1a5b8f07ca60c8c79a431ddfd48f4369b6031e67 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 16:36:42 -0800 Subject: [PATCH 37/49] Simplify freeing code --- .../EditAndContinue/PEDeltaAssemblyBuilder.cs | 2 +- .../Collections/DictionaryExtensions.cs | 21 ++++++++++++------- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 8 ++----- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs index 636dd4a119a61..c565c056a507c 100644 --- a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs @@ -112,7 +112,7 @@ internal static EmitBaseline.MetadataSymbols GetOrCreateMetadataSymbols(EmitBase internal static SynthesizedTypeMaps GetSynthesizedTypesFromMetadata(MetadataReader reader, MetadataDecoder metadataDecoder) { var anonymousTypes = ImmutableSegmentedDictionary.CreateBuilder(); - var anonymousDelegatesWithIndexedNames = new Dictionary>(); + var anonymousDelegatesWithIndexedNames = PooledDictionary>.GetInstance(); var anonymousDelegates = ImmutableSegmentedDictionary.CreateBuilder(); foreach (var handle in reader.TypeDefinitions) diff --git a/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs b/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs index ff221f3610bc3..e452142d70ae6 100644 --- a/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs @@ -88,16 +88,23 @@ public static void AddPooled(this Dictionary> dictionar values.Add(value); } - public static ImmutableSegmentedDictionary> ToImmutableSegmentedDictionaryAndFree(this Dictionary> builder) + /// + /// Converts the passed in dictionary to an , where all + /// the values in the passed builder will be converted to an using . The will be freed at the end of + /// this method as well, and should not be used afterwards. + /// + public static ImmutableSegmentedDictionary> ToImmutableSegmentedDictionaryAndFree( + this PooledDictionary> dictionary) where K : notnull { - var result = ImmutableSegmentedDictionary.CreateBuilder>(); - foreach (var (key, values) in builder) - { - result.Add(key, values.ToImmutableAndFree()); - } + var builder = ImmutableSegmentedDictionary.CreateBuilder>(); + foreach (var (key, values) in dictionary) + builder.Add(key, values.ToImmutableAndFree()); - return result.ToImmutable(); + var map = builder.ToImmutable(); + dictionary.Free(); + return map; } } } diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 896a15a6cae37..3abbe632ab853 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -968,9 +968,7 @@ internal static ImmutableSegmentedDictionary @@ -1061,9 +1059,7 @@ internal static ImmutableSegmentedDictionary From 8ae5e9e4ce7e99b967f9211c8e2d2ab5694b01e2 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 16:39:31 -0800 Subject: [PATCH 38/49] Simplify --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 3abbe632ab853..1c1b913de6674 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -711,7 +711,7 @@ public void ExecuteCodeBlockActions( analyzer, declaredNode, declaredSymbol, - operationBlocks: ImmutableArray.Empty, + operationBlocks: [], semanticModel, filterSpan, isGeneratedCode, From 53de2cd12faefad016aef2105851fd11d7589f59 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 16:52:09 -0800 Subject: [PATCH 39/49] Simplify capture --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 1c1b913de6674..fb94243488467 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -726,16 +726,13 @@ public void ExecuteCodeBlockActions( // Catch Exception from the start action. @this.ExecuteAndCatchIfThrows( startAction.Analyzer, - static args => - { - var (startAction, startContext, scope, endActions, syntaxNodeActions) = args; - startAction.Action(startContext); - endActions.AddAll(scope.CodeBlockEndActions); - syntaxNodeActions.AddRange(scope.SyntaxNodeActions); - }, - argument: (startAction, startContext, scope, endActions, ephemeralActions), + static args => args.startAction.Action(args.startContext), + argument: (startAction, startContext), new AnalysisContextInfo(@this.Compilation, declaredSymbol, declaredNode), cancellationToken); + + endActions.AddAll(scope.CodeBlockEndActions); + ephemeralActions.AddRange(scope.SyntaxNodeActions); }, executeActions: static (diagReporter, isSupportedDiagnostic, args, cancellationToken) => { @@ -819,16 +816,13 @@ public void ExecuteOperationBlockActions( // Catch Exception from the start action. @this.ExecuteAndCatchIfThrows( startAction.Analyzer, - static args => - { - var (startAction, startContext, scope, endActions, ephemeralActions) = args; - startAction.Action(startContext); - endActions.AddAll(scope.OperationBlockEndActions); - ephemeralActions.AddRange(scope.OperationActions); - }, - argument: (startAction, startContext, scope, endActions, ephemeralActions), + static args => args.startAction.Action(args.startContext), + argument: (startAction, startContext), new AnalysisContextInfo(@this.Compilation, declaredSymbol), cancellationToken); + + endActions.AddAll(scope.OperationBlockEndActions); + ephemeralActions.AddRange(scope.OperationActions); }, executeActions: static (diagReporter, isSupportedDiagnostic, args, cancellationToken) => { From 6fbb77c7a1bf3d0bc5c453bc2967670260779eef Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 16:56:02 -0800 Subject: [PATCH 40/49] Add arg type --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index fb94243488467..7d2c30e1d19a4 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -682,6 +682,14 @@ private void ExecuteOperationAction( cancellationToken); } + private readonly record struct ExecutionData( + DiagnosticAnalyzer Analyzer, + SyntaxNode DeclaredNode, + ISymbol DeclaredSymbol, + SemanticModel SemanticModel, + TextSpan? filterSpan, + bool isGeneratedCode); + /// /// Execute code block actions for the given analyzer for the given declaration. /// From 5c79b6e1d3f9d5588b22220b20c3308c4ce5744e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 24 Jan 2025 17:18:42 -0800 Subject: [PATCH 41/49] Reduce the amount of data we need to pass along --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 263 +++++++++--------- 1 file changed, 137 insertions(+), 126 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 7d2c30e1d19a4..50e276b9b5c7d 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -204,7 +204,7 @@ public void ExecuteInitializeMethod(HostSessionStartAnalysisScope sessionScope, // The Initialize method should be run asynchronously in case it is not well behaved, e.g. does not terminate. ExecuteAndCatchIfThrows( sessionScope.Analyzer, - data => data.analyzer.Initialize(data.context), + static data => data.analyzer.Initialize(data.context), (analyzer: sessionScope.Analyzer, context), contextInfo: null, cancellationToken); @@ -227,7 +227,7 @@ public void ExecuteCompilationStartActions(ImmutableArray data.action(data.context), + static data => data.action(data.context), (action: startAction.Action, context), new AnalysisContextInfo(Compilation), cancellationToken); @@ -267,7 +267,7 @@ public void ExecuteSymbolStartActions( ExecuteAndCatchIfThrows( startAction.Analyzer, - data => data.action(data.context), + static data => data.action(data.context), (action: startAction.Action, context), new AnalysisContextInfo(Compilation, symbol), cancellationToken); @@ -299,7 +299,7 @@ public void ExecuteSuppressionAction(DiagnosticSuppressor suppressor, ImmutableA ExecuteAndCatchIfThrows( suppressor, - data => data.action(data.context), + static data => data.action(data.context), (action, context), new AnalysisContextInfo(Compilation), cancellationToken); @@ -322,7 +322,10 @@ public void ExecuteCompilationActions( var addDiagnostic = GetAddCompilationDiagnostic(analyzer, cancellationToken); - using var _ = PooledDelegates.GetPooledFunction((d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), (self: this, analyzer), out Func isSupportedDiagnostic); + using var _ = PooledDelegates.GetPooledFunction( + static (d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), + (self: this, analyzer), + out Func isSupportedDiagnostic); foreach (var endAction in compilationActions) { @@ -334,7 +337,7 @@ public void ExecuteCompilationActions( ExecuteAndCatchIfThrows( endAction.Analyzer, - data => data.action(data.context), + static data => data.action(data.context), (action: endAction.Action, context), new AnalysisContextInfo(Compilation), cancellationToken); @@ -372,7 +375,10 @@ public void ExecuteSymbolActions( var symbol = symbolDeclaredEvent.Symbol; var addDiagnostic = GetAddDiagnostic(symbol, symbolDeclaredEvent.DeclaringSyntaxReferences, analyzer, getTopMostNodeForAnalysis, cancellationToken); - using var _ = PooledDelegates.GetPooledFunction((d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), (self: this, analyzer), out Func isSupportedDiagnostic); + using var _ = PooledDelegates.GetPooledFunction( + static (d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), + (self: this, analyzer), + out Func isSupportedDiagnostic); foreach (var symbolAction in symbolActions) { @@ -388,7 +394,7 @@ public void ExecuteSymbolActions( ExecuteAndCatchIfThrows( symbolAction.Analyzer, - data => data.action(data.context), + static data => data.action(data.context), (action, context), new AnalysisContextInfo(Compilation, symbol), cancellationToken); @@ -477,7 +483,10 @@ private void ExecuteSymbolEndActionsCore( var symbol = symbolDeclaredEvent.Symbol; var addDiagnostic = GetAddDiagnostic(symbol, symbolDeclaredEvent.DeclaringSyntaxReferences, analyzer, getTopMostNodeForAnalysis, cancellationToken); - using var _ = PooledDelegates.GetPooledFunction((d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), (self: this, analyzer), out Func isSupportedDiagnostic); + using var _ = PooledDelegates.GetPooledFunction( + static (d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), + (self: this, analyzer), + out Func isSupportedDiagnostic); foreach (var symbolAction in symbolEndActions) { @@ -490,7 +499,7 @@ private void ExecuteSymbolEndActionsCore( ExecuteAndCatchIfThrows( symbolAction.Analyzer, - data => data.action(data.context), + static data => data.action(data.context), (action, context), new AnalysisContextInfo(Compilation, symbol), cancellationToken); @@ -524,7 +533,10 @@ public void ExecuteSemanticModelActions( var diagReporter = GetAddSemanticDiagnostic(semanticModel.SyntaxTree, analyzer, cancellationToken); - using var _ = PooledDelegates.GetPooledFunction((d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), (self: this, analyzer), out Func isSupportedDiagnostic); + using var _ = PooledDelegates.GetPooledFunction( + static (d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), + (self: this, analyzer), + out Func isSupportedDiagnostic); foreach (var semanticModelAction in semanticModelActions) { @@ -536,7 +548,7 @@ public void ExecuteSemanticModelActions( // Catch Exception from action. ExecuteAndCatchIfThrows( semanticModelAction.Analyzer, - data => data.action(data.context), + static data => data.action(data.context), (action: semanticModelAction.Action, context), new AnalysisContextInfo(semanticModel), cancellationToken); @@ -573,7 +585,10 @@ public void ExecuteSyntaxTreeActions( var diagReporter = GetAddSyntaxDiagnostic(file, analyzer, cancellationToken); - using var _ = PooledDelegates.GetPooledFunction((d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), (self: this, analyzer), out Func isSupportedDiagnostic); + using var _ = PooledDelegates.GetPooledFunction( + static (d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), + (self: this, analyzer), + out Func isSupportedDiagnostic); foreach (var syntaxTreeAction in syntaxTreeActions) { @@ -584,7 +599,7 @@ public void ExecuteSyntaxTreeActions( // Catch Exception from action. ExecuteAndCatchIfThrows( syntaxTreeAction.Analyzer, - data => data.action(data.context), + static data => data.action(data.context), (action: syntaxTreeAction.Action, context), new AnalysisContextInfo(Compilation, file), cancellationToken); @@ -613,7 +628,11 @@ public void ExecuteAdditionalFileActions( var diagReporter = GetAddSyntaxDiagnostic(file, analyzer, cancellationToken); - using var _ = PooledDelegates.GetPooledFunction((d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), (self: this, analyzer), out Func isSupportedDiagnostic); + using var _ = PooledDelegates.GetPooledFunction( + static (d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), + (self: this, analyzer), + out Func isSupportedDiagnostic); + foreach (var additionalFileAction in additionalFileActions) { cancellationToken.ThrowIfCancellationRequested(); @@ -623,7 +642,7 @@ public void ExecuteAdditionalFileActions( // Catch Exception from action. ExecuteAndCatchIfThrows( additionalFileAction.Analyzer, - data => data.action(data.context), + static data => data.action(data.context), (action: additionalFileAction.Action, context), new AnalysisContextInfo(Compilation, file), cancellationToken); @@ -635,24 +654,22 @@ public void ExecuteAdditionalFileActions( private void ExecuteSyntaxNodeAction( SyntaxNodeAnalyzerAction syntaxNodeAction, SyntaxNode node, - ISymbol containingSymbol, - SemanticModel semanticModel, + ExecutionData executionData, Action addDiagnostic, Func isSupportedDiagnostic, - TextSpan? filterSpan, - bool isGeneratedCode, CancellationToken cancellationToken) where TLanguageKindEnum : struct { - Debug.Assert(!isGeneratedCode || !_shouldSkipAnalysisOnGeneratedCode(syntaxNodeAction.Analyzer)); + Debug.Assert(!executionData.IsGeneratedCode || !_shouldSkipAnalysisOnGeneratedCode(syntaxNodeAction.Analyzer)); Debug.Assert(!IsAnalyzerSuppressedForTree(syntaxNodeAction.Analyzer, node.SyntaxTree, cancellationToken)); - var syntaxNodeContext = new SyntaxNodeAnalysisContext(node, containingSymbol, semanticModel, AnalyzerOptions, addDiagnostic, - isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); + var syntaxNodeContext = new SyntaxNodeAnalysisContext( + node, executionData.DeclaredSymbol, executionData.SemanticModel, AnalyzerOptions, addDiagnostic, + isSupportedDiagnostic, executionData.FilterSpan, executionData.IsGeneratedCode, cancellationToken); ExecuteAndCatchIfThrows( syntaxNodeAction.Analyzer, - data => data.action(data.context), + static data => data.action(data.context), (action: syntaxNodeAction.Action, context: syntaxNodeContext), new AnalysisContextInfo(Compilation, node), cancellationToken); @@ -661,22 +678,22 @@ private void ExecuteSyntaxNodeAction( private void ExecuteOperationAction( OperationAnalyzerAction operationAction, IOperation operation, - ISymbol containingSymbol, - SemanticModel semanticModel, + ExecutionData executionData, Action addDiagnostic, Func isSupportedDiagnostic, - TextSpan? filterSpan, - bool isGeneratedCode, CancellationToken cancellationToken) { - Debug.Assert(!isGeneratedCode || !_shouldSkipAnalysisOnGeneratedCode(operationAction.Analyzer)); - Debug.Assert(!IsAnalyzerSuppressedForTree(operationAction.Analyzer, semanticModel.SyntaxTree, cancellationToken)); + Debug.Assert(!executionData.IsGeneratedCode || !_shouldSkipAnalysisOnGeneratedCode(operationAction.Analyzer)); + Debug.Assert(!IsAnalyzerSuppressedForTree(operationAction.Analyzer, executionData.SemanticModel.SyntaxTree, cancellationToken)); + + var operationContext = new OperationAnalysisContext( + operation, executionData.DeclaredSymbol, executionData.SemanticModel.Compilation, + AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, GetControlFlowGraph, + executionData.FilterSpan, executionData.IsGeneratedCode, cancellationToken); - var operationContext = new OperationAnalysisContext(operation, containingSymbol, semanticModel.Compilation, - AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, GetControlFlowGraph, filterSpan, isGeneratedCode, cancellationToken); ExecuteAndCatchIfThrows( operationAction.Analyzer, - data => data.action(data.context), + static data => data.action(data.context), (action: operationAction.Action, context: operationContext), new AnalysisContextInfo(Compilation, operation), cancellationToken); @@ -684,11 +701,11 @@ private void ExecuteOperationAction( private readonly record struct ExecutionData( DiagnosticAnalyzer Analyzer, - SyntaxNode DeclaredNode, + // SyntaxNode DeclaredNode, ISymbol DeclaredSymbol, SemanticModel SemanticModel, - TextSpan? filterSpan, - bool isGeneratedCode); + TextSpan? FilterSpan, + bool IsGeneratedCode); /// /// Execute code block actions for the given analyzer for the given declaration. @@ -716,35 +733,32 @@ public void ExecuteCodeBlockActions( startActions, actions, endActions, - analyzer, - declaredNode, - declaredSymbol, operationBlocks: [], - semanticModel, - filterSpan, - isGeneratedCode, - addActions: static (startAction, endActions, args, cancellationToken) => + declaredNode, + new ExecutionData(analyzer, declaredSymbol, semanticModel, filterSpan, isGeneratedCode), + addActions: static (startAction, endActions, executionData, args, cancellationToken) => { - var (@this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode, ephemeralActions) = args; + var (@this, startActions, executableCodeBlocks, declaredNode, getKind, ephemeralActions) = args; var scope = new HostCodeBlockStartAnalysisScope(startAction.Analyzer); var startContext = new AnalyzerCodeBlockStartAnalysisContext( - scope, declaredNode, declaredSymbol, semanticModel, @this.AnalyzerOptions, filterSpan, isGeneratedCode, cancellationToken); + scope, declaredNode, executionData.DeclaredSymbol, executionData.SemanticModel, + @this.AnalyzerOptions, executionData.FilterSpan, executionData.IsGeneratedCode, cancellationToken); // Catch Exception from the start action. @this.ExecuteAndCatchIfThrows( startAction.Analyzer, static args => args.startAction.Action(args.startContext), argument: (startAction, startContext), - new AnalysisContextInfo(@this.Compilation, declaredSymbol, declaredNode), + new AnalysisContextInfo(@this.Compilation, executionData.DeclaredSymbol, declaredNode), cancellationToken); endActions.AddAll(scope.CodeBlockEndActions); ephemeralActions.AddRange(scope.SyntaxNodeActions); }, - executeActions: static (diagReporter, isSupportedDiagnostic, args, cancellationToken) => + executeActions: static (diagReporter, isSupportedDiagnostic, executionData, args, cancellationToken) => { - var (@this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode, ephemeralActions) = args; + var (@this, startActions, executableCodeBlocks, declaredNode, getKind, ephemeralActions) = args; if (ephemeralActions.Any()) { var executableNodeActionsByKind = GetNodeActionsByKind(ephemeralActions); @@ -752,7 +766,7 @@ public void ExecuteCodeBlockActions( foreach (var block in executableCodeBlocks) { - var filter = semanticModel.GetSyntaxNodesToAnalyzeFilter(block, declaredSymbol); + var filter = executionData.SemanticModel.GetSyntaxNodesToAnalyzeFilter(block, executionData.DeclaredSymbol); if (filter is not null) { foreach (var descendantNode in block.DescendantNodesAndSelf(descendIntoChildren: filter)) @@ -768,15 +782,14 @@ public void ExecuteCodeBlockActions( } @this.ExecuteSyntaxNodeActions( - syntaxNodesToAnalyze, executableNodeActionsByKind, - analyzer, declaredSymbol, semanticModel, getKind, diagReporter, - isSupportedDiagnostic, filterSpan, isGeneratedCode, + syntaxNodesToAnalyze, executableNodeActionsByKind, executionData, + getKind, diagReporter, isSupportedDiagnostic, hasCodeBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); syntaxNodesToAnalyze.Free(); } }, - argument: (@this: this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode, ephemeralActions), + argument: (@this: this, startActions, executableCodeBlocks, declaredNode, getKind, ephemeralActions), cancellationToken); ephemeralActions.Free(); } @@ -806,46 +819,41 @@ public void ExecuteOperationBlockActions( startActions, actions, endActions, - analyzer, - declaredNode, - declaredSymbol, operationBlocks, - semanticModel, - filterSpan, - isGeneratedCode, - addActions: static (startAction, endActions, args, cancellationToken) => + declaredNode, + new ExecutionData(analyzer, declaredSymbol, semanticModel, filterSpan, isGeneratedCode), + addActions: static (startAction, endActions, executionData, args, cancellationToken) => { - var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions) = args; + var (@this, startActions, declaredNode, operationBlocks, operations, ephemeralActions) = args; var scope = new HostOperationBlockStartAnalysisScope(startAction.Analyzer); var startContext = new AnalyzerOperationBlockStartAnalysisContext( - scope, operationBlocks, declaredSymbol, semanticModel.Compilation, @this.AnalyzerOptions, - @this.GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); + scope, operationBlocks, executionData.DeclaredSymbol, executionData.SemanticModel.Compilation, @this.AnalyzerOptions, + @this.GetControlFlowGraph, declaredNode.SyntaxTree, executionData.FilterSpan, executionData.IsGeneratedCode, cancellationToken); // Catch Exception from the start action. @this.ExecuteAndCatchIfThrows( startAction.Analyzer, static args => args.startAction.Action(args.startContext), argument: (startAction, startContext), - new AnalysisContextInfo(@this.Compilation, declaredSymbol), + new AnalysisContextInfo(@this.Compilation, executionData.DeclaredSymbol), cancellationToken); endActions.AddAll(scope.OperationBlockEndActions); ephemeralActions.AddRange(scope.OperationActions); }, - executeActions: static (diagReporter, isSupportedDiagnostic, args, cancellationToken) => + executeActions: static (diagReporter, isSupportedDiagnostic, executionData, args, cancellationToken) => { - var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions) = args; + var (@this, startActions, declaredNode, operationBlocks, operations, ephemeralActions) = args; if (ephemeralActions.Any()) { @this.ExecuteOperationActions( operations, GetOperationActionsByKind(ephemeralActions), - analyzer, declaredSymbol, semanticModel, diagReporter, - isSupportedDiagnostic, filterSpan, isGeneratedCode, + executionData, diagReporter, isSupportedDiagnostic, hasOperationBlockStartOrSymbolStartActions: startActions.Any(), cancellationToken); } }, - argument: (@this: this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions), + argument: (@this: this, startActions, declaredNode, operationBlocks, operations, ephemeralActions), cancellationToken); ephemeralActions.Free(); } @@ -854,15 +862,11 @@ private void ExecuteBlockActionsCore( ImmutableArray startActions, ImmutableArray actions, ImmutableArray endActions, - DiagnosticAnalyzer analyzer, - SyntaxNode declaredNode, - ISymbol declaredSymbol, ImmutableArray operationBlocks, - SemanticModel semanticModel, - TextSpan? filterSpan, - bool isGeneratedCode, - Action, TArgs, CancellationToken> addActions, - Action, TArgs, CancellationToken> executeActions, + SyntaxNode declaredNode, + ExecutionData executionData, + Action, ExecutionData, TArgs, CancellationToken> addActions, + Action, ExecutionData, TArgs, CancellationToken> executeActions, TArgs argument, CancellationToken cancellationToken) where TBlockStartAction : AnalyzerAction @@ -870,12 +874,12 @@ private void ExecuteBlockActionsCore( where TArgs : struct { Debug.Assert(declaredNode != null); - Debug.Assert(declaredSymbol != null); - Debug.Assert(CanHaveExecutableCodeBlock(declaredSymbol)); + Debug.Assert(executionData.DeclaredSymbol != null); + Debug.Assert(CanHaveExecutableCodeBlock(executionData.DeclaredSymbol)); Debug.Assert(startActions.Any() || endActions.Any() || actions.Any()); - if (isGeneratedCode && _shouldSkipAnalysisOnGeneratedCode(analyzer) || - IsAnalyzerSuppressedForTree(analyzer, declaredNode.SyntaxTree, cancellationToken)) + if (executionData.IsGeneratedCode && _shouldSkipAnalysisOnGeneratedCode(executionData.Analyzer) || + IsAnalyzerSuppressedForTree(executionData.Analyzer, declaredNode.SyntaxTree, cancellationToken)) { return; } @@ -891,19 +895,23 @@ private void ExecuteBlockActionsCore( // Include the initial code block end actions. blockEndActions.AddAll(endActions); - var diagReporter = GetAddSemanticDiagnostic(semanticModel.SyntaxTree, declaredNode.FullSpan, analyzer, cancellationToken); + var diagReporter = GetAddSemanticDiagnostic( + executionData.SemanticModel.SyntaxTree, declaredNode.FullSpan, executionData.Analyzer, cancellationToken); // Include the stateful actions. foreach (var startAction in startActions) - addActions(startAction, blockEndActions, argument, cancellationToken); + addActions(startAction, blockEndActions, executionData, argument, cancellationToken); - using var _ = PooledDelegates.GetPooledFunction((d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), (self: this, analyzer), out Func isSupportedDiagnostic); + using var _ = PooledDelegates.GetPooledFunction( + static (d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.Analyzer, d, ct), + (self: this, executionData.Analyzer), + out Func isSupportedDiagnostic); // Execute stateful executable node analyzers, if any. - executeActions(diagReporter, isSupportedDiagnostic, argument, cancellationToken); + executeActions(diagReporter, isSupportedDiagnostic, executionData, argument, cancellationToken); - ExecuteBlockActions(blockActions, declaredNode, declaredSymbol, analyzer, semanticModel, operationBlocks, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); - ExecuteBlockActions(blockEndActions, declaredNode, declaredSymbol, analyzer, semanticModel, operationBlocks, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); + ExecuteBlockActions(blockActions, declaredNode, executionData, operationBlocks, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, cancellationToken); + ExecuteBlockActions(blockEndActions, declaredNode, executionData, operationBlocks, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, cancellationToken); diagReporter.Free(); blockActions.Free(); @@ -913,44 +921,41 @@ private void ExecuteBlockActionsCore( private void ExecuteBlockActions( HashSet blockActions, SyntaxNode declaredNode, - ISymbol declaredSymbol, - DiagnosticAnalyzer analyzer, - SemanticModel semanticModel, + ExecutionData executionData, ImmutableArray operationBlocks, Action addDiagnostic, Func isSupportedDiagnostic, - TextSpan? filterSpan, - bool isGeneratedCode, CancellationToken cancellationToken) where TBlockAction : AnalyzerAction { - Debug.Assert(!isGeneratedCode || !_shouldSkipAnalysisOnGeneratedCode(analyzer)); - Debug.Assert(!IsAnalyzerSuppressedForTree(analyzer, declaredNode.SyntaxTree, cancellationToken)); + Debug.Assert(!executionData.IsGeneratedCode || !_shouldSkipAnalysisOnGeneratedCode(executionData.Analyzer)); + Debug.Assert(!IsAnalyzerSuppressedForTree(executionData.Analyzer, declaredNode.SyntaxTree, cancellationToken)); foreach (var blockAction in blockActions) { if (blockAction is CodeBlockAnalyzerAction codeBlockAction) { - var context = new CodeBlockAnalysisContext(declaredNode, declaredSymbol, semanticModel, - AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); + var context = new CodeBlockAnalysisContext(declaredNode, executionData.DeclaredSymbol, executionData.SemanticModel, + AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, executionData.FilterSpan, executionData.IsGeneratedCode, cancellationToken); ExecuteAndCatchIfThrows( codeBlockAction.Analyzer, - static data => data.action(data.context), - argument: (action: codeBlockAction.Action, context), - new AnalysisContextInfo(Compilation, declaredSymbol, declaredNode), + static data => data.codeBlockAction.Action(data.context), + argument: (codeBlockAction, context), + new AnalysisContextInfo(Compilation, executionData.DeclaredSymbol, declaredNode), cancellationToken); } else if (blockAction is OperationBlockAnalyzerAction operationBlockAction) { - var context = new OperationBlockAnalysisContext(operationBlocks, declaredSymbol, semanticModel.Compilation, - AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); + var context = new OperationBlockAnalysisContext(operationBlocks, executionData.DeclaredSymbol, executionData.SemanticModel.Compilation, + AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, GetControlFlowGraph, declaredNode.SyntaxTree, + executionData.FilterSpan, executionData.IsGeneratedCode, cancellationToken); ExecuteAndCatchIfThrows( operationBlockAction.Analyzer, - static data => data.action(data.context), - argument: (action: operationBlockAction.Action, context), - new AnalysisContextInfo(Compilation, declaredSymbol), + static data => data.operationBlockAction.Action(data.context), + argument: (operationBlockAction, context), + new AnalysisContextInfo(Compilation, executionData.DeclaredSymbol), cancellationToken); } } @@ -998,29 +1003,32 @@ public void ExecuteSyntaxNodeActions( var diagReporter = GetAddSemanticDiagnostic(model.SyntaxTree, spanForContainingTopmostNodeForAnalysis, analyzer, cancellationToken); - using var _ = PooledDelegates.GetPooledFunction((d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), (self: this, analyzer), out Func isSupportedDiagnostic); - ExecuteSyntaxNodeActions(nodesToAnalyze, nodeActionsByKind, analyzer, declaredSymbol, model, getKind, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasCodeBlockStartOrSymbolStartActions, cancellationToken); + using var _ = PooledDelegates.GetPooledFunction( + static (d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), + (self: this, analyzer), + out Func isSupportedDiagnostic); + + ExecuteSyntaxNodeActions( + nodesToAnalyze, nodeActionsByKind, + new ExecutionData(analyzer, declaredSymbol, model, filterSpan, isGeneratedCode), + getKind, diagReporter, isSupportedDiagnostic, hasCodeBlockStartOrSymbolStartActions, cancellationToken); diagReporter.Free(); } private void ExecuteSyntaxNodeActions( ArrayBuilder nodesToAnalyze, ImmutableSegmentedDictionary>> nodeActionsByKind, - DiagnosticAnalyzer analyzer, - ISymbol containingSymbol, - SemanticModel model, + ExecutionData executionData, Func getKind, AnalyzerDiagnosticReporter diagReporter, Func isSupportedDiagnostic, - TextSpan? filterSpan, - bool isGeneratedCode, bool hasCodeBlockStartOrSymbolStartActions, CancellationToken cancellationToken) where TLanguageKindEnum : struct { Debug.Assert(nodeActionsByKind.Any()); - Debug.Assert(!isGeneratedCode || !_shouldSkipAnalysisOnGeneratedCode(analyzer)); - Debug.Assert(!IsAnalyzerSuppressedForTree(analyzer, model.SyntaxTree, cancellationToken)); + Debug.Assert(!executionData.IsGeneratedCode || !_shouldSkipAnalysisOnGeneratedCode(executionData.Analyzer)); + Debug.Assert(!IsAnalyzerSuppressedForTree(executionData.Analyzer, executionData.SemanticModel.SyntaxTree, cancellationToken)); foreach (var node in nodesToAnalyze) { @@ -1030,7 +1038,7 @@ private void ExecuteSyntaxNodeActions( if (nodeActionsByKind.TryGetValue(getKind(node), out var actionsForKind)) { RoslynDebug.Assert(!actionsForKind.IsEmpty, $"Unexpected empty action collection in {nameof(nodeActionsByKind)}"); - if (ShouldExecuteNode(node, analyzer, cancellationToken)) + if (ShouldExecuteNode(node, executionData.Analyzer, cancellationToken)) { // If analyzer hasn't registered any CodeBlockStart or SymbolStart actions, then update the filter span // for local diagnostics to be the callback node's full span. @@ -1041,7 +1049,7 @@ private void ExecuteSyntaxNodeActions( foreach (var action in actionsForKind) { - ExecuteSyntaxNodeAction(action, node, containingSymbol, model, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); + ExecuteSyntaxNodeAction(action, node, executionData, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, cancellationToken); } } } @@ -1091,28 +1099,31 @@ public void ExecuteOperationActions( var diagReporter = GetAddSemanticDiagnostic(model.SyntaxTree, spanForContainingOperationBlock, analyzer, cancellationToken); - using var _ = PooledDelegates.GetPooledFunction((d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), (self: this, analyzer), out Func isSupportedDiagnostic); - ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, model, diagReporter, isSupportedDiagnostic, filterSpan, isGeneratedCode, hasOperationBlockStartOrSymbolStartActions, cancellationToken); + using var _ = PooledDelegates.GetPooledFunction( + static (d, ct, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d, ct), + (self: this, analyzer), + out Func isSupportedDiagnostic); + + ExecuteOperationActions( + operationsToAnalyze, operationActionsByKind, + new ExecutionData(analyzer, declaredSymbol, model, filterSpan, isGeneratedCode), + diagReporter, isSupportedDiagnostic, hasOperationBlockStartOrSymbolStartActions, cancellationToken); diagReporter.Free(); } private void ExecuteOperationActions( ImmutableArray operationsToAnalyze, ImmutableSegmentedDictionary> operationActionsByKind, - DiagnosticAnalyzer analyzer, - ISymbol containingSymbol, - SemanticModel model, + ExecutionData executionData, AnalyzerDiagnosticReporter diagReporter, Func isSupportedDiagnostic, - TextSpan? filterSpan, - bool isGeneratedCode, bool hasOperationBlockStartOrSymbolStartActions, CancellationToken cancellationToken) { Debug.Assert(operationActionsByKind != null); Debug.Assert(operationActionsByKind.Any()); - Debug.Assert(!isGeneratedCode || !_shouldSkipAnalysisOnGeneratedCode(analyzer)); - Debug.Assert(!IsAnalyzerSuppressedForTree(analyzer, model.SyntaxTree, cancellationToken)); + Debug.Assert(!executionData.IsGeneratedCode || !_shouldSkipAnalysisOnGeneratedCode(executionData.Analyzer)); + Debug.Assert(!IsAnalyzerSuppressedForTree(executionData.Analyzer, executionData.SemanticModel.SyntaxTree, cancellationToken)); foreach (var operation in operationsToAnalyze) { @@ -1122,7 +1133,7 @@ private void ExecuteOperationActions( if (operationActionsByKind.TryGetValue(operation.Kind, out var actionsForKind)) { RoslynDebug.Assert(!actionsForKind.IsEmpty, $"Unexpected empty action collection in {nameof(operationActionsByKind)}"); - if (ShouldExecuteOperation(operation, analyzer, cancellationToken)) + if (ShouldExecuteOperation(operation, executionData.Analyzer, cancellationToken)) { // If analyzer hasn't registered any OperationBlockStart or SymbolStart actions, then update // the filter span for local diagnostics to be the callback operation's full span. @@ -1133,7 +1144,7 @@ private void ExecuteOperationActions( foreach (var action in actionsForKind) { - ExecuteOperationAction(action, operation, containingSymbol, model, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); + ExecuteOperationAction(action, operation, executionData, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, cancellationToken); } } } From d87e8922d2f26cb780966e56658bd218df5e4783 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 25 Jan 2025 11:23:16 -0800 Subject: [PATCH 42/49] Checking something --- .../Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs | 2 +- .../Core/Portable/Collections/DictionaryExtensions.cs | 10 ++++------ .../AnalyzerDriver.GroupedAnalyzerActions.cs | 1 - .../Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 8 ++++++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs index c565c056a507c..636dd4a119a61 100644 --- a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs @@ -112,7 +112,7 @@ internal static EmitBaseline.MetadataSymbols GetOrCreateMetadataSymbols(EmitBase internal static SynthesizedTypeMaps GetSynthesizedTypesFromMetadata(MetadataReader reader, MetadataDecoder metadataDecoder) { var anonymousTypes = ImmutableSegmentedDictionary.CreateBuilder(); - var anonymousDelegatesWithIndexedNames = PooledDictionary>.GetInstance(); + var anonymousDelegatesWithIndexedNames = new Dictionary>(); var anonymousDelegates = ImmutableSegmentedDictionary.CreateBuilder(); foreach (var handle in reader.TypeDefinitions) diff --git a/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs b/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs index e452142d70ae6..ba8c55c1a7e29 100644 --- a/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs @@ -91,20 +91,18 @@ public static void AddPooled(this Dictionary> dictionar /// /// Converts the passed in dictionary to an , where all /// the values in the passed builder will be converted to an using . The will be freed at the end of - /// this method as well, and should not be used afterwards. + /// cref="ArrayBuilder{T}.ToImmutableAndFree"/>. The will not be freed at the end of + /// this method. /// public static ImmutableSegmentedDictionary> ToImmutableSegmentedDictionaryAndFree( - this PooledDictionary> dictionary) + this Dictionary> dictionary) where K : notnull { var builder = ImmutableSegmentedDictionary.CreateBuilder>(); foreach (var (key, values) in dictionary) builder.Add(key, values.ToImmutableAndFree()); - var map = builder.ToImmutable(); - dictionary.Free(); - return map; + return builder.ToImmutable(); } } } diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs index 807eda886d926..02ce903603a5b 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs @@ -103,7 +103,6 @@ private static ImmutableSegmentedDictionary @@ -1053,7 +1055,9 @@ internal static ImmutableSegmentedDictionary From bd21cc77708133571035dcf4150cc883875668af Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 25 Jan 2025 13:51:24 -0800 Subject: [PATCH 43/49] Restore original --- .../Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs | 2 +- .../Core/Portable/Collections/DictionaryExtensions.cs | 7 ++++--- .../AnalyzerDriver.GroupedAnalyzerActions.cs | 4 +--- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 8 ++------ 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs index 636dd4a119a61..c565c056a507c 100644 --- a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/PEDeltaAssemblyBuilder.cs @@ -112,7 +112,7 @@ internal static EmitBaseline.MetadataSymbols GetOrCreateMetadataSymbols(EmitBase internal static SynthesizedTypeMaps GetSynthesizedTypesFromMetadata(MetadataReader reader, MetadataDecoder metadataDecoder) { var anonymousTypes = ImmutableSegmentedDictionary.CreateBuilder(); - var anonymousDelegatesWithIndexedNames = new Dictionary>(); + var anonymousDelegatesWithIndexedNames = PooledDictionary>.GetInstance(); var anonymousDelegates = ImmutableSegmentedDictionary.CreateBuilder(); foreach (var handle in reader.TypeDefinitions) diff --git a/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs b/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs index ba8c55c1a7e29..4a9027162e5b4 100644 --- a/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/DictionaryExtensions.cs @@ -91,17 +91,18 @@ public static void AddPooled(this Dictionary> dictionar /// /// Converts the passed in dictionary to an , where all /// the values in the passed builder will be converted to an using . The will not be freed at the end of - /// this method. + /// cref="ArrayBuilder{T}.ToImmutableAndFree"/>. The will be freed at the end of + /// this method as well, and should not be used afterwards. /// public static ImmutableSegmentedDictionary> ToImmutableSegmentedDictionaryAndFree( - this Dictionary> dictionary) + this PooledDictionary> dictionary) where K : notnull { var builder = ImmutableSegmentedDictionary.CreateBuilder>(); foreach (var (key, values) in dictionary) builder.Add(key, values.ToImmutableAndFree()); + dictionary.Free(); return builder.ToImmutable(); } } diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs index 02ce903603a5b..521c4437f1a98 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActions.cs @@ -101,9 +101,7 @@ private static ImmutableSegmentedDictionary @@ -1055,9 +1053,7 @@ internal static ImmutableSegmentedDictionary From d134178e99d8f283cdeb56b42090c9a97553cbbb Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 31 Jan 2025 16:10:30 -0800 Subject: [PATCH 44/49] In progress --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 3ff31f6173891..fea70e47a73de 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -804,6 +804,24 @@ public void ExecuteCodeBlockActions( syntaxNodesToAnalyze.Free(); } }, + executeBlockActions: static (blockActions, diagReporter, isSupportedDiagnostic, args, cancellationToken) => + { + var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions) = args; + + foreach (var blockAction in blockActions) + { + // This context is a struct, so it's fine to create a new one for each action. + var context = new OperationBlockAnalysisContext(operationBlocks, declaredSymbol, semanticModel.Compilation, + @this.AnalyzerOptions, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, @this.GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); + + @this.ExecuteAndCatchIfThrows( + blockAction.Analyzer, + static data => data.blockAction.Action(data.context), + (blockAction, context), + new AnalysisContextInfo(@this.Compilation, declaredSymbol), + cancellationToken); + } + }, argument: (@this: this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode, ephemeralActions), cancellationToken); ephemeralActions.Free(); @@ -873,6 +891,24 @@ public void ExecuteOperationBlockActions( cancellationToken); } }, + executeBlockActions: static (blockActions, diagReporter, isSupportedDiagnostic, args, cancellationToken) => + { + var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions) = args; + + foreach (var blockAction in blockActions) + { + // This context is a struct, so it's fine to create a new one for each action. + var context = new OperationBlockAnalysisContext(operationBlocks, declaredSymbol, semanticModel.Compilation, + @this.AnalyzerOptions, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, @this.GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); + + @this.ExecuteAndCatchIfThrows( + blockAction.Analyzer, + static data => data.blockAction.Action(data.context), + (blockAction, context), + new AnalysisContextInfo(@this.Compilation, declaredSymbol), + cancellationToken); + } + }, argument: (@this: this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions), cancellationToken); ephemeralActions.Free(); @@ -891,6 +927,7 @@ private void ExecuteBlockActionsCore( bool isGeneratedCode, Action, TArgs, CancellationToken> addActions, Action, TArgs, CancellationToken> executeActions, + Action, AnalyzerDiagnosticReporter, Func, TArgs, CancellationToken> executeBlockActions, TArgs argument, CancellationToken cancellationToken) where TBlockStartAction : AnalyzerAction From dba6f04c99b3ad979ec3bc48c48d345f122f84eb Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 31 Jan 2025 16:14:45 -0800 Subject: [PATCH 45/49] Inline moree --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 76 +++---------------- 1 file changed, 10 insertions(+), 66 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index fea70e47a73de..bd81e6296edee 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -747,9 +747,7 @@ public void ExecuteCodeBlockActions( analyzer, declaredNode, declaredSymbol, - operationBlocks: [], semanticModel, - filterSpan, isGeneratedCode, addActions: static (startAction, endActions, args, cancellationToken) => { @@ -806,19 +804,18 @@ public void ExecuteCodeBlockActions( }, executeBlockActions: static (blockActions, diagReporter, isSupportedDiagnostic, args, cancellationToken) => { - var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions) = args; + var (@this, startActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, filterSpan, isGeneratedCode, ephemeralActions) = args; + + var context = new CodeBlockAnalysisContext(declaredNode, declaredSymbol, semanticModel, + @this.AnalyzerOptions, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); foreach (var blockAction in blockActions) { - // This context is a struct, so it's fine to create a new one for each action. - var context = new OperationBlockAnalysisContext(operationBlocks, declaredSymbol, semanticModel.Compilation, - @this.AnalyzerOptions, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, @this.GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); - @this.ExecuteAndCatchIfThrows( blockAction.Analyzer, static data => data.blockAction.Action(data.context), (blockAction, context), - new AnalysisContextInfo(@this.Compilation, declaredSymbol), + new AnalysisContextInfo(@this.Compilation, declaredSymbol, declaredNode), cancellationToken); } }, @@ -855,9 +852,7 @@ public void ExecuteOperationBlockActions( analyzer, declaredNode, declaredSymbol, - operationBlocks, semanticModel, - filterSpan, isGeneratedCode, addActions: static (startAction, endActions, args, cancellationToken) => { @@ -895,12 +890,11 @@ public void ExecuteOperationBlockActions( { var (@this, startActions, analyzer, declaredNode, operationBlocks, declaredSymbol, operations, semanticModel, filterSpan, isGeneratedCode, ephemeralActions) = args; + var context = new OperationBlockAnalysisContext(operationBlocks, declaredSymbol, semanticModel.Compilation, + @this.AnalyzerOptions, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, @this.GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); + foreach (var blockAction in blockActions) { - // This context is a struct, so it's fine to create a new one for each action. - var context = new OperationBlockAnalysisContext(operationBlocks, declaredSymbol, semanticModel.Compilation, - @this.AnalyzerOptions, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, @this.GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); - @this.ExecuteAndCatchIfThrows( blockAction.Analyzer, static data => data.blockAction.Action(data.context), @@ -921,9 +915,7 @@ private void ExecuteBlockActionsCore( DiagnosticAnalyzer analyzer, SyntaxNode declaredNode, ISymbol declaredSymbol, - ImmutableArray operationBlocks, SemanticModel semanticModel, - TextSpan? filterSpan, bool isGeneratedCode, Action, TArgs, CancellationToken> addActions, Action, TArgs, CancellationToken> executeActions, @@ -970,62 +962,14 @@ private void ExecuteBlockActionsCore( // Execute stateful executable node analyzers, if any. executeActions(diagReporter, isSupportedDiagnostic, argument, cancellationToken); - ExecuteBlockActions(blockActions, declaredNode, declaredSymbol, analyzer, semanticModel, operationBlocks, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); - ExecuteBlockActions(blockEndActions, declaredNode, declaredSymbol, analyzer, semanticModel, operationBlocks, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); + executeBlockActions(blockActions, diagReporter, isSupportedDiagnostic, argument, cancellationToken); + executeBlockActions(blockEndActions, diagReporter, isSupportedDiagnostic, argument, cancellationToken); diagReporter.Free(); blockActions.Free(); blockEndActions.Free(); } - private void ExecuteBlockActions( - HashSet blockActions, - SyntaxNode declaredNode, - ISymbol declaredSymbol, - DiagnosticAnalyzer analyzer, - SemanticModel semanticModel, - ImmutableArray operationBlocks, - Action addDiagnostic, - Func isSupportedDiagnostic, - TextSpan? filterSpan, - bool isGeneratedCode, - CancellationToken cancellationToken) - where TBlockAction : AnalyzerAction - { - Debug.Assert(!isGeneratedCode || !_shouldSkipAnalysisOnGeneratedCode(analyzer)); - Debug.Assert(!IsAnalyzerSuppressedForTree(analyzer, declaredNode.SyntaxTree, cancellationToken)); - - foreach (var blockAction in blockActions) - { - if (blockAction is CodeBlockAnalyzerAction codeBlockAction) - { - // This context is a struct, so it's fine to create a new one for each action. - var context = new CodeBlockAnalysisContext(declaredNode, declaredSymbol, semanticModel, - AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, filterSpan, isGeneratedCode, cancellationToken); - - ExecuteAndCatchIfThrows( - codeBlockAction.Analyzer, - static data => data.codeBlockAction.Action(data.context), - (codeBlockAction, context), - new AnalysisContextInfo(Compilation, declaredSymbol, declaredNode), - cancellationToken); - } - else if (blockAction is OperationBlockAnalyzerAction operationBlockAction) - { - // This context is a struct, so it's fine to create a new one for each action. - var context = new OperationBlockAnalysisContext(operationBlocks, declaredSymbol, semanticModel.Compilation, - AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, GetControlFlowGraph, declaredNode.SyntaxTree, filterSpan, isGeneratedCode, cancellationToken); - - ExecuteAndCatchIfThrows( - operationBlockAction.Analyzer, - static data => data.operationBlockAction.Action(data.context), - (operationBlockAction, context), - new AnalysisContextInfo(Compilation, declaredSymbol), - cancellationToken); - } - } - } - internal static ImmutableSegmentedDictionary>> GetNodeActionsByKind( ArrayBuilder> nodeActions) where TLanguageKindEnum : struct From 7069af47d86ae4a5cdbe44982577fc6bf38fe470 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 1 Feb 2025 10:33:43 -0800 Subject: [PATCH 46/49] Simplifiy --- ...AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs index c60c65d449108..9ab025f37f345 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs @@ -88,9 +88,8 @@ public ImmutableSegmentedDictionary.GetInstance(); AddFilteredActions(AnalyzerActions.OperationActions, operationActions); + VerifyActions(operationActions, _analyzer); - var analyzerActionsByKind = AnalyzerExecutor.GetOperationActionsByKind(operationActions); - RoslynImmutableInterlocked.InterlockedInitialize(ref _lazyOperationActionsByKind, analyzerActionsByKind); + RoslynImmutableInterlocked.InterlockedInitialize( + ref _lazyOperationActionsByKind, AnalyzerExecutor.GetOperationActionsByKind(operationActions)); operationActions.Free(); } From a01c5f5e4d4f26cc6f44040c45e4ac7efcaa1f73 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 1 Feb 2025 10:34:27 -0800 Subject: [PATCH 47/49] Simplifiy --- .../AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs index 9ab025f37f345..021710ef3d925 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.GroupedAnalyzerActionsForAnalyzer.cs @@ -88,8 +88,7 @@ public ImmutableSegmentedDictionary.GetInstance(); AddFilteredActions(AnalyzerActions.OperationActions, operationActions); - VerifyActions(operationActions, _analyzer); - RoslynImmutableInterlocked.InterlockedInitialize( - ref _lazyOperationActionsByKind, AnalyzerExecutor.GetOperationActionsByKind(operationActions)); + RoslynImmutableInterlocked.InterlockedInitialize(ref _lazyOperationActionsByKind, AnalyzerExecutor.GetOperationActionsByKind(operationActions)); operationActions.Free(); } From c3e7d88bebfabbf7ac3fd500d77036af2f65349f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 4 Feb 2025 14:09:06 -0800 Subject: [PATCH 48/49] Simplify --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 6770fcb95f32d..71df135dd3a23 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -714,7 +714,6 @@ private void ExecuteOperationAction( private readonly record struct ExecutionData( DiagnosticAnalyzer Analyzer, - // SyntaxNode DeclaredNode, ISymbol DeclaredSymbol, SemanticModel SemanticModel, TextSpan? FilterSpan, From e83d9c739e7aac4c14ac0a81317df31b32c5d630 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 5 Feb 2025 17:38:41 -0800 Subject: [PATCH 49/49] stop using record --- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 71df135dd3a23..19d913bc9aa2a 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -712,12 +712,19 @@ private void ExecuteOperationAction( cancellationToken); } - private readonly record struct ExecutionData( - DiagnosticAnalyzer Analyzer, - ISymbol DeclaredSymbol, - SemanticModel SemanticModel, - TextSpan? FilterSpan, - bool IsGeneratedCode); + private readonly struct ExecutionData( + DiagnosticAnalyzer analyzer, + ISymbol declaredSymbol, + SemanticModel semanticModel, + TextSpan? filterSpan, + bool isGeneratedCode) + { + public readonly DiagnosticAnalyzer Analyzer = analyzer; + public readonly ISymbol DeclaredSymbol = declaredSymbol; + public readonly SemanticModel SemanticModel = semanticModel; + public readonly TextSpan? FilterSpan = filterSpan; + public readonly bool IsGeneratedCode = isGeneratedCode; + } /// /// Execute code block actions for the given analyzer for the given declaration.