public void AddTypeLocations(IMemberDatabase db, Symbol current) { // If the type already has a location, it's already a source parse or fixed if (current.HasLocation) { return; } // Try to find a file path for any member within the type HashSet <string> typeFilePaths = new HashSet <string>(); current.Walk((c) => { if (c.HasLocation) { typeFilePaths.Add(c.FilePath.ToString()); } }); if (typeFilePaths.Count == 0) { return; } Compilation compilation = CreateCompilation(typeFilePaths.ToList(), current.AssemblyNameWithoutExtension + ".pdb"); if (compilation == null) { return; } AddTypeLocations(db, current, compilation); }
private bool ContainsPublics(IMemberDatabase source, int index) { SymbolType type = source.GetMemberType(index); SymbolModifier modifier = source.GetMemberModifiers(index); // If this is a public type or extension method, we contain them if ((type.IsType() || type.IsExtensionMethod()) && modifier.HasFlag(SymbolModifier.Public)) { return(true); } // If any descendants contain public types, we contain them int childIndex = source.DeclaredMembers.GetFirstChild(index); while (childIndex > 0) { if (ContainsPublics(source, childIndex)) { return(true); } childIndex = source.DeclaredMembers.GetNextSibling(childIndex); } // Otherwise, we don't return(false); }
public static void SearchScenarios(IMemberDatabase db) { // Verify search works (partial method name) Assert.AreEqual("Method FromGigabytes(double) @src\\net35\\Diagnostics\\Memory.cs(32,28)", SearchToString(db, "From")); // Verify search works (multiple matches) Assert.AreEqual( @"Method LogException(Exception) @src\net20\Diagnostics\Logger.cs(37,21) Method LogException(Exception) @src\net35\Diagnostics\Logger.cs(37,21) Class Logger @src\net20\Diagnostics\Logger.cs(8,18) Constructor Logger(string) @src\net20\Diagnostics\Logger.cs(22,16) Class Logger @src\net35\Diagnostics\Logger.cs(8,18) Constructor Logger(string) @src\net35\Diagnostics\Logger.cs(22,16) Method LogUse @src\net20\Diagnostics\Logger.cs(32,21) Method LogUse @src\net35\Diagnostics\Logger.cs(32,21)" , SearchToString(db, "Log")); // Verify search works (whole method name) Assert.AreEqual("Method FromGigabytes(double) @src\\net35\\Diagnostics\\Memory.cs(32,28)", SearchToString(db, "FromGigabytes")); // Verify search works (name plus more fails) Assert.AreEqual("", SearchToString(db, "FromGigabytesS")); // Verify search works (misspelling) Assert.AreEqual("", SearchToString(db, "AromGigabytes")); }
private void Load() { LoadStatus = "Loading Index..."; Draw(); try { IMemberDatabase db = null; MeasureDiagnostics diagnostics = Memory.Measure(() => { db = MemberDatabase.Load(Options.DatabasePath); return(db); }); lock (_queryLock) { Database = db; } LoadStatus = String.Format("Loaded {0:n0} members in {1} in {2}.", db.Count, diagnostics.MemoryUsedBytes.SizeString(), diagnostics.LoadTime.ToFriendlyString()); } catch (IOException ex) { LoadStatus = ""; RebuildStatus = String.Format("Error loading: {0}.", ex.Message); return; } RunQuery(); Draw(); }
private bool MatchesDetailed(ItemTree declaredMembers, StringStore strings, IMemberDatabase db, int symbolIndex) { if (!Matches(declaredMembers, strings, symbolIndex)) { return(false); } if (Type != SymbolType.Any && db.GetMemberType(symbolIndex) != Type) { return(false); } if (!Modifiers.Matches(db.GetMemberModifiers(symbolIndex))) { return(false); } // ISSUE: Need a way to specify you want the empty params overload of a method (other than full match) // NOTE: Parameters8 was a copy gotten from StringStore to make this comparison fast (rather than a byte-by-byte comparison) // NOTE: Case insensitive comparison because StringStore lookup was case-insensitive, so Parameters8 casing isn't specific // NOTE: Need String8 rather than just checking Range.Contains because IMemberDatabase doesn't offer returning the identifier if ((IsFullSuffix || !this.ParametersIdentifiers.IsEmpty()) && db.GetMemberParameters(symbolIndex).CompareTo(Parameters8, true) != 0) { return(false); } return(true); }
private static void WriteTextTree(TextWriter w, IMemberDatabase db, int index, int indent, bool[] nodesToDraw) { if (indent >= 0) { if (nodesToDraw[index] == false) { return; } for (int i = 0; i < indent; ++i) { w.Write("\t"); } w.Write((char)db.GetMemberType(index)); w.Write(" "); db.StringStore[db.DeclaredMembers.GetNameIdentifier(index)].WriteTo(w); w.WriteLine(); } int child = db.DeclaredMembers.GetFirstChild(index); while (child > 0) { WriteTextTree(w, db, child, indent + 1, nodesToDraw); child = db.DeclaredMembers.GetNextSibling(child); } }
public void AddTypeLocations(IMemberDatabase db, Symbol current, Compilation compilation) { // Try to find the type itself INamedTypeSymbol typeSymbol = FindTypeSymbol(compilation, current.ContainerName.ToString(), current.Name.ToString()); if (typeSymbol == null) { return; } // If found, add the type location AddLocation(db, current, typeSymbol); // Try to find member locations Symbol typeMember = current.FirstChild(); while (typeMember.IsValid) { ISymbol memberSymbol = FindMember(typeSymbol, typeMember.Name.ToString(), typeMember.Parameters.ToString()); if (memberSymbol != null) { AddLocation(db, typeMember, memberSymbol); } typeMember = typeMember.NextSibling(); } }
internal static string SearchToString(IMemberDatabase db, string memberName) { MemberQuery query = new MemberQuery(memberName, false, false); PartialArray <Symbol> results = new PartialArray <Symbol>(10); query.TryFindMembers(db, ref results); return(ResultToString(results)); }
/// <summary> /// Search the given IMemberDatabase for matches to this query, up to the given /// result count limit. /// </summary> /// <param name="db">Database to search</param> /// <param name="maxResultCount">Maximum count of results to return</param> /// <returns>Array of Symbol for each result</returns> public Symbol[] FindMembers(IMemberDatabase db, int maxResultCount) { PartialArray <Symbol> results = new PartialArray <Symbol>(maxResultCount); if (!TryFindMembers(db, ref results)) { return(EmptyArray <Symbol> .Instance); } return(results.ToArray()); }
public static bool TryGetFirstChildOfType(this IMemberDatabase db, int memberIndex, SymbolType symbolType, out int childIndex) { childIndex = db.DeclaredMembers.GetFirstChild(memberIndex); while (childIndex > 0) { if (db.GetMemberType(childIndex) == symbolType) { return(true); } childIndex = db.DeclaredMembers.GetNextSibling(childIndex); } return(false); }
public static bool TryGetAncestorOfType(this IMemberDatabase db, int memberIndex, SymbolType ancestorType, out int ancestor) { ancestor = memberIndex; while (ancestor > 0) { if (db.GetMemberType(ancestor) == ancestorType) { return(true); } ancestor = db.DeclaredMembers.GetParent(ancestor); } return(false); }
private void AddLocation(IMemberDatabase db, Symbol current, ISymbol roslynSymbol) { // Get MutableSymbol declaration location from Roslyn, if available if (roslynSymbol.Locations.Length != 0) { if (roslynSymbol.Locations[0].IsInSource) { // Roslyn locations are zero-based. Correct to normal positions. FileLinePositionSpan location = roslynSymbol.Locations[0].GetLineSpan(); db.SetLocation( current.Index, location.Path, (location.StartLinePosition.Line + 1).TrimToUShort(), (location.StartLinePosition.Character + 1).TrimToUShort()); } } }
public static PartialArray <Symbol> SearchPerformance(IMemberDatabase db, int iterations = 1) { MemberQuery[] searches = { new MemberQuery("St", false, false), // Small prefix in Elfie new MemberQuery("String8", false, false), // Short Type Name new MemberQuery("String8.", false, false), // Get Members new MemberQuery("String8.Com", false, false), // Get Members with filter new MemberQuery("Sorted", false, false), // Prefix in Arriba new MemberQuery("SortedColumn.Set", false, false), // Longer Name and member new MemberQuery("Newtonsoft.Json.JsonC", false, false), // Multi-part prefix in Json.NET new MemberQuery("JsonSerializerSettings.MaxD", false, false), // Long type name in JSON.NET new MemberQuery("PENam", false, false), // Short name in Roslyn new MemberQuery("PENamedTypeSymbol.", false, false) // Members in Roslyn }; return(SearchPerformance(db, searches, iterations)); }
public static PartialArray <Symbol> SearchPerformance(IMemberDatabase db, MemberQuery[] searches, int iterations = 1) { PartialArray <Symbol> lastSuccessfulResults = new PartialArray <Symbol>(); PartialArray <Symbol> results = new PartialArray <Symbol>(20); using (new TraceWatch("Searching {0:n0} times across {1:n0} values...", iterations, searches.Length)) { for (int iteration = 0; iteration < iterations; ++iteration) { MemberQuery query = searches[iteration % searches.Length]; query.TryFindMembers(db, ref results); if (results.Count > 0) { results.CopyTo(ref lastSuccessfulResults); } } } if (lastSuccessfulResults.Count > 0) { for (int i = 0; i < Math.Min(lastSuccessfulResults.Count, 5); ++i) { Symbol result = lastSuccessfulResults[i]; int lengthWritten = 0; lengthWritten += result.FullName.WriteTo(Console.Out); Console.Write(new string(' ', Math.Max(1, 60 - lengthWritten))); result.PackageName.WriteTo(Console.Out); Console.WriteLine(); } } else { Console.WriteLine("NOT FOUND."); } Console.WriteLine(); return(results); }
internal static string GetLocation(IMemberDatabase db, MemberQuery query) { PartialArray <Symbol> results = new PartialArray <Symbol>(10); query.TryFindMembers(db, ref results); StringBuilder resultText = new StringBuilder(); using (StringWriter writer = new StringWriter(resultText)) { for (int i = 0; i < results.Count; ++i) { if (i > 0) { writer.WriteLine(); } results[i].WriteLocation(writer); } } return(resultText.ToString()); }
public Symbol(IMemberDatabase database, int index) { _database = database; Index = index; }
public static void WriteMatchesInTreeFormat(TextWriter w, PartialArray <Symbol> results, IMemberDatabase db) { // Mark every result and every ancestor to draw bool[] nodesToDraw = new bool[db.Count]; for (int i = 0; i < results.Count; ++i) { Symbol result = results[i]; while (result.IsValid) { nodesToDraw[result.Index] = true; result = result.Parent(); } } // Draw the results of interest [assemblies and down only] WriteTextTree(w, db, 0, -2, nodesToDraw); }
public IncrementalCrawler(ICrawler innerCrawler, IMemberDatabase previousDatabase, DateTime previousWriteUtc) { this.InnerCrawler = innerCrawler; this.Previous = previousDatabase; this.PreviousWriteUtc = previousWriteUtc; }
/// <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); }