2828from .utils import has_scope_resolution_outside_angles , parse_qualified_path
2929
3030
31+ def _process_namespace_sections (snapshot , namespace_scope , compound_object ):
32+ """
33+ Process all section definitions inside a namespace compound.
34+ """
35+ for section_def in compound_object .sectiondef :
36+ if section_def .kind == "var" :
37+ for variable_def in section_def .memberdef :
38+ # Skip out-of-class definitions (e.g. "Strct<T>::VALUE")
39+ if has_scope_resolution_outside_angles (variable_def .get_name ()):
40+ continue
41+ is_static = variable_def .static == "yes"
42+ namespace_scope .add_member (
43+ get_variable_member (variable_def , "public" , is_static )
44+ )
45+ elif section_def .kind == "func" :
46+ for function_def in section_def .memberdef :
47+ # Skip out-of-class definitions (e.g. "Strct<T>::convert")
48+ if has_scope_resolution_outside_angles (function_def .get_name ()):
49+ continue
50+ function_static = function_def .static == "yes"
51+
52+ if not function_static :
53+ namespace_scope .add_member (
54+ get_function_member (function_def , "public" )
55+ )
56+ elif section_def .kind == "typedef" :
57+ for typedef_def in section_def .memberdef :
58+ namespace_scope .add_member (get_typedef_member (typedef_def , "public" ))
59+ elif section_def .kind == "enum" :
60+ for enum_def in section_def .memberdef :
61+ create_enum_scope (snapshot , enum_def )
62+ else :
63+ print (
64+ f"Unknown section kind: { section_def .kind } in { compound_object .location .file } "
65+ )
66+
67+
68+ def _handle_namespace_compound (snapshot , compound_object ):
69+ """
70+ Handle a namespace compound definition.
71+ """
72+ # Skip anonymous namespaces (internal linkage, not public API).
73+ # Doxygen encodes them with a '@' prefix in the compound name.
74+ if "@" in compound_object .compoundname :
75+ return
76+
77+ namespace_scope = snapshot .create_or_get_namespace (compound_object .compoundname )
78+
79+ namespace_scope .location = compound_object .location .file
80+
81+ _process_namespace_sections (snapshot , namespace_scope , compound_object )
82+
83+
84+ def _handle_concept_compound (snapshot , compound_object ):
85+ """
86+ Handle a concept compound definition.
87+ """
88+ # Concepts belong to a namespace, so we need to find or create the parent namespace
89+ concept_name = compound_object .compoundname
90+ concept_path = parse_qualified_path (concept_name )
91+ namespace_path = "::" .join (concept_path [:- 1 ]) if concept_path else ""
92+
93+ if namespace_path :
94+ namespace_scope = snapshot .create_or_get_namespace (namespace_path )
95+ else :
96+ namespace_scope = snapshot .root_scope
97+
98+ namespace_scope .add_member (get_concept_member (compound_object ))
99+
100+
101+ def _handle_class_compound (snapshot , compound_object ):
102+ """
103+ Handle class, struct, and union compound definitions.
104+ """
105+ # Check if this is an Objective-C interface by looking at the compound id
106+ # Doxygen reports ObjC interfaces as kind="class" but with id starting with "interface"
107+ is_objc_interface = (
108+ compound_object .kind == "class" and compound_object .id .startswith ("interface" )
109+ )
110+
111+ # Handle Objective-C interfaces separately
112+ if is_objc_interface :
113+ create_interface_scope (snapshot , compound_object )
114+ return
115+
116+ # classes and structs are represented by the same scope with a different kind
117+ create_class_scope (snapshot , compound_object )
118+
119+
120+ # Dispatch table for compound kinds that map directly to a single builder call.
121+ _COMPOUND_HANDLERS = {
122+ "class" : _handle_class_compound ,
123+ "struct" : _handle_class_compound ,
124+ "union" : _handle_class_compound ,
125+ "namespace" : _handle_namespace_compound ,
126+ "concept" : _handle_concept_compound ,
127+ "category" : create_category_scope ,
128+ "protocol" : create_protocol_scope ,
129+ "interface" : create_interface_scope ,
130+ }
131+
132+ # Compound kinds that are intentionally ignored.
133+ _IGNORED_COMPOUNDS = frozenset (
134+ {
135+ "file" ,
136+ "dir" ,
137+ # Contains deprecation info
138+ "page" ,
139+ }
140+ )
141+
142+
31143def build_snapshot (xml_dir : str ) -> Snapshot :
32144 """
33145 Reads the Doxygen XML output and builds a snapshot of the C++ API.
@@ -51,100 +163,14 @@ def build_snapshot(xml_dir: str) -> Snapshot:
51163 if compound_object .prot == "private" :
52164 continue
53165
54- # Check if this is an Objective-C interface by looking at the compound id
55- # Doxygen reports ObjC interfaces as kind="class" but with id starting with "interface"
56- is_objc_interface = (
57- compound_object .kind == "class"
58- and compound_object .id .startswith ("interface" )
59- )
60-
61- # classes and structs are represented by the same scope with a different kind
62- if (
63- compound_object .kind == "class"
64- or compound_object .kind == "struct"
65- or compound_object .kind == "union"
66- ):
67- # Handle Objective-C interfaces separately
68- if is_objc_interface :
69- create_interface_scope (snapshot , compound_object )
70- continue
71- create_class_scope (snapshot , compound_object )
72- elif compound_object .kind == "namespace" :
73- # Skip anonymous namespaces (internal linkage, not public API).
74- # Doxygen encodes them with a '@' prefix in the compound name.
75- if "@" in compound_object .compoundname :
76- continue
166+ kind = compound_object .kind
77167
78- namespace_scope = snapshot .create_or_get_namespace (
79- compound_object .compoundname
80- )
81-
82- namespace_scope .location = compound_object .location .file
83-
84- for section_def in compound_object .sectiondef :
85- if section_def .kind == "var" :
86- for variable_def in section_def .memberdef :
87- # Skip out-of-class definitions (e.g. "Strct<T>::VALUE")
88- if has_scope_resolution_outside_angles (
89- variable_def .get_name ()
90- ):
91- continue
92- is_static = variable_def .static == "yes"
93- namespace_scope .add_member (
94- get_variable_member (variable_def , "public" , is_static )
95- )
96- elif section_def .kind == "func" :
97- for function_def in section_def .memberdef :
98- # Skip out-of-class definitions (e.g. "Strct<T>::convert")
99- if has_scope_resolution_outside_angles (
100- function_def .get_name ()
101- ):
102- continue
103- function_static = function_def .static == "yes"
104-
105- if not function_static :
106- namespace_scope .add_member (
107- get_function_member (function_def , "public" )
108- )
109- elif section_def .kind == "typedef" :
110- for typedef_def in section_def .memberdef :
111- namespace_scope .add_member (
112- get_typedef_member (typedef_def , "public" )
113- )
114- elif section_def .kind == "enum" :
115- for enum_def in section_def .memberdef :
116- create_enum_scope (snapshot , enum_def )
117- else :
118- print (
119- f"Unknown section kind: { section_def .kind } in { compound_object .location .file } "
120- )
121- elif compound_object .kind == "concept" :
122- # Concepts belong to a namespace, so we need to find or create the parent namespace
123- concept_name = compound_object .compoundname
124- concept_path = parse_qualified_path (concept_name )
125- namespace_path = "::" .join (concept_path [:- 1 ]) if concept_path else ""
126-
127- if namespace_path :
128- namespace_scope = snapshot .create_or_get_namespace (namespace_path )
129- else :
130- namespace_scope = snapshot .root_scope
131-
132- namespace_scope .add_member (get_concept_member (compound_object ))
133- elif compound_object .kind == "file" :
134- pass
135- elif compound_object .kind == "dir" :
136- pass
137- elif compound_object .kind == "category" :
138- create_category_scope (snapshot , compound_object )
139- elif compound_object .kind == "page" :
140- # Contains deprecation info
168+ if kind in _IGNORED_COMPOUNDS :
141169 pass
142- elif compound_object .kind == "protocol" :
143- create_protocol_scope (snapshot , compound_object )
144- elif compound_object .kind == "interface" :
145- create_interface_scope (snapshot , compound_object )
170+ elif kind in _COMPOUND_HANDLERS :
171+ _COMPOUND_HANDLERS [kind ](snapshot , compound_object )
146172 else :
147- print (f"Unknown compound kind: { compound_object . kind } " )
173+ print (f"Unknown compound kind: { kind } " )
148174
149175 snapshot .finish ()
150176 return snapshot
0 commit comments