private AnalyzerActions GetPerCompilationAnalyzerActions(
            DiagnosticAnalyzer analyzer,
            AnalyzerActions sessionActions,
            Compilation compilation,
            Action <Diagnostic> addDiagnostic)
        {
            Contract.ThrowIfFalse(sessionActions.CompilationStartActionsCount > 0);

            var             compilationActionsMap = s_compilationActionsTable.GetOrCreateValue(compilation);
            AnalyzerActions result;

            if (compilationActionsMap.TryGetValue(analyzer, out result))
            {
                return(result);
            }

            result = AnalyzerDriverHelper.ExecuteCompilationStartActions(sessionActions, analyzer, compilation,
                                                                         _analyzerOptions, addDiagnostic, CatchAnalyzerException, _cancellationToken);

            if (!compilationActionsMap.TryAdd(analyzer, result))
            {
                return(compilationActionsMap[analyzer]);
            }

            return(result);
        }
        private static ImmutableArray <Diagnostic> AnalyzerExceptionToDiagnostics(DiagnosticAnalyzer analyzer, Exception e, CancellationToken cancellationToken)
        {
            if (!IsCanceled(e, cancellationToken))
            {
                // Create a info diagnostic saying that the analyzer failed
                return(ImmutableArray.Create(AnalyzerDriverHelper.GetAnalyzerDiagnostic(analyzer, e)));
            }

            return(ImmutableArray <Diagnostic> .Empty);
        }
 private Tuple <AnalyzerActions, ImmutableArray <Diagnostic> > GetSessionAnalyzerActionsAndDiagnosticsCore(DiagnosticAnalyzer analyzer)
 {
     using (var pooledObject = SharedPools.Default <List <Diagnostic> >().GetPooledObject())
     {
         var diagnostics = pooledObject.Object;
         var actions     = AnalyzerDriverHelper.GetSessionAnalyzerActions(analyzer, diagnostics.Add, CatchAnalyzerException, _cancellationToken);
         var diagArray   = diagnostics.ToImmutableArrayOrEmpty();
         return(Tuple.Create(actions, diagArray));
     }
 }
 public void ExecuteCodeBlockActions(
     AnalyzerActions actions,
     IEnumerable <DeclarationInfo> declarationsInNode,
     SemanticModel semanticModel,
     AnalyzerOptions analyzerOptions,
     Action <Diagnostic> reportDiagnostic,
     Func <Exception, DiagnosticAnalyzer, bool> continueOnAnalyzerException,
     CancellationToken cancellationToken)
 {
     AnalyzerDriverHelper.ExecuteCodeBlockActions(actions, declarationsInNode,
                                                  semanticModel, analyzerOptions, reportDiagnostic, continueOnAnalyzerException, this.GetKind, cancellationToken);
 }
 public void ExecuteSyntaxNodeActions(
     AnalyzerActions actions,
     IEnumerable <SyntaxNode> descendantNodes,
     SemanticModel semanticModel,
     AnalyzerOptions analyzerOptions,
     Action <Diagnostic> reportDiagnostic,
     Func <Exception, DiagnosticAnalyzer, bool> continueOnAnalyzerException,
     CancellationToken cancellationToken)
 {
     AnalyzerDriverHelper.ExecuteSyntaxNodeActions(actions, descendantNodes, semanticModel,
                                                   analyzerOptions, reportDiagnostic, continueOnAnalyzerException, this.GetKind, cancellationToken);
 }
        public async Task <IEnumerable <Diagnostic> > GetSyntaxDiagnosticsAsync(DiagnosticAnalyzer analyzer)
        {
            var compilation = _document.Project.SupportsCompilation ? await _document.Project.GetCompilationAsync(_cancellationToken).ConfigureAwait(false) : null;

            Contract.ThrowIfNull(_document);
            Contract.ThrowIfFalse(analyzer.SupportsSyntaxDiagnosticAnalysis(this));

            using (var pooledObject = SharedPools.Default <List <Diagnostic> >().GetPooledObject())
            {
                var diagnostics = pooledObject.Object;

                _cancellationToken.ThrowIfCancellationRequested();
                var documentAnalyzer = analyzer as DocumentDiagnosticAnalyzer;
                if (documentAnalyzer != null)
                {
                    try
                    {
                        await documentAnalyzer.AnalyzeSyntaxAsync(_document, diagnostics.Add, _cancellationToken).ConfigureAwait(false);

                        return(diagnostics.ToImmutableArrayOrEmpty());
                    }
                    catch (Exception e) when(CatchAnalyzerException(e, analyzer))
                    {
                        var exceptionDiagnostics = AnalyzerExceptionToDiagnostics(analyzer, e, _cancellationToken);

                        return(GetFilteredDocumentDiagnostics(exceptionDiagnostics, compilation).ToImmutableArray());
                    }
                }

                var analyzerActions = await this.GetAnalyzerActionsAsync(analyzer, diagnostics.Add).ConfigureAwait(false);

                DiagnosticAnalyzerLogger.UpdateAnalyzerTypeCount(analyzer, analyzerActions, (DiagnosticLogAggregator)_logAggregator);

                if (analyzerActions != null)
                {
                    if (_document.SupportsSyntaxTree)
                    {
                        AnalyzerDriverHelper.ExecuteSyntaxTreeActions(analyzerActions, _root.SyntaxTree,
                                                                      _analyzerOptions, diagnostics.Add, CatchAnalyzerException, _cancellationToken);
                    }
                }

                if (diagnostics.Count == 0)
                {
                    return(SpecializedCollections.EmptyEnumerable <Diagnostic>());
                }

                return(GetFilteredDocumentDiagnostics(diagnostics, compilation).ToImmutableArray());
            }
        }
        private async Task GetCompilationDiagnosticsAsync(DiagnosticAnalyzer analyzer, List <Diagnostic> diagnostics, Action <Project, DiagnosticAnalyzer, CancellationToken> forceAnalyzeAllDocuments)
        {
            Contract.ThrowIfFalse(_project.SupportsCompilation);

            var analyzerActionsAndDiagnostics = GetSessionAnalyzerActionsAndDiagnostics(analyzer);
            var analyzerActions = analyzerActionsAndDiagnostics.Item1;

            var compilation = await _project.GetCompilationAsync(_cancellationToken).ConfigureAwait(false);

            diagnostics.AddRange(CompilationWithAnalyzers.GetEffectiveDiagnostics(analyzerActionsAndDiagnostics.Item2, compilation));

            DiagnosticAnalyzerLogger.UpdateAnalyzerTypeCount(analyzer, analyzerActions, (DiagnosticLogAggregator)_logAggregator);

            if (analyzerActions == null || (analyzerActions.CompilationStartActionsCount == 0 && analyzerActions.CompilationEndActionsCount == 0))
            {
                return;
            }

            using (var pooledObject = SharedPools.Default <List <Diagnostic> >().GetPooledObject())
            {
                var localDiagnostics = pooledObject.Object;

                // Get all the analyzer actions, including the per-compilation actions.
                var allAnalyzerActions = await GetAnalyzerActionsAsync(analyzer, localDiagnostics.Add).ConfigureAwait(false);

                if (analyzerActions.CompilationEndActionsCount < allAnalyzerActions.CompilationEndActionsCount && forceAnalyzeAllDocuments != null)
                {
                    if (allAnalyzerActions.CodeBlockEndActionsCount > analyzerActions.CodeBlockEndActionsCount ||
                        allAnalyzerActions.CodeBlockStartActionsCount > analyzerActions.CodeBlockStartActionsCount ||
                        allAnalyzerActions.SemanticModelActionsCount > analyzerActions.SemanticModelActionsCount ||
                        allAnalyzerActions.SymbolActionsCount > analyzerActions.SymbolActionsCount ||
                        allAnalyzerActions.SyntaxNodeActionsCount > analyzerActions.SyntaxNodeActionsCount ||
                        allAnalyzerActions.SyntaxTreeActionsCount > analyzerActions.SyntaxTreeActionsCount)
                    {
                        // Analyzer registered a compilation end action and at least one other analyzer action during it's compilation start action.
                        // We need to ensure that we have force analyzed all documents in this project for this analyzer before executing the end actions.
                        forceAnalyzeAllDocuments(_project, analyzer, _cancellationToken);
                    }
                }

                // CompilationEnd actions.
                AnalyzerDriverHelper.ExecuteCompilationEndActions(allAnalyzerActions, compilation, _analyzerOptions, localDiagnostics.Add, CatchAnalyzerException, _cancellationToken);
                diagnostics.AddRange(CompilationWithAnalyzers.GetEffectiveDiagnostics(localDiagnostics, compilation));
            }
        }
        public async Task <IEnumerable <Diagnostic> > GetSemanticDiagnosticsAsync(DiagnosticAnalyzer analyzer)
        {
            var model = await _document.GetSemanticModelAsync(_cancellationToken).ConfigureAwait(false);

            Contract.ThrowIfNull(_document);
            Contract.ThrowIfFalse(analyzer.SupportsSemanticDiagnosticAnalysis(this));

            using (var pooledObject = SharedPools.Default <List <Diagnostic> >().GetPooledObject())
            {
                var diagnostics = pooledObject.Object;

                // Stateless semantic analyzers:
                //  1) ISemanticModelAnalyzer/IDocumentBasedDiagnosticAnalyzer
                //  2) ISymbolAnalyzer
                //  3) ISyntaxNodeAnalyzer

                _cancellationToken.ThrowIfCancellationRequested();

                var documentAnalyzer = analyzer as DocumentDiagnosticAnalyzer;
                if (documentAnalyzer != null)
                {
                    try
                    {
                        await documentAnalyzer.AnalyzeSemanticsAsync(_document, diagnostics.Add, _cancellationToken).ConfigureAwait(false);
                    }
                    catch (Exception e) when(CatchAnalyzerException(e, analyzer))
                    {
                        var exceptionDiagnostics = AnalyzerExceptionToDiagnostics(analyzer, e, _cancellationToken);

                        return(model == null ? exceptionDiagnostics : GetFilteredDocumentDiagnostics(exceptionDiagnostics, model.Compilation));
                    }
                }
                else
                {
                    var analyzerActions = await GetAnalyzerActionsAsync(analyzer, diagnostics.Add).ConfigureAwait(false);

                    if (analyzerActions != null)
                    {
                        // SemanticModel actions.
                        if (analyzerActions.SemanticModelActionsCount > 0)
                        {
                            AnalyzerDriverHelper.ExecuteSemanticModelActions(analyzerActions, model, _analyzerOptions,
                                                                             diagnostics.Add, CatchAnalyzerException, _cancellationToken);
                        }

                        var compilation = model.Compilation;

                        // Symbol actions.
                        if (analyzerActions.SymbolActionsCount > 0)
                        {
                            var symbols = this.GetSymbolsToAnalyze(model);
                            AnalyzerDriverHelper.ExecuteSymbolActions(analyzerActions, symbols, compilation,
                                                                      _analyzerOptions, diagnostics.Add, CatchAnalyzerException, _cancellationToken);
                        }

                        if (this.SyntaxNodeAnalyzerService != null)
                        {
                            // SyntaxNode actions.
                            if (analyzerActions.SyntaxNodeActionsCount > 0)
                            {
                                this.SyntaxNodeAnalyzerService.ExecuteSyntaxNodeActions(analyzerActions, GetSyntaxNodesToAnalyze(), model,
                                                                                        _analyzerOptions, diagnostics.Add, CatchAnalyzerException, _cancellationToken);
                            }

                            // CodeBlockStart, CodeBlockEnd, and generated SyntaxNode actions.
                            if (analyzerActions.CodeBlockStartActionsCount > 0 || analyzerActions.CodeBlockEndActionsCount > 0)
                            {
                                this.SyntaxNodeAnalyzerService.ExecuteCodeBlockActions(analyzerActions, this.GetDeclarationInfos(model), model,
                                                                                       _analyzerOptions, diagnostics.Add, CatchAnalyzerException, _cancellationToken);
                            }
                        }
                    }
                }

                var result = model == null
                        ? diagnostics
                        : GetFilteredDocumentDiagnostics(diagnostics, model.Compilation);

                return(result.ToImmutableArray());
            }
        }