Skip to content

Commit 0cb9ffb

Browse files
coadometa-codesync[bot]
authored andcommitted
Filter category members from interface scope (#55899)
Summary: Pull Request resolved: #55899 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. Changelog: [Internal] Reviewed By: cortinico Differential Revision: D95191148
1 parent b2ce353 commit 0cb9ffb

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
@@ -389,15 +389,40 @@ def create_enum_scope(snapshot: Snapshot, enum_def: compound.EnumdefType) -> Non
389389
)
390390

391391

392+
def _is_category_member(member_def: compound.MemberdefType) -> bool:
393+
"""
394+
Check if a member comes from a category based on its definition.
395+
396+
Doxygen merges category members into the base interface XML output, but the
397+
member's definition field contains the category name in parentheses, e.g.:
398+
"int RCTBridgeProxy(Cxx)::cxxOnlyProperty"
399+
400+
We use this to filter out category members from the interface scope.
401+
"""
402+
definition = member_def.definition
403+
if not definition:
404+
return False
405+
406+
# Look for pattern: ClassName(CategoryName)::memberName
407+
# The definition contains the qualified name with category info
408+
return bool(re.search(r"\w+\([^)]+\)::", definition))
409+
410+
392411
def _process_objc_sections(
393412
snapshot: Snapshot,
394413
scope,
395414
section_defs: list,
396415
location_file: str,
397416
scope_type: str,
417+
filter_category_members: bool = False,
398418
) -> None:
399419
"""
400420
Common section processing for protocols and interfaces.
421+
422+
Args:
423+
filter_category_members: If True, skip members that come from categories.
424+
This is used for interfaces since Doxygen incorrectly merges category
425+
members into the base interface XML output.
401426
"""
402427
for section_def in section_defs:
403428
kind = section_def.kind
@@ -412,11 +437,15 @@ def _process_objc_sections(
412437
if member_type == "attrib":
413438
for member_def in section_def.memberdef:
414439
if member_def.kind == "variable":
440+
if filter_category_members and _is_category_member(member_def):
441+
continue
415442
scope.add_member(
416443
get_variable_member(member_def, visibility, is_static)
417444
)
418445
elif member_type == "func":
419446
for function_def in section_def.memberdef:
447+
if filter_category_members and _is_category_member(function_def):
448+
continue
420449
scope.add_member(
421450
get_function_member(function_def, visibility, is_static)
422451
)
@@ -425,6 +454,8 @@ def _process_objc_sections(
425454
if member_def.kind == "enum":
426455
create_enum_scope(snapshot, member_def)
427456
elif member_def.kind == "typedef":
457+
if filter_category_members and _is_category_member(member_def):
458+
continue
428459
scope.add_member(get_typedef_member(member_def, visibility))
429460
else:
430461
print(
@@ -435,6 +466,8 @@ def _process_objc_sections(
435466
elif visibility == "property":
436467
for member_def in section_def.memberdef:
437468
if member_def.kind == "property":
469+
if filter_category_members and _is_category_member(member_def):
470+
continue
438471
scope.add_member(
439472
get_property_member(member_def, "public", is_static)
440473
)
@@ -504,6 +537,7 @@ def create_interface_scope(
504537
scope_def.sectiondef,
505538
scope_def.location.file,
506539
"interface",
540+
filter_category_members=True,
507541
)
508542

509543

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)