in Elfie/Elfie/Model/MemberQuery.cs [164:249]
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;
}