MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / extractSearchTerms

Function extractSearchTerms

src/search/query-utils.ts:156–215  ·  view source on GitHub ↗
(query: string, options?: { stems?: boolean })

Source from the content-addressed store, hash-verified

154 * so FTS prefix matching can find related code symbols.
155 */
156export function extractSearchTerms(query: string, options?: { stems?: boolean }): string[] {
157 const includeStems = options?.stems !== false;
158 const tokens = new Set<string>();
159
160 // First, extract and preserve compound identifiers before splitting
161 // CamelCase: scrapeLoop, UserService, getCallGraph
162 const compoundPattern = /\b([a-zA-Z][a-zA-Z0-9]*(?:[A-Z][a-z]+)+|[A-Z][a-z]+(?:[A-Z][a-z]*)+)\b/g;
163 let match;
164 while ((match = compoundPattern.exec(query)) !== null) {
165 if (match[1] && match[1].length >= 3) {
166 tokens.add(match[1].toLowerCase()); // preserve full compound: "scrapeloop"
167 }
168 }
169
170 // snake_case: scrape_loop, user_service
171 const snakePattern = /\b([a-zA-Z][a-zA-Z0-9]*(?:_[a-zA-Z0-9]+)+)\b/g;
172 while ((match = snakePattern.exec(query)) !== null) {
173 if (match[1] && match[1].length >= 3) {
174 tokens.add(match[1].toLowerCase());
175 }
176 }
177
178 // Split camelCase / PascalCase: "getUserName" → "get User Name"
179 const camelSplit = query
180 .replace(/([a-z])([A-Z])/g, '$1 $2')
181 .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2');
182
183 // Replace underscores and dots with spaces (snake_case, dot.notation)
184 const normalised = camelSplit.replace(/[_.]+/g, ' ');
185
186 // Split on any non-alphanumeric character
187 const words = normalised.split(/[^a-zA-Z0-9]+/).filter(Boolean);
188
189 for (const word of words) {
190 const lower = word.toLowerCase();
191 if (lower.length < 3) continue;
192 if (STOP_WORDS.has(lower)) continue;
193 tokens.add(lower);
194 }
195
196 // Generate stem variants for broader FTS matching.
197 // "caching" → "cache" finds CacheBuilder; "eviction" → "evict" finds evictEntries.
198 // Also enables co-occurrence dampening by increasing term count above 1.
199 // Stems are skipped when scoring path relevance (stems inflate path scores).
200 if (includeStems) {
201 const stems = new Set<string>();
202 for (const token of tokens) {
203 for (const variant of getStemVariants(token)) {
204 if (!tokens.has(variant) && !STOP_WORDS.has(variant)) {
205 stems.add(variant);
206 }
207 }
208 }
209 for (const stem of stems) {
210 tokens.add(stem);
211 }
212 }
213

Callers 2

findRelevantContextMethod · 0.90
scorePathRelevanceFunction · 0.85

Calls 3

getStemVariantsFunction · 0.85
hasMethod · 0.80
execMethod · 0.65

Tested by

no test coverage detected