private static void ProcessBodies <TSyntaxKind>( SemanticModel model, ImmutableArray <IDiagnosticAnalyzer> analyzers, CancellationToken cancellationToken, ImmutableArray <SemanticModel.DeclarationInSpan> declarations, Action <Diagnostic> addDiagnostic, AnalyzerOptions analyzerOptions, bool continueOnError, Func <SyntaxNode, TSyntaxKind> getKind) { var bodyAnalyzers = analyzers.OfType <ICodeBlockStartedAnalyzer>().ToArray(); // process the bodies foreach (var d in declarations) { if (d.Body == null) { continue; } ISymbol symbol = model.GetDeclaredSymbolForNode(d.Declaration, cancellationToken); if (symbol == null) { continue; } var addBodyDiagnostic = GetDiagnosticSinkWithSuppression(model.Compilation, addDiagnostic, symbol); ProcessBody <TSyntaxKind>(model, analyzers, bodyAnalyzers, symbol, d.Body, cancellationToken, addBodyDiagnostic, analyzerOptions, continueOnError, getKind); } }
private static void RunAnalyzersCoreInternal <TSyntaxKind>( SemanticModel model, TextSpan span, ImmutableArray <IDiagnosticAnalyzer> analyzers, Func <SyntaxNode, TSyntaxKind> getKind, Action <Diagnostic> addDiagnosticWithLocationFilter, AnalyzerOptions analyzerOptions, bool continueOnError, CancellationToken cancellationToken = default(CancellationToken)) { if (analyzers.Length == 0) { return; } // execute the symbol based analyzers. var declarations = model.DeclarationsInSpanInternal(span); var declarationAnalyzers = analyzers.OfType <ISymbolAnalyzer>(); foreach (var d in declarations) { ISymbol symbol = model.GetDeclaredSymbolForNode(d.Declaration, cancellationToken); if (symbol == null || symbol.DeclaringSyntaxReferences.Length > 1 && !d.Declaration.Span.OverlapsWith(symbol.DeclaringSyntaxReferences[0].Span)) { continue; } var namespaceSymbol = symbol as INamespaceSymbol; if (namespaceSymbol != null) { // process implicitly declared parent namespaces for (var ns = namespaceSymbol.ContainingNamespace; ns != null; ns = ns.ContainingNamespace) { bool isImplicitlyDeclaredParent = ns.DeclaringSyntaxReferences .Where(r => r.SyntaxTree == model.SyntaxTree && r.Span.OverlapsWith(d.Declaration.Span)) .FirstOrDefault() != null; if (isImplicitlyDeclaredParent) { var addNamespaceDiagnostic = GetDiagnosticSinkWithSuppression(model.Compilation, addDiagnosticWithLocationFilter, ns); foreach (var da in declarationAnalyzers) { // Catch Exception from da.SymbolKindsOfInterest and da.AnalyzeSymbol ExecuteAndCatchIfThrows(da, addDiagnosticWithLocationFilter, continueOnError, cancellationToken, () => { if (da.SymbolKindsOfInterest.Contains(SymbolKind.Namespace)) { cancellationToken.ThrowIfCancellationRequested(); da.AnalyzeSymbol(ns, model.Compilation, addNamespaceDiagnostic, analyzerOptions, cancellationToken); } }); } } } } var addSymbolDiagnostic = GetDiagnosticSinkWithSuppression(model.Compilation, addDiagnosticWithLocationFilter, symbol); foreach (var da in declarationAnalyzers) { // Catch Exception from da.SymbolKindsOfInterest and da.AnalyzeSymbol ExecuteAndCatchIfThrows(da, addDiagnosticWithLocationFilter, continueOnError, cancellationToken, () => { cancellationToken.ThrowIfCancellationRequested(); if (da.SymbolKindsOfInterest.Contains(symbol.Kind)) { da.AnalyzeSymbol(symbol, model.Compilation, addSymbolDiagnostic, analyzerOptions, cancellationToken); } }); } } // execute the tree based analyzers. var addTreeAnalyzerDiagnostic = GetDiagnosticSinkWithSuppression(model.Compilation, addDiagnosticWithLocationFilter, symbolOpt: null); foreach (var a in analyzers.OfType <ISemanticModelAnalyzer>()) { // Catch Exception from a.AnalyzeSemanticModel ExecuteAndCatchIfThrows(a, addDiagnosticWithLocationFilter, continueOnError, cancellationToken, () => { a.AnalyzeSemanticModel(model, addTreeAnalyzerDiagnostic, analyzerOptions, cancellationToken); }); } foreach (var a in analyzers.OfType <ISyntaxTreeAnalyzer>()) { // Catch Exception from a.AnalyzeSyntaxTree ExecuteAndCatchIfThrows(a, addDiagnosticWithLocationFilter, continueOnError, cancellationToken, () => { a.AnalyzeSyntaxTree(model.SyntaxTree, addTreeAnalyzerDiagnostic, analyzerOptions, cancellationToken); }); } // execute the executable code based analyzers. ProcessBodies(model, analyzers, cancellationToken, declarations, addDiagnosticWithLocationFilter, analyzerOptions, continueOnError, getKind); }