Skip to content

fix(extraction): strip generic type arguments from supertype names so extends Base<T> resolves#729

Open
paiyahooJay wants to merge 1 commit into
colbymchenry:mainfrom
paiyahooJay:fix/generic-supertype-edges
Open

fix(extraction): strip generic type arguments from supertype names so extends Base<T> resolves#729
paiyahooJay wants to merge 1 commit into
colbymchenry:mainfrom
paiyahooJay:fix/generic-supertype-edges

Conversation

@paiyahooJay

Copy link
Copy Markdown

Problem

Class inheritance edges were silently dropped whenever a superclass or implemented interface carried generic type arguments, e.g. class A extends Base<T> or class B implements Iface<T>.

Root cause: in the shared tree-sitter supertype extraction the extends/implements/C++-base paths used getNodeText() on the supertype node. For a generic supertype the node is generic_type (C++ template_type), so the captured reference name included the type arguments ("Base"). During resolution this never matched the class node named "Base", and the reference was discarded — it was not even kept in unresolved_refs, so the loss was silent.

This affects every language that goes through the shared supertype extraction path: Java, TypeScript, and C++ templates. (C#, Kotlin, Swift, Rust and Go already narrow to the bare type identifier or handle generic_type explicitly, so they were unaffected.) The dropped edges land disproportionately on *ServiceImpl extends BaseXxx<T> interface+DI classes that matter most for call-graph reachability.

Fix

Add a shared stripTypeArguments helper and use it when recording the extends/implements reference name, dropping the angle-bracket suffix (including nested generics) while preserving any qualified prefix so resolution can still disambiguate same-named types across packages.

Test

Added regression tests asserting the extends/implements reference names are stripped for generic and nested-generic Java supertypes and C++ template base classes. Verified end-to-end that a generic Java project now produces the extends/implements edges that were previously dropped.

… `extends Base<T>` resolves

## Problem
Class inheritance edges were silently dropped whenever a superclass or
implemented interface carried generic type arguments, e.g.
`class A extends Base<T>` or `class B implements Iface<T>`.

Root cause: in the shared tree-sitter supertype extraction the
extends/implements/C++-base paths used getNodeText() on the supertype
node. For a generic supertype the node is `generic_type` (C++
`template_type`), so the captured reference name included the type
arguments ("Base<T>"). During resolution this never matched the class
node named "Base", and the reference was discarded — it was not even
kept in unresolved_refs, so the loss was silent.

This affects every language that goes through the shared supertype
extraction path: Java, TypeScript, and C++ templates. (C#, Kotlin,
Swift, Rust and Go already narrow to the bare type identifier or
handle `generic_type` explicitly, so they were unaffected.) The dropped
edges land disproportionately on `*ServiceImpl extends BaseXxx<T>`
interface+DI classes that matter most for call-graph reachability.

## Fix
Add a shared `stripTypeArguments` helper and use it when recording the
extends/implements reference name, dropping the angle-bracket suffix
(including nested generics) while preserving any qualified prefix so
resolution can still disambiguate same-named types across packages.

## Test
Added regression tests asserting the extends/implements reference names
are stripped for generic and nested-generic Java supertypes and C++
template base classes. Verified end-to-end that a generic Java project
now produces the extends/implements edges that were previously dropped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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