예제 #1
0
        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);
        }
예제 #4
0
            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()));
 }
예제 #6
0
                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);
                    }
                }
예제 #7
0
        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));
        }
예제 #8
0
        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());
            }
        }
예제 #9
0
        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)));
        }