mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
perf(palette): reuse allowed quality arrays during matching (#18966)
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import {
|
||||
indexPaletteField,
|
||||
type PaletteIdentifierKind,
|
||||
type PaletteFieldProfile
|
||||
} from './indexed-field'
|
||||
import { matchPaletteField } from './match-field'
|
||||
import { createPaletteQueryToken } from './palette-query'
|
||||
|
||||
describe('palette field quality allocation', () => {
|
||||
it.each(['scan', 's', '123', 'scna', 'zzz'])(
|
||||
'does not allocate a Set per field for %s',
|
||||
(query) => {
|
||||
const profiles: PaletteFieldProfile[] = [
|
||||
'structured-label',
|
||||
'identifier',
|
||||
'path',
|
||||
'prose',
|
||||
'exact-alias'
|
||||
]
|
||||
const fields = Array.from({ length: 1_000 }, (_, i) =>
|
||||
indexPaletteField({
|
||||
id: String(i),
|
||||
profile: profiles[i % profiles.length],
|
||||
text: 'scan daily 1234 workspace',
|
||||
...(i % 2 === 0 ? { identifier: { kind: 'number' as const } } : {})
|
||||
})!
|
||||
)
|
||||
const token = createPaletteQueryToken(query, 0)
|
||||
let allocations = 0
|
||||
const NativeSet = globalThis.Set
|
||||
class CountedSet<T> extends NativeSet<T> {
|
||||
constructor(values?: Iterable<T> | null) {
|
||||
super(values)
|
||||
allocations++
|
||||
}
|
||||
}
|
||||
vi.stubGlobal('Set', CountedSet)
|
||||
try {
|
||||
for (const field of fields) {
|
||||
matchPaletteField(field, token)
|
||||
}
|
||||
} finally {
|
||||
vi.unstubAllGlobals()
|
||||
}
|
||||
expect(allocations).toBe(0)
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
describe('palette quality restrictions remain local to each match', () => {
|
||||
it.each<PaletteIdentifierKind>(['number', 'version', 'date', 'port', 'sha', 'key'])(
|
||||
'preserves prefix permissions for %s',
|
||||
(kind) => {
|
||||
const field = indexPaletteField({
|
||||
id: 'id',
|
||||
profile: 'identifier',
|
||||
text: '12345',
|
||||
identifier: { kind }
|
||||
})!
|
||||
const prefix = createPaletteQueryToken('123', 0)
|
||||
const exact = createPaletteQueryToken('12345', 0)
|
||||
const expected = ['port', 'sha', 'key'].includes(kind)
|
||||
? { quality: 'field-prefix', ranges: [{ start: 0, end: 3 }] }
|
||||
: null
|
||||
expect(matchPaletteField(field, prefix)).toEqual(expected)
|
||||
expect(matchPaletteField(field, exact)).toEqual({
|
||||
quality: 'field-exact',
|
||||
ranges: [{ start: 0, end: 5 }]
|
||||
})
|
||||
expect(matchPaletteField(field, prefix)).toEqual(expected)
|
||||
}
|
||||
)
|
||||
|
||||
it.each<PaletteFieldProfile>(['structured-label', 'identifier', 'path', 'prose', 'exact-alias'])(
|
||||
'preserves typo restrictions for %s without mutating the profile',
|
||||
(profile) => {
|
||||
const field = indexPaletteField({ id: 'id', profile, text: 'scan' })!
|
||||
expect(matchPaletteField(field, createPaletteQueryToken('s', 0))).toEqual({
|
||||
quality: 'field-prefix',
|
||||
ranges: [{ start: 0, end: 1 }]
|
||||
})
|
||||
expect(matchPaletteField(field, createPaletteQueryToken('scam', 0))).toEqual(
|
||||
['structured-label', 'prose'].includes(profile)
|
||||
? { quality: 'typo', ranges: [{ start: 0, end: 4 }] }
|
||||
: null
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
@@ -32,7 +32,7 @@ const SIGILS = new Set(['#', '!'])
|
||||
function allowedQualities(
|
||||
field: PaletteIndexedField,
|
||||
token: PaletteQueryToken
|
||||
): ReadonlySet<PaletteMatchQuality> {
|
||||
): readonly PaletteMatchQuality[] {
|
||||
let qualities = paletteProfileAllowedQualities(field.profile)
|
||||
if (field.identifier && !identifierKindAllowsPrefix(field.identifier.kind)) {
|
||||
qualities = qualities.filter((quality) => !PREFIX_QUALITIES.has(quality))
|
||||
@@ -43,7 +43,7 @@ function allowedQualities(
|
||||
if (token.isIdentifierLike) {
|
||||
qualities = qualities.filter((quality) => quality !== 'typo')
|
||||
}
|
||||
return new Set(qualities)
|
||||
return qualities
|
||||
}
|
||||
|
||||
/** `#123` must not reach a GitLab MR, and `!123` must not reach a GitHub PR. */
|
||||
@@ -83,15 +83,15 @@ function toRanges(field: PaletteIndexedField, start: number, end: number): reado
|
||||
function matchLiteral(
|
||||
field: PaletteIndexedField,
|
||||
token: PaletteQueryToken,
|
||||
qualities: ReadonlySet<PaletteMatchQuality>
|
||||
qualities: readonly PaletteMatchQuality[]
|
||||
): PaletteFieldMatch | null {
|
||||
const normalized = field.text.normalized
|
||||
const text = token.text
|
||||
|
||||
if (qualities.has('field-exact') && normalized === text) {
|
||||
if (qualities.includes('field-exact') && normalized === text) {
|
||||
return { quality: 'field-exact', ranges: toRanges(field, 0, normalized.length) }
|
||||
}
|
||||
if (qualities.has('word-exact')) {
|
||||
if (qualities.includes('word-exact')) {
|
||||
const word = field.words.find((entry) => entry.text === text)
|
||||
if (word) {
|
||||
return { quality: 'word-exact', ranges: toRanges(field, word.start, word.end) }
|
||||
@@ -101,10 +101,10 @@ function matchLiteral(
|
||||
return { quality: 'word-exact', ranges: toRanges(field, atom.start, atom.end) }
|
||||
}
|
||||
}
|
||||
if (qualities.has('field-prefix') && normalized.startsWith(text)) {
|
||||
if (qualities.includes('field-prefix') && normalized.startsWith(text)) {
|
||||
return { quality: 'field-prefix', ranges: toRanges(field, 0, text.length) }
|
||||
}
|
||||
if (qualities.has('word-prefix')) {
|
||||
if (qualities.includes('word-prefix')) {
|
||||
const word = field.words.find((entry) => entry.text.startsWith(text))
|
||||
const atom = field.atoms.find((entry) => normalized.startsWith(text, entry.start))
|
||||
const start = word && atom ? Math.min(word.start, atom.start) : (word?.start ?? atom?.start)
|
||||
@@ -117,13 +117,13 @@ function matchLiteral(
|
||||
if (literalIndex === -1) {
|
||||
return null
|
||||
}
|
||||
if (qualities.has('boundary-substring') && isWordStart(field, literalIndex)) {
|
||||
if (qualities.includes('boundary-substring') && isWordStart(field, literalIndex)) {
|
||||
return {
|
||||
quality: 'boundary-substring',
|
||||
ranges: toRanges(field, literalIndex, literalIndex + text.length)
|
||||
}
|
||||
}
|
||||
if (qualities.has('literal-substring')) {
|
||||
if (qualities.includes('literal-substring')) {
|
||||
return {
|
||||
quality: 'literal-substring',
|
||||
ranges: toRanges(field, literalIndex, literalIndex + text.length)
|
||||
@@ -135,9 +135,9 @@ function matchLiteral(
|
||||
function matchCompact(
|
||||
field: PaletteIndexedField,
|
||||
token: PaletteQueryToken,
|
||||
qualities: ReadonlySet<PaletteMatchQuality>
|
||||
qualities: readonly PaletteMatchQuality[]
|
||||
): PaletteFieldMatch | null {
|
||||
if (!qualities.has('compact') || token.compact.length < MIN_COMPACT_LENGTH) {
|
||||
if (!qualities.includes('compact') || token.compact.length < MIN_COMPACT_LENGTH) {
|
||||
return null
|
||||
}
|
||||
for (const atom of field.atoms) {
|
||||
@@ -152,9 +152,9 @@ function matchCompact(
|
||||
function matchTypo(
|
||||
field: PaletteIndexedField,
|
||||
token: PaletteQueryToken,
|
||||
qualities: ReadonlySet<PaletteMatchQuality>
|
||||
qualities: readonly PaletteMatchQuality[]
|
||||
): PaletteFieldMatch | null {
|
||||
if (!qualities.has('typo') || !token.isLetterOnly || !isPaletteTypoCandidate(token.text)) {
|
||||
if (!qualities.includes('typo') || !token.isLetterOnly || !isPaletteTypoCandidate(token.text)) {
|
||||
return null
|
||||
}
|
||||
for (const word of field.words) {
|
||||
|
||||
Reference in New Issue
Block a user