Esempio n. 1
0
 private Task ProcessSymbolDeclared(CompilationEvent.SymbolDeclared symbolEvent, CancellationToken cancellationToken)
 {
     try
     {
         return(AnalyzeSymbol(symbolEvent, cancellationToken));
     }
     finally
     {
         symbolEvent.FlushCache();
     }
 }
Esempio n. 2
0
        private Task AnalyzeSymbol(CompilationEvent.SymbolDeclared symbolEvent, CancellationToken cancellationToken)
        {
            var symbol = symbolEvent.Symbol;
            Action <Diagnostic> addDiagnostic = diagnostic => AddDiagnostic(diagnostic, symbol);
            var tasks = ArrayBuilder <Task> .GetInstance();

            if ((int)symbol.Kind < DeclarationAnalyzersByKind.Length)
            {
                foreach (var da in DeclarationAnalyzersByKind[(int)symbol.Kind])
                {
                    // TODO: is the overhead of creating tasks here too high compared to the cost of running them sequentially?
                    tasks.Add(Task.Run(() =>
                    {
                        // Catch Exception from da.AnalyzeSymbol
                        ExecuteAndCatchIfThrows(da, addDiagnostic, continueOnError, cancellationToken, () =>
                        {
                            cancellationToken.ThrowIfCancellationRequested();
                            da.AnalyzeSymbol(symbol, Compilation, addDiagnostic, cancellationToken);
                        });
                    }));
                }
            }

            // TODO: what about syntax references elsewhere, for example in a class base clause?
            switch (symbol.Kind)
            {
            // TODO: what about other syntax, such as base clauses, using directives, top-level attributes, etc?
            case SymbolKind.Method:
            case SymbolKind.Field:
            case SymbolKind.Event:     // TODO: should this be restricted to field-like events?
                foreach (var decl in symbol.DeclaringSyntaxReferences)
                {
                    tasks.Add(AnalyzeDeclaringReference(symbolEvent, decl, AddDiagnostic, cancellationToken));
                }
                break;
            }

            return(Task.WhenAll(tasks.ToImmutableAndFree()));
        }
Esempio n. 3
0
        private async Task AnalyzeDeclaringReference(CompilationEvent.SymbolDeclared symbolEvent, SyntaxReference decl, Action <Diagnostic> addDiagnostic, CancellationToken cancellationToken)
        {
            var symbol = symbolEvent.Symbol;
            var syntax = await decl.GetSyntaxAsync();

            var endedAnalyzers = ArrayBuilder <ICodeBlockEndedAnalyzer> .GetInstance();

            endedAnalyzers.AddRange(CodeBlockEndedAnalyzers);
            var nodeAnalyzers = ArrayBuilder <ISyntaxNodeAnalyzer <TSyntaxKind> > .GetInstance();

            nodeAnalyzers.AddRange(Analyzers.OfType <ISyntaxNodeAnalyzer <TSyntaxKind> >());
            foreach (var da in CodeBlockStartedAnalyzers)
            {
                // Catch Exception from da.OnCodeBlockStarted
                ExecuteAndCatchIfThrows(da, addDiagnostic, continueOnError, cancellationToken, () =>
                {
                    var blockStatefulAnalyzer = da.OnCodeBlockStarted(syntax, symbol, symbolEvent.SemanticModel(decl), addDiagnostic, cancellationToken);
                    var endedAnalyzer         = blockStatefulAnalyzer as ICodeBlockEndedAnalyzer;
                    if (endedAnalyzer != null)
                    {
                        endedAnalyzers.Add(endedAnalyzer);
                    }
                    var nodeAnalyzer = blockStatefulAnalyzer as ISyntaxNodeAnalyzer <TSyntaxKind>;
                    if (nodeAnalyzer != null)
                    {
                        nodeAnalyzers.Add(nodeAnalyzer);
                    }
                });
            }

            PooledDictionary <TSyntaxKind, ArrayBuilder <ISyntaxNodeAnalyzer <TSyntaxKind> > > nodeAnalyzersByKind = null;

            foreach (var nodeAnalyzer in nodeAnalyzers)
            {
                // Catch Exception from  nodeAnalyzer.SyntaxKindsOfInterest
                try
                {
                    foreach (var kind in nodeAnalyzer.SyntaxKindsOfInterest)
                    {
                        if (nodeAnalyzersByKind == null)
                        {
                            nodeAnalyzersByKind = PooledDictionary <TSyntaxKind, ArrayBuilder <ISyntaxNodeAnalyzer <TSyntaxKind> > > .GetInstance();
                        }
                        ArrayBuilder <ISyntaxNodeAnalyzer <TSyntaxKind> > analyzersForKind;
                        if (!nodeAnalyzersByKind.TryGetValue(kind, out analyzersForKind))
                        {
                            nodeAnalyzersByKind.Add(kind, analyzersForKind = ArrayBuilder <ISyntaxNodeAnalyzer <TSyntaxKind> > .GetInstance());
                        }
                        analyzersForKind.Add(nodeAnalyzer);
                    }
                }
                catch (Exception e)
                {
                    // Create a info diagnostic saying that the analyzer failed
                    addDiagnostic(GetAnalyzerDiagnostic(nodeAnalyzer, e));
                }
            }
            nodeAnalyzers.Free();

            SemanticModel semanticModel = (nodeAnalyzersByKind != null || endedAnalyzers.Any()) ? symbolEvent.SemanticModel(decl) : null;

            if (nodeAnalyzersByKind != null)
            {
                semanticModel = symbolEvent.SemanticModel(decl);
                foreach (var child in syntax.DescendantNodesAndSelf())
                {
                    ArrayBuilder <ISyntaxNodeAnalyzer <TSyntaxKind> > analyzersForKind;
                    if (nodeAnalyzersByKind.TryGetValue(GetKind(child), out analyzersForKind))
                    {
                        foreach (var analyzer in analyzersForKind)
                        {
                            // Catch Exception from analyzer.AnalyzeNode
                            ExecuteAndCatchIfThrows(analyzer, addDiagnostic, continueOnError, cancellationToken, () => { analyzer.AnalyzeNode(child, semanticModel, addDiagnostic, cancellationToken); });
                        }
                    }
                }

                foreach (var b in nodeAnalyzersByKind.Values)
                {
                    b.Free();
                }
                nodeAnalyzersByKind.Free();
            }

            foreach (var a in endedAnalyzers)
            {
                // Catch Exception from a.OnCodeBlockEnded
                ExecuteAndCatchIfThrows(a, addDiagnostic, continueOnError, cancellationToken, () => { a.OnCodeBlockEnded(syntax, symbol, semanticModel, addDiagnostic, cancellationToken); });
            }
            endedAnalyzers.Free();
        }