示例#1
0
        private List <string> CreateWords(StringBreaks wordBreaks, string name)
        {
            var result = new List <string>(wordBreaks.GetCount());

            for (int i = 0, n = wordBreaks.GetCount(); i < n; i++)
            {
                var br = wordBreaks[i];
                result.Add(name.Substring(br.Start, br.Length));
            }

            return(result);
        }
示例#2
0
            private static Words GetLongestBackwardSubsequence(int length, StringBreaks breaks, string baseName)
            {
                var breakCount = breaks.GetCount();
                var start      = breakCount - length;

                return(GetWords(start, breakCount, breaks, baseName));
            }
示例#3
0
 private static PatternMatchKind GetCamelCaseKind(CamelCaseResult result, StringBreaks candidateHumps)
 {
     var toEnd = result.MatchCount == candidateHumps.GetCount();
     if (result.FromStart)
     {
         if (result.Contiguous)
         {
             // We contiguously matched humps from the start of this candidate.  If we 
             // matched all the humps, then this was an exact match, otherwise it was a 
             // contiguous prefix match
             return toEnd
                 ? PatternMatchKind.CamelCaseExact
                 : PatternMatchKind.CamelCasePrefix;
         }
         else
         {
             return PatternMatchKind.CamelCaseNonContiguousPrefix;
         }
     }
     else
     {
         // We didn't match from the start.  Distinguish between a match whose humps are all
         // contiguous, and one that isn't.
         return result.Contiguous
             ? PatternMatchKind.CamelCaseSubstring
             : PatternMatchKind.CamelCaseNonContiguousSubstring;
     }
 }
示例#4
0
        private static IList<string> PartListToSubstrings(string identifier, StringBreaks parts)
        {
            var result = new List<string>();
            for (int i = 0, n = parts.GetCount(); i < n; i++)
            {
                var span = parts[i];
                result.Add(identifier.Substring(span.Start, span.Length));
            }

            return result;
        }
示例#5
0
            private static ImmutableArray <IEnumerable <string> > GetInterleavedPatterns(StringBreaks breaks, string baseName)
            {
                var result = ArrayBuilder <IEnumerable <string> > .GetInstance();

                var breakCount = breaks.GetCount();

                result.Add(GetWords(0, breakCount, breaks, baseName));

                for (int length = breakCount - 1; length > 0; length--)
                {
                    // going forward
                    result.Add(GetLongestForwardSubsequence(length, breaks, baseName));

                    // going backward
                    result.Add(GetLongestBackwardSubsequence(length, breaks, baseName));
                }

                return(result.ToImmutable());
            }
            private CamelCaseResult?TryMatch(
                int patternIndex, int candidateHumpIndex, bool?contiguous)
            {
                if (patternIndex == _patternText.Length)
                {
                    // We hit the end.  So we were able to match against this candidate.
                    // We are contiguous if our contiguous tracker was not set to false.
                    var matchedSpansInReverse = _includeMatchedSpans ? ArrayBuilder <TextSpan> .GetInstance() : null;

                    return(new CamelCaseResult(
                               fromStart: false,
                               contiguous: contiguous != false,
                               matchCount: 0,
                               matchedSpansInReverse: matchedSpansInReverse));
                }

                var bestResult = default(CamelCaseResult?);

                // Look for a hump in the candidate that matches the current letter we're on.
                var patternCharacter = _patternText[patternIndex];

                for (int humpIndex = candidateHumpIndex, n = _candidateHumps.GetCount(); humpIndex < n; humpIndex++)
                {
                    // If we've been contiguous, but we jumped past a hump, then we're no longer contiguous.
                    if (contiguous.HasValue && contiguous.Value)
                    {
                        contiguous = humpIndex == candidateHumpIndex;
                    }

                    var candidateHump = _candidateHumps[humpIndex];
                    if (char.ToLower(_candidate[candidateHump.Start]) == patternCharacter)
                    {
                        // Found a hump in the candidate string that matches the current pattern
                        // character we're on.  i.e. we matched the c in cofipro against the C in
                        // CodeFixProvider.
                        //
                        // Now, for each subsequent character, we need to both try to consume it
                        // as part of the current hump, or see if it should match the next hump.
                        //
                        // Note, if the candidate is something like CodeFixProvider and our pattern
                        // is cofipro, and we've matched the 'f' against the 'F', then the max of
                        // the pattern we'll want to consume is "fip" against "Fix".  We don't want
                        // consume parts of the pattern once we reach the next hump.

                        // We matched something.  If this was our first match, consider ourselves
                        // contiguous.
                        var localContiguous = contiguous == null ? true : contiguous.Value;

                        var result = TryConsumePatternOrMatchNextHump(
                            patternIndex, humpIndex, localContiguous);

                        if (result == null)
                        {
                            continue;
                        }

                        if (UpdateBestResultIfBetter(result.Value, ref bestResult, matchSpanToAdd: null))
                        {
                            // We found the best result so far.  We can stop immediately.
                            break;
                        }
                    }
                }

                return(bestResult);
            }
示例#7
0
        private PatternMatchKind?TryUpperCaseCamelCaseMatch(
            string candidate,
            StringBreaks candidateHumps,
            TextChunk patternChunk,
            CompareOptions compareOption,
            out ImmutableArray <TextSpan> matchedSpans)
        {
            var patternHumps = patternChunk.CharacterSpans;

            // Note: we may have more pattern parts than candidate parts.  This is because multiple
            // pattern parts may match a candidate part.  For example "SiUI" against "SimpleUI".
            // We'll have 3 pattern parts Si/U/I against two candidate parts Simple/UI.  However, U
            // and I will both match in UI.

            int  currentCandidateHump = 0;
            int  currentPatternHump   = 0;
            int? firstMatch           = null;
            bool?contiguous           = null;

            var patternHumpCount   = patternHumps.GetCount();
            var candidateHumpCount = candidateHumps.GetCount();

            var matchSpans = ArrayBuilder <TextSpan> .GetInstance();

            while (true)
            {
                // Let's consider our termination cases
                if (currentPatternHump == patternHumpCount)
                {
                    Contract.Requires(firstMatch.HasValue);
                    Contract.Requires(contiguous.HasValue);

                    var matchCount = matchSpans.Count;
                    matchedSpans = _includeMatchedSpans
                        ? new NormalizedTextSpanCollection(matchSpans).ToImmutableArray()
                        : ImmutableArray <TextSpan> .Empty;
                    matchSpans.Free();

                    var camelCaseResult = new CamelCaseResult(firstMatch == 0, contiguous.Value, matchCount, null);
                    return(GetCamelCaseKind(camelCaseResult, candidateHumps));
                }
                else if (currentCandidateHump == candidateHumpCount)
                {
                    // No match, since we still have more of the pattern to hit
                    matchedSpans = ImmutableArray <TextSpan> .Empty;
                    matchSpans.Free();
                    return(null);
                }

                var  candidateHump            = candidateHumps[currentCandidateHump];
                bool gotOneMatchThisCandidate = false;

                // Consider the case of matching SiUI against SimpleUIElement. The candidate parts
                // will be Simple/UI/Element, and the pattern parts will be Si/U/I.  We'll match 'Si'
                // against 'Simple' first.  Then we'll match 'U' against 'UI'. However, we want to
                // still keep matching pattern parts against that candidate part.
                for (; currentPatternHump < patternHumpCount; currentPatternHump++)
                {
                    var patternChunkCharacterSpan = patternHumps[currentPatternHump];

                    if (gotOneMatchThisCandidate)
                    {
                        // We've already gotten one pattern part match in this candidate.  We will
                        // only continue trying to consume pattern parts if the last part and this
                        // part are both upper case.
                        if (!char.IsUpper(patternChunk.Text[patternHumps[currentPatternHump - 1].Start]) ||
                            !char.IsUpper(patternChunk.Text[patternHumps[currentPatternHump].Start]))
                        {
                            break;
                        }
                    }

                    if (!PartStartsWith(candidate, candidateHump, patternChunk.Text, patternChunkCharacterSpan, compareOption))
                    {
                        break;
                    }

                    matchSpans.Add(new TextSpan(candidateHump.Start, patternChunkCharacterSpan.Length));
                    gotOneMatchThisCandidate = true;

                    firstMatch = firstMatch ?? currentCandidateHump;

                    // If we were contiguous, then keep that value.  If we weren't, then keep that
                    // value.  If we don't know, then set the value to 'true' as an initial match is
                    // obviously contiguous.
                    contiguous = contiguous ?? true;

                    candidateHump = new TextSpan(candidateHump.Start + patternChunkCharacterSpan.Length, candidateHump.Length - patternChunkCharacterSpan.Length);
                }

                // Check if we matched anything at all.  If we didn't, then we need to unset the
                // contiguous bit if we currently had it set.
                // If we haven't set the bit yet, then that means we haven't matched anything so
                // far, and we don't want to change that.
                if (!gotOneMatchThisCandidate && contiguous.HasValue)
                {
                    contiguous = false;
                }

                // Move onto the next candidate.
                currentCandidateHump++;
            }
        }