Răsfoiți Sursa

feat: Add Go struct and interface embedding extraction for inheritance relationships

Addresses Go's embedding mechanism where structs can embed other types without field names (e.g. `type DB struct { *Head; Queryable }`) and interfaces can embed other interfaces via constraint_elem nodes. Extracts these embedded types as 'extends' relationships to properly model Go's composition-based inheritance patterns in the code graph.
Colby McHenry 2 luni în urmă
părinte
comite
1244c62193
1 a modificat fișierele cu 42 adăugiri și 0 ștergeri
  1. 42 0
      src/extraction/tree-sitter.ts

+ 42 - 0
src/extraction/tree-sitter.ts

@@ -878,6 +878,8 @@ export class TreeSitterExtractor {
       this.nodeStack.push(structNode.id);
       const typeChild = getChildByField(node, 'type');
       if (typeChild) {
+        // Extract struct embedding (e.g. Go: `type DB struct { *Head; Queryable }`)
+        this.extractInheritance(typeChild, structNode.id);
         const body = getChildByField(typeChild, this.extractor.bodyField) || typeChild;
         for (let i = 0; i < body.namedChildCount; i++) {
           const child = body.namedChild(i);
@@ -1225,6 +1227,46 @@ export class TreeSitterExtractor {
           }
         }
       }
+
+      // Go interface embedding: `type Querier interface { LabelQuerier; ... }`
+      // constraint_elem wraps the embedded interface type identifier
+      if (child.type === 'constraint_elem') {
+        const typeId = child.namedChildren.find((c: SyntaxNode) => c.type === 'type_identifier');
+        if (typeId) {
+          const name = getNodeText(typeId, this.source);
+          this.unresolvedReferences.push({
+            fromNodeId: classId,
+            referenceName: name,
+            referenceKind: 'extends',
+            line: typeId.startPosition.row + 1,
+            column: typeId.startPosition.column,
+          });
+        }
+      }
+
+      // 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') {
+        const hasFieldIdentifier = child.namedChildren.some((c: SyntaxNode) => c.type === 'field_identifier');
+        if (!hasFieldIdentifier) {
+          const typeId = child.namedChildren.find((c: SyntaxNode) => c.type === 'type_identifier');
+          if (typeId) {
+            const name = getNodeText(typeId, this.source);
+            this.unresolvedReferences.push({
+              fromNodeId: classId,
+              referenceName: name,
+              referenceKind: 'extends',
+              line: typeId.startPosition.row + 1,
+              column: typeId.startPosition.column,
+            });
+          }
+        }
+      }
+
+      // Recurse into container nodes (e.g. field_declaration_list in Go structs)
+      if (child.type === 'field_declaration_list') {
+        this.extractInheritance(child, classId);
+      }
     }
   }