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 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 (await ShouldRunAnalyzerForStateTypeAsync(analyzerDriver, stateSet.Analyzer, StateType.Project, diagnosticIds).ConfigureAwait(false) && (skipClosedFileChecks || ShouldRunAnalyzerForClosedFile(openedDocument: false, analyzer: stateSet.Analyzer))) { 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); } } } 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 HandleSuppressedAnalyzerAsync(document, stateSet, StateType.Document, cancellationToken).ConfigureAwait(false); } else 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; } }
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 _stateManger.GetOrUpdateStateSets(document.Project)) { if (userDiagnosticDriver.IsAnalyzerSuppressed(stateSet.Analyzer)) { await HandleSuppressedAnalyzerAsync(document, stateSet, StateType.Document, cancellationToken).ConfigureAwait(false); } else if (await ShouldRunAnalyzerForStateTypeAsync(userDiagnosticDriver, stateSet.Analyzer, StateType.Document, diagnosticIds).ConfigureAwait(false) && (skipClosedFileChecks || ShouldRunAnalyzerForClosedFile(openedDocument, stateSet.Analyzer))) { 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); } } } catch (Exception e) when (FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
private bool SkipRunningAnalyzer( CompilationOptions compilationOptions, DiagnosticAnalyzerDriver userDiagnosticDriver, bool openedDocument, bool skipClosedFileChecks, StateSet stateSet) { if (userDiagnosticDriver.IsAnalyzerSuppressed(stateSet.Analyzer)) { return true; } if (skipClosedFileChecks) { return false; } if (ShouldRunAnalyzerForClosedFile(compilationOptions, openedDocument, stateSet.Analyzer)) { return false; } return true; }