private void ExecuteSymbolActionsCore(
            ImmutableArray <SymbolAnalyzerAction> symbolActions,
            DiagnosticAnalyzer analyzer,
            ISymbol symbol,
            Func <ISymbol, SyntaxReference, Compilation, SyntaxNode> getTopMostNodeForAnalysis,
            AnalyzerStateData analyzerStateOpt)
        {
            Debug.Assert(getTopMostNodeForAnalysis != null);

            var addDiagnostic = GetAddDiagnostic(symbol, _compilation, analyzer, _addDiagnostic, _addLocalDiagnosticOpt, _addNonLocalDiagnosticOpt, getTopMostNodeForAnalysis);

            foreach (var symbolAction in symbolActions)
            {
                var action = symbolAction.Action;
                var kinds  = symbolAction.Kinds;

                if (kinds.Contains(symbol.Kind))
                {
                    if (ShouldExecuteAction(analyzerStateOpt, symbolAction))
                    {
                        _cancellationToken.ThrowIfCancellationRequested();

                        ExecuteAndCatchIfThrows(symbolAction.Analyzer,
                                                () => action(new SymbolAnalysisContext(symbol, _compilation, _analyzerOptions, addDiagnostic,
                                                                                       d => IsSupportedDiagnostic(symbolAction.Analyzer, d), _cancellationToken)));

                        analyzerStateOpt?.ProcessedActions.Add(symbolAction);
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Executes the symbol actions on the given symbol.
        /// </summary>
        /// <param name="symbolActions">Symbol actions to be executed.</param>
        /// <param name="analyzer">Analyzer whose actions are to be executed.</param>
        /// <param name="symbol">Symbol to be analyzed.</param>
        /// <param name="overriddenAddDiagnostic">Overridden add diagnostic delegate.</param>
        /// <param name="overriddenAddLocalDiagnostic">Overridden add local diagnostic delegate.</param>
        /// <param name="overriddenAddNonLocalDiagnostic">Overridden add non-local diagnostic delegate.</param>
        /// <param name="getTopMostNodeForAnalysis">Delegate to get topmost declaration node for a symbol declaration reference.</param>
        /// <param name="analysisScope">Scope for analyzer execution.</param>
        /// <param name="analysisStateOpt">An optional object to track analysis state.</param>
        public void ExecuteSymbolActions(
            ImmutableArray <SymbolAnalyzerAction> symbolActions,
            DiagnosticAnalyzer analyzer,
            ISymbol symbol,
            Action <Diagnostic> overriddenAddDiagnostic,
            Action <Diagnostic, DiagnosticAnalyzer, bool> overriddenAddLocalDiagnostic,
            Action <Diagnostic, DiagnosticAnalyzer> overriddenAddNonLocalDiagnostic,
            Func <ISymbol, SyntaxReference, Compilation, SyntaxNode> getTopMostNodeForAnalysis,
            AnalysisScope analysisScope,
            AnalysisState analysisStateOpt)
        {
            AnalyzerStateData analyzerStateOpt = null;

            try
            {
                if (TryStartAnalyzingSymbol(symbol, analyzer, analysisScope, analysisStateOpt, out analyzerStateOpt))
                {
                    ExecuteSymbolActionsCore(symbolActions, analyzer, symbol, overriddenAddDiagnostic,
                                             overriddenAddLocalDiagnostic, overriddenAddNonLocalDiagnostic, getTopMostNodeForAnalysis, analyzerStateOpt);
                    analysisStateOpt?.MarkSymbolComplete(symbol, analyzer);
                }
            }
            finally
            {
                analyzerStateOpt?.ResetToReadyState();
            }
        }
        /// <summary>
        /// Executes the syntax tree actions on the given syntax tree.
        /// </summary>
        /// <param name="syntaxTreeActions">Syntax tree actions to be executed.</param>
        /// <param name="analyzer">Analyzer whose actions are to be executed.</param>
        /// <param name="tree">Syntax tree to analyze.</param>
        /// <param name="analysisScope">Scope for analyzer execution.</param>
        /// <param name="analysisStateOpt">An optional object to track analysis state.</param>
        public void ExecuteSyntaxTreeActions(
            ImmutableArray <SyntaxTreeAnalyzerAction> syntaxTreeActions,
            DiagnosticAnalyzer analyzer,
            SyntaxTree tree,
            AnalysisScope analysisScope,
            AnalysisState analysisStateOpt)
        {
            AnalyzerStateData analyzerStateOpt = null;

            try
            {
                if (TryStartSyntaxAnalysis(tree, analyzer, analysisScope, analysisStateOpt, out analyzerStateOpt))
                {
                    ExecuteSyntaxTreeActionsCore(syntaxTreeActions, analyzer, tree, analyzerStateOpt);
                    analysisStateOpt?.MarkSyntaxAnalysisComplete(tree, analyzer);
                }
            }
            finally
            {
                analyzerStateOpt?.ResetToReadyState();
            }
        }
        private void ExecuteSyntaxTreeActionsCore(
            ImmutableArray <SyntaxTreeAnalyzerAction> syntaxTreeActions,
            DiagnosticAnalyzer analyzer,
            SyntaxTree tree,
            AnalyzerStateData analyzerStateOpt)
        {
            var addDiagnostic = GetAddDiagnostic(tree, analyzer, isSyntaxDiagnostic: true);

            foreach (var syntaxTreeAction in syntaxTreeActions)
            {
                if (ShouldExecuteAction(analyzerStateOpt, syntaxTreeAction))
                {
                    _cancellationToken.ThrowIfCancellationRequested();

                    // Catch Exception from action.
                    ExecuteAndCatchIfThrows(syntaxTreeAction.Analyzer,
                                            () => syntaxTreeAction.Action(new SyntaxTreeAnalysisContext(tree, _analyzerOptions, addDiagnostic,
                                                                                                        d => IsSupportedDiagnostic(syntaxTreeAction.Analyzer, d), _cancellationToken)));

                    analyzerStateOpt?.ProcessedActions.Add(syntaxTreeAction);
                }
            }
        }
        /// <summary>
        /// Executes the semantic model actions on the given semantic model.
        /// </summary>
        /// <param name="semanticModelActions">Semantic model actions to be executed.</param>
        /// <param name="analyzer">Analyzer whose actions are to be executed.</param>
        /// <param name="semanticModel">Semantic model to analyze.</param>
        /// <param name="compilationUnitCompletedEvent">Compilation event for semantic model analysis.</param>
        /// <param name="analysisScope">Scope for analyzer execution.</param>
        /// <param name="analysisStateOpt">An optional object to track analysis state.</param>
        public void ExecuteSemanticModelActions(
            ImmutableArray <SemanticModelAnalyzerAction> semanticModelActions,
            DiagnosticAnalyzer analyzer,
            SemanticModel semanticModel,
            CompilationEvent compilationUnitCompletedEvent,
            AnalysisScope analysisScope,
            AnalysisState analysisStateOpt)
        {
            AnalyzerStateData analyzerStateOpt = null;

            try
            {
                if (TryStartProcessingEvent(compilationUnitCompletedEvent, analyzer, analysisScope, analysisStateOpt, out analyzerStateOpt))
                {
                    ExecuteSemanticModelActionsCore(semanticModelActions, analyzer, semanticModel, analyzerStateOpt);
                    analysisStateOpt?.MarkEventComplete(compilationUnitCompletedEvent, analyzer);
                }
            }
            finally
            {
                analyzerStateOpt?.ResetToReadyState();
            }
        }
        /// <summary>
        /// Executes compilation actions or compilation end actions.
        /// </summary>
        /// <param name="compilationActions">Compilation actions to be executed.</param>
        /// <param name="analyzer">Analyzer whose actions are to be executed.</param>
        /// <param name="compilationEvent">Compilation event.</param>
        /// <param name="analysisScope">Scope for analyzer execution.</param>
        /// <param name="analysisStateOpt">An optional object to track analysis state.</param>
        public void ExecuteCompilationActions(
            ImmutableArray <CompilationAnalyzerAction> compilationActions,
            DiagnosticAnalyzer analyzer,
            CompilationEvent compilationEvent,
            AnalysisScope analysisScope,
            AnalysisState analysisStateOpt)
        {
            Debug.Assert(compilationEvent is CompilationStartedEvent || compilationEvent is CompilationCompletedEvent);

            AnalyzerStateData analyzerStateOpt = null;

            try
            {
                if (TryStartProcessingEvent(compilationEvent, analyzer, analysisScope, analysisStateOpt, out analyzerStateOpt))
                {
                    ExecuteCompilationActionsCore(compilationActions, analyzer, analyzerStateOpt);
                    analysisStateOpt?.MarkEventComplete(compilationEvent, analyzer);
                }
            }
            finally
            {
                analyzerStateOpt?.ResetToReadyState();
            }
        }
        private static bool TryStartAnalyzingSymbol(ISymbol symbol, DiagnosticAnalyzer analyzer, AnalysisScope analysisScope, AnalysisState analysisStateOpt, out AnalyzerStateData analyzerStateOpt)
        {
            Debug.Assert(analysisScope.Analyzers.Contains(analyzer));

            analyzerStateOpt = null;
            return(analysisStateOpt == null || analysisStateOpt.TryStartAnalyzingSymbol(symbol, analyzer, out analyzerStateOpt));
        }
        private static bool TryStartSyntaxAnalysis(SyntaxTree tree, DiagnosticAnalyzer analyzer, AnalysisScope analysisScope, AnalysisState analysisStateOpt, out AnalyzerStateData analyzerStateOpt)
        {
            Debug.Assert(analysisScope.Analyzers.Contains(analyzer));

            analyzerStateOpt = null;
            return(analysisStateOpt == null || analysisStateOpt.TryStartSyntaxAnalysis(tree, analyzer, out analyzerStateOpt));
        }
        private static bool TryStartProcessingEvent(CompilationEvent nonSymbolCompilationEvent, DiagnosticAnalyzer analyzer, AnalysisScope analysisScope, AnalysisState analysisStateOpt, out AnalyzerStateData analyzerStateOpt)
        {
            Debug.Assert(!(nonSymbolCompilationEvent is SymbolDeclaredCompilationEvent));
            Debug.Assert(analysisScope.Analyzers.Contains(analyzer));

            analyzerStateOpt = null;
            return(analysisStateOpt == null || analysisStateOpt.TryStartProcessingEvent(nonSymbolCompilationEvent, analyzer, out analyzerStateOpt));
        }
 private static bool ShouldExecuteAction(AnalyzerStateData analyzerStateOpt, AnalyzerAction action)
 {
     return(analyzerStateOpt == null || !analyzerStateOpt.ProcessedActions.Contains(action));
 }
        private void ExecuteCompilationActionsCore(ImmutableArray <CompilationAnalyzerAction> compilationActions, DiagnosticAnalyzer analyzer, AnalyzerStateData analyzerStateOpt)
        {
            var addDiagnostic = GetAddCompilationDiagnostic(analyzer);

            foreach (var endAction in compilationActions)
            {
                _cancellationToken.ThrowIfCancellationRequested();

                if (ShouldExecuteAction(analyzerStateOpt, endAction))
                {
                    ExecuteAndCatchIfThrows(endAction.Analyzer,
                                            () => endAction.Action(new CompilationAnalysisContext(_compilation, _analyzerOptions, addDiagnostic,
                                                                                                  d => IsSupportedDiagnostic(endAction.Analyzer, d), _cancellationToken)));

                    analyzerStateOpt?.ProcessedActions.Add(endAction);
                }
            }
        }