fix(c,cpp): a pointer, array or function member is not a supertype (#2394)

extractInheritance carried Go's struct-embedding check (a field_declaration
with no direct field_identifier names an embedded type) into every grammar
with a field_declaration_list. tree-sitter-c/cpp, and Objective-C's C
structs, nest a member's field_identifier inside its pointer/array/
function/reference declarator, so `SharedState* shared;`, `jv elements[];`
and `virtual Status Put(...) = 0;` all became `extends` edges to the
member's type: false supertypes in the type hierarchy, blast radius and
codegraph_explore, and false cpp-override call edges built on them
(google/leveldb: 246 of 302 extends edges).

Gate the branch to Go in the TS extractor, drop the mirrored arm from the
C/C++ kernel port (and the "kept for parity" quirk note), and drop the
inert copy from the Rust-language port. C++ base_class_clause, Objective-C
superclasses and Go embedding are unchanged.

Validated on leveldb, jq, llm.c and redis: every removed extends edge is a
member site, no base-clause edge is lost; gin, SDWebImage and ripgrep
dumps are byte-identical; kernel/wasm parity sweeps show 0 diffs.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Colby Mchenry
2026-10-06 23:27:58 +00:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 0a670dc8cc
commit ac1f430d3e
7 changed files with 292 additions and 45 deletions
+6 -2
View File
@@ -7001,8 +7001,12 @@ export class TreeSitterExtractor {
}
// Go struct embedding: field_declaration without field_identifier
// e.g. `type DB struct { *Head; Queryable }` — no field name means embedded type
if (child.type === 'field_declaration') {
// e.g. `type DB struct { *Head; Queryable }` — no field name means embedded type.
// Go only: C, C++ and Objective-C members are field_declarations too, but
// nest their name inside the declarator (`Cache* cache_;`, `jv elems[];`,
// `Status Get(int);`), so this test read every such member's type as a
// supertype. Their supertypes come from base_class_clause / superclass.
if (this.language === 'go' && child.type === 'field_declaration') {
const hasFieldIdentifier = child.namedChildren.some((c: SyntaxNode) => c.type === 'field_identifier');
if (!hasFieldIdentifier) {
const typeId = child.namedChildren.find((c: SyntaxNode) => c.type === 'type_identifier');