diff --git a/src/Workspaces/Core/Portable/Utilities/BKTree.Builder.cs b/src/Workspaces/Core/Portable/Utilities/BKTree.Builder.cs new file mode 100644 index 0000000000000000000000000000000000000000..f5b8c530d11280f86d9e0d7d262267dbe12ccbcd --- /dev/null +++ b/src/Workspaces/Core/Portable/Utilities/BKTree.Builder.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Roslyn.Utilities +{ + internal partial class BKTree + { + private class Builder + { + private readonly char[][] values; + + public Builder(IEnumerable values) + { + this.values = values.Select(v => v.ToLower()).Distinct().Select(v => v.ToCharArray()).ToArray(); + } + + internal BKTree Create() + { + var nodes = new List(); + foreach (var value in values) + { + if (value.Length > 0) + { + Add(nodes, value); + } + } + + return new BKTree(nodes.ToArray()); + } + + private static void Add(List nodes, char[] lowerCaseCharacters) + { + if (nodes.Count == 0) + { + nodes.Add(new Node(lowerCaseCharacters)); + return; + } + + var currentNodeIndex = 0; + while (true) + { + var currentNode = nodes[currentNodeIndex]; + + var editDistance = EditDistance.GetEditDistance(currentNode.LowerCaseCharacters, lowerCaseCharacters); + // This shoudl never happen. We dedupe all items before proceeding to the 'Add' step. + Debug.Assert(editDistance != 0); + + if (currentNode.AllChildren == null) + { + currentNode.AllChildren = new Dictionary(); + nodes[currentNodeIndex] = currentNode; + // Fall through. to actually add the child to this node. + } + else + { + int childNodeIndex; + if (currentNode.AllChildren.TryGetValue(editDistance, out childNodeIndex)) + { + // Edit distances collide. Move to this child and add this word to it. + currentNodeIndex = childNodeIndex; + continue; + } + + // Fall through. to actually add the child to this node. + } + + currentNode.AllChildren.Add(editDistance, nodes.Count); + nodes.Add(new Node(lowerCaseCharacters)); + return; + } + } + } + } +} diff --git a/src/Workspaces/Core/Portable/Utilities/BKTree.cs b/src/Workspaces/Core/Portable/Utilities/BKTree.cs index 4d47ef463dea135b71d383b262f3b1315df6861e..2dc01506b51c1171a9ff927fc193a4cdb6a4696e 100644 --- a/src/Workspaces/Core/Portable/Utilities/BKTree.cs +++ b/src/Workspaces/Core/Portable/Utilities/BKTree.cs @@ -10,7 +10,7 @@ namespace Roslyn.Utilities { - internal class BKTree + internal partial class BKTree { // Root node is at index 0. private readonly Node[] nodes; @@ -48,67 +48,7 @@ public static BKTree Create(params string[] values) public static BKTree Create(IEnumerable values) { - return Create(values.Select(v => v.ToLower()).Distinct().Select(v => v.ToCharArray()).ToArray()); - } - - private static BKTree Create(char[][] values) - { - var nodes = new List(); - foreach (var value in values) - { - if (value.Length > 0) - { - Add(nodes, value); - } - } - - return new BKTree(nodes.ToArray()); - } - - private static void Add(List nodes, char[] lowerCaseCharacters) - { - if (nodes.Count == 0) - { - nodes.Add(new Node(lowerCaseCharacters)); - return; - } - - var currentNodeIndex = 0; - while (true) - { - var currentNode = nodes[currentNodeIndex]; - - var editDistance = EditDistance.GetEditDistance(currentNode.LowerCaseCharacters, lowerCaseCharacters); - if (editDistance == 0) - { - // Already in the graph. Can happen because we added something that is the same - // as an existing item, but only differs in case. - return; - } - - if (currentNode.AllChildren == null) - { - currentNode.AllChildren = new Dictionary(); - nodes[currentNodeIndex] = currentNode; - // Fall through. to actually add the child to this node. - } - else - { - int childNodeIndex; - if (currentNode.AllChildren.TryGetValue(editDistance, out childNodeIndex)) - { - // Edit distances collide. Move to this child and add this word to it. - currentNodeIndex = childNodeIndex; - continue; - } - - // Fall through. to actually add the child to this node. - } - - currentNode.AllChildren.Add(editDistance, nodes.Count); - nodes.Add(new Node(lowerCaseCharacters)); - return; - } + return new Builder(values).Create(); } public IList Find(string value, int? threshold = null) diff --git a/src/Workspaces/Core/Portable/Workspaces.csproj b/src/Workspaces/Core/Portable/Workspaces.csproj index 9bc9f663195e17670f5544932d5cd057a8129c2e..942753028d10e5db8a054f0aca27caed508d7b0b 100644 --- a/src/Workspaces/Core/Portable/Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Workspaces.csproj @@ -949,6 +949,7 @@ +