Skip to content

fix(extract): filter language built-in globals from call edges (#726)#916

Closed
otyeung wants to merge 1 commit into
Graphify-Labs:v8from
otyeung:fix/filter-language-builtin-globals
Closed

fix(extract): filter language built-in globals from call edges (#726)#916
otyeung wants to merge 1 commit into
Graphify-Labs:v8from
otyeung:fix/filter-language-builtin-globals

Conversation

@otyeung

@otyeung otyeung commented May 17, 2026

Copy link
Copy Markdown

Partial fix for #726. Prevents String(), Number(), Boolean(), fetch(), and other ECMAScript/Python language built-ins from becoming god-nodes by adding a 89-entry _LANGUAGE_BUILTIN_GLOBALS frozenset and filtering at both same-file (4 sites) and cross-file resolution.

Real-world impact

Reproduced on a 3848-node Next.js + TypeScript codebase (1021 code files):

Metric Before After
String() god-node degree 134 edges 1 (file containment)
String() cross-community edges 30+ communities 0
Total graph edges 5232 4946 (−286 spurious)
Top god-node String() (134) withCache() (49)

"Surprising Connections" no longer shows entries like:

parseMinImpressions() --calls--> String()  [INFERRED]
  docker/opencli/source/adlibrary/lib.js → src/components/data-table/data-table-pagination.tsx

Root cause

Tree-sitter classifies String(value) as call_expression with callee "String". With no local declaration matching, the callee goes to raw_calls for cross-file resolution. The resolver matches any node whose label is "String" (typically the first inline call expression encountered) and creates INFERRED edges from every String(...) call in the corpus.

Implementation

Same architecture as merged PR #908 (Rust scoped_identifier / trait-method blocklist) — name-blocklist filtering for ambiguous cross-corpus names.

Builtins blocked: 89 entries spanning JS/TS ECMAScript (String, Number, Boolean, Promise, Map, Set, JSON, Math, parseInt, etc.), Browser/Node (fetch, URL, URLSearchParams, FormData, Headers, Request, Response, AbortController, TextEncoder/TextDecoder, console), and Python (str, int, float, list, dict, set, len, range, enumerate, zip, map, filter, print, isinstance, etc.).

Tests

All 122 existing tests pass: test_extract.py (53), test_analyze.py (24), test_build.py (19), test_cluster.py (26). No new tests because existing fixtures do not include calls to builtins — filter is a no-op against current corpus. Validation done on real 3848-node Next.js codebase.

Scope

Partial fix for #726 — addresses the String()-style god-node pattern specifically. Cross-repo origin filtering also mentioned in #726 is not in scope for this PR.

🤖 Generated with Claude Code

…ify-Labs#726)

Prevents `String()`, `Number()`, `Boolean()`, `fetch()`, and other
language built-ins from becoming god-nodes that accumulate spurious
edges from every call site across the codebase.

## Root cause

Tree-sitter classifies `String(value)`, `Number(value)`, etc. as
`call_expression` with the callee identifier as "String". With no
local declaration to match in `label_to_nid`, the callee goes to
`raw_calls` for cross-file resolution. The cross-file resolver then
matches any node whose label happens to be "String" — typically the
first inline call expression the AST encountered — and creates
INFERRED edges from EVERY `String(...)` call in the corpus.

## Real-world impact

Reproduced on a 3848-node Next.js + TypeScript codebase
(revenue-proven, 1021 code files):

| Metric | Before patch | After patch |
|---|---|---|
| `String()` god-node degree | 134 edges | 1 edge (just file containment) |
| `String()` cross-community edges | 30+ communities | 0 |
| Total graph edges | 5232 | 4946 (−286 spurious) |
| Top god-node | `String()` (134) | `withCache()` (49) |

The "Surprising Connections" report previously listed entries like
`parseMinImpressions() --calls--> String()` linking `docker/opencli/`
to `src/components/data-table/` — those are gone.

## Fix

New `_LANGUAGE_BUILTIN_GLOBALS` frozenset of 89 known JS/TS/Python
language built-ins. Filtered at two call-resolution sites:

1. Same-file resolution (4 sites across Python/JS/TS/Go/Java/PHP):
   `if callee_name and callee_name not in _LANGUAGE_BUILTIN_GLOBALS`

2. Cross-file resolution (1 site in `_resolve_cross_file_calls`):
   `if callee in _LANGUAGE_BUILTIN_GLOBALS: continue`

Builtins blocked include:
- JS/TS: `String`, `Number`, `Boolean`, `Object`, `Array`, `Symbol`,
  `BigInt`, `Date`, `RegExp`, `Error`, `Promise`, `Map`, `Set`,
  `JSON`, `Math`, `parseInt`, `parseFloat`, etc.
- Browser/Node: `fetch`, `URL`, `URLSearchParams`, `FormData`,
  `Blob`, `Headers`, `Request`, `Response`, `AbortController`,
  `TextEncoder`, `TextDecoder`, `console`
- Python: `str`, `int`, `float`, `list`, `dict`, `set`, `len`,
  `range`, `enumerate`, `zip`, `map`, `filter`, `print`,
  `isinstance`, etc.

## Related to Graphify-Labs#726, similar pattern to #908

Builds on the precedent set by PR #908 (filter Rust scoped_identifier
and trait-method names) — same general approach of name-blocklist
filtering for ambiguous cross-corpus names.

Partial fix for Graphify-Labs#726: addresses the JS/TS `String` god-node pattern
specifically. Issue Graphify-Labs#726 also mentions broader "different repository"
filtering which this patch does not implement.

## Tests

All 122 existing tests pass (test_extract.py 53, test_analyze.py 24,
test_build.py 19, test_cluster.py 26). No new tests added — the
existing test corpus does not include calls to language builtins, so
the filter is a no-op there. Real-world validation was done on the
3848-node Next.js codebase cited above.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@safishamsi

Copy link
Copy Markdown
Collaborator

Implemented in v8 (commit 80301a0). Added _LANGUAGE_BUILTIN_GLOBALS frozenset with 88 JS/TS/Python builtins near the top of extract.py. Filter applied at 4 same-file call-resolution sites and the cross-file resolution in extract(). Removed fetch from the set (it's commonly used as a PHP/Go method name and same-file member-call resolution doesn't mark it is_member_call, so it would have broken PHP call edges). All 1390 tests pass. Thanks for the thorough analysis and the concrete impact measurements!

@safishamsi safishamsi closed this May 27, 2026
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