提交 64b98d70 编写于 作者: C CyrusNajmabadi

Remove caching.

上级 6ff9e44f
...@@ -30,14 +30,9 @@ internal abstract partial class PatternMatcher : IDisposable ...@@ -30,14 +30,9 @@ internal abstract partial class PatternMatcher : IDisposable
public const int CamelCaseMatchesFromStartBonus = 2; public const int CamelCaseMatchesFromStartBonus = 2;
public const int CamelCaseMaxWeight = CamelCaseContiguousBonus + CamelCaseMatchesFromStartBonus; public const int CamelCaseMaxWeight = CamelCaseContiguousBonus + CamelCaseMatchesFromStartBonus;
private readonly object _gate = new object();
private readonly bool _includeMatchedSpans; private readonly bool _includeMatchedSpans;
private readonly bool _allowFuzzyMatching; private readonly bool _allowFuzzyMatching;
private readonly Dictionary<string, StringBreaks> _stringToWordSpans = new Dictionary<string, StringBreaks>();
private static readonly Func<string, StringBreaks> _breakIntoWordSpans = StringBreaker.BreakIntoWordParts;
// PERF: Cache the culture's compareInfo to avoid the overhead of asking for them repeatedly in inner loops // PERF: Cache the culture's compareInfo to avoid the overhead of asking for them repeatedly in inner loops
private readonly CompareInfo _compareInfo; private readonly CompareInfo _compareInfo;
private readonly TextInfo _textInfo; private readonly TextInfo _textInfo;
...@@ -79,12 +74,6 @@ internal abstract partial class PatternMatcher : IDisposable ...@@ -79,12 +74,6 @@ internal abstract partial class PatternMatcher : IDisposable
public virtual void Dispose() public virtual void Dispose()
{ {
foreach (var kvp in _stringToWordSpans)
{
kvp.Value.Dispose();
}
_stringToWordSpans.Clear();
} }
public static PatternMatcher CreatePatternMatcher( public static PatternMatcher CreatePatternMatcher(
...@@ -130,14 +119,6 @@ internal static (string name, string containerOpt) GetNameAndContainer(string pa ...@@ -130,14 +119,6 @@ internal static (string name, string containerOpt) GetNameAndContainer(string pa
private bool SkipMatch(string candidate) private bool SkipMatch(string candidate)
=> _invalidPattern || string.IsNullOrWhiteSpace(candidate); => _invalidPattern || string.IsNullOrWhiteSpace(candidate);
private StringBreaks GetCandidateHumps(string word)
{
lock (_gate)
{
return _stringToWordSpans.GetOrAdd(word, _breakIntoWordSpans);
}
}
private static bool ContainsUpperCaseLetter(string pattern) private static bool ContainsUpperCaseLetter(string pattern)
{ {
// Expansion of "foreach(char ch in pattern)" to avoid a CharEnumerator allocation // Expansion of "foreach(char ch in pattern)" to avoid a CharEnumerator allocation
...@@ -207,61 +188,79 @@ private static bool ContainsUpperCaseLetter(string pattern) ...@@ -207,61 +188,79 @@ private static bool ContainsUpperCaseLetter(string pattern)
} }
} }
var patternIsLowercase = patternChunk.IsLowercase; StringBreaks? candidateHumpsOpt = null;
if (caseInsensitiveIndex > 0) try
{ {
// We found the pattern somewhere in the candidate. This could be a substring match. var patternIsLowercase = patternChunk.IsLowercase;
// However, we don't want to be overaggressive in returning just any substring results. if (caseInsensitiveIndex > 0)
// So do a few more checks to make sure this is a good result.
if (!patternIsLowercase)
{ {
// Pattern contained uppercase letters. This is a strong indication from the // We found the pattern somewhere in the candidate. This could be a substring match.
// user that they expect the same letters to be uppercase in the result. As // However, we don't want to be overaggressive in returning just any substring results.
// such, only return this if we can find this pattern exactly in the candidate. // So do a few more checks to make sure this is a good result.
var caseSensitiveIndex = _compareInfo.IndexOf(candidate, patternChunk.Text); if (!patternIsLowercase)
if (caseSensitiveIndex > 0)
{
return new PatternMatch(
PatternMatchKind.Substring, punctuationStripped, isCaseSensitive: true,
matchedSpan: GetMatchedSpan(caseSensitiveIndex, patternChunk.Text.Length));
}
}
else
{
// Pattern was all lowercase. This can lead to lots of false positives. For
// example, we don't want "bin" to match "CombineUnits". Instead, we want it
// to match "BinaryOperator". As such, make sure our match looks like it's
// starting an actual word in the candidate.
// Do a quick check to avoid the expensive work of having to go get the candidate
// humps.
if (char.IsUpper(candidate[caseInsensitiveIndex]))
{ {
return new PatternMatch(PatternMatchKind.Substring, punctuationStripped, // Pattern contained uppercase letters. This is a strong indication from the
isCaseSensitive: false, // user that they expect the same letters to be uppercase in the result. As
matchedSpan: GetMatchedSpan(caseInsensitiveIndex, patternChunk.Text.Length)); // such, only return this if we can find this pattern exactly in the candidate.
}
var candidateHumps = GetCandidateHumps(candidate); var caseSensitiveIndex = _compareInfo.IndexOf(candidate, patternChunk.Text);
for (int i = 0, n = candidateHumps.GetCount(); i < n; i++) if (caseSensitiveIndex > 0)
{
return new PatternMatch(
PatternMatchKind.Substring, punctuationStripped, isCaseSensitive: true,
matchedSpan: GetMatchedSpan(caseSensitiveIndex, patternChunk.Text.Length));
}
}
else
{ {
var hump = TextSpan.FromBounds(candidateHumps[i].Start, candidateLength); // Pattern was all lowercase. This can lead to lots of false positives. For
if (PartStartsWith(candidate, hump, patternChunk.Text, _ignoreCaseCompareOptions)) // example, we don't want "bin" to match "CombineUnits". Instead, we want it
// to match "BinaryOperator". As such, make sure our match looks like it's
// starting an actual word in the candidate.
// Do a quick check to avoid the expensive work of having to go get the candidate
// humps.
if (char.IsUpper(candidate[caseInsensitiveIndex]))
{ {
return new PatternMatch(PatternMatchKind.Substring, punctuationStripped, return new PatternMatch(PatternMatchKind.Substring, punctuationStripped,
isCaseSensitive: PartStartsWith(candidate, hump, patternChunk.Text, _compareOptions), isCaseSensitive: false,
matchedSpan: GetMatchedSpan(hump.Start, patternChunk.Text.Length)); matchedSpan: GetMatchedSpan(caseInsensitiveIndex, patternChunk.Text.Length));
}
var candidateHumps = StringBreaker.BreakIntoWordParts(candidate);
candidateHumpsOpt = candidateHumps;
for (int i = 0, n = candidateHumps.GetCount(); i < n; i++)
{
var hump = TextSpan.FromBounds(candidateHumps[i].Start, candidateLength);
if (PartStartsWith(candidate, hump, patternChunk.Text, CompareOptions.IgnoreCase))
{
return new PatternMatch(PatternMatchKind.Substring, punctuationStripped,
isCaseSensitive: PartStartsWith(candidate, hump, patternChunk.Text, CompareOptions.None),
matchedSpan: GetMatchedSpan(hump.Start, patternChunk.Text.Length));
}
} }
} }
} }
}
// Didn't have an exact/prefix match, or a high enough quality substring match. // Didn't have an exact/prefix match, or a high enough quality substring match.
// See if we can find a camel case match. // See if we can find a camel case match.
return TryCamelCaseMatch( if (candidateHumpsOpt == null)
candidate, patternChunk, punctuationStripped, patternIsLowercase); {
candidateHumpsOpt = StringBreaker.BreakIntoWordParts(candidate);
}
return TryCamelCaseMatch(
candidate, patternChunk, punctuationStripped, patternIsLowercase, candidateHumpsOpt.Value);
}
finally
{
if (candidateHumpsOpt.HasValue)
{
candidateHumpsOpt.Value.Dispose();
}
}
} }
private TextSpan? GetMatchedSpan(int start, int length) private TextSpan? GetMatchedSpan(int start, int length)
...@@ -430,13 +429,13 @@ private bool PartStartsWith(string candidate, TextSpan candidatePart, string pat ...@@ -430,13 +429,13 @@ private bool PartStartsWith(string candidate, TextSpan candidatePart, string pat
private PatternMatch? TryCamelCaseMatch( private PatternMatch? TryCamelCaseMatch(
string candidate, TextChunk patternChunk, string candidate, TextChunk patternChunk,
bool punctuationStripped, bool isLowercase) bool punctuationStripped, bool isLowercase,
StringBreaks candidateHumps)
{ {
if (isLowercase) if (isLowercase)
{ {
// e) If the word was entirely lowercase, then attempt a special lower cased camel cased // e) If the word was entirely lowercase, then attempt a special lower cased camel cased
// match. i.e. cofipro would match CodeFixProvider. // match. i.e. cofipro would match CodeFixProvider.
var candidateHumps = GetCandidateHumps(candidate);
var camelCaseKind = TryAllLowerCamelCaseMatch( var camelCaseKind = TryAllLowerCamelCaseMatch(
candidate, candidateHumps, patternChunk, out var matchedSpans); candidate, candidateHumps, patternChunk, out var matchedSpans);
if (camelCaseKind.HasValue) if (camelCaseKind.HasValue)
...@@ -452,8 +451,7 @@ private bool PartStartsWith(string candidate, TextSpan candidatePart, string pat ...@@ -452,8 +451,7 @@ private bool PartStartsWith(string candidate, TextSpan candidatePart, string pat
// i.e. CoFiPro would match CodeFixProvider, but CofiPro would not. // i.e. CoFiPro would match CodeFixProvider, but CofiPro would not.
if (patternChunk.PatternHumps.Count > 0) if (patternChunk.PatternHumps.Count > 0)
{ {
var candidateHumps = GetCandidateHumps(candidate); var camelCaseKind = TryUpperCaseCamelCaseMatch(candidate, candidateHumps, patternChunk, CompareOptions.None, out var matchedSpans);
var camelCaseKind = TryUpperCaseCamelCaseMatch(candidate, candidateHumps, patternChunk, _compareOptions, out var matchedSpans);
if (camelCaseKind.HasValue) if (camelCaseKind.HasValue)
{ {
return new PatternMatch( return new PatternMatch(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册