Skip to content

fix(extract): emit inherits edge for JavaScript class extends#1790

Open
Synvoya wants to merge 1 commit into
Graphify-Labs:v8from
Synvoya:fix/js-class-extends-inherits
Open

fix(extract): emit inherits edge for JavaScript class extends#1790
Synvoya wants to merge 1 commit into
Graphify-Labs:v8from
Synvoya:fix/js-class-extends-inherits

Conversation

@Synvoya

@Synvoya Synvoya commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Bug

class Derived extends Base {} in a plain .js file produces no inherits edge, while the identical code in a .ts file works.

Root cause

The two tree-sitter grammars shape class heritage differently:

  • TypeScript: class_heritageextends_clauseidentifier (base wrapped in a clause node)
  • JavaScript: class_heritageextends, identifier (base held directly, no extends_clause wrapper)

_ts_walk_class_members (graphify/extractors/resolution.py) only iterated class_heritage children looking for extends_clause / implements_clause. For .js classes neither exists, so the heritage entry was silently dropped.

Minimal repro

// a.js
class Animal {}
class Dog extends Animal {}

extract(["a.js"]) yields no Dog --inherits--> Animal edge. The equivalent a.ts already emits it.

Fix

When a class_heritage node has no extends_clause/implements_clause child, treat the heritage node itself as the extends clause and emit an inherits edge — mirroring the existing extends_type_clause branch used for interface heritage (#1095). TypeScript files are unaffected (they still take the clause branch, guarded by a saw_clause flag, so there is no double emission).

Testing

  • Added test_js_class_extends_same_file to tests/test_ts_inheritance.py, mirroring the existing test_class_extends_same_file (.ts) test but with a .js file. It fails before the change and passes after.
  • tests/test_ts_inheritance.py: 8 passed.
  • tests/test_languages.py: 314 passed, 13 skipped (unchanged).
  • JS/TS import-resolution, receiver, and decorator suites: 70 passed.

The JavaScript tree-sitter grammar stores a class's base type directly
under the class_heritage node (`extends Base` -> [extends, identifier]),
whereas the TypeScript grammar wraps it in an extends_clause child.
_ts_walk_class_members only handled the extends_clause/implements_clause
shape, so `class Derived extends Base {}` in a .js file emitted no
inherits edge even though the equivalent .ts file worked.

When class_heritage has no extends_clause/implements_clause child, treat
the heritage node itself as the extends clause and emit an inherits edge,
mirroring the existing extends_type_clause branch used for interface
heritage.

Adds a regression test alongside the existing TS inheritance tests.
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