private String8Set SplitRows(String8 block, PartialArray <int> rowPositionArray) { // Split the block into lines (and save the split for use splitting columns) _blockLines = block.Split(UTF8.Newline, _lineArray); // Reset where which line the next row begins with _nextLineIndex = 0; rowPositionArray.Clear(); rowPositionArray.Add(0); for (int i = 0; i < _blockLines.Count - 1; ++i) { String8 line = _blockLines[i]; // An empty line (or \n\r\n) indicates a new logical row if (line.Length == 0 || (line.Length == 1 && line[0] == UTF8.CR)) { rowPositionArray.Add(_lineArray[i + 1]); } } rowPositionArray.Add(block.Length + 1); return(new String8Set(block, 1, rowPositionArray)); }
public static void WriteMatchesForToolUse(TextWriter writer, PartialArray <Symbol> results) { for (int i = 0; i < results.Count; ++i) { Symbol result = results[i]; Path8 containerName = result.ContainerName; if (!containerName.IsEmpty) { containerName.WriteTo(writer); writer.Write('.'); } result.WriteSignature(writer); writer.Write('\t'); // Write full location (local/found code) or package (package index) if (result.HasLocation) { result.FilePath.WriteTo(writer); writer.Write('('); writer.Write(result.Line); writer.Write(')'); } else { result.PackageName.WriteTo(writer); } writer.WriteLine(); } }
/// <summary> /// Split a string into alphanumeric words without allocation by using /// the same PartialArray<int> in a loop. When traversing over the /// returned String8Set, check if each first letter IsAlphaNumeric to /// decide whether to include it. /// </summary> /// <param name="value">String8 to split</param> /// <param name="buffer">PartialArray to contain split positions [allows reuse without allocations]</param> /// <returns>String8Set containing value split at alpha-to-non-alpha boundaries</returns> public static String8Set Split(String8 value, ref PartialArray <int> buffer) { // Reset the buffer for our use buffer.Clear(); if (!value.IsEmpty()) { // Add the beginning as a part buffer.Add(0); bool inWord = IsAlphaNumeric(value[0]); for (int i = 1; i < value.Length; ++i) { bool charIsAlpha = IsAlphaNumeric(value[i]); if (inWord != charIsAlpha) { // Add a boundary at each alpha to non-alpha transition buffer.Add(i); inWord = charIsAlpha; } } // Add the remaining part of the string buffer.Add(value.Length); } return(new String8Set(value, 0, buffer)); }
public void AlphanumericSplitter_Performance() { String8 code = AllCodeText.AllCode8; String8Set set = default(String8Set); PartialArray <int> matchContainer = new PartialArray <int>(); int iterations = 10; int totalWordsSplit = 0; int validCount = 0; // Split Goal: 75k per millisecond [75 MB/sec] Verify.PerformanceByBytes(75 * LongExtensions.Megabyte, () => { for (int iteration = 0; iteration < iterations; ++iteration) { set = AlphanumericSplitter.Split(code, ref matchContainer); totalWordsSplit += set.Count; if (set.Count > 0) { int matchIndex = AlphanumericSplitter.IsAlphaNumeric(set[0][0]) ? 0 : 1; for (; matchIndex < set.Count; matchIndex += 2) { String8 word = set[matchIndex]; if (word.Length > 2) { validCount++; } } } } return(iterations * code.Length); }); }
public void PartialArray_MembersProvided() { // Build a partially filled array int[] array = new int[10]; for (int i = 0; i < 5; ++i) { array[i] = i; } // Build a PartialArray around it PartialArray <int> a = new PartialArray <int>(array, 5, true); // Verify it knows it's partially full already Assert.AreEqual(5, a.Count); Assert.AreEqual(3, a[3]); Assert.AreEqual(10, a.Capacity); Assert.IsTrue(a.IsStaticSize); Assert.IsFalse(a.IsFull); // Add another value; verify it goes to the right place a.Add(5); Assert.AreEqual(6, a.Count); Assert.AreEqual(5, a[5]); Assert.AreEqual(5, array[5]); }
private static void GoToDefinition(PackageDatabase db, MemberQuery[] searches, int iterations = 1) { PartialArray <Symbol> lastSuccessfulResults = new PartialArray <Symbol>(); PartialArray <Symbol> results = new PartialArray <Symbol>(10); using (new TraceWatch("Go To Definition {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) { lastSuccessfulResults[0].WriteLocation(Console.Out); Console.WriteLine(); } else { Console.WriteLine("NOT FOUND."); } Console.WriteLine(); }
public void PackageDatabase_Basic() { // Build a sample database. Verify all add operations work. Verify serialization happens. Verify load is able to read serialized bits without error. BuildDefaultAndRoundtrip(); // Round trip an empty database. Verify no file written. string serializationPath = "EmptyPackage.idx"; PackageDatabase db = new PackageDatabase(); Assert.IsTrue(db.IsEmpty); db.FileWrite(serializationPath); Assert.IsFalse(File.Exists(serializationPath)); // Round trip a database without anything indexed. Verify file written, reload and search work without exceptions db.MutableRoot.AddChild(new MutableSymbol("System", SymbolType.Namespace)); Assert.IsFalse(db.IsEmpty); PackageDatabase readDB = new PackageDatabase(); Verify.RoundTrip(db, readDB); PartialArray <Symbol> results = new PartialArray <Symbol>(10); new MemberQuery(NS_SAMPLE, false, false).TryFindMembers(readDB, ref results); Assert.AreEqual(0, results.Count); }
/// <summary> /// Convert a whole PartialArray of identifiers from the ones assigned by FindOrAdd /// to the values being serialized out. /// </summary> /// <param name="stringIdentifiers">PartialArray containing string identifiers for this StringStore</param> public void ConvertToImmutable(PartialArray <int> stringIdentifiers) { for (int i = 0; i < stringIdentifiers.Count; ++i) { stringIdentifiers[i] = this.GetSerializationIdentifier(stringIdentifiers[i]); } }
/// <summary> /// Construct a BaseTabularReader to read the given stream. /// </summary> /// <param name="stream">Stream to read</param> /// <param name="hasHeaderRow">True to read the first row as column names, False not to pre-read anything</param> public BaseTabularReader(Stream stream, bool hasHeaderRow = true) { _reader = stream; _columnHeadingsList = new List <string>(); _columnHeadings = new Dictionary <string, int>(StringComparer.OrdinalIgnoreCase); _buffer = new byte[64 * 1024]; _rowCountRead = 0; _nextRowIndexInBlock = 0; _rowPositionArray = new PartialArray <int>(64, false); _cellPositionArray = new PartialArray <int>(1024, false); // Read the heading row and record heading positions if (hasHeaderRow) { if (!NextRow()) { throw new IOException("Reader didn't find any rows when trying to read a header row."); } for (int i = 0; i < _currentRow.Count; ++i) { string columnName = this.Current(i).ToString(); _columnHeadingsList.Add(columnName); _columnHeadings[columnName] = i; } // Header row doesn't count toward row count read _rowCountRead = 0; } }
public static string SplitAndJoin(string value) { String8 value8 = String8.Convert(value, new byte[String8.GetLength(value)]); PartialArray <int> boundaryArray = new PartialArray <int>(); String8Set set = AlphanumericSplitter.Split(value8, ref boundaryArray); bool firstPart = true; StringBuilder result = new StringBuilder(); using (StringWriter writer = new StringWriter(result)) { for (int i = 0; i < set.Count; ++i) { String8 part = set[i]; if (!part.IsEmpty() && AlphanumericSplitter.IsAlphaNumeric(part[0])) { if (!firstPart) { writer.Write("|"); } firstPart = false; part.WriteTo(writer); } } } return(result.ToString()); }
public ImmutableStringStore ConvertToImmutable(out int[] identifierToSerializedIdentifier) { int valueCount = _values.Count; // Build an array of string indexes sorted by the strings int[] valueIndexesSorted = new int[valueCount]; for (int i = 0; i < valueCount; ++i) { valueIndexesSorted[i] = i; } // Sort index array to point to values in sorted order // NOTE: Sort is case insensitive stable (case insensitive search and minimal diff size) Array.Sort(_values.ToArray(), valueIndexesSorted, s_comparer); // Build a map from the original identifiers (ascending order by when inserted) to the new ones (sorted order) to fix references int[] map = new int[valueCount]; for (int i = 0; i < valueCount; ++i) { int oldIdentifier = valueIndexesSorted[i]; int newIdentifier = i; map[oldIdentifier] = newIdentifier; } // Walk in sorted order and determine the byte position where each value will be written int totalLength = 0; PartialArray <int> positions = new PartialArray <int>(new int[valueIndexesSorted.Length + 1]); for (int i = 0; i < valueIndexesSorted.Length; ++i) { positions.Add(totalLength); // Compute space needed for this value and delimiter (\r\n delimited) totalLength += String8.GetLength(_values[valueIndexesSorted[i]]) + 2; } positions.Add(totalLength); // Build byte[] with the concatenated values byte[] sortedValueBytes = new byte[totalLength]; int nextWritePosition = 0; for (int i = 0; i < valueIndexesSorted.Length; ++i) { // Copy value to output array String8 newValue = String8.Convert(_values[valueIndexesSorted[i]], sortedValueBytes, nextWritePosition); nextWritePosition += newValue.Length; sortedValueBytes[nextWritePosition] = UTF8.CR; sortedValueBytes[nextWritePosition + 1] = UTF8.LF; nextWritePosition += 2; } // Build the ImmutableStore equivalent of this and an array to translate identifiers identifierToSerializedIdentifier = map; return(new ImmutableStringStore(new String8Set(new String8(sortedValueBytes, 0, sortedValueBytes.Length), 2, positions))); }
public void Clear() { this.Strings = new StringStore(); this.NameIdentifiers = new PartialArray <int>(); this.TargetIdentifiers = new PartialArray <int>(); this.Types = new PartialArray <byte>(); this.EventTimes = new PartialArray <long>(); }
public BufferedRowReader(Stream stream, Func <String8, PartialArray <int>, String8Set> splitRows) { _stream = stream; _splitRows = splitRows; _buffer = new byte[Math.Min(stream.Length + 1, 64 * 1024)]; _rowPositionArray = new PartialArray <int>(64, false); }
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)); }
protected override String8Set SplitCells(String8 row, PartialArray <int> cellPositionArray) { // Remove trailing '\r' to handle '\r\n' and '\n' line endings uniformly if (row.EndsWith(UTF8.CR)) { row = row.Substring(0, row.Length - 1); } return(row.SplitAndDecodeCsvCells(cellPositionArray)); }
public void Indexer_GenericSignature() { MemberQuery q = new MemberQuery("GenericSignature", true, false); PartialArray <Symbol> results = new PartialArray <Symbol>(10); Assert.IsTrue(q.TryFindMembers(DB, ref results)); Symbol first = results[0]; Assert.AreEqual("List<Q>", first.Parameters.ToString()); }
public void ReadBinary(BinaryReader r) { _delimiterWidth = r.ReadInt32(); _content = new String8(); _content.ReadBinary(r); _partPositions = new PartialArray <int>(); _partPositions.ReadBinary(r); }
private List <Symbol> FilterToViableTypes(PartialArray <Symbol> symbols) { // Don't return nested types. Currently their value does not seem worth // it given all the extra stuff we'd have to plumb through. Namely // going down the "using static" code path and whatnot. return(new List <Symbol>( from symbol in symbols where this.IsType(symbol) && !this.IsType(symbol.Parent()) select symbol)); }
public bool Run(TextWriter writer) { bool result = true; string testDataPath = Path.Combine(Environment.CurrentDirectory, @"..\..\TestData\PackageDatabases"); string rootPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); string[] dirs = new string[] { "v4.0", "v4.5.2" }; string[] files = new string[] { "System.Data.dll" }; rootPath = Path.Combine(rootPath, @"Reference Assemblies\Microsoft\Framework\.NETFramework\"); foreach (string dir in dirs) { foreach (string file in files) { HashSet <string> publicNonNested = new HashSet <string>(); HashSet <string> otherTypes = new HashSet <string>(); string assemblyPath = Path.Combine(rootPath, dir, file); Walk(assemblyPath, publicNonNested, otherTypes); PackageDatabase db = Indexer.IndexCommand.Index(assemblyPath, true, true); File.WriteAllText(Path.Combine(testDataPath, file + "." + dir + ".actual.txt"), db.ToString()); db.ConvertToImmutable(); var results = new PartialArray <Symbol>(10); foreach (string typeName in publicNonNested) { var query = new MemberQuery(typeName, false, false); query.TryFindMembers(db, ref results); if (results.Count == 0) { writer.WriteLine("Found " + results.Count + " (instead of 1 or more) matches for " + typeName); result = false; } } foreach (string typeName in otherTypes) { var query = new MemberQuery(typeName, true, true); query.TryFindMembers(db, ref results); if (results.Count == 0) { writer.WriteLine("Found " + results.Count + " (instead of 1 or more) matches for " + typeName); result = false; } } } } return(result); }
public void Indexer_PrivateMethod() { MemberQuery q = new MemberQuery("PrivateMethod", true, false); PartialArray <Symbol> results = new PartialArray <Symbol>(10); // Verify private methods are indexed and modifiers are right Assert.IsTrue(q.TryFindMembers(DB, ref results)); Symbol first = results[0]; Assert.AreEqual(SymbolModifier.Private, first.Modifiers); }
/// <summary> /// Split a string on a given delimiter only outside matching double quotes. /// Used to split CSV content where the delimiters are ignored within quotes. /// </summary> /// <param name="value">String8 value to split</param> /// <param name="delimiter">Delimiter to split on</param> /// <param name="positions">PartialArray<int> to contain split positions</param> /// <returns>String8Set containing split value</returns> public static String8Set SplitOutsideQuotes(String8 value, byte delimiter, PartialArray <int> positions) { if (value.IsEmpty()) { return(String8Set.Empty); } // Clear any previous values in the array positions.Clear(); // The first part always begins at the start of the string positions.Add(0); byte[] array = value._buffer; int i = value._index; int end = i + value._length; // Walk the string. Find and mark delimiters outside of quotes only while (i < end) { // Outside Quotes for (; i < end; ++i) { // If a quote is found, we're now inside quotes if (array[i] == UTF8.Quote) { i++; break; } // If a delimiter is found, add another split position if (array[i] == delimiter) { positions.Add(i - value._index + 1); } } // Inside Quotes for (; i < end; ++i) { // If a quote was found, we're now outside quotes if (array[i] == UTF8.Quote) { i++; break; } } } // The last part always ends at the end of the string positions.Add(value.Length + 1); return(new String8Set(value, 1, positions)); }
/// <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()); }
internal static Symbol GetTryLogFromSample(PackageDatabase db) { db.ConvertToImmutable(); MemberQuery q = new MemberQuery("TryLog", false, false); PartialArray <Symbol> matches = new PartialArray <Symbol>(5); Assert.IsTrue(q.TryFindMembers(db, ref matches)); Assert.AreEqual(2, matches.Count); return(matches[0]); }
private void GoToDefinition() { Position current = new Position(); current.Save(); current.ClearUpTo(CommandEnd); Console.WriteLine(); LocationWithinFile p = VS.GetCurrentLocation(Options.DatabasePath); if (p == null) { Console.WriteLine("Unable to find current cursor position."); return; } else { Console.WriteLine("Finding Symbol at {0}({1}, {2})", p.FilePath, p.Line, p.CharInLine); } RoslynDefinitionFinder finder = new RoslynDefinitionFinder(p.FilePath, this.References); MemberQuery query = finder.BuildQueryForMemberUsedAt(p.Line, p.CharInLine); query.IgnoreCase = Options.IgnoreCase; if (query == null) { Console.WriteLine("Unable to identify symbol."); return; } Console.Write("Roslyn identified as {0}", query.SymbolName); if (query.Parameters.Length > 0) { Console.Write("({0})", query.Parameters); } Console.WriteLine(); PartialArray <Symbol> results = new PartialArray <Symbol>(1); if (query.TryFindMembers(this.Database, ref results)) { OpenSymbol(results[0]); } else { Console.WriteLine("NOT FOUND"); } CommandEnd.Save(); }
public ItemTree(int rootIdentifier) { _parentIndex = new PartialArray <int>(); _firstChildIndex = new PartialArray <int>(); _nextSiblingIndex = new PartialArray <int>(); _nameIdentifier = new PartialArray <int>(); // Add sentinel root _parentIndex.Add(-1); _firstChildIndex.Add(-1); _nextSiblingIndex.Add(-1); _nameIdentifier.Add(rootIdentifier); }
public void PackageDatabase_SearchPerformance() { PackageDatabase db = BuildCheckAndConvert(); MemberQuery[] queries = { new MemberQuery("Diag", false, false), // Namespace Prefix new MemberQuery("Log", false, false), // Prefix of Type and Methods new MemberQuery("Logger", true, false), // Class and Method name exactly new MemberQuery("Sample.Diagnostics.Logger", true, true), // Full Qualified Class Name new MemberQuery("LoggA", false, false) // Prefix with no matches }; PartialArray <Symbol> results = new PartialArray <Symbol>(40); int iterations = 20000; // Goal: ~1M searches per second [5 x 20k = 100k in under 100ms] Verify.PerformanceByOperation(1 * LongExtensions.Million, () => { for (int i = 0; i < iterations; ++i) { for (int j = 0; j < queries.Length; ++j) { queries[j].TryFindMembers(db, ref results); } } return(iterations * queries.Length); }); // ==== Case Sensitive ==== for (int j = 0; j < queries.Length; ++j) { queries[j].IgnoreCase = true; } // Goal: ~1M searches per second [5 x 20k = 100k in under 100ms] Verify.PerformanceByOperation(1 * LongExtensions.Million, () => { for (int i = 0; i < iterations; ++i) { for (int j = 0; j < queries.Length; ++j) { queries[j].TryFindMembers(db, ref results); } } return(iterations * queries.Length); }); }
public void AlphanumericSplitter_EndToEndPerformance() { String8 code = AllCodeText.AllCode8; String8Set set = default(String8Set); PartialArray <int> matchContainer = new PartialArray <int>(2048); HashSet <String8> uniqueWords = new HashSet <String8>(); StringStore strings = new StringStore(); MemberIndex index = new MemberIndex(); int iterations = 10; int totalWordsSplit = 0; // Split, Add, Index Goal: 30k per millisecond [30 MB/sec] Verify.PerformanceByBytes(30 * LongExtensions.Megabyte, () => { for (int iteration = 0; iteration < iterations; ++iteration) { String8Set codeByLine = code.Split(UTF8.Newline, new PartialArray <int>()); for (int lineIndex = 0; lineIndex < codeByLine.Count; ++lineIndex) { // Convert and Split the line String8 line = codeByLine[lineIndex]; set = AlphanumericSplitter.Split(line, ref matchContainer); totalWordsSplit += set.Count; if (set.Count > 0) { int matchIndex = AlphanumericSplitter.IsAlphaNumeric(set[0][0]) ? 0 : 1; for (; matchIndex < set.Count; matchIndex += 2) { // If the word is long enough... String8 word = set[matchIndex]; if (word.Length > 2) { if (!uniqueWords.Contains(word)) { int wordIdentifier = strings.FindOrAddString(word); uniqueWords.Add(strings[wordIdentifier]); index.AddItem(wordIdentifier, lineIndex); } } } } } } return(iterations * code.Length); }); }
// Each column needs to be constructed and added to the BaseItemSet collection public SampleSet() : base() { this.Name = new String8Column(this.Strings); this.AddColumn(this.Name); this.Target = new String8Column(this.Strings); this.AddColumn(this.Target); this.Type = new PartialArray <byte>(); this.AddColumn(this.Type); this.EventTime = new PartialArray <long>(); this.AddColumn(this.EventTime); }
public MergedMembersDatabase(StringStore sharedStore = null) { this.StringStore = sharedStore; if (this.StringStore == null) { this.StringStore = new StringStore(); } this.MergedMembers = new ItemTree(); this.MergedMemberSourcePackageIdentifier = new PartialArray <int>(); this.MergedMemberSourcePackageIdentifier.Add(0); this.MergedMemberDuplicateCount = new PartialArray <int>(); this.MergedMemberDuplicateCount.Add(0); }
public BufferedRowReader(Stream stream, Func<String8, PartialArray<int>, String8Set> splitRows) { _stream = stream; _splitRows = splitRows; _startOfStream = true; long length = 64 * 1024; if (stream.CanSeek) { length = Math.Min(length, stream.Length + 1); } _buffer = new byte[length]; _rowPositionArray = new PartialArray<int>(64, false); }
public IEnumerable<ReferenceAssemblyWithTypeResult> FindReferenceAssembliesWithType( string name, int arity, CancellationToken cancellationToken) { // Our reference assembly data is stored in the nuget.org DB. IAddReferenceDatabaseWrapper databaseWrapper; if (!_sourceToDatabase.TryGetValue(NugetOrgSource, out databaseWrapper)) { // Don't have a database to search. yield break; } var database = databaseWrapper.Database; if (name == "var") { // never find anything named 'var'. yield break; } var query = new MemberQuery(name, isFullSuffix: true, isFullNamespace: false); var symbols = new PartialArray<Symbol>(100); if (query.TryFindMembers(database, ref symbols)) { var types = FilterToViableTypes(symbols); foreach (var type in types) { // Only look at reference assembly results. if (type.PackageName.ToString() == MicrosoftAssemblyReferencesName) { var nameParts = new List<string>(); GetFullName(nameParts, type.FullName.Parent); yield return new ReferenceAssemblyWithTypeResult( type.AssemblyName.ToString(), type.Name.ToString(), containingNamespaceNames: nameParts); } } } }
public IEnumerable<PackageWithTypeResult> FindPackagesWithType( string source, string name, int arity, CancellationToken cancellationToken) { //if (!StringComparer.OrdinalIgnoreCase.Equals(source, NugetOrgSource)) //{ // // We only support searching nuget.org // yield break; //} AddReferenceDatabase database; if (!_sourceToDatabase.TryGetValue(source, out database)) { // Don't have a database to search. yield break; } if (name == "var") { // never find anything named 'var'. yield break; } var query = new MemberQuery(name, isFullSuffix: true, isFullNamespace: false); var symbols = new PartialArray<Symbol>(100); if (query.TryFindMembers(database, ref symbols)) { // Don't return nested types. Currently their value does not seem worth // it given all the extra stuff we'd have to plumb through. Namely // going down the "using static" code path and whatnot. var types = new List<Symbol>( from symbol in symbols where this.IsType(symbol) && !this.IsType(symbol.Parent()) select symbol); var typesFromPackagesUsedInOtherProjects = new List<Symbol>(); var typesFromPackagesNotUsedInOtherProjects = new List<Symbol>(); foreach (var type in types) { var packageName = type.PackageName.ToString(); if (_installerService.GetInstalledVersions(packageName).Any()) { typesFromPackagesUsedInOtherProjects.Add(type); } else { typesFromPackagesNotUsedInOtherProjects.Add(type); } } var result = new List<Symbol>(); // We always returm types from packages that we've use elsewhere in the project. int? bestRank = null; foreach (var type in typesFromPackagesUsedInOtherProjects) { if (type.PackageName.ToString() != MicrosoftAssemblyReferencesName) { var rank = GetRank(type); bestRank = bestRank == null ? rank : Math.Max(bestRank.Value, rank); } yield return CreateResult(database, type); } // For all other hits include as long as the popularity is high enough. // Popularity ranks are in powers of two. So if two packages differ by // one rank, then one is at least twice as popular as the next. Two // ranks would be four times as popular. Three ranks = 8 times, etc. // etc. We keep packages that within 1 rank of the best package we find. // // Note: we only do rankings for nuget packages. Results from reference // assemblies are always returned. foreach (var type in typesFromPackagesNotUsedInOtherProjects) { if (type.PackageName.ToString() != MicrosoftAssemblyReferencesName) { var rank = GetRank(type); bestRank = bestRank == null ? rank : Math.Max(bestRank.Value, rank); if (Math.Abs(bestRank.Value - rank) > 1) { yield break; } } yield return CreateResult(database, type); } } }
public IEnumerable<PackageWithTypeResult> FindPackagesWithType( string source, string name, int arity, CancellationToken cancellationToken) { IAddReferenceDatabaseWrapper databaseWrapper; if (!_sourceToDatabase.TryGetValue(source, out databaseWrapper)) { // Don't have a database to search. yield break; } var database = databaseWrapper.Database; if (name == "var") { // never find anything named 'var'. yield break; } var query = new MemberQuery(name, isFullSuffix: true, isFullNamespace: false); var symbols = new PartialArray<Symbol>(100); if (query.TryFindMembers(database, ref symbols)) { var types = FilterToViableTypes(symbols); var typesFromPackagesUsedInOtherProjects = new List<Symbol>(); var typesFromPackagesNotUsedInOtherProjects = new List<Symbol>(); foreach (var type in types) { // Ignore any reference assembly results. if (type.PackageName.ToString() != MicrosoftAssemblyReferencesName) { var packageName = type.PackageName.ToString(); if (_installerService.GetInstalledVersions(packageName).Any()) { typesFromPackagesUsedInOtherProjects.Add(type); } else { typesFromPackagesNotUsedInOtherProjects.Add(type); } } } var result = new List<Symbol>(); // We always returm types from packages that we've use elsewhere in the project. int? bestRank = null; foreach (var type in typesFromPackagesUsedInOtherProjects) { yield return CreateResult(database, type); } // For all other hits include as long as the popularity is high enough. // Popularity ranks are in powers of two. So if two packages differ by // one rank, then one is at least twice as popular as the next. Two // ranks would be four times as popular. Three ranks = 8 times, etc. // etc. We keep packages that within 1 rank of the best package we find. foreach (var type in typesFromPackagesNotUsedInOtherProjects) { var rank = GetRank(type); bestRank = bestRank == null ? rank : Math.Max(bestRank.Value, rank); if (Math.Abs(bestRank.Value - rank) > 1) { yield break; } yield return CreateResult(database, type); } } }
public Task<ImmutableArray<ReferenceAssemblyWithTypeResult>> FindReferenceAssembliesWithTypeAsync( string name, int arity) { // Our reference assembly data is stored in the nuget.org DB. if (!_sourceToDatabase.TryGetValue(NugetOrgSource, out var databaseWrapper)) { // Don't have a database to search. return SpecializedTasks.EmptyImmutableArray<ReferenceAssemblyWithTypeResult>(); } var database = databaseWrapper.Database; if (name == "var") { // never find anything named 'var'. return SpecializedTasks.EmptyImmutableArray<ReferenceAssemblyWithTypeResult>(); } var query = new MemberQuery(name, isFullSuffix: true, isFullNamespace: false); var symbols = new PartialArray<Symbol>(100); var results = ArrayBuilder<ReferenceAssemblyWithTypeResult>.GetInstance(); if (query.TryFindMembers(database, ref symbols)) { var types = FilterToViableTypes(symbols); foreach (var type in types) { // Only look at reference assembly results. if (type.PackageName.ToString() == MicrosoftAssemblyReferencesName) { var nameParts = new List<string>(); GetFullName(nameParts, type.FullName.Parent); var result = new ReferenceAssemblyWithTypeResult( type.AssemblyName.ToString(), type.Name.ToString(), containingNamespaceNames: nameParts); results.Add(result); } } } return Task.FromResult(results.ToImmutableAndFree()); }
public Task<ImmutableArray<PackageWithTypeResult>> FindPackagesWithTypeAsync( string source, string name, int arity) { if (!_sourceToDatabase.TryGetValue(source, out var databaseWrapper)) { // Don't have a database to search. return SpecializedTasks.EmptyImmutableArray<PackageWithTypeResult>(); } var database = databaseWrapper.Database; if (name == "var") { // never find anything named 'var'. return SpecializedTasks.EmptyImmutableArray<PackageWithTypeResult>(); } var query = new MemberQuery(name, isFullSuffix: true, isFullNamespace: false); var symbols = new PartialArray<Symbol>(100); var result = ArrayBuilder<PackageWithTypeResult>.GetInstance(); if (query.TryFindMembers(database, ref symbols)) { var types = FilterToViableTypes(symbols); foreach (var type in types) { // Ignore any reference assembly results. if (type.PackageName.ToString() != MicrosoftAssemblyReferencesName) { result.Add(CreateResult(database, type)); } } } return Task.FromResult(result.ToImmutableAndFree()); }
private List<Symbol> FilterToViableTypes(PartialArray<Symbol> symbols) { // Don't return nested types. Currently their value does not seem worth // it given all the extra stuff we'd have to plumb through. Namely // going down the "using static" code path and whatnot. return new List<Symbol>( from symbol in symbols where this.IsType(symbol) && !this.IsType(symbol.Parent()) select symbol); }