Fix arrow function and function expression export indexing#18
Merged
colbymchenry merged 2 commits intoFeb 10, 2026
Merged
Conversation
Arrow functions and function expressions assigned to variables
(e.g. `export const useAuth = () => { ... }`) were not being indexed
because the arrow_function AST node has no `name` field — the name
lives on the parent variable_declarator node.
Additionally, `isExported()` for TypeScript and JavaScript extractors
only checked 10 characters back from the node's start position, which
missed `export` for deeply nested nodes like arrow functions inside
variable declarations inside export statements.
Changes:
- extractFunction(): When an arrow_function or function_expression
resolves to '<anonymous>', look up the parent variable_declarator
for the name before skipping.
- isExported() (TS + JS): Walk the parent chain to find an
export_statement ancestor instead of substring matching.
- Add 6 test cases covering arrow function exports, function
expression exports, non-exported arrow functions, anonymous
arrow functions, multiple exports, and JavaScript files.
Tested on a real monorepo (238 files): node count increased from
779 to 958 (+23%), with 94 new nodes in packages/ that previously
had 0 coverage.
Extend extraction to index two additional categories of symbols
that were previously invisible:
1. Type aliases (e.g. `export type X = ...` in TypeScript,
`type X` in Go, `type X = ...` in Rust, `typealias X` in Swift,
`type_alias` in Kotlin). Adds `typeAliasTypes` to the
LanguageExtractor interface with values for all 13 languages.
2. Exported variable declarations that aren't functions, including:
- Zustand stores: `export const useX = create(...)`
- XState machines: `export const xMachine = createMachine(...)`
- Zod schemas: `export const schema = z.object(...)`
- Config objects: `export const config = { ... }`
- Constants: `export const MAX = 3`
- Arrays: `export const NAMES = [...] as const`
The extractExportedVariables() method is called when visiting
export_statement nodes. It skips variable_declarator values that
are already handled by functionTypes (arrow_function,
function_expression) to avoid duplicate extraction.
Adds 11 new test cases (59 total extraction tests, 215 total).
Tested on production monorepo: nodes increased from 958 to 1,172
(+22%), with 109 new variable nodes and 105 new type_alias nodes.
Only 4 files remain at 0 nodes — all are re-export barrels or
ambient declaration files with no extractable symbols.
This was referenced Apr 26, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
CodeGraph v0.3.1 fails to index three common TypeScript/JavaScript patterns:
export const useAuth = () => { ... }— thearrow_functionAST node has nonamefield, soextractName()returns'<anonymous>'and bails.export type AuthContextValue = { ... }—type_alias_declarationisn't in any extraction list.export const store = create(...),export const schema = z.object(...),export const config = { ... }— these arecall_expression,object, or primitive values, not functions, so they're never visited.Additionally,
isExported()for TS/JS uses a 10-char substring lookback that missesexportfor deeply nested nodes.Real-World Impact
Tested on a production monorepo (Expo + FastAPI, 238 files):
packages/nodes7 shared packages (auth, db, cv, i18n, ui, analytics, config) had zero nodes. After this fix, all have full coverage. Only 4 files remain at 0 nodes — all are re-export barrels or ambient declarations with no extractable symbols.
Changes (2 commits)
Commit 1: Arrow function + isExported fix
extractFunction(): Whenarrow_functionorfunction_expressionresolves to'<anonymous>', check the parentvariable_declaratorfor the name:isExported()(TS + JS): Walk the parent chain instead of 10-char lookback:Commit 2: Type alias + exported variable extraction
typeAliasTypes: New field onLanguageExtractorinterface. Populated for TypeScript (type_alias_declaration), Go (type_spec), Rust (type_item), C (type_definition), C++ (type_definition,alias_declaration), Swift (typealias_declaration), Kotlin (type_alias). Empty for languages without type aliases.extractTypeAlias(): New method that createstype_aliaskind nodes.extractExportedVariables(): New method called when visitingexport_statementnodes. Findslexical_declaration > variable_declaratorchildren whose values are NOT already handled byfunctionTypes(avoids duplicating arrow functions). Createsvariablekind nodes for:export const useX = create(...)export const xMachine = createMachine(...)export const schema = z.object(...)export const config = { ... }export const MAX = 3export const NAMES = [...] as constTests
Added 17 new test cases in
__tests__/extraction.test.ts:Arrow function tests (6):
Type alias tests (3):
Exported variable tests (8):
All 215 tests pass (59 extraction + 156 others). Zero regressions in evaluation benchmarks.
AST Context
For
export const useAuth = () => { ... }, tree-sitter produces:For
export const config = { ... }:The
arrow_function/objectnodes are 3 levels deep underexport_statement, which is why the 10-char lookback failed and why parent-chain walking is needed.