/// <summary>
        /// Initiate a search and return all search items matching the search context. Other items can be found later using the asynchronous searches.
        /// </summary>
        /// <param name="context">The current search context</param>
        /// <returns>A list of search items matching the search query.</returns>
        public static List <SearchItem> GetItems(SearchContext context, SearchFlags options = SearchFlags.Default)
        {
            // Stop all search sessions every time there is a new search.
            context.sessions.StopAllAsyncSearchSessions();

            var allItems = new List <SearchItem>(3);

            #if QUICKSEARCH_DEBUG
            var debugProviderList = context.providers.ToList();
            using (new DebugTimer($"Search get items {String.Join(", ", debugProviderList.Select(p=>p.name.id))} -> {context.searchQuery}"));
            #endif
            foreach (var provider in context.providers)
            {
                using (var fetchTimer = new DebugTimer(null))
                {
                    try
                    {
                        var iterator = provider.fetchItems(context, allItems, provider);
                        if (iterator != null)
                        {
                            if (options.HasFlag(SearchFlags.Synchronous))
                            {
                                var stackedEnumerator = new StackedEnumerator <SearchItem>(iterator);
                                while (stackedEnumerator.MoveNext())
                                {
                                    if (stackedEnumerator.Current != null)
                                    {
                                        allItems.Add(stackedEnumerator.Current);
                                    }
                                }
                            }
                            else
                            {
                                var session = context.sessions.GetProviderSession(provider.name.id);
                                session.Reset(iterator, k_MaxFetchTimeMs);
                                session.Start();
                                if (!session.FetchSome(allItems, k_MaxFetchTimeMs))
                                {
                                    session.Stop();
                                }
                            }
                        }
                        provider.RecordFetchTime(fetchTimer.timeMs);
                    }
                    catch (Exception ex)
                    {
                        UnityEngine.Debug.LogException(new Exception($"Failed to get fetch {provider.name.displayName} provider items.", ex));
                    }
                }
            }

            if (!options.HasFlag(SearchFlags.Sorted))
            {
                return(allItems);
            }

            allItems.Sort(SortItemComparer);
            return(allItems.GroupBy(i => i.id).Select(i => i.First()).ToList());
        }
 /// <summary>
 /// Hard reset an async search session.
 /// </summary>
 /// <param name="itemEnumerator">The enumerator that will yield new search results. This object can be an IEnumerator or IEnumerable</param>
 /// <param name="maxFetchTimePerProviderMs">The amount of time allowed to yield new results.</param>
 /// <remarks>Normally async search sessions are re-used per search provider.</remarks>
 public void Reset(object itemEnumerator, long maxFetchTimePerProviderMs = k_MaxTimePerUpdate)
 {
     // Remove and add the event handler in case it was already removed.
     Stop();
     searchInProgress            = true;
     m_MaxFetchTimePerProviderMs = maxFetchTimePerProviderMs;
     m_ItemsEnumerator           = new StackedEnumerator <SearchItem>(itemEnumerator);
     EditorApplication.update   += OnUpdate;
 }
Example #3
0
        /// <summary>
        /// Initiate a search and return all search items matching the search context. Other items can be found later using the asynchronous searches.
        /// </summary>
        /// <param name="context">The current search context</param>
        /// <param name="options">Options defining how the query will be performed</param>
        /// <returns>A list of search items matching the search query.</returns>
        public static List <SearchItem> GetItems(SearchContext context, SearchFlags options = SearchFlags.Default)
        {
            DebugInfo.gcFetch = GC.GetTotalMemory(false);

            // Stop all search sessions every time there is a new search.
            context.sessions.StopAllAsyncSearchSessions();
            context.searchFinishTime = context.searchStartTime = EditorApplication.timeSinceStartup;
            context.sessionEnded    -= OnSearchEnded;
            context.sessionEnded    += OnSearchEnded;

            #if SHOW_SEARCH_PROGRESS
            if (Progress.Exists(context.progressId))
            {
                Progress.Finish(context.progressId, Progress.Status.Succeeded);
            }
            context.progressId = Progress.Start($"Searching...", options: Progress.Options.Indefinite);
            #endif

            if (options.HasFlag(SearchFlags.WantsMore))
            {
                context.wantsMore = true;
            }

            if (options.HasFlag(SearchFlags.Synchronous))
            {
                context.options |= SearchFlags.Synchronous;
            }

            int fetchProviderCount = 0;
            var allItems           = new List <SearchItem>(3);
            #if QUICKSEARCH_DEBUG
            var debugProviderList = context.providers.ToList();
            using (new DebugTimer($"Search get items {String.Join(", ", debugProviderList.Select(p=>p.name.id))} -> {context.searchQuery}"));
            #endif
            foreach (var provider in context.providers)
            {
                try
                {
                    var watch = new System.Diagnostics.Stopwatch();
                    watch.Start();
                    fetchProviderCount++;
                    var iterator = provider.fetchItems(context, allItems, provider);
                    if (iterator != null && options.HasFlag(SearchFlags.Synchronous))
                    {
                        var stackedEnumerator = new StackedEnumerator <SearchItem>(iterator);
                        while (stackedEnumerator.MoveNext())
                        {
                            if (stackedEnumerator.Current != null)
                            {
                                allItems.Add(stackedEnumerator.Current);
                            }
                        }
                    }
                    else
                    {
                        var session = context.sessions.GetProviderSession(context, provider.name.id);
                        session.Reset(context, iterator, k_MaxFetchTimeMs);
                        session.Start();
                        var sessionEnded = !session.FetchSome(allItems, k_MaxFetchTimeMs);
                        if (options.HasFlag(SearchFlags.FirstBatchAsync))
                        {
                            session.SendItems(allItems);
                        }
                        if (sessionEnded)
                        {
                            session.Stop();
                        }
                    }
                    provider.RecordFetchTime(watch.Elapsed.TotalMilliseconds);
                }
                catch (Exception ex)
                {
                    UnityEngine.Debug.LogException(new Exception($"Failed to get fetch {provider.name.displayName} provider items.", ex));
                }
            }

            if (fetchProviderCount == 0)
            {
                OnSearchEnded(context);
                context.sessions.StopAllAsyncSearchSessions();
            }

            DebugInfo.gcFetch = GC.GetTotalMemory(false) - DebugInfo.gcFetch;

            if (!options.HasFlag(SearchFlags.Sorted))
            {
                return(allItems);
            }

            allItems.Sort(SortItemComparer);
            return(allItems.GroupBy(i => i.id).Select(i => i.First()).ToList());
        }