@@ -225,17 +225,6 @@ namespace ts {
225225 }
226226 }
227227
228- function containsSpaceOrAsterisk ( text : string ) : boolean {
229- for ( let i = 0 ; i < text . length ; i ++ ) {
230- const ch = text . charCodeAt ( i ) ;
231- if ( ch === CharacterCodes . space || ch === CharacterCodes . asterisk ) {
232- return true ;
233- }
234- }
235-
236- return false ;
237- }
238-
239228 function matchSegment ( candidate : string , segment : Segment , stringToWordSpans : Map < TextSpan [ ] > ) : PatternMatch [ ] {
240229 // First check if the segment matches as is. This is also useful if the segment contains
241230 // characters we would normally strip when splitting into parts that we also may want to
@@ -244,7 +233,7 @@ namespace ts {
244233 //
245234 // Note: if the segment contains a space or an asterisk then we must assume that it's a
246235 // multi-word segment.
247- if ( ! containsSpaceOrAsterisk ( segment . totalTextChunk . text ) ) {
236+ if ( every ( segment . totalTextChunk . text , ch => ch !== CharacterCodes . space && ch !== CharacterCodes . asterisk ) ) {
248237 const match = matchTextChunk ( candidate , segment . totalTextChunk , stringToWordSpans ) ;
249238 if ( match ) {
250239 return [ match ] ;
@@ -304,35 +293,13 @@ namespace ts {
304293 return matches ;
305294 }
306295
307- function partStartsWith ( candidate : string , candidateSpan : TextSpan , pattern : string , ignoreCase : boolean , patternSpan ?: TextSpan ) : boolean {
308- const patternPartStart = patternSpan ? patternSpan . start : 0 ;
309- const patternPartLength = patternSpan ? patternSpan . length : pattern . length ;
310-
311- if ( patternPartLength > candidateSpan . length ) {
312- // Pattern part is longer than the candidate part. There can never be a match.
313- return false ;
314- }
315-
316- if ( ignoreCase ) {
317- for ( let i = 0 ; i < patternPartLength ; i ++ ) {
318- const ch1 = pattern . charCodeAt ( patternPartStart + i ) ;
319- const ch2 = candidate . charCodeAt ( candidateSpan . start + i ) ;
320- if ( toLowerCase ( ch1 ) !== toLowerCase ( ch2 ) ) {
321- return false ;
322- }
323- }
324- }
325- else {
326- for ( let i = 0 ; i < patternPartLength ; i ++ ) {
327- const ch1 = pattern . charCodeAt ( patternPartStart + i ) ;
328- const ch2 = candidate . charCodeAt ( candidateSpan . start + i ) ;
329- if ( ch1 !== ch2 ) {
330- return false ;
331- }
332- }
333- }
296+ function partStartsWith ( candidate : string , candidateSpan : TextSpan , pattern : string , ignoreCase : boolean , patternSpan : TextSpan = { start : 0 , length : pattern . length } ) : boolean {
297+ return patternSpan . length <= candidateSpan . length // If pattern part is longer than the candidate part there can never be a match.
298+ && everyInRange ( 0 , patternSpan . length , i => equalChars ( pattern . charCodeAt ( patternSpan . start + i ) , candidate . charCodeAt ( candidateSpan . start + i ) , ignoreCase ) ) ;
299+ }
334300
335- return true ;
301+ function equalChars ( ch1 : number , ch2 : number , ignoreCase : boolean ) : boolean {
302+ return ignoreCase ? toLowerCase ( ch1 ) === toLowerCase ( ch2 ) : ch1 === ch2 ;
336303 }
337304
338305 function tryCamelCaseMatch ( candidate : string , candidateParts : TextSpan [ ] , chunk : TextChunk , ignoreCase : boolean ) : boolean {
@@ -455,29 +422,15 @@ namespace ts {
455422 // Assumes 'value' is already lowercase.
456423 function indexOfIgnoringCase ( str : string , value : string ) : number {
457424 const n = str . length - value . length ;
458- for ( let i = 0 ; i <= n ; i ++ ) {
459- if ( startsWithIgnoringCase ( str , value , i ) ) {
460- return i ;
425+ for ( let start = 0 ; start <= n ; start ++ ) {
426+ if ( every ( value , ( valueChar , i ) => toLowerCase ( str . charCodeAt ( i + start ) ) === valueChar ) ) {
427+ return start ;
461428 }
462429 }
463430
464431 return - 1 ;
465432 }
466433
467- // Assumes 'value' is already lowercase.
468- function startsWithIgnoringCase ( str : string , value : string , start : number ) : boolean {
469- for ( let i = 0 ; i < value . length ; i ++ ) {
470- const ch1 = toLowerCase ( str . charCodeAt ( i + start ) ) ;
471- const ch2 = value . charCodeAt ( i ) ;
472-
473- if ( ch1 !== ch2 ) {
474- return false ;
475- }
476- }
477-
478- return true ;
479- }
480-
481434 function toLowerCase ( ch : number ) : number {
482435 // Fast convert for the ascii range.
483436 if ( ch >= CharacterCodes . A && ch <= CharacterCodes . Z ) {
@@ -557,7 +510,7 @@ namespace ts {
557510 const currentIsDigit = isDigit ( identifier . charCodeAt ( i ) ) ;
558511
559512 const hasTransitionFromLowerToUpper = transitionFromLowerToUpper ( identifier , word , i ) ;
560- const hasTransitionFromUpperToLower = transitionFromUpperToLower ( identifier , word , i , wordStart ) ;
513+ const hasTransitionFromUpperToLower = word && transitionFromUpperToLower ( identifier , i , wordStart ) ;
561514
562515 if ( charIsPunctuation ( identifier . charCodeAt ( i - 1 ) ) ||
563516 charIsPunctuation ( identifier . charCodeAt ( i ) ) ||
@@ -612,52 +565,29 @@ namespace ts {
612565 }
613566
614567 function isAllPunctuation ( identifier : string , start : number , end : number ) : boolean {
615- for ( let i = start ; i < end ; i ++ ) {
616- const ch = identifier . charCodeAt ( i ) ;
617-
618- // We don't consider _ or $ as punctuation as there may be things with that name.
619- if ( ! charIsPunctuation ( ch ) || ch === CharacterCodes . _ || ch === CharacterCodes . $ ) {
620- return false ;
621- }
622- }
623-
624- return true ;
568+ return every ( identifier , ch => charIsPunctuation ( ch ) && ch !== CharacterCodes . _ , start , end ) ;
625569 }
626570
627- function transitionFromUpperToLower ( identifier : string , word : boolean , index : number , wordStart : number ) : boolean {
628- if ( word ) {
629- // Cases this supports:
630- // 1) IDisposable -> I, Disposable
631- // 2) UIElement -> UI, Element
632- // 3) HTMLDocument -> HTML, Document
633- //
634- // etc.
635- if ( index !== wordStart &&
636- index + 1 < identifier . length ) {
637- const currentIsUpper = isUpperCaseLetter ( identifier . charCodeAt ( index ) ) ;
638- const nextIsLower = isLowerCaseLetter ( identifier . charCodeAt ( index + 1 ) ) ;
639-
640- if ( currentIsUpper && nextIsLower ) {
641- // We have a transition from an upper to a lower letter here. But we only
642- // want to break if all the letters that preceded are uppercase. i.e. if we
643- // have "Foo" we don't want to break that into "F, oo". But if we have
644- // "IFoo" or "UIFoo", then we want to break that into "I, Foo" and "UI,
645- // Foo". i.e. the last uppercase letter belongs to the lowercase letters
646- // that follows. Note: this will make the following not split properly:
647- // "HELLOthere". However, these sorts of names do not show up in .Net
648- // programs.
649- for ( let i = wordStart ; i < index ; i ++ ) {
650- if ( ! isUpperCaseLetter ( identifier . charCodeAt ( i ) ) ) {
651- return false ;
652- }
653- }
654-
655- return true ;
656- }
657- }
658- }
659-
660- return false ;
571+ function transitionFromUpperToLower ( identifier : string , index : number , wordStart : number ) : boolean {
572+ // Cases this supports:
573+ // 1) IDisposable -> I, Disposable
574+ // 2) UIElement -> UI, Element
575+ // 3) HTMLDocument -> HTML, Document
576+ //
577+ // etc.
578+ // We have a transition from an upper to a lower letter here. But we only
579+ // want to break if all the letters that preceded are uppercase. i.e. if we
580+ // have "Foo" we don't want to break that into "F, oo". But if we have
581+ // "IFoo" or "UIFoo", then we want to break that into "I, Foo" and "UI,
582+ // Foo". i.e. the last uppercase letter belongs to the lowercase letters
583+ // that follows. Note: this will make the following not split properly:
584+ // "HELLOthere". However, these sorts of names do not show up in .Net
585+ // programs.
586+ return index !== wordStart
587+ && index + 1 < identifier . length
588+ && isUpperCaseLetter ( identifier . charCodeAt ( index ) )
589+ && isLowerCaseLetter ( identifier . charCodeAt ( index + 1 ) )
590+ && every ( identifier , isUpperCaseLetter , wordStart , index ) ;
661591 }
662592
663593 function transitionFromLowerToUpper ( identifier : string , word : boolean , index : number ) : boolean {
@@ -677,9 +607,19 @@ namespace ts {
677607 // on characters would be: A M
678608 //
679609 // We break the search string on characters. But we break the symbol name on words.
680- const transition = word
681- ? ( currentIsUpper && ! lastIsUpper )
682- : currentIsUpper ;
683- return transition ;
610+ return currentIsUpper && ( ! word || ! lastIsUpper ) ;
611+ }
612+
613+ function everyInRange ( start : number , end : number , pred : ( n : number ) => boolean ) : boolean {
614+ for ( let i = start ; i < end ; i ++ ) {
615+ if ( ! pred ( i ) ) {
616+ return false ;
617+ }
618+ }
619+ return true ;
620+ }
621+
622+ function every ( s : string , pred : ( ch : number , index : number ) => boolean , start = 0 , end = s . length ) : boolean {
623+ return everyInRange ( start , end , i => pred ( s . charCodeAt ( i ) , i ) ) ;
684624 }
685625}
0 commit comments