feat: Extract type references from annotations and improve symbol query matching

Adds type annotation parsing to create references edges for parameter types, return types, and variable type annotations in TypeScript and other typed languages. Expands symbol extraction from queries to capture lowercase identifiers and filters out more common English words. Removes obsolete search utility tests.
This commit is contained in:
Colby McHenry
2026-04-03 16:15:44 -05:00
parent d575c945d9
commit 4af51f565b
5 changed files with 141 additions and 150 deletions
-135
View File
@@ -1,135 +0,0 @@
/**
* Search Query Utilities Tests
*
* Tests multi-signal scoring, kind bonuses, and path relevance.
*/
import { describe, it, expect } from 'vitest';
import {
extractSearchTerms,
scorePathRelevance,
kindBonus,
STOP_WORDS,
} from '../src/search/query-utils';
describe('Search Query Utilities', () => {
describe('extractSearchTerms', () => {
it('should extract meaningful terms from a query', () => {
const terms = extractSearchTerms('find the login handler');
expect(terms).toContain('login');
expect(terms).toContain('handler');
// 'find' and 'the' are stop words
expect(terms).not.toContain('find');
expect(terms).not.toContain('the');
});
it('should filter stop words', () => {
const terms = extractSearchTerms('how does the authentication work');
expect(terms).not.toContain('how');
expect(terms).not.toContain('does');
expect(terms).not.toContain('the');
expect(terms).toContain('authentication');
expect(terms).toContain('work');
});
it('should handle camelCase by lowercasing', () => {
const terms = extractSearchTerms('UserService');
expect(terms).toContain('userservice');
});
it('should strip punctuation', () => {
const terms = extractSearchTerms('payment.process()');
expect(terms).toContain('payment');
expect(terms).toContain('process');
});
it('should return empty for all stop words', () => {
const terms = extractSearchTerms('how do I get the');
expect(terms).toHaveLength(0);
});
it('should filter single-character terms', () => {
const terms = extractSearchTerms('a b c auth');
expect(terms).toEqual(['auth']);
});
});
describe('scorePathRelevance', () => {
it('should score filename matches highest', () => {
const score = scorePathRelevance('src/auth/login.ts', 'login');
expect(score).toBeGreaterThanOrEqual(10);
});
it('should score directory matches', () => {
const score = scorePathRelevance('src/auth/index.ts', 'auth');
expect(score).toBeGreaterThanOrEqual(5);
});
it('should return 0 for unrelated paths', () => {
const score = scorePathRelevance('src/utils/format.ts', 'payment');
expect(score).toBe(0);
});
it('should accumulate scores for multiple matching terms', () => {
const score = scorePathRelevance('src/auth/login.ts', 'auth login');
// Both 'auth' (dir match) and 'login' (filename match)
expect(score).toBeGreaterThanOrEqual(15);
});
it('should return 0 for empty query terms', () => {
const score = scorePathRelevance('src/auth/login.ts', 'the a an');
expect(score).toBe(0);
});
});
describe('kindBonus', () => {
it('should give functions and methods highest bonus', () => {
expect(kindBonus('function')).toBe(10);
expect(kindBonus('method')).toBe(10);
});
it('should rank functions > classes > variables > imports', () => {
expect(kindBonus('function')).toBeGreaterThan(kindBonus('class'));
expect(kindBonus('class')).toBeGreaterThan(kindBonus('variable'));
expect(kindBonus('variable')).toBeGreaterThan(kindBonus('import'));
});
it('should give routes high priority', () => {
expect(kindBonus('route')).toBeGreaterThanOrEqual(9);
});
it('should give components high priority', () => {
expect(kindBonus('component')).toBeGreaterThanOrEqual(8);
});
it('should return 0 for parameter and file kinds', () => {
expect(kindBonus('parameter')).toBe(0);
expect(kindBonus('file')).toBe(0);
});
it('should return 0 for unknown kinds', () => {
expect(kindBonus('unknown_kind' as any)).toBe(0);
});
});
describe('STOP_WORDS', () => {
it('should contain common English stop words', () => {
expect(STOP_WORDS.has('the')).toBe(true);
expect(STOP_WORDS.has('and')).toBe(true);
expect(STOP_WORDS.has('or')).toBe(true);
});
it('should contain action verbs used in queries', () => {
expect(STOP_WORDS.has('find')).toBe(true);
expect(STOP_WORDS.has('show')).toBe(true);
expect(STOP_WORDS.has('get')).toBe(true);
expect(STOP_WORDS.has('list')).toBe(true);
});
it('should not contain technical terms', () => {
expect(STOP_WORDS.has('function')).toBe(false);
expect(STOP_WORDS.has('class')).toBe(false);
expect(STOP_WORDS.has('auth')).toBe(false);
});
});
});