Skip to content

Exported generators were invisible to the code graph - #45

Merged
nedonatelli merged 1 commit into
mainfrom
fix/generator-symbols
Aug 3, 2026
Merged

Exported generators were invisible to the code graph#45
nedonatelli merged 1 commit into
mainfrom
fix/generator-symbols

Conversation

@nedonatelli

Copy link
Copy Markdown
Owner

export function* and export async function* produced no function symbol.
40 declarations across 17 files, absent from find_references,
analyze_impact and PKI retrieval.

They are not incidental code — they are the streaming core:

parseSse            streamOpenAiSse         translateAnthropicStream
pullModelStream     parseThinkTags          scanCode
streamBedrockChunks kickstandPullModel      importSafetensorsModel

Asking who calls any of them returned nothing, and an empty result is
indistinguishable from a symbol with no callers — the same property that let
221 exported constants stay invisible for the life of that feature.

Both analyzers missed it, for unrelated reasons

Which is why neither covered for the other:

analyzer cause
tree-sitter function* parses as generator_function_declaration — its own node type, not a modifier on function_declaration. Only the latter was mapped.
regex fallback gated on line.includes('function '), which is false for function* — the star sits exactly where the space would be.

The tree-sitter mapping was added for javascript/typescript/tsx/vue and
deliberately not for kotlin/swift, which have no generator syntax and where
the entry would be inert and misleading. My first pass added it to all six by a
too-loose anchor; caught before commit.

The regex replacement requires a name to be separated by whitespace or by
the star, so functionfoo still cannot match and function( still yields
nothing — both pinned by tests.

Cache invalidation

GRAPH_VERSION 4 → 5. Same reasoning as the v4 bump for variable symbols: none
of the 17 files changed, and reconciliation is by content hash, so without the
bump an existing cache would serve a generator-free graph forever.

How it was found

By auditing the four src files that still had zero symbols after the
truncation fix (#40) landed. Three were benign — two re-export barrels
(export * from, export { X } from) and a type-only index — and legitimately
own no symbols. The fourth was this.

Worth noting the truncation fix is what made this visible: while ~35 files were
being dropped per index run at random, a file with no symbols was unremarkable.

Verified

Against the real parser, not by reading the grammar:

before:  export function* charlie()  ->  charlie:export            (no function symbol)
after:   export function* charlie()  ->  charlie:export, charlie:function

And on real files: translateAnthropicStream, parseThinkTags, scanCode,
pullModelStream all now extract.

Mutation-checked: removing either analyzer's fix fails three tests.

npm run check: 8619 passed, 2 skipped, 464 files.

🤖 Generated with Claude Code

`export function*` and `export async function*` produced no `function` symbol,
so 40 declarations across 17 files were absent from find_references,
analyze_impact and PKI retrieval. They are the streaming core — parseSse,
streamOpenAiSse, translateAnthropicStream, pullModelStream, parseThinkTags,
scanCode — so asking who calls any of them returned nothing, and an empty
result is indistinguishable from a symbol with no callers.

Both analyzers missed them, for unrelated reasons, which is why neither covered
for the other:

- tree-sitter parses `function*` as `generator_function_declaration`, its own
  node type rather than a modifier on `function_declaration`, and only the
  latter was mapped. Added for javascript/typescript/tsx/vue; deliberately NOT
  for kotlin/swift, which have no such syntax and where the entry would be
  inert and misleading.
- the regex fallback gated on `line.includes('function ')`, which is false for
  `function*` — the star sits exactly where the space would be. Replaced with
  an alternation requiring a name to be separated by whitespace or by the star,
  so `functionfoo` still cannot match and `function(` still yields nothing.

GRAPH_VERSION 4 → 5. Same reasoning as the v4 bump for variable symbols: none
of the 17 files changed, and reconciliation is by content hash, so without it
an existing cache would serve a generator-free graph forever.

Found by auditing the four src files that still had zero symbols after the
truncation fix. Three were benign — two re-export barrels and a type-only
index — and the fourth was this. Mutation-checked: removing either analyzer's
fix fails three tests.

Class methods (`*iter()`) were already correct via method_definition.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

✅ All checks passed

Check Status
Type check ✅ success
Lint ✅ success
Tests ✅ success

Posted by SideCarAI-Bot

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.

1 participant