Example #1
0
        public async Task SearchAsync(
            bool searchCurrentDocument,
            NavigateToSearchScope scope,
            CancellationToken cancellationToken)
        {
            var isFullyLoaded = true;

            try
            {
                using var navigateToSearch = Logger.LogBlock(FunctionId.NavigateTo_Search, KeyValueLogMessage.Create(LogType.UserAction), cancellationToken);

                if (searchCurrentDocument)
                {
                    await SearchCurrentDocumentAsync(cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    // We consider ourselves fully loaded when both the project system has completed loaded us, and we've
                    // totally hydrated the oop side.  Until that happens, we'll attempt to return cached data from languages
                    // that support that.
                    isFullyLoaded = await _host.IsFullyLoadedAsync(cancellationToken).ConfigureAwait(false);
                    await SearchAllProjectsAsync(isFullyLoaded, scope, cancellationToken).ConfigureAwait(false);
                }
            }
            finally
            {
                // Ensure that we actually complete all our remaining progress items so that the progress bar completes.
                await ProgressItemsCompletedAsync(_remainingProgressItems, cancellationToken).ConfigureAwait(false);

                Debug.Assert(_remainingProgressItems == 0);

                // Pass along isFullyLoaded so that the UI can show indication to users that results may be incomplete.
                _callback.Done(isFullyLoaded);
            }
        }
Example #2
0
 public SearchGraphQuery(
     string searchPattern,
     NavigateToSearchScope searchScope,
     IThreadingContext threadingContext,
     IAsynchronousOperationListener asyncListener)
 {
     _threadingContext = threadingContext;
     _asyncListener    = asyncListener;
     _searchPattern    = searchPattern;
     _searchScope      = searchScope;
 }
Example #3
0
        private async Task SearchAllProjectsAsync(
            bool isFullyLoaded,
            NavigateToSearchScope scope,
            CancellationToken cancellationToken)
        {
            var seenItems       = new HashSet <INavigateToSearchResult>(NavigateToSearchResultComparer.Instance);
            var orderedProjects = GetOrderedProjectsToProcess();

            var searchRegularDocuments   = scope.HasFlag(NavigateToSearchScope.RegularDocuments);
            var searchGeneratedDocuments = scope.HasFlag(NavigateToSearchScope.GeneratedDocuments);

            Debug.Assert(searchRegularDocuments || searchGeneratedDocuments);

            var projectCount = orderedProjects.Sum(g => g.Length);

            if (isFullyLoaded)
            {
                // We may do up to two passes.  One for loaded docs.  One for source generated docs.
                await AddProgressItemsAsync(
                    projectCount *((searchRegularDocuments ? 1 : 0) + (searchGeneratedDocuments ? 1 : 0)),
                    cancellationToken).ConfigureAwait(false);

                if (searchRegularDocuments)
                {
                    await SearchFullyLoadedProjectsAsync(orderedProjects, seenItems, cancellationToken).ConfigureAwait(false);
                }

                if (searchGeneratedDocuments)
                {
                    await SearchGeneratedDocumentsAsync(seenItems, cancellationToken).ConfigureAwait(false);
                }
            }
            else
            {
                // If we're not fully loaded, we only search regular documents.  Generated documents must wait until
                // we're fully loaded (and thus have all the information necessary to properly run generators).
                if (searchRegularDocuments)
                {
                    // We do at least two passes.  One for cached docs.  One for normal docs.
                    await AddProgressItemsAsync(
                        projectCount * 2,
                        cancellationToken).ConfigureAwait(false);

                    await SearchCachedDocumentsAsync(orderedProjects, seenItems, cancellationToken).ConfigureAwait(false);

                    // If searching cached data returned any results, then we're done.  We've at least shown some results
                    // to the user.  That will hopefully serve them well enough until the solution fully loads.
                    if (seenItems.Count > 0)
                    {
                        return;
                    }

                    await SearchFullyLoadedProjectsAsync(orderedProjects, seenItems, cancellationToken).ConfigureAwait(false);

                    // Report a telemetry event to track if we found uncached items after failing to find cached items.
                    // In practice if we see that we are always finding uncached items, then it's likely something
                    // has broken in the caching system since we would expect to normally find values there.  Specifically
                    // we expect: foundFullItems <<< not foundFullItems.
                    Logger.Log(FunctionId.NavigateTo_CacheItemsMiss, KeyValueLogMessage.Create(m => m["FoundFullItems"] = seenItems.Count > 0));
                }
            }
        }