Example #1
0
        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);
        }
Example #2
0
        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);
            }
        }