private async Task <ImmutableArray <DiagnosticData> > GetDiagnosticsAsync( TextDocument document, AnalysisKind kind, CancellationToken cancellationToken) { var loadDiagnostic = await document.State.GetLoadDiagnosticAsync(cancellationToken).ConfigureAwait(false); if (loadDiagnostic != null) { return(ImmutableArray.Create(DiagnosticData.Create(loadDiagnostic, document))); } var project = document.Project; var analyzers = GetAnalyzers(project.Solution.State.Analyzers, project); if (analyzers.IsEmpty) { return(ImmutableArray <DiagnosticData> .Empty); } var ideOptions = _service._globalOptions.GetIdeAnalyzerOptions(project); var compilationWithAnalyzers = await DocumentAnalysisExecutor.CreateCompilationWithAnalyzersAsync( project, ideOptions, analyzers, includeSuppressedDiagnostics : false, cancellationToken).ConfigureAwait(false); var analysisScope = new DocumentAnalysisScope(document, span: null, analyzers, kind); var executor = new DocumentAnalysisExecutor(analysisScope, compilationWithAnalyzers, _diagnosticAnalyzerRunner, logPerformanceInfo: true); using var _ = ArrayBuilder <DiagnosticData> .GetInstance(out var builder); foreach (var analyzer in analyzers) { builder.AddRange(await executor.ComputeDiagnosticsAsync(analyzer, cancellationToken).ConfigureAwait(false)); } return(builder.ToImmutable()); }
private async Task AnalyzeProjectAsync(Project project, bool forceAnalyzerRun, CancellationToken cancellationToken) { try { var stateSets = GetStateSetsForFullSolutionAnalysis(_stateManager.GetOrUpdateStateSets(project), project); // get driver only with active analyzers. var ideOptions = AnalyzerService.GlobalOptions.GetIdeAnalyzerOptions(project); // PERF: get analyzers that are not suppressed and marked as open file only // this is perf optimization. we cache these result since we know the result. (no diagnostics) var activeAnalyzers = stateSets .Select(s => s.Analyzer) .Where(a => DocumentAnalysisExecutor.IsAnalyzerEnabledForProject(a, project, GlobalOptions) && !a.IsOpenFileOnly(ideOptions.CleanupOptions?.SimplifierOptions)); CompilationWithAnalyzers?compilationWithAnalyzers = null; if (forceAnalyzerRun || GlobalOptions.IsFullSolutionAnalysisEnabled(project.Language)) { compilationWithAnalyzers = await DocumentAnalysisExecutor.CreateCompilationWithAnalyzersAsync(project, ideOptions, activeAnalyzers, includeSuppressedDiagnostics : true, cancellationToken).ConfigureAwait(false); } var result = await GetProjectAnalysisDataAsync(compilationWithAnalyzers, project, ideOptions, stateSets, forceAnalyzerRun, cancellationToken).ConfigureAwait(false); if (result.OldResult == null) { RaiseProjectDiagnosticsIfNeeded(project, stateSets, result.Result); return; } // no cancellation after this point. // any analyzer that doesn't have result will be treated as returned empty set // which means we will remove those from error list foreach (var stateSet in stateSets) { var state = stateSet.GetOrCreateProjectState(project.Id); await state.SaveToInMemoryStorageAsync(project, result.GetResult(stateSet.Analyzer)).ConfigureAwait(false); } RaiseProjectDiagnosticsIfNeeded(project, stateSets, result.OldResult, result.Result); } catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken)) { throw ExceptionUtilities.Unreachable; } }
private static Task <CompilationWithAnalyzers?> CreateCompilationWithAnalyzersAsync(Project project, IdeAnalyzerOptions ideOptions, IEnumerable <StateSet> stateSets, bool includeSuppressedDiagnostics, CancellationToken cancellationToken) => DocumentAnalysisExecutor.CreateCompilationWithAnalyzersAsync(project, ideOptions, stateSets.Select(s => s.Analyzer), includeSuppressedDiagnostics, cancellationToken);