Browse Source

feat: Promote "extends" to "implements" for class-to-interface relationships in edge creation

Addresses semantic accuracy in inheritance relationships where classes use "extends" syntax to implement interfaces. Adds target node inspection to detect interface/protocol targets and promotes the edge kind from "extends" to "implements" when the source is a concrete class or struct, ensuring proper representation of implementation vs inheritance relationships in the code graph.
Colby McHenry 2 months ago
parent
commit
07d899b735
1 changed files with 26 additions and 11 deletions
  1. 26 11
      src/resolution/index.ts

+ 26 - 11
src/resolution/index.ts

@@ -422,17 +422,32 @@ export class ReferenceResolver {
    * Create edges from resolved references
    */
   createEdges(resolved: ResolvedRef[]): Edge[] {
-    return resolved.map((ref) => ({
-      source: ref.original.fromNodeId,
-      target: ref.targetNodeId,
-      kind: ref.original.referenceKind,
-      line: ref.original.line,
-      column: ref.original.column,
-      metadata: {
-        confidence: ref.confidence,
-        resolvedBy: ref.resolvedBy,
-      },
-    }));
+    return resolved.map((ref) => {
+      let kind = ref.original.referenceKind;
+
+      // Promote "extends" to "implements" when a class/struct targets an interface
+      if (kind === 'extends') {
+        const targetNode = this.queries.getNodeById(ref.targetNodeId);
+        if (targetNode && (targetNode.kind === 'interface' || targetNode.kind === 'protocol')) {
+          const sourceNode = this.queries.getNodeById(ref.original.fromNodeId);
+          if (sourceNode && sourceNode.kind !== 'interface' && sourceNode.kind !== 'protocol') {
+            kind = 'implements';
+          }
+        }
+      }
+
+      return {
+        source: ref.original.fromNodeId,
+        target: ref.targetNodeId,
+        kind,
+        line: ref.original.line,
+        column: ref.original.column,
+        metadata: {
+          confidence: ref.confidence,
+          resolvedBy: ref.resolvedBy,
+        },
+      };
+    });
   }
 
   /**