Exemplo n.º 1
0
        private void ExecuteCodeBlockActions(
            PooledHashSet <CodeBlockAnalyzerAction> blockActions,
            SyntaxNode declaredNode,
            ISymbol declaredSymbol,
            SemanticModel semanticModel,
            Action <Diagnostic> addDiagnostic,
            CodeBlockAnalyzerStateData analyzerStateOpt)
        {
            foreach (var blockAction in blockActions)
            {
                if (ShouldExecuteAction(analyzerStateOpt, blockAction))
                {
                    ExecuteAndCatchIfThrows(blockAction.Analyzer,
                                            () => blockAction.Action(new CodeBlockAnalysisContext(declaredNode, declaredSymbol, semanticModel, _analyzerOptions, addDiagnostic,
                                                                                                  d => IsSupportedDiagnostic(blockAction.Analyzer, d), _cancellationToken)));

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

            blockActions.Free();
        }
Exemplo n.º 2
0
        private void ExecuteCodeBlockActionsCore <TLanguageKindEnum>(
            IEnumerable <CodeBlockStartAnalyzerAction <TLanguageKindEnum> > codeBlockStartActions,
            IEnumerable <CodeBlockAnalyzerAction> codeBlockActions,
            IEnumerable <CodeBlockAnalyzerAction> codeBlockEndActions,
            DiagnosticAnalyzer analyzer,
            SyntaxNode declaredNode,
            ISymbol declaredSymbol,
            ImmutableArray <SyntaxNode> executableCodeBlocks,
            SemanticModel semanticModel,
            Func <SyntaxNode, TLanguageKindEnum> getKind,
            CodeBlockAnalyzerStateData analyzerStateOpt)
            where TLanguageKindEnum : struct
        {
            Debug.Assert(declaredNode != null);
            Debug.Assert(declaredSymbol != null);
            Debug.Assert(CanHaveExecutableCodeBlock(declaredSymbol));
            Debug.Assert(codeBlockStartActions.Any() || codeBlockEndActions.Any() || codeBlockActions.Any());
            Debug.Assert(executableCodeBlocks.Any());

            // Compute the sets of code block end, code block, and stateful syntax node actions.
            var blockEndActions = PooledHashSet <CodeBlockAnalyzerAction> .GetInstance();

            var blockActions = PooledHashSet <CodeBlockAnalyzerAction> .GetInstance();

            var executableNodeActions = ArrayBuilder <SyntaxNodeAnalyzerAction <TLanguageKindEnum> > .GetInstance();

            // Include the code block actions.
            blockActions.AddAll(codeBlockActions);

            // Include the initial code block end actions.
            if (analyzerStateOpt?.CurrentCodeBlockEndActions != null)
            {
                // We have partially processed the code block actions.
                blockEndActions.AddAll(analyzerStateOpt.CurrentCodeBlockEndActions.Cast <CodeBlockAnalyzerAction>());
                executableNodeActions.AddRange(analyzerStateOpt.CurrentCodeBlockNodeActions.Cast <SyntaxNodeAnalyzerAction <TLanguageKindEnum> >());
            }
            else
            {
                // We have beginning to process the code block actions.
                blockEndActions.AddAll(codeBlockEndActions);
            }

            var addDiagnostic = GetAddDiagnostic(semanticModel.SyntaxTree, declaredNode.FullSpan, analyzer, isSyntaxDiagnostic: false);

            try
            {
                // Include the stateful actions.
                foreach (var da in codeBlockStartActions)
                {
                    if (ShouldExecuteAction(analyzerStateOpt, da))
                    {
                        // Catch Exception from the start action.
                        ExecuteAndCatchIfThrows(da.Analyzer, () =>
                        {
                            var codeBlockScope    = new HostCodeBlockStartAnalysisScope <TLanguageKindEnum>();
                            var blockStartContext = new AnalyzerCodeBlockStartAnalysisContext <TLanguageKindEnum>(da.Analyzer,
                                                                                                                  codeBlockScope, declaredNode, declaredSymbol, semanticModel, _analyzerOptions, _cancellationToken);
                            da.Action(blockStartContext);
                            blockEndActions.AddAll(codeBlockScope.CodeBlockEndActions);
                            executableNodeActions.AddRange(codeBlockScope.SyntaxNodeActions);
                        });

                        analyzerStateOpt?.ProcessedActions.Add(da);
                    }
                }
            }
            finally
            {
                if (analyzerStateOpt != null)
                {
                    analyzerStateOpt.CurrentCodeBlockEndActions  = blockEndActions.ToImmutableHashSet <AnalyzerAction>();
                    analyzerStateOpt.CurrentCodeBlockNodeActions = executableNodeActions.ToImmutableHashSet <AnalyzerAction>();
                }
            }

            // Execute stateful executable node analyzers, if any.
            if (executableNodeActions.Any())
            {
                var executableNodeActionsByKind = GetNodeActionsByKind(executableNodeActions);

                var nodesToAnalyze = executableCodeBlocks.SelectMany(cb => cb.DescendantNodesAndSelf());
                ExecuteSyntaxNodeActions(nodesToAnalyze, executableNodeActionsByKind, semanticModel, getKind, addDiagnostic, analyzerStateOpt?.ExecutableNodesAnalysisState);
            }

            executableNodeActions.Free();

            ExecuteCodeBlockActions(blockActions, declaredNode, declaredSymbol, semanticModel, addDiagnostic, analyzerStateOpt);
            ExecuteCodeBlockActions(blockEndActions, declaredNode, declaredSymbol, semanticModel, addDiagnostic, analyzerStateOpt);
        }