Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions scripts/cxx-api/parser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
# LICENSE file in the root directory of this source tree.

from .main import build_snapshot
from .member import FunctionMember, FunctionModifiers
from .path_utils import get_repo_root

__all__ = ["build_snapshot", "FunctionMember", "FunctionModifiers", "get_repo_root"]
__all__ = ["build_snapshot", "get_repo_root"]
71 changes: 66 additions & 5 deletions scripts/cxx-api/parser/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from __future__ import annotations

import os
import re
from pprint import pprint

from doxmlparser import compound, index
Expand All @@ -20,7 +21,7 @@
from .scope import StructLikeScopeKind
from .snapshot import Snapshot
from .template import Template
from .utils import parse_qualified_path
from .utils import Argument, extract_qualifiers, parse_qualified_path


def resolve_ref_text_name(type_def: compound.refTextType) -> str:
Expand Down Expand Up @@ -206,6 +207,59 @@ def get_variable_member(
)


def get_doxygen_params(
function_def: compound.MemberdefType,
) -> list[tuple[str | None, str, str | None, str | None]] | None:
"""
Extract structured parameter information from doxygen <param> elements.

Returns a list of Argument tuples (qualifiers, type, name, default_value),
or None if no <param> elements are available.
"""
params = function_def.param
if not params:
return None

arguments: list[Argument] = []
for param in params:
param_type = (
resolve_ref_text_name(param.get_type()).strip() if param.get_type() else ""
)
param_name = param.declname or param.defname or None
param_default = (
resolve_ref_text_name(param.defval).strip() if param.defval else None
)

# Doxygen splits array dimensions into a separate <array> element.
# For complex declarators like "PropNameID (&&propertyNames)[N]",
# doxygen gives type="PropNameID(&&)", name="propertyNames",
# array="[N]". We must reconstruct the full declarator with the
# name embedded inside the grouping parentheses:
# PropNameID(&&propertyNames)[N]
param_array = param.array
if param_array:
# Match type ending with a pointer/reference declarator group:
# e.g. "PropNameID(&&)", "int(&)", "void(*)"
m = re.search(r"\([*&]+\)\s*$", param_type)
if m and param_name:
# Insert name before the closing ')' and append array
insert_pos = m.end() - 1 # position of trailing ')'
param_type = (
param_type[:insert_pos]
+ param_name
+ param_type[insert_pos:]
+ param_array
)
param_name = None
else:
param_type += param_array

qualifiers, core_type = extract_qualifiers(param_type)
arguments.append((qualifiers, core_type, param_name, param_default))

return arguments


def get_function_member(
function_def: compound.MemberdefType,
visibility: str,
Expand All @@ -217,18 +271,25 @@ def get_function_member(
function_name = function_def.get_name()
function_type = resolve_ref_text_name(function_def.get_type())
function_arg_string = function_def.get_argsstring()
function_virtual = (
function_def.get_virt() == "virtual"
or function_def.get_virt() == "pure-virtual"
)
is_pure_virtual = function_def.get_virt() == "pure-virtual"
function_virtual = function_def.get_virt() == "virtual" or is_pure_virtual

# Doxygen incorrectly merges "=0" into the return type for pure-virtual
# functions using trailing return types (e.g. "auto f() -> T = 0").
# Strip the trailing "=0" from the type string.
function_type = re.sub(r"\s*=\s*0\s*$", "", function_type)

doxygen_params = get_doxygen_params(function_def)

function = FunctionMember(
function_name,
function_type,
visibility,
function_arg_string,
function_virtual,
is_pure_virtual,
is_static,
doxygen_params,
)

function.add_template(get_template_params(function_def))
Expand Down
Loading
Loading