diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index ef3838de66839fec666cf5a76d58863fdd15d4dd..17e26b8a2636c8852a58549514d8ee03ca70a2a7 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -201,9 +201,13 @@ public AnalyzerExecutor WithCancellationToken(CancellationToken cancellationToke /// public void ExecuteInitializeMethod(DiagnosticAnalyzer analyzer, HostSessionStartAnalysisScope sessionScope) { + var context = new AnalyzerAnalysisContext(analyzer, sessionScope, _compilation.IsIOperationFeatureEnabled()); + // The Initialize method should be run asynchronously in case it is not well behaved, e.g. does not terminate. - ExecuteAndCatchIfThrows(analyzer, - () => analyzer.Initialize(new AnalyzerAnalysisContext(analyzer, sessionScope, _compilation.IsIOperationFeatureEnabled()))); + ExecuteAndCatchIfThrows( + analyzer, + data => data.analyzer.Initialize(data.context), + (analyzer: analyzer, context: context)); } /// @@ -217,9 +221,13 @@ public void ExecuteCompilationStartActions(ImmutableArray startAction.Action(new AnalyzerCompilationStartAnalysisContext(startAction.Analyzer, compilationScope, - _compilation, _analyzerOptions, _compilationAnalysisValueProviderFactory, _cancellationToken)), + var context = new AnalyzerCompilationStartAnalysisContext(startAction.Analyzer, compilationScope, + _compilation, _analyzerOptions, _compilationAnalysisValueProviderFactory, _cancellationToken); + + ExecuteAndCatchIfThrows( + startAction.Analyzer, + data => data.action(data.context), + (action: startAction.Action, context: context), new AnalysisContextInfo(_compilation)); } } @@ -267,6 +275,7 @@ public void ExecuteCompilationStartActions(ImmutableArray compilationActions, DiagnosticAnalyzer analyzer, AnalyzerStateData analyzerStateOpt) { var addDiagnostic = GetAddCompilationDiagnostic(analyzer); + Func isSupportedDiagnostic = d => IsSupportedDiagnostic(analyzer, d); foreach (var endAction in compilationActions) { @@ -274,10 +283,14 @@ private void ExecuteCompilationActionsCore(ImmutableArray endAction.Action(new CompilationAnalysisContext( - _compilation, _analyzerOptions, addDiagnostic, - d => IsSupportedDiagnostic(endAction.Analyzer, d), _compilationAnalysisValueProviderFactory, _cancellationToken)), + var context = new CompilationAnalysisContext( + _compilation, _analyzerOptions, addDiagnostic, + isSupportedDiagnostic, _compilationAnalysisValueProviderFactory, _cancellationToken); + + ExecuteAndCatchIfThrows( + endAction.Analyzer, + data => data.action(data.context), + (action: endAction.Action, context: context), new AnalysisContextInfo(_compilation)); analyzerStateOpt?.ProcessedActions.Add(endAction); @@ -345,6 +358,7 @@ private void ExecuteCompilationActionsCore(ImmutableArray isSupportedDiagnostic = d => IsSupportedDiagnostic(analyzer, d); foreach (var symbolAction in symbolActions) { @@ -357,9 +371,13 @@ private void ExecuteCompilationActionsCore(ImmutableArray action(new SymbolAnalysisContext(symbol, _compilation, _analyzerOptions, addDiagnostic, - d => IsSupportedDiagnostic(symbolAction.Analyzer, d), _cancellationToken)), + var context = new SymbolAnalysisContext(symbol, _compilation, _analyzerOptions, addDiagnostic, + isSupportedDiagnostic, _cancellationToken); + + ExecuteAndCatchIfThrows( + symbolAction.Analyzer, + data => data.action(data.context), + (action: action, context: context), new AnalysisContextInfo(_compilation, symbol)); analyzerStateOpt?.ProcessedActions.Add(symbolAction); @@ -423,6 +441,7 @@ private void ExecuteCompilationActionsCore(ImmutableArray isSupportedDiagnostic = d => IsSupportedDiagnostic(analyzer, d); foreach (var semanticModelAction in semanticModelActions) { @@ -430,10 +449,14 @@ private void ExecuteCompilationActionsCore(ImmutableArray semanticModelAction.Action(new SemanticModelAnalysisContext(semanticModel, _analyzerOptions, addDiagnostic, - d => IsSupportedDiagnostic(semanticModelAction.Analyzer, d), _cancellationToken)), + ExecuteAndCatchIfThrows( + semanticModelAction.Analyzer, + data => data.action(data.context), + (action: semanticModelAction.Action, context: context), new AnalysisContextInfo(semanticModel)); analyzerStateOpt?.ProcessedActions.Add(semanticModelAction); @@ -494,6 +517,7 @@ private void ExecuteCompilationActionsCore(ImmutableArray isSupportedDiagnostic = d => IsSupportedDiagnostic(analyzer, d); foreach (var syntaxTreeAction in syntaxTreeActions) { @@ -501,10 +525,13 @@ private void ExecuteCompilationActionsCore(ImmutableArray syntaxTreeAction.Action(new SyntaxTreeAnalysisContext(tree, _analyzerOptions, addDiagnostic, - d => IsSupportedDiagnostic(syntaxTreeAction.Analyzer, d), _compilation, _cancellationToken)), + ExecuteAndCatchIfThrows( + syntaxTreeAction.Analyzer, + data => data.action(data.context), + (action: syntaxTreeAction.Action, context: context), new AnalysisContextInfo(_compilation, tree)); analyzerStateOpt?.ProcessedActions.Add(syntaxTreeAction); @@ -518,6 +545,7 @@ private void ExecuteCompilationActionsCore(ImmutableArray addDiagnostic, + Func isSupportedDiagnostic, SyntaxNodeAnalyzerStateData analyzerStateOpt) where TLanguageKindEnum : struct { @@ -526,9 +554,12 @@ private void ExecuteCompilationActionsCore(ImmutableArray IsSupportedDiagnostic(syntaxNodeAction.Analyzer, d), _cancellationToken); - ExecuteAndCatchIfThrows(syntaxNodeAction.Analyzer, - () => syntaxNodeAction.Action(syntaxNodeContext), + isSupportedDiagnostic, _cancellationToken); + + ExecuteAndCatchIfThrows( + syntaxNodeAction.Analyzer, + data => data.action(data.context), + (action: syntaxNodeAction.Action, context: syntaxNodeContext), new AnalysisContextInfo(_compilation, node)); analyzerStateOpt?.ProcessedActions.Add(syntaxNodeAction); @@ -541,15 +572,18 @@ private void ExecuteCompilationActionsCore(ImmutableArray addDiagnostic, + Func isSupportedDiagnostic, OperationAnalyzerStateData analyzerStateOpt) { Debug.Assert(analyzerStateOpt == null || analyzerStateOpt.CurrentOperation == operation); if (ShouldExecuteAction(analyzerStateOpt, operationAction)) { - var operationContext = new OperationAnalysisContext(operation, containingSymbol, semanticModel.Compilation, _analyzerOptions, addDiagnostic, d => IsSupportedDiagnostic(operationAction.Analyzer, d), _cancellationToken); - ExecuteAndCatchIfThrows(operationAction.Analyzer, - () => operationAction.Action(operationContext), + var operationContext = new OperationAnalysisContext(operation, containingSymbol, semanticModel.Compilation, _analyzerOptions, addDiagnostic, isSupportedDiagnostic, _cancellationToken); + ExecuteAndCatchIfThrows( + operationAction.Analyzer, + data => data.action(data.context), + (action: operationAction.Action, context: operationContext), new AnalysisContextInfo(_compilation, operation)); analyzerStateOpt?.ProcessedActions.Add(operationAction); @@ -701,6 +735,7 @@ private void ExecuteCompilationActionsCore(ImmutableArray isSupportedDiagnostic = d => IsSupportedDiagnostic(analyzer, d); try { @@ -713,17 +748,21 @@ private void ExecuteCompilationActionsCore(ImmutableArray; + var codeBlockScope = new HostCodeBlockStartAnalysisScope(); + var blockStartContext = new AnalyzerCodeBlockStartAnalysisContext(startAction.Analyzer, + codeBlockScope, declaredNode, declaredSymbol, semanticModel, _analyzerOptions, _cancellationToken); + // Catch Exception from the start action. - ExecuteAndCatchIfThrows(startAction.Analyzer, () => - { - var codeBlockScope = new HostCodeBlockStartAnalysisScope(); - var blockStartContext = new AnalyzerCodeBlockStartAnalysisContext(startAction.Analyzer, - codeBlockScope, declaredNode, declaredSymbol, semanticModel, _analyzerOptions, _cancellationToken); - codeBlockStartAction.Action(blockStartContext); - codeBlockEndActions.AddAll(codeBlockScope.CodeBlockEndActions); - syntaxNodeActions.AddRange(codeBlockScope.SyntaxNodeActions); - }, - new AnalysisContextInfo(_compilation, declaredSymbol, declaredNode)); + 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: syntaxNodeActions), + new AnalysisContextInfo(_compilation, declaredSymbol, declaredNode)); } else { @@ -731,17 +770,21 @@ private void ExecuteCompilationActionsCore(ImmutableArray; + var operationBlockScope = new HostOperationBlockStartAnalysisScope(); + var operationStartContext = new AnalyzerOperationBlockStartAnalysisContext(startAction.Analyzer, + operationBlockScope, operationBlocks, declaredSymbol, semanticModel.Compilation, _analyzerOptions, _cancellationToken); + // Catch Exception from the start action. - ExecuteAndCatchIfThrows(startAction.Analyzer, () => - { - var operationBlockScope = new HostOperationBlockStartAnalysisScope(); - var operationStartContext = new AnalyzerOperationBlockStartAnalysisContext(startAction.Analyzer, - operationBlockScope, operationBlocks, declaredSymbol, semanticModel.Compilation, _analyzerOptions, _cancellationToken); - operationBlockStartAction.Action(operationStartContext); - operationBlockEndActions.AddAll(operationBlockScope.OperationBlockEndActions); - operationActions.AddRange(operationBlockScope.OperationActions); - }, - new AnalysisContextInfo(_compilation, declaredSymbol)); + 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)); } } @@ -765,20 +808,20 @@ private void ExecuteCompilationActionsCore(ImmutableArray)getNodesToAnalyze(executableBlocks); - ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, addDiagnostic, analyzerStateOpt?.ExecutableNodesAnalysisState as SyntaxNodeAnalyzerStateData); + ExecuteSyntaxNodeActions(syntaxNodesToAnalyze, executableNodeActionsByKind, analyzer, declaredSymbol, semanticModel, getKind, addDiagnostic, isSupportedDiagnostic, analyzerStateOpt?.ExecutableNodesAnalysisState as SyntaxNodeAnalyzerStateData); } else if (operationActions != null) { var operationActionsByKind = GetOperationActionsByKind(operationActions); var operationsToAnalyze = (IEnumerable)getNodesToAnalyze(executableBlocks); - ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, addDiagnostic, analyzerStateOpt?.ExecutableNodesAnalysisState as OperationAnalyzerStateData); + ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, declaredSymbol, semanticModel, addDiagnostic, isSupportedDiagnostic, analyzerStateOpt?.ExecutableNodesAnalysisState as OperationAnalyzerStateData); } } executableNodeActions.Free(); - ExecuteBlockActions(blockActions, declaredNode, declaredSymbol, semanticModel, operationBlocks, addDiagnostic, analyzerStateOpt); - ExecuteBlockActions(blockEndActions, declaredNode, declaredSymbol, semanticModel, operationBlocks, addDiagnostic, analyzerStateOpt); + ExecuteBlockActions(blockActions, declaredNode, declaredSymbol, semanticModel, operationBlocks, addDiagnostic, isSupportedDiagnostic, analyzerStateOpt); + ExecuteBlockActions(blockEndActions, declaredNode, declaredSymbol, semanticModel, operationBlocks, addDiagnostic, isSupportedDiagnostic, analyzerStateOpt); } private void ExecuteBlockActions( @@ -788,6 +831,7 @@ private void ExecuteCompilationActionsCore(ImmutableArray operationBlocks, Action addDiagnostic, + Func isSupportedDiagnostic, AnalysisState.BlockAnalyzerStateData analyzerStateOpt) where TBlockAction : AnalyzerAction where TNodeStateData : AnalyzerStateData, new() @@ -797,12 +841,14 @@ private void ExecuteCompilationActionsCore(ImmutableArray isSupportedDiagnostic = d => IsSupportedDiagnostic(blockAction.Analyzer, d); if (codeBlockAction != null) { + var context = new CodeBlockAnalysisContext(declaredNode, declaredSymbol, semanticModel, _analyzerOptions, addDiagnostic, isSupportedDiagnostic, _cancellationToken); + ExecuteAndCatchIfThrows( codeBlockAction.Analyzer, - () => codeBlockAction.Action(new CodeBlockAnalysisContext(declaredNode, declaredSymbol, semanticModel, _analyzerOptions, addDiagnostic, isSupportedDiagnostic, _cancellationToken)), + data => data.action(data.context), + (action: codeBlockAction.Action, context: context), new AnalysisContextInfo(_compilation, declaredSymbol, declaredNode)); } else @@ -810,9 +856,12 @@ private void ExecuteCompilationActionsCore(ImmutableArray operationBlockAction.Action(new OperationBlockAnalysisContext(operationBlocks, declaredSymbol, semanticModel.Compilation, _analyzerOptions, addDiagnostic, isSupportedDiagnostic, _cancellationToken)), + data => data.action(data.context), + (action: operationBlockAction.Action, context: context), new AnalysisContextInfo(_compilation, declaredSymbol)); } } @@ -909,7 +958,8 @@ private void ExecuteCompilationActionsCore(ImmutableArray isSupportedDiagnostic = d => IsSupportedDiagnostic(analyzer, d); + ExecuteSyntaxNodeActions(nodesToAnalyze, nodeActionsByKind, analyzer, containingSymbol, model, getKind, addDiagnostic, isSupportedDiagnostic, analyzerStateOpt); } private void ExecuteSyntaxNodeActions( @@ -920,6 +970,7 @@ private void ExecuteCompilationActionsCore(ImmutableArray getKind, Action addDiagnostic, + Func isSupportedDiagnostic, SyntaxNodeAnalyzerStateData analyzerStateOpt) where TLanguageKindEnum : struct { @@ -929,7 +980,7 @@ private void ExecuteCompilationActionsCore(ImmutableArray getKind, Action addDiagnostic, + Func isSupportedDiagnostic, SyntaxNodeAnalyzerStateData analyzerStateOpt) where TLanguageKindEnum : struct { @@ -958,7 +1010,7 @@ private void ExecuteCompilationActionsCore(ImmutableArray isSupportedDiagnostic = d => IsSupportedDiagnostic(analyzer, d); + ExecuteOperationActions(operationsToAnalyze, operationActionsByKind, analyzer, containingSymbol, model, addDiagnostic, isSupportedDiagnostic, analyzerStateOpt); } private void ExecuteOperationActions( @@ -1054,6 +1107,7 @@ private void ExecuteCompilationActionsCore(ImmutableArray addDiagnostic, + Func isSupportedDiagnostic, OperationAnalyzerStateData analyzerStateOpt) { Debug.Assert(operationActionsByKind != null); @@ -1062,7 +1116,7 @@ private void ExecuteCompilationActionsCore(ImmutableArray addDiagnostic, + Func isSupportedDiagnostic, OperationAnalyzerStateData analyzerStateOpt) { ImmutableArray actionsForKind; @@ -1089,7 +1144,7 @@ private void ExecuteCompilationActionsCore(ImmutableArray(DiagnosticAnalyzer analyzer, Action analyze, TArg argument, AnalysisContextInfo? info = null) { object gate = _getAnalyzerGateOpt?.Invoke(analyzer); if (gate != null) { lock (gate) { - ExecuteAndCatchIfThrows_NoLock(analyzer, analyze, info); + ExecuteAndCatchIfThrows_NoLock(analyzer, analyze, argument, info); } } else { - ExecuteAndCatchIfThrows_NoLock(analyzer, analyze, info); + ExecuteAndCatchIfThrows_NoLock(analyzer, analyze, argument, info); } } - private void ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, Action analyze, AnalysisContextInfo? info) + private void ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, Action analyze, TArg argument, AnalysisContextInfo? info) { try { @@ -1143,7 +1198,7 @@ private void ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, Action timer = Stopwatch.StartNew(); } - analyze(); + analyze(argument); if (timer != null) { diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs index e190a47a203c62d764ab32ba03a3c7baa489607d..6826fb443eecee2d8c60e2c5b9db7c2b2cb9be31 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs @@ -151,14 +151,17 @@ public ImmutableArray GetOrComputeDescriptors(DiagnosticAn var supportedDiagnostics = ImmutableArray.Empty; // Catch Exception from analyzer.SupportedDiagnostics - analyzerExecutor.ExecuteAndCatchIfThrows(analyzer, () => - { - var supportedDiagnosticsLocal = analyzer.SupportedDiagnostics; - if (!supportedDiagnosticsLocal.IsDefaultOrEmpty) + analyzerExecutor.ExecuteAndCatchIfThrows( + analyzer, + _ => { - supportedDiagnostics = supportedDiagnosticsLocal; - } - }); + var supportedDiagnosticsLocal = analyzer.SupportedDiagnostics; + if (!supportedDiagnosticsLocal.IsDefaultOrEmpty) + { + supportedDiagnostics = supportedDiagnosticsLocal; + } + }, + argument: default(object)); // Force evaluate and report exception diagnostics from LocalizableString.ToString(). Action onAnalyzerException = analyzerExecutor.OnAnalyzerException;