public AllLowerCamelCaseMatcher(bool includeMatchedSpans, string candidate, StringBreaks candidateHumps, TextChunk patternChunk) { _includeMatchedSpans = includeMatchedSpans; _candidate = candidate; _candidateHumps = candidateHumps; _patternChunk = patternChunk; _patternText = _patternChunk.Text; }
public TextChunk(string text, bool allowFuzzingMatching) { this.Text = text; this.CharacterSpans = StringBreaker.BreakIntoCharacterParts(text); this.SimilarityChecker = allowFuzzingMatching ? WordSimilarityChecker.Allocate(text, substringsAreSimilar: false) : null; }
private PatternMatchKind?TryAllLowerCamelCaseMatch( string candidate, StringBreaks candidateParts, TextChunk patternChunk, out ImmutableArray <TextSpan> matchedSpans, int chunkOffset) { var matcher = new AllLowerCamelCaseMatcher(_includeMatchedSpans, candidate, candidateParts, patternChunk); return(matcher.TryMatch(chunkOffset, out matchedSpans)); }
private PatternMatchKind?TryUpperCaseCamelCaseMatch( string candidate, StringBreaks candidateHumps, TextChunk patternChunk, CompareOptions compareOption, out ImmutableArray <TextSpan> matchedSpans, int chunkOffset) { 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; int? lastMatch = 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 NormalizedSpanCollection(matchSpans).ToImmutableArray() : ImmutableArray <TextSpan> .Empty; matchSpans.Free(); var camelCaseResult = new CamelCaseResult( fromStart: firstMatch == 0, contiguous: contiguous.Value, toEnd: lastMatch == candidateHumpCount - 1, matchCount: matchCount, matchedSpansInReverse: null, chunkOffset: chunkOffset ); return(GetCamelCaseKind(camelCaseResult)); } 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(chunkOffset + candidateHump.Start, patternChunkCharacterSpan.Length)); gotOneMatchThisCandidate = true; firstMatch = firstMatch ?? currentCandidateHump; lastMatch = 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++; } }
/// <summary> /// Breaks an identifier string into constituent parts. /// </summary> public static StringBreaks BreakIntoWordParts(string identifier) => StringBreaks.Create(identifier, s_wordPartsGenerator);
/// <summary> /// Breaks an identifier string into constituent parts. /// </summary> public static StringBreaks BreakIntoCharacterParts(string identifier) => StringBreaks.Create(identifier, s_characterPartsGenerator);