예제 #1
0
        internal void ExecuteCodeBlockActions <TLanguageKindEnum>(
            IEnumerable <CodeBlockStartAnalyzerAction <TLanguageKindEnum> > codeBlockStartActions,
            IEnumerable <CodeBlockAnalyzerAction> codeBlockActions,
            IEnumerable <CodeBlockAnalyzerAction> codeBlockEndActions,
            SyntaxNode declaredNode,
            ISymbol declaredSymbol,
            ImmutableArray <SyntaxNode> executableCodeBlocks,
            SemanticModel semanticModel,
            Func <SyntaxNode, TLanguageKindEnum> getKind)
            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.
            blockEndActions.AddAll(codeBlockEndActions);

            // Include the stateful actions.
            foreach (var da in codeBlockStartActions)
            {
                // 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);
                });
            }

            // 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);
            }

            executableNodeActions.Free();

            ExecuteCodeBlockActions(blockActions, declaredNode, declaredSymbol, semanticModel);
            ExecuteCodeBlockActions(blockEndActions, declaredNode, declaredSymbol, semanticModel);
        }
 internal AnalyzerCodeBlockStartAnalysisContext(DiagnosticAnalyzer analyzer,
                                                HostCodeBlockStartAnalysisScope <TLanguageKindEnum> scope,
                                                SyntaxNode codeBlock,
                                                ISymbol owningSymbol,
                                                SemanticModel semanticModel,
                                                AnalyzerOptions options,
                                                CancellationToken cancellationToken)
     : base(codeBlock, owningSymbol, semanticModel, options, cancellationToken)
 {
     _analyzer = analyzer;
     _scope    = scope;
 }
예제 #3
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);
        }
예제 #4
0
        internal static void ExecuteCodeBlockActions <TLanguageKindEnum>(
            IEnumerable <CodeBlockStartAnalyzerAction <TLanguageKindEnum> > codeBlockStartActions,
            IEnumerable <CodeBlockEndAnalyzerAction> codeBlockEndActions,
            SyntaxNode declaredNode,
            ISymbol declaredSymbol,
            ImmutableArray <SyntaxNode> executableCodeBlocks,
            AnalyzerOptions analyzerOptions,
            SemanticModel semanticModel,
            Action <Diagnostic> addDiagnostic,
            Func <Exception, DiagnosticAnalyzer, bool> continueOnAnalyzerException,
            Func <SyntaxNode, TLanguageKindEnum> getKind,
            CancellationToken cancellationToken)
            where TLanguageKindEnum : struct
        {
            Debug.Assert(declaredNode != null);
            Debug.Assert(declaredSymbol != null);
            Debug.Assert(CanHaveExecutableCodeBlock(declaredSymbol));
            Debug.Assert(codeBlockStartActions.Any() || codeBlockEndActions.Any());
            Debug.Assert(executableCodeBlocks.Any());

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

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

            // Include the stateless code block actions.
            endedActions.AddAll(codeBlockEndActions);

            // Include the stateful actions.
            foreach (var da in codeBlockStartActions)
            {
                // Catch Exception from the start action.
                ExecuteAndCatchIfThrows(da.Analyzer, addDiagnostic, continueOnAnalyzerException, () =>
                {
                    HostCodeBlockStartAnalysisScope <TLanguageKindEnum> codeBlockScope  = new HostCodeBlockStartAnalysisScope <TLanguageKindEnum>();
                    CodeBlockStartAnalysisContext <TLanguageKindEnum> blockStartContext = new AnalyzerCodeBlockStartAnalysisContext <TLanguageKindEnum>(da.Analyzer, codeBlockScope, declaredNode, declaredSymbol, semanticModel, analyzerOptions, cancellationToken);
                    da.Action(blockStartContext);
                    endedActions.AddAll(codeBlockScope.CodeBlockEndActions);
                    executableNodeActions.AddRange(codeBlockScope.SyntaxNodeActions);
                }, cancellationToken);
            }

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

                var nodesToAnalyze = executableCodeBlocks.SelectMany(cb => cb.DescendantNodesAndSelf());
                ExecuteSyntaxNodeActions(nodesToAnalyze, executableNodeActionsByKind, semanticModel,
                                         analyzerOptions, addDiagnostic, continueOnAnalyzerException, getKind, cancellationToken);
            }

            // Execute code block end actions.
            foreach (var a in endedActions)
            {
                // Catch Exception from a.OnCodeBlockEnded
                ExecuteAndCatchIfThrows(a.Analyzer, addDiagnostic, continueOnAnalyzerException, () => a.Action(new CodeBlockEndAnalysisContext(declaredNode, declaredSymbol, semanticModel, analyzerOptions, addDiagnostic, cancellationToken)), cancellationToken);
            }

            endedActions.Free();
            executableNodeActions.Free();
        }