Skip to content

Commit 2bd6933

Browse files
Dawid Małeckimeta-codesync[bot]
authored andcommitted
Fix parsing of Objective-C interface generic inheritance
Summary: Doxygen incorrectly parses Objective-C interface declarations with protocol conformance. For example: ```objc interface RCTAppearance : RCTEventEmitter <RCTBridgeModule> ``` Doxygen splits this into **two separate base classes** in the XML: ```xml <basecompoundref>RCTEventEmitter</basecompoundref> <basecompoundref>&lt;RCTBridgeModule&gt;</basecompoundref> ``` This caused the parser to output: ``` interface RCTAppearance : public RCTEventEmitter, public <RCTBridgeModule> { ``` Instead of the expected: ``` interface RCTAppearance : public RCTEventEmitter <RCTBridgeModule> { ``` The fix detects when a "base class" name starts and ends with `<...>` (indicating it's a protocol conformance) and combines it with the preceding actual base class name. Differential Revision: D94351731
1 parent 87cf577 commit 2bd6933

5 files changed

Lines changed: 55 additions & 1 deletion

File tree

scripts/cxx-api/parser/builders.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,24 @@ def create_interface_scope(
480480

481481
interface_scope = snapshot.create_interface(interface_name)
482482
base_classes = get_base_classes(scope_def, base_class=InterfaceScopeKind.Base)
483-
interface_scope.kind.add_base(base_classes)
483+
484+
# Doxygen incorrectly splits "Foo <Protocol1, Protocol2>" into separate base classes:
485+
# "Foo", "<Protocol1>", "<Protocol2>". Combine them back into "Foo <Protocol1, Protocol2>".
486+
combined_bases = []
487+
for base in base_classes:
488+
if base.name.startswith("<") and base.name.endswith(">") and combined_bases:
489+
prev_name = combined_bases[-1].name
490+
protocol = base.name[1:-1] # Strip < and >
491+
if "<" in prev_name and prev_name.endswith(">"):
492+
# Previous base already has protocols, merge inside the brackets
493+
combined_bases[-1].name = f"{prev_name[:-1]}, {protocol}>"
494+
else:
495+
# First protocol for this base class
496+
combined_bases[-1].name = f"{prev_name} <{protocol}>"
497+
else:
498+
combined_bases.append(base)
499+
500+
interface_scope.kind.add_base(combined_bases)
484501
interface_scope.location = scope_def.location.file
485502

486503
_process_objc_sections(
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
interface RCTAppearance : public RCTEventEmitter <RCTBridgeModule> {
2+
public virtual instancetype init();
3+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
namespace test {
11+
12+
@interface RCTAppearance : RCTEventEmitter <RCTBridgeModule>
13+
- (instancetype)init;
14+
@end
15+
16+
} // namespace test
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
interface RCTAlertManager : public NSObject <RCTBridgeModule, RCTInvalidating> {
2+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
namespace test {
11+
12+
@interface RCTAlertManager : NSObject <RCTBridgeModule, RCTInvalidating>
13+
14+
@end
15+
16+
} // namespace test

0 commit comments

Comments
 (0)