public async Task <AnalysisData> GetProjectAnalysisDataAsync(DiagnosticAnalyzerDriver analyzerDriver, StateSet stateSet, VersionArgument versions)
            {
                try
                {
                    var project           = analyzerDriver.Project;
                    var cancellationToken = analyzerDriver.CancellationToken;

                    var state        = stateSet.GetState(StateType.Project);
                    var existingData = await state.TryGetExistingDataAsync(project, cancellationToken).ConfigureAwait(false);

                    if (CheckSemanticVersions(project, existingData, versions))
                    {
                        return(existingData);
                    }

                    // TODO: remove ForceAnalyzeAllDocuments at some point
                    var diagnosticData = await GetProjectDiagnosticsAsync(analyzerDriver, stateSet.Analyzer, _owner.ForceAnalyzeAllDocuments).ConfigureAwait(false);

                    return(new AnalysisData(VersionStamp.Default, versions.DataVersion, GetExistingItems(existingData), diagnosticData.AsImmutableOrEmpty()));
                }
                catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
예제 #2
0
        private bool ShouldRunAnalyzerForStateType(DiagnosticAnalyzerDriver driver, DiagnosticAnalyzer analyzer,
                                                   StateType stateTypeId, ImmutableHashSet <string> diagnosticIds)
        {
            bool discarded;

            return(ShouldRunAnalyzerForStateType(driver, analyzer, stateTypeId, out discarded, diagnosticIds, Owner.GetDiagnosticDescriptors));
        }
예제 #3
0
            public async Task <AnalysisData> GetDocumentBodyAnalysisDataAsync(
                StateSet stateSet, VersionArgument versions, DiagnosticAnalyzerDriver analyzerDriver,
                SyntaxNode root, SyntaxNode member, int memberId, bool supportsSemanticInSpan, MemberRangeMap.MemberRanges ranges)
            {
                try
                {
                    var document          = analyzerDriver.Document;
                    var cancellationToken = analyzerDriver.CancellationToken;

                    var state        = stateSet.GetState(StateType.Document);
                    var existingData = await state.TryGetExistingDataAsync(document, cancellationToken).ConfigureAwait(false);

                    ImmutableArray <DiagnosticData> diagnosticData;
                    if (supportsSemanticInSpan && CanUseRange(memberId, ranges.Ranges) && CanUseDocumentState(existingData, ranges.TextVersion, versions.DataVersion))
                    {
                        var memberDxData = await GetSemanticDiagnosticsAsync(analyzerDriver, stateSet.Analyzer).ConfigureAwait(false);

                        diagnosticData = _owner.UpdateDocumentDiagnostics(existingData, ranges.Ranges, memberDxData.AsImmutableOrEmpty(), root.SyntaxTree, member, memberId);
                        ValidateMemberDiagnostics(stateSet.Analyzer, document, root, diagnosticData);
                    }
                    else
                    {
                        // if we can't re-use existing document state, only option we have is updating whole document state here.
                        var dx = await GetSemanticDiagnosticsAsync(analyzerDriver, stateSet.Analyzer).ConfigureAwait(false);

                        diagnosticData = dx.AsImmutableOrEmpty();
                    }

                    return(new AnalysisData(versions.TextVersion, versions.DataVersion, GetExistingItems(existingData), diagnosticData));
                }
                catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
            public async Task<AnalysisData> GetDocumentBodyAnalysisDataAsync(
                StateSet stateSet, VersionArgument versions, DiagnosticAnalyzerDriver analyzerDriver,
                SyntaxNode root, SyntaxNode member, int memberId, bool supportsSemanticInSpan, MemberRangeMap.MemberRanges ranges)
            {
                try
                {
                    var document = analyzerDriver.Document;
                    var cancellationToken = analyzerDriver.CancellationToken;

                    var state = stateSet.GetState(StateType.Document);
                    var existingData = await state.TryGetExistingDataAsync(document, cancellationToken).ConfigureAwait(false);

                    ImmutableArray<DiagnosticData> diagnosticData;
                    if (supportsSemanticInSpan && CanUseRange(memberId, ranges.Ranges) && CanUseDocumentState(existingData, ranges.TextVersion, versions.DataVersion))
                    {
                        var memberDxData = await GetSemanticDiagnosticsAsync(analyzerDriver, stateSet.Analyzer).ConfigureAwait(false);

                        diagnosticData = _owner.UpdateDocumentDiagnostics(existingData, ranges.Ranges, memberDxData.AsImmutableOrEmpty(), root.SyntaxTree, member, memberId);
                        ValidateMemberDiagnostics(stateSet.Analyzer, document, root, diagnosticData);
                    }
                    else
                    {
                        // if we can't re-use existing document state, only option we have is updating whole document state here.
                        var dx = await GetSemanticDiagnosticsAsync(analyzerDriver, stateSet.Analyzer).ConfigureAwait(false);
                        diagnosticData = dx.AsImmutableOrEmpty();
                    }
                    return new AnalysisData(versions.TextVersion, versions.DataVersion, GetExistingItems(existingData), diagnosticData);
                }
                catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
            public LatestDiagnosticsForSpanGetter(
                DiagnosticIncrementalAnalyzer owner, Document document, SyntaxNode root, TextSpan range, bool blockForData, List <DiagnosticData> diagnostics, bool includeSuppressedDiagnostics, CancellationToken cancellationToken)
            {
                _owner = owner;

                _document         = document;
                _compilerAnalyzer = _owner.HostAnalyzerManager.GetCompilerDiagnosticAnalyzer(_document.Project.Language);

                _range        = range;
                _blockForData = blockForData;
                _includeSuppressedDiagnostics = includeSuppressedDiagnostics;
                _cancellationToken            = cancellationToken;

                Diagnostics = diagnostics;

                // Share the diagnostic analyzer driver across all analyzers.
                var fullSpan = root?.FullSpan;

                // We are computing diagnostics for a single document/span, so we don't need to enable concurrent analysis.
                const bool concurrentAnalysis          = false;
                const bool reportSuppressedDiagnostics = true;

                _spanBasedDriver     = new DiagnosticAnalyzerDriver(_document, _range, root, _owner, concurrentAnalysis, reportSuppressedDiagnostics, _cancellationToken);
                _documentBasedDriver = new DiagnosticAnalyzerDriver(_document, fullSpan, root, _owner, concurrentAnalysis, reportSuppressedDiagnostics, _cancellationToken);
                _projectDriver       = new DiagnosticAnalyzerDriver(_document.Project, _owner, concurrentAnalysis, reportSuppressedDiagnostics, _cancellationToken);
            }
예제 #6
0
        private static bool ShouldRunAnalyzerForStateType(DiagnosticAnalyzerDriver driver, DiagnosticAnalyzer analyzer, StateType stateTypeId,
                                                          out bool supportsSemanticInSpan, ImmutableHashSet <string> diagnosticIds = null, Func <DiagnosticAnalyzer, ImmutableArray <DiagnosticDescriptor> > getDescriptor = null)
        {
            Debug.Assert(!driver.IsAnalyzerSuppressed(analyzer));

            supportsSemanticInSpan = false;
            if (diagnosticIds != null && getDescriptor(analyzer).All(d => !diagnosticIds.Contains(d.Id)))
            {
                return(false);
            }

            switch (stateTypeId)
            {
            case StateType.Syntax:
                return(analyzer.SupportsSyntaxDiagnosticAnalysis(driver));

            case StateType.Document:
                return(analyzer.SupportsSemanticDiagnosticAnalysis(driver, out supportsSemanticInSpan));

            case StateType.Project:
                return(analyzer.SupportsProjectDiagnosticAnalysis(driver));

            default:
                throw ExceptionUtilities.Unreachable;
            }
        }
            private void ValidateMemberDiagnostics(DiagnosticAnalyzer analyzer, Document document, SyntaxNode root, ImmutableArray <DiagnosticData> diagnostics)
            {
#if RANGE
                var documentBasedDriver = new DiagnosticAnalyzerDriver(document, root.FullSpan, root, this, ConcurrentAnalysis, ReportSuppressedDiagnostics, CancellationToken.None);
                var expected            = GetSemanticDiagnosticsAsync(documentBasedDriver, analyzer).WaitAndGetResult(documentBasedDriver.CancellationToken) ?? SpecializedCollections.EmptyEnumerable <DiagnosticData>();
                Contract.Requires(diagnostics.SetEquals(expected));
#endif
            }
            private static async Task <ImmutableArray <DiagnosticData> > UpdateAllSemanticDiagnosticsAsync(
                StateSet stateSet, DiagnosticAnalyzerDriver analyzerDriver, ImmutableArray <DiagnosticData> diagnosticData)
            {
                var dx = await GetSemanticDiagnosticsAsync(analyzerDriver, stateSet.Analyzer).ConfigureAwait(false);

                diagnosticData = dx.AsImmutableOrEmpty();
                return(diagnosticData);
            }
예제 #9
0
        private async Task AnalyzeSyntaxAsync(Document document, ImmutableHashSet <string> diagnosticIds, bool skipClosedFileChecks, CancellationToken cancellationToken)
        {
            try
            {
                if (!skipClosedFileChecks && !CheckOption(document.Project.Solution.Workspace, document.Project.Language, document.IsOpen()))
                {
                    return;
                }

                var textVersion = await document.GetTextVersionAsync(cancellationToken).ConfigureAwait(false);

                var dataVersion = await document.GetSyntaxVersionAsync(cancellationToken).ConfigureAwait(false);

                var versions = new VersionArgument(textVersion, dataVersion);

                var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var fullSpan = root == null ? null : (TextSpan?)root.FullSpan;

                var userDiagnosticDriver = new DiagnosticAnalyzerDriver(document, fullSpan, root, _diagnosticLogAggregator, cancellationToken);
                var options        = document.Project.CompilationOptions;
                var openedDocument = document.IsOpen();

                foreach (var providerAndId in await _analyzersAndState.GetAllProviderAndIdsAsync(document.Project, cancellationToken).ConfigureAwait(false))
                {
                    var provider   = providerAndId.Key;
                    var providerId = providerAndId.Value;

                    if (IsAnalyzerSuppressed(provider, options, userDiagnosticDriver))
                    {
                        await HandleSuppressedAnalyzerAsync(document, StateType.Syntax, providerId, provider, cancellationToken).ConfigureAwait(false);
                    }
                    else if (ShouldRunProviderForStateType(StateType.Syntax, provider, userDiagnosticDriver, diagnosticIds) &&
                             (skipClosedFileChecks || ShouldRunProviderForClosedFile(openedDocument, provider)))
                    {
                        var data = await _executor.GetSyntaxAnalysisDataAsync(provider, providerId, versions, userDiagnosticDriver).ConfigureAwait(false);

                        if (data.FromCache)
                        {
                            RaiseDiagnosticsUpdated(StateType.Syntax, document.Id, providerId, new SolutionArgument(document), data.Items);
                            continue;
                        }

                        var state = _analyzersAndState.GetOrCreateDiagnosticState(StateType.Syntax, providerId, provider, document.Project.Id, document.Project.Language);
                        await state.PersistAsync(document, data.ToPersistData(), cancellationToken).ConfigureAwait(false);

                        RaiseDiagnosticsUpdatedIfNeeded(StateType.Syntax, document, providerId, data.OldItems, data.Items);
                    }
                }
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
예제 #10
0
        private async Task AnalyzeProjectAsync(Project project, CancellationToken cancellationToken)
        {
            try
            {
                // Compilation actions can report diagnostics on open files, so "documentOpened = true"
                if (!CheckOption(project.Solution.Workspace, project.Language, documentOpened: true))
                {
                    return;
                }

                var projectTextVersion = await project.GetLatestDocumentVersionAsync(cancellationToken).ConfigureAwait(false);

                var semanticVersion = await project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);

                var projectVersion = await project.GetDependentVersionAsync(cancellationToken).ConfigureAwait(false);

                var analyzerDriver = new DiagnosticAnalyzerDriver(project, this, cancellationToken);

                var versions = new VersionArgument(projectTextVersion, semanticVersion, projectVersion);
                foreach (var stateSet in _stateManager.GetOrUpdateStateSets(project))
                {
                    // Compilation actions can report diagnostics on open files, so we skipClosedFileChecks.
                    if (SkipRunningAnalyzer(project.CompilationOptions, analyzerDriver, openedDocument: true, skipClosedFileChecks: true, stateSet: stateSet))
                    {
                        await ClearExistingDiagnostics(project, stateSet, cancellationToken).ConfigureAwait(false);

                        continue;
                    }

                    if (ShouldRunAnalyzerForStateType(stateSet.Analyzer, StateType.Project, diagnosticIds: null))
                    {
                        var data = await _executor.GetProjectAnalysisDataAsync(analyzerDriver, stateSet, versions).ConfigureAwait(false);

                        if (data.FromCache)
                        {
                            RaiseProjectDiagnosticsUpdated(project, stateSet, data.Items);
                            continue;
                        }

                        var state = stateSet.GetState(StateType.Project);
                        await PersistProjectData(project, state, data).ConfigureAwait(false);

                        RaiseProjectDiagnosticsUpdatedIfNeeded(project, stateSet, data.OldItems, data.Items);
                    }
                }

                _solutionCrawlerAnalysisState.OnProjectAnalyzed(project);
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
예제 #11
0
        private async Task AnalyzeSyntaxAsync(Document document, ImmutableHashSet <string> diagnosticIds, bool skipClosedFileChecks, CancellationToken cancellationToken)
        {
            try
            {
                if (!skipClosedFileChecks && !CheckOption(document.Project.Solution.Workspace, document.Project.Language, document.IsOpen()))
                {
                    return;
                }

                var textVersion = await document.GetTextVersionAsync(cancellationToken).ConfigureAwait(false);

                var dataVersion = await document.GetSyntaxVersionAsync(cancellationToken).ConfigureAwait(false);

                var versions = new VersionArgument(textVersion, dataVersion);

                var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var fullSpan = root == null ? null : (TextSpan?)root.FullSpan;

                var userDiagnosticDriver = new DiagnosticAnalyzerDriver(document, fullSpan, root, this, cancellationToken);
                var openedDocument       = document.IsOpen();

                foreach (var stateSet in _stateManager.GetOrUpdateStateSets(document.Project))
                {
                    if (SkipRunningAnalyzer(document.Project.CompilationOptions, userDiagnosticDriver, openedDocument, skipClosedFileChecks, stateSet))
                    {
                        await ClearExistingDiagnostics(document, stateSet, StateType.Syntax, cancellationToken).ConfigureAwait(false);

                        continue;
                    }

                    if (ShouldRunAnalyzerForStateType(stateSet.Analyzer, StateType.Syntax, diagnosticIds))
                    {
                        var data = await _executor.GetSyntaxAnalysisDataAsync(userDiagnosticDriver, stateSet, versions).ConfigureAwait(false);

                        if (data.FromCache)
                        {
                            RaiseDiagnosticsUpdated(StateType.Syntax, document.Id, stateSet, new SolutionArgument(document), data.Items);
                            continue;
                        }

                        var state = stateSet.GetState(StateType.Syntax);
                        await state.PersistAsync(document, data.ToPersistData(), cancellationToken).ConfigureAwait(false);

                        RaiseDocumentDiagnosticsUpdatedIfNeeded(StateType.Syntax, document, stateSet, data.OldItems, data.Items);
                    }
                }
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
예제 #12
0
        private async Task <bool> TryGetLatestDiagnosticsAsync(
            StateSet stateSet, StateType stateType, Document document, TextSpan range, SyntaxNode root,
            List <DiagnosticData> diagnostics, bool requireUpToDateDocumentDiagnostic,
            Func <VersionStamp, VersionStamp, bool> versionCheck,
            Func <DiagnosticAnalyzerDriver, DiagnosticAnalyzer, Task <IEnumerable <DiagnosticData> > > getDiagnostics,
            bool supportsSemanticInSpan,
            DiagnosticAnalyzerDriver userDiagnosticDriver,
            CancellationToken cancellationToken)
        {
            try
            {
                var shouldInclude = (Func <DiagnosticData, bool>)(d => range.IntersectsWith(d.TextSpan));

                // make sure we get state even when none of our analyzer has ran yet.
                // but this shouldn't create analyzer that doesnt belong to this project (language)
                var state = stateSet.GetState(stateType);

                // see whether we can use existing info
                var existingData = await state.TryGetExistingDataAsync(document, cancellationToken).ConfigureAwait(false);

                if (existingData != null && versionCheck(existingData.TextVersion, existingData.DataVersion))
                {
                    if (existingData.Items == null)
                    {
                        return(true);
                    }

                    diagnostics.AddRange(existingData.Items.Where(shouldInclude));
                    return(true);
                }

                // check whether we want up-to-date document wide diagnostics
                if (stateType == StateType.Document && !supportsSemanticInSpan && !requireUpToDateDocumentDiagnostic)
                {
                    return(false);
                }

                var dx = await getDiagnostics(userDiagnosticDriver, stateSet.Analyzer).ConfigureAwait(false);

                if (dx != null)
                {
                    // no state yet
                    diagnostics.AddRange(dx.Where(shouldInclude));
                }

                return(true);
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
예제 #13
0
        private async Task AnalyzeBodyDocumentAsync(Document document, SyntaxNode member, VersionArgument versions, CancellationToken cancellationToken)
        {
            try
            {
                // syntax facts service must exist, otherwise, this method won't have called.
                var syntaxFacts = document.Project.LanguageServices.GetService <ISyntaxFactsService>();
                var root        = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var memberId = syntaxFacts.GetMethodLevelMemberId(root, member);

                var spanBasedDriver     = new DiagnosticAnalyzerDriver(document, member.FullSpan, root, _diagnosticLogAggregator, cancellationToken);
                var documentBasedDriver = new DiagnosticAnalyzerDriver(document, root.FullSpan, root, _diagnosticLogAggregator, cancellationToken);
                var options             = document.Project.CompilationOptions;

                foreach (var providerAndId in await _analyzersAndState.GetAllProviderAndIdsAsync(document.Project, cancellationToken).ConfigureAwait(false))
                {
                    var provider   = providerAndId.Key;
                    var providerId = providerAndId.Value;

                    bool supportsSemanticInSpan;
                    if (IsAnalyzerSuppressed(provider, options, spanBasedDriver))
                    {
                        await HandleSuppressedAnalyzerAsync(document, StateType.Document, providerId, provider, cancellationToken).ConfigureAwait(false);
                    }
                    else if (ShouldRunProviderForStateType(StateType.Document, provider, spanBasedDriver, out supportsSemanticInSpan))
                    {
                        var userDiagnosticDriver = supportsSemanticInSpan ? spanBasedDriver : documentBasedDriver;

                        var ranges = _memberRangeMap.GetSavedMemberRange(providerId, document);
                        var data   = await _executor.GetDocumentBodyAnalysisDataAsync(
                            provider, providerId, versions, userDiagnosticDriver, root, member, memberId, supportsSemanticInSpan, ranges).ConfigureAwait(false);

                        _memberRangeMap.UpdateMemberRange(providerId, document, versions.TextVersion, memberId, member.FullSpan, ranges);

                        var state = _analyzersAndState.GetOrCreateDiagnosticState(StateType.Document, providerId, provider, document.Project.Id, document.Project.Language);
                        await state.PersistAsync(document, data.ToPersistData(), cancellationToken).ConfigureAwait(false);

                        if (data.FromCache)
                        {
                            RaiseDiagnosticsUpdated(StateType.Document, document.Id, providerId, new SolutionArgument(document), data.Items);
                            continue;
                        }

                        RaiseDiagnosticsUpdatedIfNeeded(StateType.Document, document, providerId, data.OldItems, data.Items);
                    }
                }
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
        private async Task AnalyzeBodyDocumentAsync(Document document, SyntaxNode member, VersionArgument versions, CancellationToken cancellationToken)
        {
            try
            {
                // syntax facts service must exist, otherwise, this method won't have called.
                var syntaxFacts = document.Project.LanguageServices.GetService <ISyntaxFactsService>();
                var root        = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var memberId = syntaxFacts.GetMethodLevelMemberId(root, member);

                var spanBasedDriver     = new DiagnosticAnalyzerDriver(document, member.FullSpan, root, this, cancellationToken);
                var documentBasedDriver = new DiagnosticAnalyzerDriver(document, root.FullSpan, root, this, cancellationToken);

                foreach (var stateSet in _stateManger.GetOrUpdateStateSets(document.Project))
                {
                    if (spanBasedDriver.IsAnalyzerSuppressed(stateSet.Analyzer))
                    {
                        await ClearExistingDiagnostics(document, stateSet, StateType.Document, cancellationToken).ConfigureAwait(false);

                        continue;
                    }

                    if (await ShouldRunAnalyzerForStateTypeAsync(spanBasedDriver, stateSet.Analyzer, StateType.Document).ConfigureAwait(false))
                    {
                        var supportsSemanticInSpan = await stateSet.Analyzer.SupportsSpanBasedSemanticDiagnosticAnalysisAsync(spanBasedDriver).ConfigureAwait(false);

                        var userDiagnosticDriver = supportsSemanticInSpan ? spanBasedDriver : documentBasedDriver;

                        var ranges = _memberRangeMap.GetSavedMemberRange(stateSet.Analyzer, document);
                        var data   = await _executor.GetDocumentBodyAnalysisDataAsync(
                            stateSet, versions, userDiagnosticDriver, root, member, memberId, supportsSemanticInSpan, ranges).ConfigureAwait(false);

                        _memberRangeMap.UpdateMemberRange(stateSet.Analyzer, document, versions.TextVersion, memberId, member.FullSpan, ranges);

                        var state = stateSet.GetState(StateType.Document);
                        await state.PersistAsync(document, data.ToPersistData(), cancellationToken).ConfigureAwait(false);

                        if (data.FromCache)
                        {
                            RaiseDiagnosticsUpdated(StateType.Document, document.Id, stateSet, new SolutionArgument(document), data.Items);
                            continue;
                        }

                        RaiseDocumentDiagnosticsUpdatedIfNeeded(StateType.Document, document, stateSet, data.OldItems, data.Items);
                    }
                }
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
예제 #15
0
        private async Task AnalyzeProjectAsync(Project project, ImmutableHashSet <string> diagnosticIds, bool skipClosedFileChecks, CancellationToken cancellationToken)
        {
            try
            {
                if (!skipClosedFileChecks && !CheckOption(project.Solution.Workspace, project.Language, documentOpened: project.Documents.Any(d => d.IsOpen())))
                {
                    return;
                }

                var projectVersion = await project.GetDependentVersionAsync(cancellationToken).ConfigureAwait(false);

                var semanticVersion = await project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);

                var userDiagnosticDriver = new DiagnosticAnalyzerDriver(project, _diagnosticLogAggregator, cancellationToken);
                var options = project.CompilationOptions;

                var versions = new VersionArgument(VersionStamp.Default, semanticVersion, projectVersion);
                foreach (var providerAndId in await _analyzersAndState.GetAllProviderAndIdsAsync(project, cancellationToken).ConfigureAwait(false))
                {
                    var provider   = providerAndId.Key;
                    var providerId = providerAndId.Value;

                    if (IsAnalyzerSuppressed(provider, options, userDiagnosticDriver))
                    {
                        await HandleSuppressedAnalyzerAsync(project, providerId, provider, cancellationToken).ConfigureAwait(false);
                    }
                    else if (ShouldRunProviderForStateType(StateType.Project, provider, userDiagnosticDriver, diagnosticIds) &&
                             (skipClosedFileChecks || ShouldRunProviderForClosedFile(openedDocument: false, provider: provider)))
                    {
                        var data = await _executor.GetProjectAnalysisDataAsync(provider, providerId, versions, userDiagnosticDriver).ConfigureAwait(false);

                        if (data.FromCache)
                        {
                            RaiseDiagnosticsUpdated(StateType.Project, project.Id, providerId, new SolutionArgument(project), data.Items);
                            continue;
                        }

                        var state = _analyzersAndState.GetOrCreateDiagnosticState(StateType.Project, providerId, provider, project.Id, project.Language);
                        await state.PersistAsync(project, data.ToPersistData(), cancellationToken).ConfigureAwait(false);

                        RaiseDiagnosticsUpdatedIfNeeded(project, providerId, data.OldItems, data.Items);
                    }
                }
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
예제 #16
0
        private async Task AnalyzeProjectAsync(Project project, ImmutableHashSet <string> diagnosticIds, bool skipClosedFileChecks, CancellationToken cancellationToken)
        {
            try
            {
                if (!skipClosedFileChecks && !CheckOption(project.Solution.Workspace, project.Language, documentOpened: project.Documents.Any(d => d.IsOpen())))
                {
                    return;
                }

                var projectTextVersion = await project.GetLatestDocumentVersionAsync(cancellationToken).ConfigureAwait(false);

                var semanticVersion = await project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);

                var projectVersion = await project.GetDependentVersionAsync(cancellationToken).ConfigureAwait(false);

                var analyzerDriver = new DiagnosticAnalyzerDriver(project, this, cancellationToken);

                var versions = new VersionArgument(projectTextVersion, semanticVersion, projectVersion);
                foreach (var stateSet in _stateManger.GetOrUpdateStateSets(project))
                {
                    if (analyzerDriver.IsAnalyzerSuppressed(stateSet.Analyzer))
                    {
                        await HandleSuppressedAnalyzerAsync(project, stateSet, cancellationToken).ConfigureAwait(false);
                    }
                    else if (ShouldRunAnalyzerForStateType(analyzerDriver, stateSet.Analyzer, StateType.Project, diagnosticIds) &&
                             (skipClosedFileChecks || ShouldRunAnalyzerForClosedFile(openedDocument: false, analyzer: stateSet.Analyzer)))
                    {
                        var data = await _executor.GetProjectAnalysisDataAsync(analyzerDriver, stateSet, versions).ConfigureAwait(false);

                        if (data.FromCache)
                        {
                            RaiseProjectDiagnosticsUpdated(project, stateSet.Analyzer, data.Items);
                            continue;
                        }

                        var state = stateSet.GetState(StateType.Project);
                        await PersistProjectData(project, state, data).ConfigureAwait(false);

                        RaiseProjectDiagnosticsUpdatedIfNeeded(project, stateSet.Analyzer, data.OldItems, data.Items);
                    }
                }
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
        private async Task AnalyzeDocumentAsync(Document document, VersionArgument versions, ImmutableHashSet <string> diagnosticIds, bool skipClosedFileChecks, CancellationToken cancellationToken)
        {
            try
            {
                var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var fullSpan = root == null ? null : (TextSpan?)root.FullSpan;

                var  userDiagnosticDriver = new DiagnosticAnalyzerDriver(document, fullSpan, root, this, ConcurrentAnalysis, ReportSuppressedDiagnostics, cancellationToken);
                bool openedDocument       = document.IsOpen();

                foreach (var stateSet in _stateManager.GetOrUpdateStateSets(document.Project))
                {
                    if (SkipRunningAnalyzer(document.Project.CompilationOptions, userDiagnosticDriver, openedDocument, skipClosedFileChecks, stateSet))
                    {
                        await ClearExistingDiagnostics(document, stateSet, StateType.Document, cancellationToken).ConfigureAwait(false);

                        continue;
                    }

                    if (ShouldRunAnalyzerForStateType(stateSet.Analyzer, StateType.Document, diagnosticIds))
                    {
                        var data = await _executor.GetDocumentAnalysisDataAsync(userDiagnosticDriver, stateSet, versions).ConfigureAwait(false);

                        if (data.FromCache)
                        {
                            RaiseDiagnosticsCreatedFromCacheIfNeeded(StateType.Document, document, stateSet, data.Items);
                            continue;
                        }

                        if (openedDocument)
                        {
                            _memberRangeMap.Touch(stateSet.Analyzer, document, versions.TextVersion);
                        }

                        var state = stateSet.GetState(StateType.Document);
                        await state.PersistAsync(document, data.ToPersistData(), cancellationToken).ConfigureAwait(false);

                        RaiseDocumentDiagnosticsUpdatedIfNeeded(StateType.Document, document, stateSet, data.OldItems, data.Items);
                    }
                }
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
예제 #18
0
            private async Task <bool> TryGetDocumentDiagnosticsAsync(
                StateSet stateSet, StateType stateType, bool supportsSemanticInSpan,
                Func <VersionStamp, VersionStamp, bool> versionCheck,
                Func <DiagnosticAnalyzerDriver, DiagnosticAnalyzer, Task <IEnumerable <DiagnosticData> > > getDiagnostics,
                DiagnosticAnalyzerDriver analyzerDriverOpt = null)
            {
                Func <DiagnosticData, bool> shouldInclude = d =>
                                                            d.DocumentId == _document.Id &&
                                                            _range.IntersectsWith(d.TextSpan) &&
                                                            (_includeSuppressedDiagnostics || !d.IsSuppressed);

                // make sure we get state even when none of our analyzer has ran yet.
                // but this shouldn't create analyzer that doesn't belong to this project (language)
                var state = stateSet.GetState(stateType);

                // see whether we can use existing info
                var existingData = await state.TryGetExistingDataAsync(_document, _cancellationToken).ConfigureAwait(false);

                if (existingData != null && versionCheck(existingData.TextVersion, existingData.DataVersion))
                {
                    if (existingData.Items == null || existingData.Items.Length == 0)
                    {
                        return(true);
                    }

                    Diagnostics.AddRange(existingData.Items.Where(shouldInclude));
                    return(true);
                }

                // check whether we want up-to-date document wide diagnostics
                if (!BlockForData(stateType, supportsSemanticInSpan))
                {
                    return(false);
                }

                var dx = await getDiagnostics(analyzerDriverOpt, stateSet.Analyzer).ConfigureAwait(false);

                if (dx != null)
                {
                    // no state yet
                    Diagnostics.AddRange(dx.Where(shouldInclude));
                }

                return(true);
            }
            protected override Task <AnalysisData> GetDiagnosticAnalysisDataAsync(
                Solution solution, DiagnosticAnalyzerDriver analyzerDriver, StateSet stateSet, StateType stateType, VersionArgument versions)
            {
                switch (stateType)
                {
                case StateType.Syntax:
                    return(this.AnalyzerExecutor.GetSyntaxAnalysisDataAsync(analyzerDriver, stateSet, versions));

                case StateType.Document:
                    return(this.AnalyzerExecutor.GetDocumentAnalysisDataAsync(analyzerDriver, stateSet, versions));

                case StateType.Project:
                    return(this.AnalyzerExecutor.GetProjectAnalysisDataAsync(analyzerDriver, stateSet, versions));

                default:
                    return(Contract.FailWithReturn <Task <AnalysisData> >("Can't reach here"));
                }
            }
            public LatestDiagnosticsForSpanGetter(
                DiagnosticIncrementalAnalyzer owner, Document document, SyntaxNode root, TextSpan range, bool blockForData, List<DiagnosticData> diagnostics, CancellationToken cancellationToken)
            {
                _owner = owner;

                _document = document;
                _range = range;
                _blockForData = blockForData;
                _cancellationToken = cancellationToken;

                Diagnostics = diagnostics;

                // Share the diagnostic analyzer driver across all analyzers.
                var fullSpan = root?.FullSpan;

                _spanBasedDriver = new DiagnosticAnalyzerDriver(_document, _range, root, _owner, _cancellationToken);
                _documentBasedDriver = new DiagnosticAnalyzerDriver(_document, fullSpan, root, _owner, _cancellationToken);
                _projectDriver = new DiagnosticAnalyzerDriver(_document.Project, _owner, _cancellationToken);
            }
예제 #21
0
        private async Task <bool> TryGetLatestDiagnosticsAsync(
            StateType stateType,
            Document document, TextSpan range, SyntaxNode root,
            List <DiagnosticData> diagnostics, bool requireUpToDateDocumentDiagnostic,
            Func <VersionStamp, VersionStamp, bool> versionCheck,
            Func <ProviderId, DiagnosticAnalyzer, DiagnosticAnalyzerDriver, Task <IEnumerable <DiagnosticData> > > getDiagnostics,
            CancellationToken cancellationToken)
        {
            try
            {
                bool result   = true;
                var  fullSpan = root == null ? null : (TextSpan?)root.FullSpan;

                // Share the diagnostic analyzer driver across all analyzers.
                var spanBasedDriver     = new DiagnosticAnalyzerDriver(document, range, root, _diagnosticLogAggregator, cancellationToken);
                var documentBasedDriver = new DiagnosticAnalyzerDriver(document, fullSpan, root, _diagnosticLogAggregator, cancellationToken);
                var options             = document.Project.CompilationOptions;

                foreach (var providerAndId in await _analyzersAndState.GetAllProviderAndIdsAsync(document.Project, cancellationToken).ConfigureAwait(false))
                {
                    var provider   = providerAndId.Key;
                    var providerId = providerAndId.Value;

                    bool supportsSemanticInSpan;
                    if (!IsAnalyzerSuppressed(provider, options, spanBasedDriver) &&
                        ShouldRunProviderForStateType(stateType, provider, spanBasedDriver, out supportsSemanticInSpan))
                    {
                        var userDiagnosticDriver = supportsSemanticInSpan ? spanBasedDriver : documentBasedDriver;

                        result &= await TryGetLatestDiagnosticsAsync(
                            provider, providerId, stateType,
                            document, range, root, diagnostics, requireUpToDateDocumentDiagnostic,
                            versionCheck, getDiagnostics, supportsSemanticInSpan, userDiagnosticDriver, cancellationToken).ConfigureAwait(false);
                    }
                }

                return(result);
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
예제 #22
0
            public LatestDiagnosticsForSpanGetter(
                DiagnosticIncrementalAnalyzer owner, Document document, SyntaxNode root, TextSpan range, bool blockForData, List <DiagnosticData> diagnostics, CancellationToken cancellationToken)
            {
                _owner = owner;

                _document          = document;
                _range             = range;
                _blockForData      = blockForData;
                _cancellationToken = cancellationToken;

                Diagnostics = diagnostics;

                // Share the diagnostic analyzer driver across all analyzers.
                var fullSpan = root?.FullSpan;

                _spanBasedDriver     = new DiagnosticAnalyzerDriver(_document, _range, root, _owner._diagnosticLogAggregator, _owner.HostDiagnosticUpdateSource, _cancellationToken);
                _documentBasedDriver = new DiagnosticAnalyzerDriver(_document, fullSpan, root, _owner._diagnosticLogAggregator, _owner.HostDiagnosticUpdateSource, _cancellationToken);
                _projectDriver       = new DiagnosticAnalyzerDriver(_document.Project, _owner._diagnosticLogAggregator, _owner.HostDiagnosticUpdateSource, _cancellationToken);
            }
예제 #23
0
            public LatestDiagnosticsForSpanGetter(
                DiagnosticIncrementalAnalyzer owner, Document document, SyntaxNode root, TextSpan range, bool blockForData, List <DiagnosticData> diagnostics, bool includeSuppressedDiagnostics, CancellationToken cancellationToken)
            {
                _owner = owner;

                _document         = document;
                _compilerAnalyzer = _owner.HostAnalyzerManager.GetCompilerDiagnosticAnalyzer(_document.Project.Language);

                _range        = range;
                _blockForData = blockForData;
                _includeSuppressedDiagnostics = includeSuppressedDiagnostics;
                _cancellationToken            = cancellationToken;

                Diagnostics = diagnostics;

                // Share the diagnostic analyzer driver across all analyzers.
                var fullSpan = root?.FullSpan;

                _spanBasedDriver     = new DiagnosticAnalyzerDriver(_document, _range, root, _owner, _cancellationToken);
                _documentBasedDriver = new DiagnosticAnalyzerDriver(_document, fullSpan, root, _owner, _cancellationToken);
                _projectDriver       = new DiagnosticAnalyzerDriver(_document.Project, _owner, _cancellationToken);
            }
            public async Task<AnalysisData> GetDocumentAnalysisDataAsync(DiagnosticAnalyzerDriver analyzerDriver, StateSet stateSet, VersionArgument versions)
            {
                try
                {
                    var document = analyzerDriver.Document;
                    var cancellationToken = analyzerDriver.CancellationToken;

                    var state = stateSet.GetState(StateType.Document);
                    var existingData = await state.TryGetExistingDataAsync(document, cancellationToken).ConfigureAwait(false);

                    if (CheckSemanticVersions(document, existingData, versions))
                    {
                        return existingData;
                    }

                    var diagnosticData = await GetSemanticDiagnosticsAsync(analyzerDriver, stateSet.Analyzer).ConfigureAwait(false);
                    return new AnalysisData(versions.TextVersion, versions.DataVersion, GetExistingItems(existingData), diagnosticData.AsImmutableOrEmpty());
                }
                catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
            protected override async Task <AnalysisData> GetDiagnosticAnalysisDataAsync(
                Solution solution, DiagnosticAnalyzerDriver analyzerDriver, StateSet stateSet, StateType stateType, VersionArgument versions)
            {
                // we don't care about result
                switch (stateType)
                {
                case StateType.Syntax:
                    await GetSyntaxDiagnosticsAsync(analyzerDriver, stateSet.Analyzer).ConfigureAwait(false);

                    break;

                case StateType.Document:
                    await GetSemanticDiagnosticsAsync(analyzerDriver, stateSet.Analyzer).ConfigureAwait(false);

                    break;

                case StateType.Project:
                default:
                    return(Contract.FailWithReturn <AnalysisData>("Can't reach here"));
                }

                return(AnalysisData.Empty);
            }
예제 #26
0
        private async Task <bool> TryGetLatestDiagnosticsAsync(
            StateType stateType, Document document, TextSpan range, SyntaxNode root,
            List <DiagnosticData> diagnostics, bool requireUpToDateDocumentDiagnostic,
            Func <VersionStamp, VersionStamp, bool> versionCheck,
            Func <DiagnosticAnalyzerDriver, DiagnosticAnalyzer, Task <IEnumerable <DiagnosticData> > > getDiagnostics,
            CancellationToken cancellationToken)
        {
            try
            {
                bool result   = true;
                var  fullSpan = root == null ? null : (TextSpan?)root.FullSpan;

                // Share the diagnostic analyzer driver across all analyzers.
                var spanBasedDriver     = new DiagnosticAnalyzerDriver(document, range, root, _diagnosticLogAggregator, HostDiagnosticUpdateSource, cancellationToken);
                var documentBasedDriver = new DiagnosticAnalyzerDriver(document, fullSpan, root, _diagnosticLogAggregator, HostDiagnosticUpdateSource, cancellationToken);

                foreach (var stateSet in _stateManger.GetOrCreateStateSets(document.Project))
                {
                    bool supportsSemanticInSpan;
                    if (!spanBasedDriver.IsAnalyzerSuppressed(stateSet.Analyzer) &&
                        ShouldRunAnalyzerForStateType(spanBasedDriver, stateSet.Analyzer, stateType, out supportsSemanticInSpan))
                    {
                        var userDiagnosticDriver = supportsSemanticInSpan ? spanBasedDriver : documentBasedDriver;

                        result &= await TryGetLatestDiagnosticsAsync(
                            stateSet, stateType, document, range, root, diagnostics, requireUpToDateDocumentDiagnostic,
                            versionCheck, getDiagnostics, supportsSemanticInSpan, userDiagnosticDriver, cancellationToken).ConfigureAwait(false);
                    }
                }

                return(result);
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
            public async Task <AnalysisData> GetDocumentAnalysisDataAsync(DiagnosticAnalyzerDriver analyzerDriver, StateSet stateSet, VersionArgument versions)
            {
                try
                {
                    var document          = analyzerDriver.Document;
                    var cancellationToken = analyzerDriver.CancellationToken;

                    var state        = stateSet.GetState(StateType.Document);
                    var existingData = await state.TryGetExistingDataAsync(document, cancellationToken).ConfigureAwait(false);

                    if (CheckSemanticVersions(document, existingData, versions))
                    {
                        return(existingData);
                    }

                    var diagnosticData = await GetSemanticDiagnosticsAsync(analyzerDriver, stateSet.Analyzer).ConfigureAwait(false);

                    return(new AnalysisData(versions.TextVersion, versions.DataVersion, GetExistingItems(existingData), diagnosticData.AsImmutableOrEmpty()));
                }
                catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
예제 #28
0
        private bool SkipRunningAnalyzer(
            CompilationOptions compilationOptions,
            DiagnosticAnalyzerDriver userDiagnosticDriver,
            bool openedDocument,
            bool skipClosedFileChecks,
            StateSet stateSet)
        {
            if (Owner.IsAnalyzerSuppressed(stateSet.Analyzer, userDiagnosticDriver.Project))
            {
                return(true);
            }

            if (skipClosedFileChecks)
            {
                return(false);
            }

            if (ShouldRunAnalyzerForClosedFile(compilationOptions, openedDocument, stateSet.Analyzer))
            {
                return(false);
            }

            return(true);
        }
            public async Task<AnalysisData> GetSyntaxAnalysisDataAsync(
                DiagnosticAnalyzer provider, ProviderId providerId, VersionArgument versions, DiagnosticAnalyzerDriver analyzerDriver)
            {
                try
                {
                    var document = analyzerDriver.Document;
                    var cancellationToken = analyzerDriver.CancellationToken;

                    var state = AnalyzersAndState.GetOrCreateDiagnosticState(StateType.Syntax, providerId, provider, document.Project.Id, document.Project.Language);
                    var existingData = await state.TryGetExistingDataAsync(document, cancellationToken).ConfigureAwait(false);

                    if (CheckSyntaxVersions(document, existingData, versions))
                    {
                        return existingData;
                    }

                    var diagnosticData = await GetSyntaxDiagnosticsAsync(providerId, provider, analyzerDriver).ConfigureAwait(false);
                    return new AnalysisData(versions.TextVersion, versions.DataVersion, GetExistingItems(existingData), diagnosticData.AsImmutableOrEmpty());
                }
                catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
        private async Task AnalyzeDocumentAsync(Document document, VersionArgument versions, ImmutableHashSet<string> diagnosticIds, bool skipClosedFileChecks, CancellationToken cancellationToken)
        {
            try
            {
                var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
                var fullSpan = root == null ? null : (TextSpan?)root.FullSpan;

                var userDiagnosticDriver = new DiagnosticAnalyzerDriver(document, fullSpan, root, this, cancellationToken);
                bool openedDocument = document.IsOpen();

                foreach (var stateSet in _stateManager.GetOrUpdateStateSets(document.Project))
                {
                    if (SkipRunningAnalyzer(document.Project.CompilationOptions, userDiagnosticDriver, openedDocument, skipClosedFileChecks, stateSet))
                    {
                        await ClearExistingDiagnostics(document, stateSet, StateType.Document, cancellationToken).ConfigureAwait(false);
                        continue;
                    }

                    if (ShouldRunAnalyzerForStateType(stateSet.Analyzer, StateType.Document, diagnosticIds))
                    {
                        var data = await _executor.GetDocumentAnalysisDataAsync(userDiagnosticDriver, stateSet, versions).ConfigureAwait(false);
                        if (data.FromCache)
                        {
                            RaiseDiagnosticsUpdated(StateType.Document, document.Id, stateSet, new SolutionArgument(document), data.Items);
                            continue;
                        }

                        if (openedDocument)
                        {
                            _memberRangeMap.Touch(stateSet.Analyzer, document, versions.TextVersion);
                        }

                        var state = stateSet.GetState(StateType.Document);
                        await state.PersistAsync(document, data.ToPersistData(), cancellationToken).ConfigureAwait(false);

                        RaiseDocumentDiagnosticsUpdatedIfNeeded(StateType.Document, document, stateSet, data.OldItems, data.Items);
                    }
                }

                _solutionCrawlerAnalysisState.OnDocumentAnalyzed(document);
            }
            catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
 private static bool ShouldRunProviderForStateType(StateType stateTypeId, DiagnosticAnalyzer provider, DiagnosticAnalyzerDriver driver,
     ImmutableHashSet<string> diagnosticIds, Func<DiagnosticAnalyzer, ImmutableArray<DiagnosticDescriptor>> getDescriptor)
 {
     bool discarded;
     return ShouldRunProviderForStateType(stateTypeId, provider, driver, out discarded, diagnosticIds, getDescriptor);
 }
 protected abstract Task <AnalysisData> GetDiagnosticAnalysisDataAsync(Solution solution, DiagnosticAnalyzerDriver analyzerDriver, StateSet stateSet, StateType stateType, VersionArgument versions);
 protected abstract Task <AnalysisData> GetSpecificDiagnosticsAsync(Solution solution, DiagnosticAnalyzer provider, ProviderId providerId, StateType stateType, VersionArgument versions, DiagnosticAnalyzerDriver analyzerDriver);
        private static bool IsAnalyzerSuppressed(DiagnosticAnalyzer provider, CompilationOptions options, DiagnosticAnalyzerDriver driver)
        {
            if (options != null && CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(provider, options, driver.CatchAnalyzerExceptionHandler))
            {
                // All diagnostics that are generated by this DiagnosticAnalyzer will be suppressed, so we need not run the analyzer.
                return true;
            }

            return false;
        }
        private static async Task<IEnumerable<DiagnosticData>> GetProjectDiagnosticsAsync(DiagnosticAnalyzerDriver userDiagnosticDriver, DiagnosticAnalyzer analyzer)
        {
            using (Logger.LogBlock(FunctionId.Diagnostics_ProjectDiagnostic, GetProjectLogMessage, userDiagnosticDriver.Project, analyzer, userDiagnosticDriver.CancellationToken))
            {
                try
                {
                    Contract.ThrowIfNull(analyzer);

                    var diagnostics = await userDiagnosticDriver.GetProjectDiagnosticsAsync(analyzer).ConfigureAwait(false);
                    return GetDiagnosticData(userDiagnosticDriver.Project, diagnostics);
                }
                catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
        }
            private async Task<bool> TryGetDocumentDiagnosticsAsync(
                StateSet stateSet, StateType stateType, bool supportsSemanticInSpan,
                Func<VersionStamp, VersionStamp, bool> versionCheck,
                Func<DiagnosticAnalyzerDriver, DiagnosticAnalyzer, Task<IEnumerable<DiagnosticData>>> getDiagnostics,
                DiagnosticAnalyzerDriver analyzerDriverOpt = null)
            {
                Func<DiagnosticData, bool> shouldInclude = d =>
                    d.DocumentId == _document.Id &&
                    _range.IntersectsWith(d.TextSpan) &&
                    (_includeSuppressedDiagnostics || !d.IsSuppressed);

                // make sure we get state even when none of our analyzer has ran yet. 
                // but this shouldn't create analyzer that doesn't belong to this project (language)
                var state = stateSet.GetState(stateType);

                // see whether we can use existing info
                var existingData = await state.TryGetExistingDataAsync(_document, _cancellationToken).ConfigureAwait(false);
                if (existingData != null && versionCheck(existingData.TextVersion, existingData.DataVersion))
                {
                    if (existingData.Items == null || existingData.Items.Length == 0)
                    {
                        return true;
                    }

                    Diagnostics.AddRange(existingData.Items.Where(shouldInclude));
                    return true;
                }

                // check whether we want up-to-date document wide diagnostics
                if (!BlockForData(stateType, supportsSemanticInSpan))
                {
                    return false;
                }

                var dx = await getDiagnostics(analyzerDriverOpt, stateSet.Analyzer).ConfigureAwait(false);
                if (dx != null)
                {
                    // no state yet
                    Diagnostics.AddRange(dx.Where(shouldInclude));
                }

                return true;
            }
            protected override async Task<AnalysisData> GetDiagnosticAnalysisDataAsync(
                Solution solution, DiagnosticAnalyzerDriver analyzerDriver, StateSet stateSet, StateType stateType, VersionArgument versions)
            {
                // we don't care about result
                switch (stateType)
                {
                    case StateType.Syntax:
                        await GetSyntaxDiagnosticsAsync(analyzerDriver, _analyzer).ConfigureAwait(false);
                        break;
                    case StateType.Document:
                        await GetSemanticDiagnosticsAsync(analyzerDriver, _analyzer).ConfigureAwait(false);
                        break;
                    case StateType.Project:
                    default:
                        return Contract.FailWithReturn<AnalysisData>("Can't reach here");
                }

                return AnalysisData.Empty;
            }
예제 #38
0
 private Task <IEnumerable <DiagnosticData> > GetProjectDiagnosticsWorkerAsync(DiagnosticAnalyzerDriver driver, DiagnosticAnalyzer analyzer)
 {
     return(GetProjectDiagnosticsAsync(driver, analyzer, _owner.ForceAnalyzeAllDocuments));
 }
        private async Task<bool> TryGetLatestDiagnosticsAsync(
            DiagnosticAnalyzer provider, ProviderId providerId,
            StateType stateType, Document document, TextSpan range, SyntaxNode root,
            List<DiagnosticData> diagnostics, bool requireUpToDateDocumentDiagnostic,
            Func<VersionStamp, VersionStamp, bool> versionCheck,
            Func<ProviderId, DiagnosticAnalyzer, DiagnosticAnalyzerDriver, Task<IEnumerable<DiagnosticData>>> getDiagnostics,
            bool supportsSemanticInSpan,
            DiagnosticAnalyzerDriver userDiagnosticDriver,
            CancellationToken cancellationToken)
        {
            try
            {
                var shouldInclude = (Func<DiagnosticData, bool>)(d => range.IntersectsWith(d.TextSpan));

                // make sure we get state even when none of our analyzer has ran yet. 
                // but this shouldn't create analyzer that doesnt belong to this project (language)
                var state = _analyzersAndState.GetOrCreateDiagnosticState(stateType, providerId, provider, document.Project.Id, document.Project.Language);
                if (state == null)
                {
                    if (!requireUpToDateDocumentDiagnostic)
                    {
                        // the provider never ran yet.
                        return true;
                    }
                }
                else
                {
                    // see whether we can use existing info
                    var existingData = await state.TryGetExistingDataAsync(document, cancellationToken).ConfigureAwait(false);
                    if (existingData != null && versionCheck(existingData.TextVersion, existingData.DataVersion))
                    {
                        if (existingData.Items == null)
                        {
                            return true;
                        }

                        diagnostics.AddRange(existingData.Items.Where(shouldInclude));
                        return true;
                    }
                }

                // check whether we want up-to-date document wide diagnostics
                if (stateType == StateType.Document && !supportsSemanticInSpan && !requireUpToDateDocumentDiagnostic)
                {
                    return false;
                }

                var dx = await getDiagnostics(providerId, provider, userDiagnosticDriver).ConfigureAwait(false);
                if (dx != null)
                {
                    // no state yet
                    diagnostics.AddRange(dx.Where(shouldInclude));
                }

                return true;
            }
            catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
 private bool ShouldRunProviderForStateType(StateType stateTypeId, DiagnosticAnalyzer provider,
     DiagnosticAnalyzerDriver driver, ImmutableHashSet<string> diagnosticIds)
 {
     return ShouldRunProviderForStateType(stateTypeId, provider, driver, diagnosticIds, _owner.GetDiagnosticDescriptors);
 }
        private async Task AnalyzeProjectAsync(Project project, CancellationToken cancellationToken)
        {
            try
            {
                if (!CheckOption(project.Solution.Workspace, project.Language, documentOpened: false))
                {
                    return;
                }

                var projectTextVersion = await project.GetLatestDocumentVersionAsync(cancellationToken).ConfigureAwait(false);
                var semanticVersion = await project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);
                var projectVersion = await project.GetDependentVersionAsync(cancellationToken).ConfigureAwait(false);
                var analyzerDriver = new DiagnosticAnalyzerDriver(project, this, cancellationToken);

                var versions = new VersionArgument(projectTextVersion, semanticVersion, projectVersion);
                foreach (var stateSet in _stateManager.GetOrUpdateStateSets(project))
                {
                    if (SkipRunningAnalyzer(project.CompilationOptions, analyzerDriver, openedDocument: false, skipClosedFileChecks: false, stateSet: stateSet))
                    {
                        await ClearExistingDiagnostics(project, stateSet, cancellationToken).ConfigureAwait(false);
                        continue;
                    }

                    if (ShouldRunAnalyzerForStateType(stateSet.Analyzer, StateType.Project, diagnosticIds: null))
                    {
                        var data = await _executor.GetProjectAnalysisDataAsync(analyzerDriver, stateSet, versions).ConfigureAwait(false);
                        if (data.FromCache)
                        {
                            RaiseProjectDiagnosticsUpdated(project, stateSet, data.Items);
                            continue;
                        }

                        var state = stateSet.GetState(StateType.Project);
                        await PersistProjectData(project, state, data).ConfigureAwait(false);

                        RaiseProjectDiagnosticsUpdatedIfNeeded(project, stateSet, data.OldItems, data.Items);
                    }
                }

                _solutionCrawlerAnalysisState.OnProjectAnalyzed(project);
            }
            catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
        private async Task AnalyzeSyntaxAsync(Document document, ImmutableHashSet<string> diagnosticIds, CancellationToken cancellationToken)
        {
            try
            {
                if (!CheckOptions(document.Project, document.IsOpen()))
                {
                    return;
                }

                var textVersion = await document.GetTextVersionAsync(cancellationToken).ConfigureAwait(false);
                var dataVersion = await document.GetSyntaxVersionAsync(cancellationToken).ConfigureAwait(false);
                var versions = new VersionArgument(textVersion, dataVersion);

                var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
                var fullSpan = root == null ? null : (TextSpan?)root.FullSpan;

                var openedDocument = document.IsOpen();

                var stateSets = _stateManager.GetOrUpdateStateSets(document.Project);
                var analyzers = stateSets.Select(s => s.Analyzer);

                var userDiagnosticDriver = new DiagnosticAnalyzerDriver(
                    document, fullSpan, root, this, analyzers, ConcurrentAnalysis, ReportSuppressedDiagnostics, cancellationToken);

                foreach (var stateSet in stateSets)
                {
                    if (await SkipRunningAnalyzerAsync(document.Project, stateSet.Analyzer, openedDocument, skipClosedFileCheck: false, cancellationToken: cancellationToken).ConfigureAwait(false))
                    {
                        await ClearExistingDiagnostics(document, stateSet, StateType.Syntax, cancellationToken).ConfigureAwait(false);
                        continue;
                    }

                    if (ShouldRunAnalyzerForStateType(stateSet.Analyzer, StateType.Syntax, diagnosticIds))
                    {
                        var data = await _executor.GetSyntaxAnalysisDataAsync(userDiagnosticDriver, stateSet, versions).ConfigureAwait(false);
                        if (data.FromCache)
                        {
                            RaiseDiagnosticsCreatedFromCacheIfNeeded(StateType.Syntax, document, stateSet, data.Items);
                            continue;
                        }

                        var state = stateSet.GetState(StateType.Syntax);
                        await state.PersistAsync(document, data.ToPersistData(), cancellationToken).ConfigureAwait(false);

                        RaiseDocumentDiagnosticsUpdatedIfNeeded(StateType.Syntax, document, stateSet, data.OldItems, data.Items);
                    }
                }
            }
            catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
        private bool SkipRunningAnalyzer(
            CompilationOptions compilationOptions,
            DiagnosticAnalyzerDriver userDiagnosticDriver,
            bool openedDocument,
            bool skipClosedFileChecks,
            StateSet stateSet)
        {
            if (Owner.IsAnalyzerSuppressed(stateSet.Analyzer, userDiagnosticDriver.Project))
            {
                return true;
            }

            if (skipClosedFileChecks)
            {
                return false;
            }

            if (ShouldRunAnalyzerForClosedFile(compilationOptions, openedDocument, stateSet.Analyzer))
            {
                return false;
            }

            return true;
        }
        private async Task AnalyzeProjectAsync(Project project, CancellationToken cancellationToken)
        {
            try
            {
                if (!CheckOptions(project, forceAnalysis: false))
                {
                    return;
                }

                var projectTextVersion = await project.GetLatestDocumentVersionAsync(cancellationToken).ConfigureAwait(false);
                var semanticVersion = await project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);
                var projectVersion = await project.GetDependentVersionAsync(cancellationToken).ConfigureAwait(false);

                var versions = new VersionArgument(projectTextVersion, semanticVersion, projectVersion);

                var stateSets = _stateManager.GetOrUpdateStateSets(project);
                var analyzers = stateSets.Select(s => s.Analyzer);
                var analyzerDriver = new DiagnosticAnalyzerDriver(project, this, analyzers, ConcurrentAnalysis, ReportSuppressedDiagnostics, cancellationToken);

                foreach (var stateSet in stateSets)
                {
                    // Compilation actions can report diagnostics on open files, so we skipClosedFileChecks.
                    if (await SkipRunningAnalyzerAsync(project, stateSet.Analyzer, openedDocument: false, skipClosedFileCheck: true, cancellationToken: cancellationToken).ConfigureAwait(false))
                    {
                        await ClearExistingDiagnostics(project, stateSet, cancellationToken).ConfigureAwait(false);
                        continue;
                    }

                    if (ShouldRunAnalyzerForStateType(stateSet.Analyzer, StateType.Project, diagnosticIds: null))
                    {
                        var data = await _executor.GetProjectAnalysisDataAsync(analyzerDriver, stateSet, versions).ConfigureAwait(false);
                        if (data.FromCache)
                        {
                            RaiseProjectDiagnosticsUpdatedIfNeeded(project, stateSet, ImmutableArray<DiagnosticData>.Empty, data.Items);
                            continue;
                        }

                        var state = stateSet.GetState(StateType.Project);
                        await PersistProjectData(project, state, data).ConfigureAwait(false);

                        RaiseProjectDiagnosticsUpdatedIfNeeded(project, stateSet, data.OldItems, data.Items);
                    }
                }
            }
            catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
        private async Task AnalyzeBodyDocumentAsync(Document document, SyntaxNode member, VersionArgument versions, CancellationToken cancellationToken)
        {
            try
            {
                // syntax facts service must exist, otherwise, this method won't have called.
                var syntaxFacts = document.Project.LanguageServices.GetService<ISyntaxFactsService>();
                var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
                var memberId = syntaxFacts.GetMethodLevelMemberId(root, member);

                var spanBasedDriver = new DiagnosticAnalyzerDriver(document, member.FullSpan, root, _diagnosticLogAggregator, cancellationToken);
                var documentBasedDriver = new DiagnosticAnalyzerDriver(document, root.FullSpan, root, _diagnosticLogAggregator, cancellationToken);
                var options = document.Project.CompilationOptions;

                foreach (var providerAndId in await _analyzersAndState.GetAllProviderAndIdsAsync(document.Project, cancellationToken).ConfigureAwait(false))
                {
                    var provider = providerAndId.Key;
                    var providerId = providerAndId.Value;

                    bool supportsSemanticInSpan;
                    if (IsAnalyzerSuppressed(provider, options, spanBasedDriver))
                    {
                        await HandleSuppressedAnalyzerAsync(document, StateType.Document, providerId, provider, cancellationToken).ConfigureAwait(false);
                    }
                    else if (ShouldRunProviderForStateType(StateType.Document, provider, spanBasedDriver, out supportsSemanticInSpan))
                    {
                        var userDiagnosticDriver = supportsSemanticInSpan ? spanBasedDriver : documentBasedDriver;

                        var ranges = _memberRangeMap.GetSavedMemberRange(providerId, document);
                        var data = await _executor.GetDocumentBodyAnalysisDataAsync(
                            provider, providerId, versions, userDiagnosticDriver, root, member, memberId, supportsSemanticInSpan, ranges).ConfigureAwait(false);

                        _memberRangeMap.UpdateMemberRange(providerId, document, versions.TextVersion, memberId, member.FullSpan, ranges);

                        var state = _analyzersAndState.GetOrCreateDiagnosticState(StateType.Document, providerId, provider, document.Project.Id, document.Project.Language);
                        await state.PersistAsync(document, data.ToPersistData(), cancellationToken).ConfigureAwait(false);

                        if (data.FromCache)
                        {
                            RaiseDiagnosticsUpdated(StateType.Document, document.Id, providerId, new SolutionArgument(document), data.Items);
                            continue;
                        }

                        RaiseDiagnosticsUpdatedIfNeeded(StateType.Document, document, providerId, data.OldItems, data.Items);
                    }
                }
            }
            catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
 protected abstract Task<AnalysisData> GetSpecificDiagnosticsAsync(Solution solution, DiagnosticAnalyzer provider, ProviderId providerId, StateType stateType, VersionArgument versions, DiagnosticAnalyzerDriver analyzerDriver);
            private void ValidateMemberDiagnostics(DiagnosticAnalyzer analyzer, Document document, SyntaxNode root, ImmutableArray<DiagnosticData> diagnostics)
            {
#if RANGE
                var documentBasedDriver = new DiagnosticAnalyzerDriver(document, root.FullSpan, root, this, CancellationToken.None);
                var expected = GetSemanticDiagnosticsAsync(documentBasedDriver, analyzer).WaitAndGetResult(documentBasedDriver.CancellationToken) ?? SpecializedCollections.EmptyEnumerable<DiagnosticData>();
                Contract.Requires(diagnostics.SetEquals(expected));
#endif
            }
 private async Task<bool> ShouldRunAnalyzerForStateTypeAsync(DiagnosticAnalyzerDriver driver, DiagnosticAnalyzer analyzer, StateType stateTypeId, ImmutableHashSet<string> diagnosticIds)
 {
     return await ShouldRunAnalyzerForStateTypeAsync(driver, analyzer, stateTypeId, diagnosticIds, Owner.GetDiagnosticDescriptors).ConfigureAwait(false);
 }
 private static async Task<ImmutableArray<DiagnosticData>> UpdateAllSemanticDiagnosticsAsync(
     StateSet stateSet, DiagnosticAnalyzerDriver analyzerDriver, ImmutableArray<DiagnosticData> diagnosticData)
 {
     var dx = await GetSemanticDiagnosticsAsync(analyzerDriver, stateSet.Analyzer).ConfigureAwait(false);
     diagnosticData = dx.AsImmutableOrEmpty();
     return diagnosticData;
 }
 protected abstract Task<AnalysisData> GetDiagnosticAnalysisDataAsync(Solution solution, DiagnosticAnalyzerDriver analyzerDriver, StateSet stateSet, StateType stateType, VersionArgument versions);
예제 #51
0
        private static async Task <IEnumerable <DiagnosticData> > GetProjectDiagnosticsAsync(DiagnosticAnalyzerDriver userDiagnosticDriver, DiagnosticAnalyzer analyzer)
        {
            using (Logger.LogBlock(FunctionId.Diagnostics_ProjectDiagnostic, GetProjectLogMessage, userDiagnosticDriver.Project, analyzer, userDiagnosticDriver.CancellationToken))
            {
                try
                {
                    Contract.ThrowIfNull(analyzer);

                    var diagnostics = await userDiagnosticDriver.GetProjectDiagnosticsAsync(analyzer).ConfigureAwait(false);

                    return(GetDiagnosticData(userDiagnosticDriver.Project, diagnostics));
                }
                catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
        }
        private static bool ShouldRunProviderForStateType(StateType stateTypeId, DiagnosticAnalyzer provider, DiagnosticAnalyzerDriver driver,
            out bool supportsSemanticInSpan, ImmutableHashSet<string> diagnosticIds = null, Func<DiagnosticAnalyzer, ImmutableArray<DiagnosticDescriptor>> getDescriptor = null)
        {
            Debug.Assert(!IsAnalyzerSuppressed(provider, driver.Project.CompilationOptions, driver));

            supportsSemanticInSpan = false;
            if (diagnosticIds != null && getDescriptor(provider).All(d => !diagnosticIds.Contains(d.Id)))
            {
                return false;
            }

            switch (stateTypeId)
            {
                case StateType.Syntax:
                    return provider.SupportsSyntaxDiagnosticAnalysis(driver);

                case StateType.Document:
                    return provider.SupportsSemanticDiagnosticAnalysis(driver, out supportsSemanticInSpan);

                case StateType.Project:
                    return provider.SupportsProjectDiagnosticAnalysis(driver);

                default:
                    throw ExceptionUtilities.Unreachable;
            }
        }
        private async Task<bool> TryGetLatestDiagnosticsAsync(
            StateType stateType,
            Document document, TextSpan range, SyntaxNode root,
            List<DiagnosticData> diagnostics, bool requireUpToDateDocumentDiagnostic,
            Func<VersionStamp, VersionStamp, bool> versionCheck,
            Func<ProviderId, DiagnosticAnalyzer, DiagnosticAnalyzerDriver, Task<IEnumerable<DiagnosticData>>> getDiagnostics,
            CancellationToken cancellationToken)
        {
            try
            {
                bool result = true;
                var fullSpan = root == null ? null : (TextSpan?)root.FullSpan;

                // Share the diagnostic analyzer driver across all analyzers.
                var spanBasedDriver = new DiagnosticAnalyzerDriver(document, range, root, _diagnosticLogAggregator, cancellationToken);
                var documentBasedDriver = new DiagnosticAnalyzerDriver(document, fullSpan, root, _diagnosticLogAggregator, cancellationToken);
                var options = document.Project.CompilationOptions;

                foreach (var providerAndId in await _analyzersAndState.GetAllProviderAndIdsAsync(document.Project, cancellationToken).ConfigureAwait(false))
                {
                    var provider = providerAndId.Key;
                    var providerId = providerAndId.Value;

                    bool supportsSemanticInSpan;
                    if (!IsAnalyzerSuppressed(provider, options, spanBasedDriver) &&
                        ShouldRunProviderForStateType(stateType, provider, spanBasedDriver, out supportsSemanticInSpan))
                    {
                        var userDiagnosticDriver = supportsSemanticInSpan ? spanBasedDriver : documentBasedDriver;

                        result &= await TryGetLatestDiagnosticsAsync(
                            provider, providerId, stateType,
                            document, range, root, diagnostics, requireUpToDateDocumentDiagnostic,
                            versionCheck, getDiagnostics, supportsSemanticInSpan, userDiagnosticDriver, cancellationToken).ConfigureAwait(false);
                    }
                }

                return result;
            }
            catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
 private Task<IEnumerable<DiagnosticData>> GetProjectDiagnosticsWorkerAsync(DiagnosticAnalyzerDriver driver, DiagnosticAnalyzer analyzer)
 {
     return GetProjectDiagnosticsAsync(driver, analyzer, _owner.ForceAnalyzeAllDocuments);
 }
        private static async Task<bool> ShouldRunAnalyzerForStateTypeAsync(DiagnosticAnalyzerDriver driver, DiagnosticAnalyzer analyzer, StateType stateTypeId,
            ImmutableHashSet<string> diagnosticIds = null, Func<DiagnosticAnalyzer, ImmutableArray<DiagnosticDescriptor>> getDescriptors = null)
        {
            Debug.Assert(!driver.IsAnalyzerSuppressed(analyzer));

            if (diagnosticIds != null && getDescriptors(analyzer).All(d => !diagnosticIds.Contains(d.Id)))
            {
                return false;
            }

            switch (stateTypeId)
            {
                case StateType.Syntax:
                    return await analyzer.SupportsSyntaxDiagnosticAnalysisAsync(driver).ConfigureAwait(false);

                case StateType.Document:
                    return await analyzer.SupportsSemanticDiagnosticAnalysisAsync(driver).ConfigureAwait(false);

                case StateType.Project:
                    return await analyzer.SupportsProjectDiagnosticAnalysisAsync(driver).ConfigureAwait(false);

                default:
                    throw ExceptionUtilities.Unreachable;
            }
        }
        private async Task AnalyzeProjectAsync(Project project, ImmutableHashSet<string> diagnosticIds, bool skipClosedFileChecks, CancellationToken cancellationToken)
        {
            try
            {
                if (!skipClosedFileChecks && !CheckOption(project.Solution.Workspace, project.Language, documentOpened: project.Documents.Any(d => d.IsOpen())))
                {
                    return;
                }

                var projectVersion = await project.GetDependentVersionAsync(cancellationToken).ConfigureAwait(false);
                var semanticVersion = await project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);
                var userDiagnosticDriver = new DiagnosticAnalyzerDriver(project, _diagnosticLogAggregator, cancellationToken);
                var options = project.CompilationOptions;

                var versions = new VersionArgument(VersionStamp.Default, semanticVersion, projectVersion);
                foreach (var providerAndId in await _analyzersAndState.GetAllProviderAndIdsAsync(project, cancellationToken).ConfigureAwait(false))
                {
                    var provider = providerAndId.Key;
                    var providerId = providerAndId.Value;

                    if (IsAnalyzerSuppressed(provider, options, userDiagnosticDriver))
                    {
                        await HandleSuppressedAnalyzerAsync(project, providerId, provider, cancellationToken).ConfigureAwait(false);
                    }
                    else if (ShouldRunProviderForStateType(StateType.Project, provider, userDiagnosticDriver, diagnosticIds) &&
                        (skipClosedFileChecks || ShouldRunProviderForClosedFile(openedDocument: false, provider: provider)))
                    {
                        var data = await _executor.GetProjectAnalysisDataAsync(provider, providerId, versions, userDiagnosticDriver).ConfigureAwait(false);
                        if (data.FromCache)
                        {
                            RaiseDiagnosticsUpdated(StateType.Project, project.Id, providerId, new SolutionArgument(project), data.Items);
                            continue;
                        }

                        var state = _analyzersAndState.GetOrCreateDiagnosticState(StateType.Project, providerId, provider, project.Id, project.Language);
                        await state.PersistAsync(project, data.ToPersistData(), cancellationToken).ConfigureAwait(false);

                        RaiseDiagnosticsUpdatedIfNeeded(project, providerId, data.OldItems, data.Items);
                    }
                }
            }
            catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
 private async Task <bool> ShouldRunAnalyzerForStateTypeAsync(DiagnosticAnalyzerDriver driver, DiagnosticAnalyzer analyzer, StateType stateTypeId, ImmutableHashSet <string> diagnosticIds)
 {
     return(await ShouldRunAnalyzerForStateTypeAsync(driver, analyzer, stateTypeId, diagnosticIds, Owner.GetDiagnosticDescriptors).ConfigureAwait(false));
 }
        private async Task AnalyzeBodyDocumentAsync(Document document, SyntaxNode member, VersionArgument versions, CancellationToken cancellationToken)
        {
            try
            {
                // syntax facts service must exist, otherwise, this method won't have called.
                var syntaxFacts = document.Project.LanguageServices.GetService<ISyntaxFactsService>();
                var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
                var memberId = syntaxFacts.GetMethodLevelMemberId(root, member);

                var spanBasedDriver = new DiagnosticAnalyzerDriver(document, member.FullSpan, root, this, cancellationToken);
                var documentBasedDriver = new DiagnosticAnalyzerDriver(document, root.FullSpan, root, this, cancellationToken);

                foreach (var stateSet in _stateManager.GetOrUpdateStateSets(document.Project))
                {
                    if (Owner.IsAnalyzerSuppressed(stateSet.Analyzer, document.Project))
                    {
                        await ClearExistingDiagnostics(document, stateSet, StateType.Document, cancellationToken).ConfigureAwait(false);
                        continue;
                    }

                    if (ShouldRunAnalyzerForStateType(stateSet.Analyzer, StateType.Document))
                    {
                        var supportsSemanticInSpan = stateSet.Analyzer.SupportsSpanBasedSemanticDiagnosticAnalysis();
                        var userDiagnosticDriver = supportsSemanticInSpan ? spanBasedDriver : documentBasedDriver;

                        var ranges = _memberRangeMap.GetSavedMemberRange(stateSet.Analyzer, document);
                        var data = await _executor.GetDocumentBodyAnalysisDataAsync(
                            stateSet, versions, userDiagnosticDriver, root, member, memberId, supportsSemanticInSpan, ranges).ConfigureAwait(false);

                        _memberRangeMap.UpdateMemberRange(stateSet.Analyzer, document, versions.TextVersion, memberId, member.FullSpan, ranges);

                        var state = stateSet.GetState(StateType.Document);
                        await state.PersistAsync(document, data.ToPersistData(), cancellationToken).ConfigureAwait(false);

                        if (data.FromCache)
                        {
                            RaiseDiagnosticsUpdated(StateType.Document, document.Id, stateSet, new SolutionArgument(document), data.Items);
                            continue;
                        }

                        RaiseDocumentDiagnosticsUpdatedIfNeeded(StateType.Document, document, stateSet, data.OldItems, data.Items);
                    }
                }
            }
            catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
 protected override Task<AnalysisData> GetDiagnosticAnalysisDataAsync(
     Solution solution, DiagnosticAnalyzerDriver analyzerDriver, StateSet stateSet, StateType stateType, VersionArgument versions)
 {
     switch (stateType)
     {
         case StateType.Syntax:
             return this.AnalyzerExecutor.GetSyntaxAnalysisDataAsync(analyzerDriver, stateSet, versions);
         case StateType.Document:
             return this.AnalyzerExecutor.GetDocumentAnalysisDataAsync(analyzerDriver, stateSet, versions);
         case StateType.Project:
             return this.AnalyzerExecutor.GetProjectAnalysisDataAsync(analyzerDriver, stateSet, versions);
         default:
             return Contract.FailWithReturn<Task<AnalysisData>>("Can't reach here");
     }
 }
        private async Task AnalyzeSyntaxAsync(Document document, ImmutableHashSet<string> diagnosticIds, bool skipClosedFileChecks, CancellationToken cancellationToken)
        {
            try
            {
                if (!skipClosedFileChecks && !CheckOption(document.Project.Solution.Workspace, document.Project.Language, document.IsOpen()))
                {
                    return;
                }

                var textVersion = await document.GetTextVersionAsync(cancellationToken).ConfigureAwait(false);
                var dataVersion = await document.GetSyntaxVersionAsync(cancellationToken).ConfigureAwait(false);
                var versions = new VersionArgument(textVersion, dataVersion);

                var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
                var fullSpan = root == null ? null : (TextSpan?)root.FullSpan;

                var userDiagnosticDriver = new DiagnosticAnalyzerDriver(document, fullSpan, root, _diagnosticLogAggregator, cancellationToken);
                var options = document.Project.CompilationOptions;
                var openedDocument = document.IsOpen();

                foreach (var providerAndId in await _analyzersAndState.GetAllProviderAndIdsAsync(document.Project, cancellationToken).ConfigureAwait(false))
                {
                    var provider = providerAndId.Key;
                    var providerId = providerAndId.Value;

                    if (IsAnalyzerSuppressed(provider, options, userDiagnosticDriver))
                    {
                        await HandleSuppressedAnalyzerAsync(document, StateType.Syntax, providerId, provider, cancellationToken).ConfigureAwait(false);
                    }
                    else if (ShouldRunProviderForStateType(StateType.Syntax, provider, userDiagnosticDriver, diagnosticIds) &&
                        (skipClosedFileChecks || ShouldRunProviderForClosedFile(openedDocument, provider)))
                    {
                        var data = await _executor.GetSyntaxAnalysisDataAsync(provider, providerId, versions, userDiagnosticDriver).ConfigureAwait(false);
                        if (data.FromCache)
                        {
                            RaiseDiagnosticsUpdated(StateType.Syntax, document.Id, providerId, new SolutionArgument(document), data.Items);
                            continue;
                        }

                        var state = _analyzersAndState.GetOrCreateDiagnosticState(StateType.Syntax, providerId, provider, document.Project.Id, document.Project.Language);
                        await state.PersistAsync(document, data.ToPersistData(), cancellationToken).ConfigureAwait(false);

                        RaiseDiagnosticsUpdatedIfNeeded(StateType.Syntax, document, providerId, data.OldItems, data.Items);
                    }
                }
            }
            catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }