/// <summary> /// Search the given IMemberDatabase for matches to this query and put /// results into the results array provided. The capacity of the results /// array determines how many results are returned. /// </summary> /// <param name="db">Database to search</param> /// <param name="results">PartialArray to contain results, sized for the count desired.</param> /// <returns>True if results were added, False otherwise</returns> public bool TryFindMembers(IMemberDatabase db, ref PartialArray <Symbol> results) { // Ensure strings must be found again so that benchmarks are realistic ForceReresolve(); // Clear results from a previous query results.Clear(); // If there was no query, return with no results if (String.IsNullOrEmpty(SymbolName)) { return(false); } // Get required members from database StringStore strings = db.StringStore; ItemTree declaredMembers = db.DeclaredMembers; MemberIndex index = db.Index; // Map strings to the local StringStore. Stop immediately if any values aren't found. if (!ResolveStringsTo(strings)) { return(false); } // Cache whether this query needs details to match bool usesDetails = !this.Parameters8.IsEmpty() || this.Type != SymbolType.Any || this.Modifiers != SymbolModifier.None; int[] matches; int matchesIndex, matchesCount; if (SplitSymbolName8.Count == 1) { // Find the set of symbols with names in range. If no symbols in index, return nothing if (!index.TryGetMatchesInRange(SymbolNameSuffixIdentifiers, out matches, out matchesIndex, out matchesCount)) { return(false); } // If there was just one name part searched for, all matches count for (int i = matchesIndex; i < matchesIndex + matchesCount; ++i) { if ((usesDetails ? MatchesDetailed(declaredMembers, strings, db, matches[i]) : Matches(declaredMembers, strings, matches[i]))) { results.Add(new Symbol(db, matches[i])); if (results.IsFull) { return(true); } } } } else { // Find all entries with exactly the second-to-last name if (!index.TryGetMatchesInRange(SymbolNamePrefixIdentifiers[SymbolNamePrefixIdentifiers.Length - 1], out matches, out matchesIndex, out matchesCount)) { return(false); } for (int i = matchesIndex; i < matchesIndex + matchesCount; ++i) { int currentMatchIndex = matches[i]; // First, do all previous name parts in the query match? int currentAncestorIndex = currentMatchIndex; int namePartIndex = SymbolNamePrefixIdentifiers.Length - 2; for (; namePartIndex >= 0; --namePartIndex) { currentAncestorIndex = declaredMembers.GetParent(currentAncestorIndex); int currentAncestorNameIdentifier = declaredMembers.GetNameIdentifier(currentAncestorIndex); if (!SymbolNamePrefixIdentifiers[namePartIndex].Contains(currentAncestorNameIdentifier)) { break; } } if (namePartIndex != -1) { continue; } // If this was a full match, are we out of namespaces? if (IsFullNamespace) { currentAncestorIndex = declaredMembers.GetParent(currentAncestorIndex); SymbolType symbolAboveFullNameType = db.GetMemberType(currentAncestorIndex); if (!symbolAboveFullNameType.IsAboveNamespace()) { return(false); } } // Next, find children of this item which match the last part typed int leafId = declaredMembers.GetFirstChild(currentMatchIndex); while (leafId > 0) { if ((usesDetails ? MatchesDetailed(declaredMembers, strings, db, leafId) : Matches(declaredMembers, strings, leafId))) { results.Add(new Symbol(db, leafId)); if (results.IsFull) { return(true); } } leafId = declaredMembers.GetNextSibling(leafId); } } } return(results.Count > 0); }