(candidate, candidateParts, chunk, ignoreCase)
| 142576 | return ignoreCase ? toLowerCase(ch1) === toLowerCase(ch2) : ch1 === ch2; |
| 142577 | } |
| 142578 | function tryCamelCaseMatch(candidate, candidateParts, chunk, ignoreCase) { |
| 142579 | var chunkCharacterSpans = chunk.characterSpans; |
| 142580 | // Note: we may have more pattern parts than candidate parts. This is because multiple |
| 142581 | // pattern parts may match a candidate part. For example "SiUI" against "SimpleUI". |
| 142582 | // We'll have 3 pattern parts Si/U/I against two candidate parts Simple/UI. However, U |
| 142583 | // and I will both match in UI. |
| 142584 | var currentCandidate = 0; |
| 142585 | var currentChunkSpan = 0; |
| 142586 | var firstMatch; |
| 142587 | var contiguous; |
| 142588 | while (true) { |
| 142589 | // Let's consider our termination cases |
| 142590 | if (currentChunkSpan === chunkCharacterSpans.length) { |
| 142591 | return true; |
| 142592 | } |
| 142593 | else if (currentCandidate === candidateParts.length) { |
| 142594 | // No match, since we still have more of the pattern to hit |
| 142595 | return false; |
| 142596 | } |
| 142597 | var candidatePart = candidateParts[currentCandidate]; |
| 142598 | var gotOneMatchThisCandidate = false; |
| 142599 | // Consider the case of matching SiUI against SimpleUIElement. The candidate parts |
| 142600 | // will be Simple/UI/Element, and the pattern parts will be Si/U/I. We'll match 'Si' |
| 142601 | // against 'Simple' first. Then we'll match 'U' against 'UI'. However, we want to |
| 142602 | // still keep matching pattern parts against that candidate part. |
| 142603 | for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) { |
| 142604 | var chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan]; |
| 142605 | if (gotOneMatchThisCandidate) { |
| 142606 | // We've already gotten one pattern part match in this candidate. We will |
| 142607 | // only continue trying to consumer pattern parts if the last part and this |
| 142608 | // part are both upper case. |
| 142609 | if (!isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) || |
| 142610 | !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start))) { |
| 142611 | break; |
| 142612 | } |
| 142613 | } |
| 142614 | if (!partStartsWith(candidate, candidatePart, chunk.text, ignoreCase, chunkCharacterSpan)) { |
| 142615 | break; |
| 142616 | } |
| 142617 | gotOneMatchThisCandidate = true; |
| 142618 | firstMatch = firstMatch === undefined ? currentCandidate : firstMatch; |
| 142619 | // If we were contiguous, then keep that value. If we weren't, then keep that |
| 142620 | // value. If we don't know, then set the value to 'true' as an initial match is |
| 142621 | // obviously contiguous. |
| 142622 | contiguous = contiguous === undefined ? true : contiguous; |
| 142623 | candidatePart = ts.createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length); |
| 142624 | } |
| 142625 | // Check if we matched anything at all. If we didn't, then we need to unset the |
| 142626 | // contiguous bit if we currently had it set. |
| 142627 | // If we haven't set the bit yet, then that means we haven't matched anything so |
| 142628 | // far, and we don't want to change that. |
| 142629 | if (!gotOneMatchThisCandidate && contiguous !== undefined) { |
| 142630 | contiguous = false; |
| 142631 | } |
| 142632 | // Move onto the next candidate. |
| 142633 | currentCandidate++; |
| 142634 | } |
| 142635 | } |
no test coverage detected