fix(java,ts): a parameterized supertype links its type, like implements Store<String>

A Java class implementing a parameterized interface (implements
Store<String>), one extending a generic base (extends Base<Integer>), a
Java interface's extends Store<T>, and a TypeScript class's implements
Store<string> got no implements or extends edge. The grammars wrap the
type in a generic_type node, and the supertype reader took its whole
text, which no node is named. Without the edge the interface-impl
synthesizer had nothing to walk, so a call on the interface stopped there.

Both engines (extractInheritance on the wasm path, the kernel's java.rs
and tsjs) now name a generic_type by its first child that is not
type_arguments; any other supertype node is its own text, as before.

Validation: the new tests fail 3 of 3 on main with both engines and pass
here. A/B against main 0d46dba0, kernel per arm: flask and Slim (PHP)
byte-identical. mybatis-3 gains 107 supertype edges (extends
BaseTypeHandler<T> 58 times, TypeHandler<T>, ResultHandler<T>,
BaseMapper<T>...) with 31 interface-impl and inherited calls, 2 calls
retargeted from another package's Mapper to the BaseMapper the interface
extends, and 17 inherited calls typed. pixijs gains 43 implements
(System<T>, RenderPipe<T>, InstructionPipe<T>...) and 11 interface-impl
calls; excalidraw 2 implements DeltaContainer<T> and 4 interface-impl
calls; vscode's base and editor 142 implements (IListRenderer<T>,
IListVirtualDelegate<T>, ISpliceable<T>...) and 183 interface-impl calls.
Nothing removed. Kernel parity holds on mybatis-3 (1,396 Java files),
pixijs, excalidraw and vscode's base and editor, 0 diffs. Index CPU time
within noise: mybatis-3 29.9 s to 30.1 s, pixijs 37.3 s to 38.1 s over 6
interleaved rounds in both orders (spread 35.8 to 38.5 s).

The older PR #729 by @paiyahooJay made the same fix in the wasm extractor;
it is credited in the CHANGELOG.

Original PR #2705 by @danusha2345.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
danusha2345
2026-10-23 19:21:32 +00:00
committed by Colby Mchenry
co-authored by Claude Opus 5.5
parent 428b3c487d
commit 8f8f04b7fc
5 changed files with 156 additions and 6 deletions
+16 -2
View File
@@ -1034,7 +1034,7 @@ impl<'t> Walker<'t> {
None => child.named_child(0).into_iter().collect(),
};
for target in targets {
let name = self.text(target).to_string();
let name = self.supertype_name(target);
self.push_ref_at(class_row, &name, extends_kind, target);
}
}
@@ -1047,7 +1047,7 @@ impl<'t> Walker<'t> {
None => (0..child.named_child_count()).filter_map(|j| child.named_child(j)).collect(),
};
for iface in targets {
let name = self.text(iface).to_string();
let name = self.supertype_name(iface);
self.push_ref_at(class_row, &name, implements_kind, iface);
}
}
@@ -1056,6 +1056,20 @@ impl<'t> Walker<'t> {
}
}
/// supertypeName — a parameterized supertype (`generic_type`) by the name
/// before its type arguments: `Store` for `implements Store<String>`.
fn supertype_name(&self, node: Node<'t>) -> String {
if node.kind() == "generic_type" {
let named = (0..node.named_child_count())
.filter_map(|j| node.named_child(j))
.find(|c| c.kind() != "type_arguments");
if let Some(named) = named {
return self.text(named).to_string();
}
}
self.text(node).to_string()
}
/// extractDecoratorsFor — Java annotations live inside `modifiers`.
fn extract_decorators_for(&mut self, decl: Node<'t>, decorated_row: u32) {
for i in 0..decl.named_child_count() {
+16 -2
View File
@@ -1984,14 +1984,14 @@ impl<'t> Walker<'t> {
// TS `extends_clause` (the other spellings are other grammars').
"extends_clause" | "superclass" | "base_clause" | "extends_interfaces" => {
if let Some(target) = child.named_child(0) {
let name = self.text(target).to_string();
let name = self.supertype_name(target);
self.push_ref(class_row, &name, extends_kind, target);
}
}
"implements_clause" | "class_interface_clause" | "super_interfaces" | "interfaces" => {
for j in 0..child.named_child_count() {
if let Some(iface) = child.named_child(j) {
let name = self.text(iface).to_string();
let name = self.supertype_name(iface);
self.push_ref(class_row, &name, implements_kind, iface);
}
}
@@ -2027,6 +2027,20 @@ impl<'t> Walker<'t> {
}
}
/// supertypeName — a parameterized supertype (`generic_type`) by the name
/// before its type arguments: `Store` for `implements Store<string>`.
fn supertype_name(&self, node: Node<'t>) -> String {
if node.kind() == "generic_type" {
let named = (0..node.named_child_count())
.filter_map(|j| node.named_child(j))
.find(|c| c.kind() != "type_arguments");
if let Some(named) = named {
return self.text(named).to_string();
}
}
self.text(node).to_string()
}
// --- type annotations (#381 — TS family only) ----------------------------------------------
pub(super) fn extract_type_annotations(&mut self, node: Node<'t>, from_row: u32) {