diff --git a/graphify/extract.py b/graphify/extract.py
index 19dcaa2..6887d08 100644
--- a/graphify/extract.py
+++ b/graphify/extract.py
@@ -11625,6 +11625,18 @@ def extract_objc(path: Path) -> dict:
proto_nid = _make_id(stem, name)
add_node(proto_nid, f"<{name}>", line)
add_edge(file_nid, proto_nid, "contains", line)
+ # Adopted protocols: `@protocol Derived `. These
+ # nest under a protocol_reference_list node (distinct from the
+ # parameterized_arguments node used by @interface adoption), so
+ # they were never emitted. Emit an `implements` edge for each,
+ # matching how @interface protocol adoption is handled.
+ for child in node.children:
+ if child.type == "protocol_reference_list":
+ for sub in child.children:
+ if sub.type == "identifier":
+ base_nid = ensure_named_node(_read(sub), line)
+ if base_nid != proto_nid:
+ add_edge(proto_nid, base_nid, "implements", line)
for child in node.children:
walk(child, proto_nid)
return
diff --git a/tests/fixtures/sample.m b/tests/fixtures/sample.m
index 2f1209a..4fd0f93 100644
--- a/tests/fixtures/sample.m
+++ b/tests/fixtures/sample.m
@@ -40,3 +40,15 @@
}
@end
+
+@protocol Base
+
+- (void)baseMethod;
+
+@end
+
+@protocol Derived
+
+- (void)derivedMethod;
+
+@end
diff --git a/tests/test_languages.py b/tests/test_languages.py
index 35569c5..8227131 100644
--- a/tests/test_languages.py
+++ b/tests/test_languages.py
@@ -1064,6 +1064,16 @@ def test_objc_splits_inherits_and_implements():
assert ("Animal", "SampleDelegate") in _edge_labels(r, "implements")
+def test_objc_protocol_adopts_protocol():
+ """`@protocol Derived ` must emit an implements edge Derived->Base.
+ Protocol-on-protocol adoption nests under a protocol_reference_list node
+ (distinct from the parameterized_arguments node used by @interface
+ adoption), so the edge was previously dropped. Protocol nodes are labeled
+ ``, so the edge reads (, )."""
+ r = extract_objc(FIXTURES / "sample.m")
+ assert ("", "") in _edge_labels(r, "implements")
+
+
def test_objc_property_type_context():
r = extract_objc(FIXTURES / "sample.m")
assert ("Animal", "NSString") in _edge_labels(r, "references", "field")