/// <summary>Gets a list of nodes close to the requested range, ordered by similarity /// so that the first item in the returned list is the best result.</summary> /// <returns>A list of nodes and their ranges, sorted by similarity to the targetRange /// (most similar first), and limited in size as requested. The nodes and ranges must /// have been previously saved via <see cref="SaveRange(ILNode, IndexRange)"/>.</returns> public IReadOnlyList <Pair <ILNode, IndexRange> > FindRelatedNodes(IndexRange targetRange, int maxSearchResults) => FindRelatedNodesCore(targetRange, maxSearchResults, true);
/// <summary>Scores the extent to which a location-table item does NOT match the source file.</summary> private static float GetMismatchScore(KeyValuePair <int, Pair <ILNode, int> > pair, IndexRange targetRange) { var range = RangeOf(pair); int offs1 = range.StartIndex - targetRange.StartIndex; int offs2 = range.EndIndex - targetRange.EndIndex; bool terrible = !range.Overlaps(targetRange) && !range.Contains(targetRange); // Prefer ranges closer to the start, rather than the end, of the target range return((terrible ? 1_000_000 : 0) + Abs(offs1) * 4f + Abs(offs2)); }
/// <summary>Associates a node with a range.</summary> /// <remarks>Typically this method is set as the value of /// <see cref="ILNodePrinterOptions.SaveRange"/> so that range info is captured /// while converting a node to text. This class does not need or use the third /// parameter (depth).</remarks> public void SaveRange(ILNode node, IndexRange range, int depth = -1) { _startLocations[range.StartIndex].Add(Pair.Create(node, range.EndIndex)); _endLocations [range.EndIndex].Add(Pair.Create(node, range.StartIndex)); }
private static void Scan(BMultiMap <int, Pair <ILNode, int> > locations, int charIndex, IndexRange targetRange, int scanDirection, int iterations, Dictionary <Pair <ILNode, IndexRange>, float> results) { for (int i = locations.FindLowerBound(charIndex); iterations > 0; iterations--, i += scanDirection) { var pair = locations.TryGet(i, out bool fail); if (!fail) { var nodeWithRange = Pair.Create(pair.Value.Item1, RangeOf(pair)); float score = GetMismatchScore(pair, targetRange); if (score < results.TryGetValue(nodeWithRange, float.MaxValue)) { results[nodeWithRange] = score; } } } }