Skip to content

feat(search): signature search + callers-of / callees-of graph qualifiers#2

Open
mschreib28 wants to merge 2 commits into
mainfrom
upstream/feat/search-signature-and-graph-qualifiers
Open

feat(search): signature search + callers-of / callees-of graph qualifiers#2
mschreib28 wants to merge 2 commits into
mainfrom
upstream/feat/search-signature-and-graph-qualifiers

Conversation

@mschreib28
Copy link
Copy Markdown
Owner

Summary\n\nThree new search query qualifiers extending PR colbymchenry#131's field-qualified parser. All compose with the existing kind: / lang: / path: / name: filters.\n\n### sig: / signature: — substring of node.signature\nFind functions by what they accept or return:\n\nquery "sig:Promise<User> kind:function"\nquery "sig:context.Context"\nquery "sig:io.Reader sig:io.Writer" # OR semantics\n\n\n### callers-of:NAME — nodes that call NAME\n\nquery "callers-of:authenticate"\nquery "callers-of:authenticate name:Handler"\nquery "callers-of:Forward kind:function"\n\n\n### callees-of:NAME — nodes called BY NAME\n\nquery "callees-of:bootstrap"\n\n\n## Implementation notes\n\n- New nodesCallingAny(names) and nodesCalledByAny(names) SQL helpers; nodesByIds(ids) for bulk node fetching when seeded from the graph.\n- Graph-seeded candidate set when callers-of/callees-of is given without text — otherwise the filter-only path scans 50 arbitrary name-ordered nodes that rarely intersect with the graph result.\n- searchAllByFilters accepts signatureLike: string[] and OR's all entries in SQL — matches the OR semantics of path: / name: post-filters.\n- All IN-clause helpers chunk inputs to 900 per query (under SQLite's 999 variable cap) so pathological inputs can't trigger SQLITE_ERROR: too many SQL variables.\n- Graph-seeded path applies kinds/languages post-filter to the seed set so callers-of:foo kind:method correctly narrows.\n- Reviewer-driven: also memoises callersSet() / calleesSet() closures so the seed and the filter pass don't re-query the same names.\n\n## Test plan\n\nVerified live on ollama/ollama@v0.22.0:\n\n| Query | Result |\n|-------|--------|\n| sig:context.Context kind:function | BuildLauncherState, Chat, ... |\n| callers-of:Forward kind:function | audioFeedForward, forwardConvBlock, ... |\n| auth sig:error | getAuthorizationToken (text + sig: composes) |\n\n- [x] 5 new integration tests in __tests__/search-qualifiers.test.ts covering sig:, multi-sig: OR, callers-of:, callees-of:, and callers-of: + kind: composition\n- [x] 2 new parser tests for sig: and callers-of: / callees-of: parsing\n- [x] npx vitest run410 passed (was 405)\n- [x] npx tsc --noEmit clean\n- [x] npm run build succeeds\n\n## Depends on\n\n- PR colbymchenry#131 (feat/search-fields-and-fuzzy) — parser foundation + chunking infrastructure\n\n🤖 Generated with Claude Code\n


Copied from colbymchenry/codegraph#135

… callees-of)

Three additional query-parser fields on top of PR colbymchenry#131's
field-qualified-query foundation:

- sig:/signature: SUBSTR — case-insensitive substring of node.signature.
  Lets users find functions by what they return / accept (e.g.
  `sig:Promise<User>`, `sig:context.Context`). Pushed into SQL via a
  new `signatureLike` parameter on searchAllByFilters when sig: is
  the only criterion, so the filter-only path doesn't waste candidate
  slots on signatureless rows.

- callers-of:NAME — restricts results to nodes that have at least one
  outgoing `calls` edge to a node named NAME. Backed by a new
  nodesCallingAny() SQL helper. When this is the only criterion (no
  text), the candidate set is seeded FROM the graph (via nodesByIds)
  rather than scanning a name-ordered slice of arbitrary nodes — that
  way a 3-caller function correctly returns 3 candidates instead of
  zero.

- callees-of:NAME — symmetric: nodes that are called BY a node named
  NAME. Backed by nodesCalledByAny() and the same graph-seeded path.

Verified live against ollama/ollama@v0.22.0:
  query "sig:context.Context kind:function" → BuildLauncherState, Chat,...
  query "callers-of:Forward kind:function"  → audioFeedForward, forwardConvBlock,...
  query "auth sig:error"                    → getAuthorizationToken (filters compose with text)

Two new parser tests (sig: + alias, callers-of/callees-of). Full suite:
405 passed.
…ndant graph helpers, IN-clause cap, integration tests

Five reviewer fixes:

- searchAllByFilters: signatureLike is now a string[] (OR'd in SQL),
  not a single string. The previous version pre-filtered SQL on
  signatureFilters[0] only while the JS post-filter used `some()`
  (OR) on all filters — the intersection silently dropped every
  sig: token after the first. Multi-sig now works as proper OR
  (matching path:/name: filter semantics).

- callersSet() / calleesSet() are computed once via a memoised
  closure and reused by both the graph-seeded candidate path and
  the post-filter pass. Previously each was queried twice per
  filter-only callers-of:/callees-of: query.

- New chunkIds() helper splits IN-clause inputs into batches of 900
  (under SQLite's default SQLITE_LIMIT_VARIABLE_NUMBER of 999) so
  pathological inputs (large name lists or seeded id sets) can't
  trigger 'too many SQL variables'. Applied to nodesByIds,
  nodesCallingAny, nodesCalledByAny.

- Graph-seeded path now applies kinds/languages filters to the
  result. Previously `callers-of:foo kind:method` returned every
  caller regardless of kind because the post-filter pass only
  intersected the graph-derived set without re-filtering.

- 5 new integration tests in __tests__/search-qualifiers.test.ts:
  sig: filter, multi-sig OR, callers-of:, callees-of:,
  callers-of: + kind: composition. Catches the bugs above.

Note: an idx_nodes_signature SQL index was considered but skipped —
LIKE '%substr%' matches don't use a btree index, so adding one would
just bloat the DB without helping. Substring sig: queries are
intentionally full-table scans; FTS already covers signature for
text queries.

Full suite: 410 passed (was 405, +5).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants