diff --git a/src/vs/base/common/filters.ts b/src/vs/base/common/filters.ts index 3cf2c078d4a54ee2e14897b84626da8b87e8294e..536d31b327d48b5052988a3e923b82802f66bfaf 100644 --- a/src/vs/base/common/filters.ts +++ b/src/vs/base/common/filters.ts @@ -503,21 +503,14 @@ export function fuzzyScore(pattern: string, word: string): [number, number[]] { } else if (_seps[lastLowWordChar]) { score = 5; - } else if (j === i) { - score = 3; - } else { score = 1; } - - if (i > 1 && j > 1 && _scores[i - 1][j - 1] > score) { - score = _scores[i - 1][j - 1]; - } } _scores[i][j] = score; - let diag = _table[i - 1][j - 1] + score; + let diag = _table[i - 1][j - 1] + (score > 1 ? 1 : score); let top = _table[i - 1][j] + -1; let left = _table[i][j - 1] + -1; @@ -578,24 +571,34 @@ export function fuzzyScore(pattern: string, word: string): [number, number[]] { function findAllMatches(patternLen: number, patternPos: number, wordPos: number, total: number, matches: number[], bucket: [number, number[]][], lastMatched: boolean): void { + let simpleMatchCount = 0; + while (patternPos > 0 && wordPos > 0) { let score = _scores[patternPos][wordPos]; let arrow = _arrows[patternPos][wordPos]; - if (arrow === Arrow.Left || score < 0) { + if (arrow === Arrow.Left) { // left wordPos -= 1; if (lastMatched) { - total -= 5; // gap penalty + total -= 5; // new gap penalty + } else if (matches.length !== 0) { + total -= 1; // gap penalty after first match } lastMatched = false; + simpleMatchCount = 0; } else if (arrow & Arrow.Diag) { if (arrow & Arrow.Left) { // left - findAllMatches(patternLen, patternPos, wordPos - 1, total, matches.slice(0), bucket, lastMatched); + findAllMatches( + patternLen, patternPos, + wordPos - 1, + matches.length !== 0 ? total - 1 : total, + matches.slice(0), bucket, lastMatched + ); } // diag @@ -605,6 +608,13 @@ function findAllMatches(patternLen: number, patternPos: number, wordPos: number, matches.unshift(wordPos); lastMatched = true; + if (score === 1) { + simpleMatchCount += 1; + } else { + total += simpleMatchCount * (score - 1); + simpleMatchCount = 0; + } + } else { return undefined; } @@ -621,7 +631,6 @@ function findAllMatches(patternLen: number, patternPos: number, wordPos: number, } total -= wordPos >= 3 ? 9 : wordPos * 3; // late start penalty - total -= (1 + matches[matches.length - 1]) - patternLen; // penalty for all non matching characters between first and last bucket.push([total, matches]); } diff --git a/src/vs/base/test/common/filters.test.ts b/src/vs/base/test/common/filters.test.ts index 9c305e979797142d21d647c4db634cc5463c428a..bd7f89439bae7fa985df94ae35befeb0a369e599 100644 --- a/src/vs/base/test/common/filters.test.ts +++ b/src/vs/base/test/common/filters.test.ts @@ -211,7 +211,7 @@ suite('Filters', () => { test('fuzzyScore, #23215', function () { assertMatches('tit', 'win.tit', 'win.^t^i^t', fuzzyScore); assertMatches('title', 'win.title', 'win.^t^i^t^l^e', fuzzyScore); - assertMatches('WordCla', 'WordCharacterClassifier', '^W^o^r^d^CharacterC^l^assifier', fuzzyScore); + assertMatches('WordCla', 'WordCharacterClassifier', '^W^o^r^dCharacter^C^l^assifier', fuzzyScore); assertMatches('WordCCla', 'WordCharacterClassifier', '^W^o^r^d^Character^C^l^assifier', fuzzyScore); }); @@ -253,13 +253,13 @@ suite('Filters', () => { assertMatches('LLL', 'SVisualLoggerLogsList', 'SVisual^Logger^Logs^List', fuzzyScore); assertMatches('LLLL', 'SVilLoLosLi', undefined, fuzzyScore); assertMatches('LLLL', 'SVisualLoggerLogsList', undefined, fuzzyScore); - assertMatches('TEdit', 'TextEdit', '^T^extE^d^i^t', fuzzyScore); - assertMatches('TEdit', 'TextEditor', '^T^extE^d^i^tor', fuzzyScore); + assertMatches('TEdit', 'TextEdit', '^Text^E^d^i^t', fuzzyScore); + assertMatches('TEdit', 'TextEditor', '^Text^E^d^i^tor', fuzzyScore); assertMatches('TEdit', 'Textedit', '^T^exte^d^i^t', fuzzyScore); - assertMatches('TEdit', 'text_edit', '^t^ext_e^d^i^t', fuzzyScore); - assertMatches('TEditDit', 'TextEditorDecorationType', '^T^extE^d^i^tor^Decorat^ion^Type', fuzzyScore); - assertMatches('TEdit', 'TextEditorDecorationType', '^T^extE^d^i^torDecorationType', fuzzyScore); - assertMatches('Tedit', 'TextEdit', '^T^extE^d^i^t', fuzzyScore); + assertMatches('TEdit', 'text_edit', '^text_^e^d^i^t', fuzzyScore); + assertMatches('TEditDit', 'TextEditorDecorationType', '^Text^E^d^i^tor^Decorat^ion^Type', fuzzyScore); + assertMatches('TEdit', 'TextEditorDecorationType', '^Text^E^d^i^torDecorationType', fuzzyScore); + assertMatches('Tedit', 'TextEdit', '^Text^E^d^i^t', fuzzyScore); assertMatches('ba', '?AB?', undefined, fuzzyScore); assertMatches('bkn', 'the_black_knight', 'the_^black_^k^night', fuzzyScore); assertMatches('bt', 'the_black_knight', 'the_^black_knigh^t', fuzzyScore);