public async Task <IEnumerable <DiagnosticData> > ComputeDiagnosticsAsync(DiagnosticAnalyzer analyzer, CancellationToken cancellationToken) { Contract.ThrowIfFalse(AnalysisScope.Analyzers.Contains(analyzer)); var textDocument = AnalysisScope.TextDocument; var span = AnalysisScope.Span; var kind = AnalysisScope.Kind; var document = textDocument as Document; RoslynDebug.Assert(document != null || kind == AnalysisKind.Syntax, "We only support syntactic analysis for non-source documents"); var loadDiagnostic = await textDocument.State.GetLoadDiagnosticAsync(cancellationToken).ConfigureAwait(false); if (analyzer == FileContentLoadAnalyzer.Instance) { return(loadDiagnostic != null? SpecializedCollections.SingletonEnumerable(DiagnosticData.Create(loadDiagnostic, textDocument)) : SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } if (loadDiagnostic != null) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } if (analyzer is DocumentDiagnosticAnalyzer documentAnalyzer) { if (document == null) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } var documentDiagnostics = await AnalyzerHelper.ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync( documentAnalyzer, document, kind, _compilationWithAnalyzers?.Compilation, cancellationToken).ConfigureAwait(false); return(documentDiagnostics.ConvertToLocalDiagnostics(document, span)); } // quick optimization to reduce allocations. if (_compilationWithAnalyzers == null || !analyzer.SupportAnalysisKind(kind)) { if (kind == AnalysisKind.Syntax) { Logger.Log(FunctionId.Diagnostics_SyntaxDiagnostic, (r, d, a, k) => $"Driver: {r != null}, {d.Id}, {d.Project.Id}, {a}, {k}", _compilationWithAnalyzers, textDocument, analyzer, kind); } return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } // if project is not loaded successfully then, we disable semantic errors for compiler analyzers var isCompilerAnalyzer = analyzer.IsCompilerAnalyzer(); if (kind != AnalysisKind.Syntax && isCompilerAnalyzer) { var isEnabled = await textDocument.Project.HasSuccessfullyLoadedAsync(cancellationToken).ConfigureAwait(false); Logger.Log(FunctionId.Diagnostics_SemanticDiagnostic, (a, d, e) => $"{a}, ({d.Id}, {d.Project.Id}), Enabled:{e}", analyzer, textDocument, isEnabled); if (!isEnabled) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } } if (document == null && textDocument is not AdditionalDocument) { // We currently support document analysis only for source documents and additional documents. return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } var diagnostics = kind switch { AnalysisKind.Syntax => await GetSyntaxDiagnosticsAsync(analyzer, isCompilerAnalyzer, cancellationToken).ConfigureAwait(false), AnalysisKind.Semantic => await GetSemanticDiagnosticsAsync(analyzer, isCompilerAnalyzer, cancellationToken).ConfigureAwait(false), _ => throw ExceptionUtilities.UnexpectedValue(kind), }; #if DEBUG var diags = await diagnostics.ToDiagnosticsAsync(textDocument.Project, cancellationToken).ConfigureAwait(false); Debug.Assert(diags.Length == CompilationWithAnalyzers.GetEffectiveDiagnostics(diags, _compilationWithAnalyzers.Compilation).Count()); Debug.Assert(diagnostics.Length == diags.ConvertToLocalDiagnostics(textDocument, span).Count()); #endif return(diagnostics); }
public async Task <IEnumerable <DiagnosticData> > ComputeDiagnosticsAsync(DiagnosticAnalyzer analyzer, CancellationToken cancellationToken) { Contract.ThrowIfFalse(AnalysisScope.Analyzers.Contains(analyzer)); var document = AnalysisScope.Document; var span = AnalysisScope.Span; var kind = AnalysisScope.Kind; var loadDiagnostic = await document.State.GetLoadDiagnosticAsync(cancellationToken).ConfigureAwait(false); if (analyzer == FileContentLoadAnalyzer.Instance) { return(loadDiagnostic != null? SpecializedCollections.SingletonEnumerable(DiagnosticData.Create(loadDiagnostic, document)) : SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } if (loadDiagnostic != null) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } if (analyzer is DocumentDiagnosticAnalyzer documentAnalyzer) { var diagnostics = await AnalyzerHelper.ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync( documentAnalyzer, document, kind, _compilationWithAnalyzers?.Compilation, cancellationToken).ConfigureAwait(false); return(diagnostics.ConvertToLocalDiagnostics(document, span)); } // quick optimization to reduce allocations. if (_compilationWithAnalyzers == null || !analyzer.SupportAnalysisKind(kind)) { if (kind == AnalysisKind.Syntax) { Logger.Log(FunctionId.Diagnostics_SyntaxDiagnostic, (r, d, a, k) => $"Driver: {r != null}, {d.Id}, {d.Project.Id}, {a}, {k}", _compilationWithAnalyzers, document, analyzer, kind); } return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } // if project is not loaded successfully then, we disable semantic errors for compiler analyzers var isCompilerAnalyzer = analyzer.IsCompilerAnalyzer(); if (kind != AnalysisKind.Syntax && isCompilerAnalyzer) { var isEnabled = await document.Project.HasSuccessfullyLoadedAsync(cancellationToken).ConfigureAwait(false); Logger.Log(FunctionId.Diagnostics_SemanticDiagnostic, (a, d, e) => $"{a}, ({d.Id}, {d.Project.Id}), Enabled:{e}", analyzer, document, isEnabled); if (!isEnabled) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } } var skippedAnalyzerInfo = document.Project.GetSkippedAnalyzersInfo(_analyzerInfoCache); ImmutableArray <string> filteredIds; switch (kind) { case AnalysisKind.Syntax: var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (tree == null) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } var diagnostics = await GetSyntaxDiagnosticsAsync(tree, analyzer, isCompilerAnalyzer, cancellationToken).ConfigureAwait(false); if (diagnostics.IsDefaultOrEmpty) { Logger.Log(FunctionId.Diagnostics_SyntaxDiagnostic, (d, a, t) => $"{d.Id}, {d.Project.Id}, {a}, {t.Length}", document, analyzer, tree); } else if (skippedAnalyzerInfo.FilteredDiagnosticIdsForAnalyzers.TryGetValue(analyzer, out filteredIds)) { diagnostics = diagnostics.Filter(filteredIds); } Debug.Assert(diagnostics.Length == CompilationWithAnalyzers.GetEffectiveDiagnostics(diagnostics, _compilationWithAnalyzers.Compilation).Count()); return(diagnostics.ConvertToLocalDiagnostics(document, span)); case AnalysisKind.Semantic: var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model == null) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } diagnostics = await GetSemanticDiagnosticsAsync(model, analyzer, isCompilerAnalyzer, cancellationToken).ConfigureAwait(false); if (skippedAnalyzerInfo.FilteredDiagnosticIdsForAnalyzers.TryGetValue(analyzer, out filteredIds)) { diagnostics = diagnostics.Filter(filteredIds); } Debug.Assert(diagnostics.Length == CompilationWithAnalyzers.GetEffectiveDiagnostics(diagnostics, _compilationWithAnalyzers.Compilation).Count()); return(diagnostics.ConvertToLocalDiagnostics(document, span)); default: throw ExceptionUtilities.UnexpectedValue(kind); } }