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; } }
private bool ShouldRunAnalyzerForStateType(DiagnosticAnalyzerDriver driver, DiagnosticAnalyzer analyzer, StateType stateTypeId, ImmutableHashSet <string> diagnosticIds) { bool discarded; return(ShouldRunAnalyzerForStateType(driver, analyzer, stateTypeId, out discarded, diagnosticIds, Owner.GetDiagnosticDescriptors)); }
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); }
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); }
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; } }
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; } }
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; } }
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; } }
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; } }
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 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; } }
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); }
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; } }
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); }
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); }
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; } }
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; }
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);
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; } }