Skip to content

Commit d4f569c

Browse files
Dawid Małeckimeta-codesync[bot]
authored andcommitted
Filter category members from interface scope
Summary: Doxygen incorrectly merges category members into the base interface XML output. This causes duplicate members to appear in both the category scope and the interface scope. The fix detects category members by checking if their definition contains the pattern `ClassName(CategoryName)::` (e.g., `RCTBridgeProxy(Cxx)::cxxOnlyProperty`) and filters them out when processing interface sections. Differential Revision: D95191148
1 parent 7f4313b commit d4f569c

File tree

5 files changed

+34
-6
lines changed

5 files changed

+34
-6
lines changed

scripts/cxx-api/parser/builders.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,15 +395,40 @@ def create_enum_scope(snapshot: Snapshot, enum_def: compound.EnumdefType) -> Non
395395
)
396396

397397

398+
def _is_category_member(member_def: compound.MemberdefType) -> bool:
399+
"""
400+
Check if a member comes from a category based on its definition.
401+
402+
Doxygen merges category members into the base interface XML output, but the
403+
member's definition field contains the category name in parentheses, e.g.:
404+
"int RCTBridgeProxy(Cxx)::cxxOnlyProperty"
405+
406+
We use this to filter out category members from the interface scope.
407+
"""
408+
definition = member_def.definition
409+
if not definition:
410+
return False
411+
412+
# Look for pattern: ClassName(CategoryName)::memberName
413+
# The definition contains the qualified name with category info
414+
return bool(re.search(r"\w+\([^)]+\)::", definition))
415+
416+
398417
def _process_objc_sections(
399418
snapshot: Snapshot,
400419
scope,
401420
section_defs: list,
402421
location_file: str,
403422
scope_type: str,
423+
filter_category_members: bool = False,
404424
) -> None:
405425
"""
406426
Common section processing for protocols and interfaces.
427+
428+
Args:
429+
filter_category_members: If True, skip members that come from categories.
430+
This is used for interfaces since Doxygen incorrectly merges category
431+
members into the base interface XML output.
407432
"""
408433
for section_def in section_defs:
409434
kind = section_def.kind
@@ -418,11 +443,15 @@ def _process_objc_sections(
418443
if member_type == "attrib":
419444
for member_def in section_def.memberdef:
420445
if member_def.kind == "variable":
446+
if filter_category_members and _is_category_member(member_def):
447+
continue
421448
scope.add_member(
422449
get_variable_member(member_def, visibility, is_static)
423450
)
424451
elif member_type == "func":
425452
for function_def in section_def.memberdef:
453+
if filter_category_members and _is_category_member(function_def):
454+
continue
426455
scope.add_member(
427456
get_function_member(function_def, visibility, is_static)
428457
)
@@ -431,6 +460,8 @@ def _process_objc_sections(
431460
if member_def.kind == "enum":
432461
create_enum_scope(snapshot, member_def)
433462
elif member_def.kind == "typedef":
463+
if filter_category_members and _is_category_member(member_def):
464+
continue
434465
scope.add_member(get_typedef_member(member_def, visibility))
435466
else:
436467
print(
@@ -441,6 +472,8 @@ def _process_objc_sections(
441472
elif visibility == "property":
442473
for member_def in section_def.memberdef:
443474
if member_def.kind == "property":
475+
if filter_category_members and _is_category_member(member_def):
476+
continue
444477
scope.add_member(
445478
get_property_member(member_def, "public", is_static)
446479
)
@@ -510,6 +543,7 @@ def create_interface_scope(
510543
scope_def.sectiondef,
511544
scope_def.location.file,
512545
"interface",
546+
filter_category_members=True,
513547
)
514548

515549

scripts/cxx-api/tests/snapshots/should_handle_category_with_method/snapshot.api

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@ category RCTConvert(UIActivityIndicatorView) {
33
}
44

55
interface RCTConvert : public NSObject {
6-
public virtual static UIActivityIndicatorViewStyle UIActivityIndicatorViewStyle:(id json);
76
}

scripts/cxx-api/tests/snapshots/should_handle_category_with_multiple_methods/snapshot.api

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,4 @@ category RCTConvert(Transform) {
44
}
55

66
interface RCTConvert : public NSObject {
7-
public virtual static CATransform3D CATransform3D:(id json);
8-
public virtual static RCTTransformOrigin RCTTransformOrigin:(id json);
97
}

scripts/cxx-api/tests/snapshots/should_handle_ifdef_cplusplus/snapshot.api

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@ category RCTBridgeProxy(Cxx) {
33
}
44

55
interface RCTBridgeProxy : public NSObject {
6-
public @property (assign) int cxxOnlyProperty;
76
}

scripts/cxx-api/tests/snapshots/should_handle_multiple_categories/snapshot.api

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,4 @@ category RCTConvert(CategoryTwo) {
77
}
88

99
interface RCTConvert : public NSObject {
10-
public virtual static NSString* methodOne:(id json);
11-
public virtual static NSString* methodTwo:(id json);
1210
}

0 commit comments

Comments
 (0)