public void Parse(Document document) { if (document != null) { lock (_parseGate) { CancelParse(document.Id); if (SolutionCrawlerOptions.GetBackgroundAnalysisScope(document.Project) == BackgroundAnalysisScope.ActiveFile && _documentTrackingService?.TryGetActiveDocument() != document.Id) { // Avoid performing any background parsing for non-active files // if the user has explicitly set the background analysis scope // to only analyze active files. // Note that we bail out after executing CancelParse to ensure // all the current background parsing tasks are cancelled. return; } if (IsStarted) { _ = ParseDocumentAsync(document); } } } }
private bool IsNuGetInstalled() { if (_nugetInstallStatusForCurrentSolution != FxCopAnalyzersInstallStatus.Installed) { var activeDocumentId = _documentTrackingService.TryGetActiveDocument(); if (activeDocumentId == null) { return(false); } var document = _workspace.CurrentSolution.GetTextDocument(activeDocumentId); if (document == null) { return(false); } foreach (var analyzerReference in document.Project.AnalyzerReferences) { if (ChildAnalyzerNuGetPackageIds.Contains(analyzerReference.Display)) { // We set installed to ensure we don't go through this again next time a // suggested action is called for any document in current solution. _nugetInstallStatusForCurrentSolution = FxCopAnalyzersInstallStatus.Installed; return(true); } } } return(false); }
private bool IsNuGetInstalled(out bool hasUnresolvedAnalyzerReference) { hasUnresolvedAnalyzerReference = false; if (_nugetInstallStatusForCurrentSolution != FxCopAnalyzersInstallStatus.Installed) { var activeDocumentId = _documentTrackingService.TryGetActiveDocument(); if (activeDocumentId == null) { return(false); } var document = _workspace.CurrentSolution.GetTextDocument(activeDocumentId); if (document == null) { return(false); } if (IsNuGetInstalled(document.Project.AnalyzerReferences, out hasUnresolvedAnalyzerReference)) { // We set installed to ensure we don't go through this again next time a // suggested action is called for any document in current solution. _nugetInstallStatusForCurrentSolution = FxCopAnalyzersInstallStatus.Installed; return(true); } } return(false); }
public ActiveProjectCacheManager(IDocumentTrackingService documentTrackingService, ProjectCacheService projectCacheService) { _projectCacheService = projectCacheService; documentTrackingService.ActiveDocumentChanged += UpdateCache; UpdateCache(null, documentTrackingService.TryGetActiveDocument()); }
/// <summary> /// Gets the active <see cref="Document"/> the user is currently working in. May be null if /// there is no active document or the active document is not in this <paramref name="solution"/>. /// </summary> public static Document?GetActiveDocument( this IDocumentTrackingService service, Solution solution ) { // Note: GetDocument checks that the DocId is contained in the solution, and returns null if not. return(solution.GetDocument(service.TryGetActiveDocument())); }
public void Enqueue(WorkItem item) { Contract.ThrowIfNull(item.DocumentId); var options = _registration.Workspace.Options; var analysisScope = SolutionCrawlerOptions.GetBackgroundAnalysisScope(options, item.Language); if (ShouldEnqueueForAllQueues(item, analysisScope)) { _highPriorityProcessor.Enqueue(item); _normalPriorityProcessor.Enqueue(item); _lowPriorityProcessor.Enqueue(item); } else { if (TryGetItemWithOverriddenAnalysisScope(item, _highPriorityProcessor.Analyzers, options, analysisScope, _listener, out var newWorkItem)) { _highPriorityProcessor.Enqueue(newWorkItem.Value); } if (TryGetItemWithOverriddenAnalysisScope(item, _normalPriorityProcessor.Analyzers, options, analysisScope, _listener, out newWorkItem)) { _normalPriorityProcessor.Enqueue(newWorkItem.Value); } if (TryGetItemWithOverriddenAnalysisScope(item, _lowPriorityProcessor.Analyzers, options, analysisScope, _listener, out newWorkItem)) { _lowPriorityProcessor.Enqueue(newWorkItem.Value); } item.AsyncToken.Dispose(); } ReportPendingWorkItemCount(); return; bool ShouldEnqueueForAllQueues(WorkItem item, BackgroundAnalysisScope analysisScope) { var reasons = item.InvocationReasons; // For active file analysis scope we only process following: // 1. Active documents // 2. Closed and removed documents to ensure that data for removed and closed documents // is no longer held in memory and removed from any user visible components. // For example, this ensures that diagnostics for closed/removed documents are removed from error list. // Note that we don't need to specially handle "Project removed" or "Project closed" case, as the solution crawler // enqueues individual "DocumentRemoved" work items for each document in the removed project. if (analysisScope == BackgroundAnalysisScope.ActiveFile && !reasons.Contains(PredefinedInvocationReasons.DocumentClosed) && !reasons.Contains(PredefinedInvocationReasons.DocumentRemoved)) { return(item.DocumentId == _documentTracker?.TryGetActiveDocument()); } return(true); } }
private async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeOutOfProcAsync( DocumentAnalysisScope?documentAnalysisScope, Project project, CompilationWithAnalyzers compilationWithAnalyzers, RemoteHostClient client, bool forceExecuteAllAnalyzers, bool logPerformanceInfo, bool getTelemetryInfo, CancellationToken cancellationToken) { var solution = project.Solution; using var pooledObject = SharedPools.Default <Dictionary <string, DiagnosticAnalyzer> >().GetPooledObject(); var analyzerMap = pooledObject.Object; var analyzers = documentAnalysisScope?.Analyzers ?? compilationWithAnalyzers.Analyzers.Where(a => forceExecuteAllAnalyzers || !a.IsOpenFileOnly(solution.Options)); analyzerMap.AppendAnalyzerMap(analyzers); if (analyzerMap.Count == 0) { return(DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty); } // Use high priority if we are force executing all analyzers for user action OR serving an active document request. var isHighPriority = forceExecuteAllAnalyzers || documentAnalysisScope != null && _documentTrackingService?.TryGetActiveDocument() == documentAnalysisScope.TextDocument.Id; var argument = new DiagnosticArguments( isHighPriority, compilationWithAnalyzers.AnalysisOptions.ReportSuppressedDiagnostics, logPerformanceInfo, getTelemetryInfo, documentAnalysisScope?.TextDocument.Id, documentAnalysisScope?.Span, documentAnalysisScope?.Kind, project.Id, analyzerMap.Keys.ToArray()); return(await client.RunRemoteAsync( WellKnownServiceHubService.CodeAnalysis, nameof(IRemoteDiagnosticAnalyzerService.CalculateDiagnosticsAsync), solution, new object[] { argument }, callbackTarget : null, (s, c) => ReadCompilerAnalysisResultAsync(s, analyzerMap, documentAnalysisScope, project, c), cancellationToken).ConfigureAwait(false)); }
private static bool AnalysisEnabled(TextDocument document, IDocumentTrackingService documentTrackingService) { if (document.Services.GetService <DocumentPropertiesService>()?.DiagnosticsLspClientName != null) { // This is a generated Razor document, and they want diagnostics, so let's report it return(true); } if (!document.SupportsDiagnostics()) { return(false); } // change it to check active file (or visible files), not open files if active file tracking is enabled. // otherwise, use open file. if (SolutionCrawlerOptions.GetBackgroundAnalysisScope(document.Project) == BackgroundAnalysisScope.ActiveFile) { return(documentTrackingService.TryGetActiveDocument() == document.Id); } else { return(document.IsOpen()); } }
private async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeOutOfProcAsync( DocumentAnalysisScope?documentAnalysisScope, Project project, CompilationWithAnalyzers compilationWithAnalyzers, RemoteHostClient client, bool forceExecuteAllAnalyzers, bool logPerformanceInfo, bool getTelemetryInfo, CancellationToken cancellationToken) { var solution = project.Solution; using var pooledObject = SharedPools.Default <Dictionary <string, DiagnosticAnalyzer> >().GetPooledObject(); var analyzerMap = pooledObject.Object; var analyzers = documentAnalysisScope?.Analyzers ?? compilationWithAnalyzers.Analyzers.Where(a => forceExecuteAllAnalyzers || !a.IsOpenFileOnly(solution.Options)); analyzerMap.AppendAnalyzerMap(analyzers); if (analyzerMap.Count == 0) { return(DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty); } // Use high priority if we are force executing all analyzers for user action OR serving an active document request. var isHighPriority = forceExecuteAllAnalyzers || documentAnalysisScope != null && _documentTrackingService?.TryGetActiveDocument() == documentAnalysisScope.TextDocument.Id; var argument = new DiagnosticArguments( isHighPriority, compilationWithAnalyzers.AnalysisOptions.ReportSuppressedDiagnostics, logPerformanceInfo, getTelemetryInfo, documentAnalysisScope?.TextDocument.Id, documentAnalysisScope?.Span, documentAnalysisScope?.Kind, project.Id, analyzerMap.Keys.ToArray()); var result = await client.TryInvokeAsync <IRemoteDiagnosticAnalyzerService, SerializableDiagnosticAnalysisResults>( solution, invocation : (service, solutionInfo, cancellationToken) => service.CalculateDiagnosticsAsync(solutionInfo, argument, cancellationToken), callbackTarget : null, cancellationToken).ConfigureAwait(false); if (!result.HasValue) { return(DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty); } // handling of cancellation and exception var version = await DiagnosticIncrementalAnalyzer.GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false); var documentIds = (documentAnalysisScope != null) ? ImmutableHashSet.Create(documentAnalysisScope.TextDocument.Id) : null; return(new DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult>( result.Value.Diagnostics.ToImmutableDictionary( entry => analyzerMap[entry.analyzerId], entry => DiagnosticAnalysisResult.Create( project, version, syntaxLocalMap: Hydrate(entry.diagnosticMap.Syntax, project), semanticLocalMap: Hydrate(entry.diagnosticMap.Semantic, project), nonLocalMap: Hydrate(entry.diagnosticMap.NonLocal, project), others: entry.diagnosticMap.Other, documentIds)), result.Value.Telemetry.ToImmutableDictionary(entry => analyzerMap[entry.analyzerId], entry => entry.telemetry))); }