Skip to content

Commit ce88e1b

Browse files
committed
Fix a code_search bug
1 parent d7e1b1e commit ce88e1b

File tree

2 files changed

+85
-4
lines changed

2 files changed

+85
-4
lines changed

sdk/src/__tests__/code-search.test.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,88 @@ describe('codeSearch', () => {
627627
})
628628
})
629629

630+
describe('glob pattern handling', () => {
631+
it('should handle -g flag with glob patterns like *.ts', async () => {
632+
const searchPromise = codeSearch({
633+
projectPath: '/test/project',
634+
pattern: 'import',
635+
flags: '-g *.ts',
636+
})
637+
638+
const output = [
639+
createRgJsonMatch('file.ts', 1, 'import foo from "bar"'),
640+
createRgJsonMatch('file.ts', 5, 'import { baz } from "qux"'),
641+
].join('\n')
642+
643+
mockProcess.stdout.emit('data', Buffer.from(output))
644+
mockProcess.emit('close', 0)
645+
646+
const result = await searchPromise
647+
expect(result[0].type).toBe('json')
648+
const value = result[0].value as any
649+
expect(value.stdout).toContain('file.ts:')
650+
651+
// Verify the args passed to spawn include the glob flag correctly
652+
expect(mockSpawn).toHaveBeenCalled()
653+
const spawnArgs = mockSpawn.mock.calls[0][1] as string[]
654+
expect(spawnArgs).toContain('-g')
655+
expect(spawnArgs).toContain('*.ts')
656+
})
657+
658+
it('should handle -g flag with multiple glob patterns', async () => {
659+
const searchPromise = codeSearch({
660+
projectPath: '/test/project',
661+
pattern: 'import',
662+
flags: '-g *.ts -g *.tsx',
663+
})
664+
665+
const output = createRgJsonMatch('file.tsx', 1, 'import React from "react"')
666+
667+
mockProcess.stdout.emit('data', Buffer.from(output))
668+
mockProcess.emit('close', 0)
669+
670+
const result = await searchPromise
671+
expect(result[0].type).toBe('json')
672+
const value = result[0].value as any
673+
expect(value.stdout).toContain('file.tsx:')
674+
675+
// Verify both glob patterns are passed correctly
676+
const spawnArgs = mockSpawn.mock.calls[0][1] as string[]
677+
// Should have two -g flags, each followed by its pattern
678+
const gFlagIndices = spawnArgs.map((arg, i) => arg === '-g' ? i : -1).filter(i => i !== -1)
679+
expect(gFlagIndices.length).toBe(2)
680+
expect(spawnArgs[gFlagIndices[0] + 1]).toBe('*.ts')
681+
expect(spawnArgs[gFlagIndices[1] + 1]).toBe('*.tsx')
682+
})
683+
684+
it('should not deduplicate flag-argument pairs', async () => {
685+
const searchPromise = codeSearch({
686+
projectPath: '/test/project',
687+
pattern: 'import',
688+
flags: '-g *.ts -i -g *.tsx',
689+
})
690+
691+
const output = createRgJsonMatch('file.tsx', 1, 'import React from "react"')
692+
693+
mockProcess.stdout.emit('data', Buffer.from(output))
694+
mockProcess.emit('close', 0)
695+
696+
const result = await searchPromise
697+
698+
// Verify flags are preserved in order without deduplication
699+
const spawnArgs = mockSpawn.mock.calls[0][1] as string[]
700+
const flagsSection = spawnArgs.slice(0, spawnArgs.indexOf('--'))
701+
expect(flagsSection).toContain('-g')
702+
expect(flagsSection).toContain('*.ts')
703+
expect(flagsSection).toContain('-i')
704+
expect(flagsSection).toContain('*.tsx')
705+
706+
// Count -g flags - should be 2, not deduplicated to 1
707+
const gCount = flagsSection.filter(arg => arg === '-g').length
708+
expect(gCount).toBe(2)
709+
})
710+
})
711+
630712
describe('timeout handling', () => {
631713
it('should timeout after specified seconds', async () => {
632714
const searchPromise = codeSearch({

sdk/src/tools/code-search.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,9 @@ export function codeSearch({
4646
searchCwd = requestedPath
4747
}
4848

49-
// Deduplicate flags
50-
const flagsArray = Array.from(
51-
new Set((flags || '').split(' ').filter(Boolean)),
52-
)
49+
// Parse flags - do NOT deduplicate to preserve flag-argument pairs like '-g *.ts'
50+
// Deduplicating would break up these pairs and cause errors
51+
const flagsArray = (flags || '').split(' ').filter(Boolean)
5352

5453
// Use JSON output for robust parsing and early stopping
5554
// --no-config prevents user/system .ripgreprc from interfering

0 commit comments

Comments
 (0)