vim-patch:9.1.1445: negative matchfuzzy scores although there is a match (#34409)

Problem:  negative matchfuzzy scores although there is a match
          (Maxim Kim)
Solution: reset the score if a match has been found but the score is
          negative (Girish Palya)

The fuzzy algorithm may miss some matches in long strings due to recursion
limits. As a result, the score can end up negative even when matches exist.
In such cases, reset the score to ensure it is non-negative.

fixes: #vim/vim#17449
closes: vim/vim#17469

328332b0b0

Co-authored-by: Girish Palya <girishji@gmail.com>
This commit is contained in:
zeertzjq
2025-06-10 08:47:14 +08:00
committed by GitHub
parent 7a58cf4b96
commit bcba067dc2
2 changed files with 7 additions and 2 deletions

View File

@@ -3021,6 +3021,11 @@ static int fuzzy_match_compute_score(const char *const fuzpat, const char *const
// Apply unmatched penalty // Apply unmatched penalty
const int unmatched = strSz - numMatches; const int unmatched = strSz - numMatches;
score += UNMATCHED_LETTER_PENALTY * unmatched; score += UNMATCHED_LETTER_PENALTY * unmatched;
// In a long string, not all matches may be found due to the recursion limit.
// If at least one match is found, reset the score to a non-negative value.
if (score < 0 && numMatches > 0) {
score = 0;
}
// Apply ordering bonuses // Apply ordering bonuses
for (int i = 0; i < numMatches; i++) { for (int i = 0; i < numMatches; i++) {

View File

@@ -129,7 +129,7 @@ func Test_matchfuzzypos()
call assert_equal([[], [], []], matchfuzzypos([], 'abc')) call assert_equal([[], [], []], matchfuzzypos([], 'abc'))
" match in a long string " match in a long string
call assert_equal([[repeat('x', 300) .. 'abc'], [[300, 301, 302]], [-60]], call assert_equal([[repeat('x', 300) .. 'abc'], [[300, 301, 302]], [155]],
\ matchfuzzypos([repeat('x', 300) .. 'abc'], 'abc')) \ matchfuzzypos([repeat('x', 300) .. 'abc'], 'abc'))
" preference for camel case match " preference for camel case match
@@ -265,7 +265,7 @@ func Test_matchfuzzypos_mbyte()
call assert_equal([[], [], []], ['세 마리의 작은 돼지', '마리의', '마리의 작은', '작은 돼지']->matchfuzzypos('파란 하늘')) call assert_equal([[], [], []], ['세 마리의 작은 돼지', '마리의', '마리의 작은', '작은 돼지']->matchfuzzypos('파란 하늘'))
" match in a long string " match in a long string
call assert_equal([[repeat('ぶ', 300) .. 'ẼẼẼ'], [[300, 301, 302]], [-110]], call assert_equal([[repeat('ぶ', 300) .. 'ẼẼẼ'], [[300, 301, 302]], [105]],
\ matchfuzzypos([repeat('ぶ', 300) .. 'ẼẼẼ'], 'ẼẼẼ')) \ matchfuzzypos([repeat('ぶ', 300) .. 'ẼẼẼ'], 'ẼẼẼ'))
" preference for camel case match " preference for camel case match
call assert_equal([['xѳѵҁxxѳѴҁ'], [[6, 7, 8]], [219]], matchfuzzypos(['xѳѵҁxxѳѴҁ'], 'ѳѵҁ')) call assert_equal([['xѳѵҁxxѳѴҁ'], [[6, 7, 8]], [219]], matchfuzzypos(['xѳѵҁxxѳѴҁ'], 'ѳѵҁ'))