/// <summary> /// Return true if the given <paramref name="analyzer"/> is suppressed for the given project. /// NOTE: This API is intended to be used only for performance optimization. /// </summary> public bool IsAnalyzerSuppressed(DiagnosticAnalyzer analyzer, Project project) { var options = project.CompilationOptions; if ( options == null || analyzer == FileContentLoadAnalyzer.Instance || analyzer.IsCompilerAnalyzer() ) { return(false); } // If user has disabled analyzer execution for this project, we only want to execute required analyzers // that report diagnostics with category "Compiler". if ( !project.State.RunAnalyzers && GetDiagnosticDescriptors(analyzer) .All(d => d.Category != DiagnosticCategory.Compiler) ) { return(true); } // NOTE: Previously we used to return "CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(options)" // on this code path, which returns true if analyzer is suppressed through compilation options. // However, this check is no longer correct as analyzers can be enabled/disabled for individual // documents through .editorconfig files. So we pessimistically assume analyzer is not suppressed // and let the core analyzer driver in the compiler layer handle skipping redundant analysis callbacks. return(false); }
private static bool IsTelemetryCollectionAllowed( DiagnosticAnalyzer analyzer, ImmutableArray <DiagnosticDescriptor> descriptors ) => analyzer.IsCompilerAnalyzer() || analyzer is IBuiltInAnalyzer || descriptors.Length > 0 && descriptors[0].CustomTags.Any(t => t == WellKnownDiagnosticTags.Telemetry);
/// <summary> /// Return true if the given <paramref name="analyzer"/> is suppressed for the given project. /// </summary> public bool IsAnalyzerSuppressed(DiagnosticAnalyzer analyzer, Project project) { var options = project.CompilationOptions; if (options == null || analyzer.IsCompilerAnalyzer()) { return(false); } // Skip telemetry logging for supported diagnostics, as that can cause an infinite loop. Action <Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = (ex, a, diagnostic) => AnalyzerHelper.OnAnalyzerException_NoTelemetryLogging(ex, a, diagnostic, _hostDiagnosticUpdateSource, project.Id); return(CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(analyzer, options, onAnalyzerException)); }
private async Task <ImmutableArray <DiagnosticData> > GetCompilerAnalyzerDiagnosticsAsync(DiagnosticAnalyzer analyzer, TextSpan?span, CancellationToken cancellationToken) { RoslynDebug.Assert(analyzer.IsCompilerAnalyzer()); RoslynDebug.Assert(_compilationWithAnalyzers != null); RoslynDebug.Assert(_compilationBasedAnalyzersInAnalysisScope.Contains(analyzer)); RoslynDebug.Assert(AnalysisScope.TextDocument is Document); var analysisScope = AnalysisScope.WithAnalyzers(ImmutableArray.Create(analyzer)).WithSpan(span); var analysisResult = await GetAnalysisResultAsync(analysisScope, cancellationToken).ConfigureAwait(false); if (!analysisResult.TryGetValue(analyzer, out var result)) { return(ImmutableArray <DiagnosticData> .Empty); } return(result.GetDocumentDiagnostics(analysisScope.TextDocument.Id, analysisScope.Kind)); }
public static bool IsBuiltInAnalyzer(this DiagnosticAnalyzer analyzer) => analyzer is IBuiltInAnalyzer || analyzer.IsWorkspaceDiagnosticAnalyzer() || analyzer.IsCompilerAnalyzer();
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); }
/// <summary> /// Return true if the given <paramref name="analyzer"/> is suppressed for the given project. /// </summary> public bool IsAnalyzerSuppressed(DiagnosticAnalyzer analyzer, Project project) { var options = project.CompilationOptions; if (options == null || analyzer.IsCompilerAnalyzer()) { return false; } // Skip telemetry logging for supported diagnostics, as that can cause an infinite loop. Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = (ex, a, diagnostic) => AnalyzerHelper.OnAnalyzerException_NoTelemetryLogging(ex, a, diagnostic, _hostDiagnosticUpdateSource, project.Id); return CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(analyzer, options, onAnalyzerException); }
public static bool IsBuiltInAnalyzer(this DiagnosticAnalyzer analyzer) { return(analyzer is IBuiltInAnalyzer || analyzer is DocumentDiagnosticAnalyzer || analyzer is ProjectDiagnosticAnalyzer || analyzer.IsCompilerAnalyzer()); }
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); } }