fix(extraction): strip generic type arguments from supertype names so extends Base<T> resolves#729
Open
paiyahooJay wants to merge 1 commit into
Open
Conversation
… `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>
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
Class inheritance edges were silently dropped whenever a superclass or implemented interface carried generic type arguments, e.g.
class A extends Base<T>orclass 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_typeexplicitly, 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
stripTypeArgumentshelper 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.