Skip to content

Commit

Permalink
cpp/apigen: Fix handling of unnamed template parameters
Browse files Browse the repository at this point in the history
Previously, unnamed template parameters were incorrectly assigned a name
of `"None"`.
  • Loading branch information
jbms committed Aug 2, 2024
1 parent 27aba8e commit 8fb0172
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 3 deletions.
12 changes: 9 additions & 3 deletions sphinx_immaterial/apidoc/cpp/api_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -1004,10 +1004,11 @@ def get_nonitpick_directives(decl: Cursor) -> List[str]:
def _clang_template_parameter_to_json(config: Config, decl: Cursor):
param_decl_str = get_extent_spelling(decl.translation_unit, decl.extent)
param = _parse_template_parameter(param_decl_str)
spelling = decl.spelling
if param is None:
return {
"declaration": param_decl_str,
"name": decl.spelling,
"name": spelling if spelling else None,
"kind": TEMPLATE_PARAMETER_KIND_TO_JSON_KIND[decl.kind],
# Heuristic to determine if it is a pack.
"pack": "..." in param_decl_str,
Expand Down Expand Up @@ -1506,9 +1507,11 @@ def _sphinx_ast_template_parameter_to_json(
else:
kind = "non_type"

identifier = param.get_identifier()

return {
"declaration": _substitute_internal_type_names(config, str(param)),
"name": str(param.get_identifier()),
"name": str(identifier) if identifier else None,
"kind": cast(TemplateParameterKind, kind),
"pack": param.isPack, # type: ignore[attr-defined]
}
Expand Down Expand Up @@ -1941,7 +1944,10 @@ def _transform_template_parameters(config: Config, template_parameters: List[Any
# the substitution `{"SfinaeXXX": "Condition"}`. To avoid parsing in cases
# that can't possibly match, first look to see if the name starts with
# `"sfinae"`.
if re.match(r"sfinae", template_parameter["name"], re.IGNORECASE) is not None:
if (
re.match(r"sfinae", template_parameter["name"] or "", re.IGNORECASE)
is not None
):
# Possibly match, parse to verify.
replacement = _extract_sfinae_replacement(decl)
if replacement is not None:
Expand Down
20 changes: 20 additions & 0 deletions tests/cpp_api_parser_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,23 @@ def test_function_fields():
]
)
assert expected == doc_str


def test_unnamed_template_parameter():
config = api_parser.Config(
input_path="a.cpp",
compiler_flags=["-std=c++17", "-x", "c++"],
input_content=rb"""
/// Tests something.
///
/// \ingroup Array
template <typename = void>
constexpr inline bool IsArray = false;
""",
)

output = api_parser.generate_output(config)
entities = output.get("entities", {})
assert len(entities) == 1
entity = list(entities.values())[0]
assert entity["template_parameters"][0]["name"] is None
38 changes: 38 additions & 0 deletions tests/cpp_apigen_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""Tests cpp/apigen."""


def test_unnamed_template_parameter(immaterial_make_app):
app = immaterial_make_app(
extra_conf="""
extensions.append("sphinx_immaterial.apidoc.cpp.apigen")
""",
confoverrides=dict(
nitpicky=True,
cpp_apigen_configs=[
dict(
document_prefix="cpp_apigen_generated/",
api_parser_config=dict(
input_content=r"""
/// Tests if something is an array.
///
/// \ingroup Array
template <typename T, typename = void>
constexpr inline bool IsArray = false;
""",
compiler_flags=["-std=c++17", "-x", "c++"],
verbose=True,
),
),
],
),
files={
"index.rst": """
.. cpp-apigen-group:: Array
"""
},
)

app.build()

assert not app._warning.getvalue()

0 comments on commit 8fb0172

Please sign in to comment.