From 41bd7baafb8b2c77796d96a2520739c5a092012a Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Fri, 16 Oct 2026 11:12:41 -0700 Subject: [PATCH] perf(palette): avoid filtering qualities for identifier tokens (#29785) --- .../match-field-allocation.test.ts | 41 +++++++++++++++++++ .../src/lib/palette-match/match-field.ts | 10 +++-- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/renderer/src/lib/palette-match/match-field-allocation.test.ts b/src/renderer/src/lib/palette-match/match-field-allocation.test.ts index 85634d27282..1f94610b42f 100644 --- a/src/renderer/src/lib/palette-match/match-field-allocation.test.ts +++ b/src/renderer/src/lib/palette-match/match-field-allocation.test.ts @@ -8,6 +8,41 @@ import { matchPaletteField } from './match-field' import { createPaletteQueryToken } from './palette-query' describe('palette field quality allocation', () => { + it('does not filter quality arrays for identifier-like queries', () => { + const profiles: PaletteFieldProfile[] = [ + 'structured-label', + 'identifier', + 'path', + 'prose', + 'exact-alias' + ] + const fields = profiles.map((profile) => + indexPaletteField({ + id: profile, + profile, + text: 'scan1', + role: 'primary', + destinationEligible: true + })! + ) + const token = createPaletteQueryToken('scan1', 0) + const matches: ReturnType[] = [] + const filter = vi.spyOn(Array.prototype, 'filter') + let allocations = 0 + try { + for (const field of fields) { + matches.push(matchPaletteField(field, token)) + } + allocations = filter.mock.calls.length + } finally { + filter.mockRestore() + } + expect(allocations).toBe(0) + expect(matches).toEqual( + profiles.map(() => ({ quality: 'field-exact', ranges: [{ start: 0, end: 5 }] })) + ) + }) + it.each(['scan', 's', '123', 'scna', 'zzz'])( 'does not allocate a Set per field for %s', (query) => { @@ -95,6 +130,12 @@ describe('palette quality restrictions remain local to each match', () => { ? { quality: 'typo', ranges: [{ start: 0, end: 4 }] } : null ) + expect( + matchPaletteField(field, { + ...createPaletteQueryToken('scam', 0), + isIdentifierLike: true + }) + ).toBeNull() } ) }) diff --git a/src/renderer/src/lib/palette-match/match-field.ts b/src/renderer/src/lib/palette-match/match-field.ts index 1744219524c..ef7a84cae07 100644 --- a/src/renderer/src/lib/palette-match/match-field.ts +++ b/src/renderer/src/lib/palette-match/match-field.ts @@ -40,9 +40,6 @@ function allowedQualities( if (token.isSingleLatinCharacter) { qualities = qualities.filter((quality) => SHORT_TOKEN_QUALITIES.has(quality)) } - if (token.isIdentifierLike) { - qualities = qualities.filter((quality) => quality !== 'typo') - } return qualities } @@ -154,7 +151,12 @@ function matchTypo( token: PaletteQueryToken, qualities: readonly PaletteMatchQuality[] ): PaletteFieldMatch | null { - if (!qualities.includes('typo') || !token.isLetterOnly || !isPaletteTypoCandidate(token.text)) { + if ( + token.isIdentifierLike || + !qualities.includes('typo') || + !token.isLetterOnly || + !isPaletteTypoCandidate(token.text) + ) { return null } for (const word of field.words) {