[api_protobuf] Support compound ifdef conditions in proto generator (#15930)

This commit is contained in:
Keith Burzinski
2026-04-22 17:57:15 -05:00
committed by GitHub
parent 36720c8495
commit 70b1d9a087
+31 -11
View File
@@ -65,11 +65,31 @@ _enum_max_values: dict[str, int] = {}
_message_desc_map: dict[str, Any] = {}
def _make_ifdef_line(condition: str) -> str:
"""Return the correct preprocessor open-guard line for a condition string.
Simple identifiers use ``#ifdef IDENTIFIER``.
Compound expressions (containing ``||`` or ``&&``) use
``#if defined(A) || defined(B)`` so that the preprocessor
evaluates them correctly.
"""
if any(op in condition for op in ("||", "&&", "!")):
# Replace each bare identifier token with defined(token)
expr = re.sub(r"\b([A-Za-z_]\w*)\b", r"defined(\1)", condition)
return f"#if {expr}"
return f"#ifdef {condition}"
def indent_list(text: str, padding: str = " ") -> list[str]:
"""Indent each line of the given text with the specified padding."""
lines = []
for line in text.splitlines():
if line == "" or line.startswith("#ifdef") or line.startswith("#endif"):
if (
line == ""
or line.startswith("#ifdef")
or line.startswith("#if ")
or line.startswith("#endif")
):
p = ""
else:
p = padding
@@ -82,7 +102,7 @@ def indent(text: str, padding: str = " ") -> str:
def wrap_with_ifdef(content: str | list[str], ifdef: str | None) -> list[str]:
"""Wrap content with #ifdef directives if ifdef is provided.
"""Wrap content with #ifdef / #if directives if ifdef is provided.
Args:
content: Single string or list of strings to wrap
@@ -96,7 +116,7 @@ def wrap_with_ifdef(content: str | list[str], ifdef: str | None) -> list[str]:
return [content]
return content
result = [f"#ifdef {ifdef}"]
result = [_make_ifdef_line(ifdef)]
if isinstance(content, str):
result.append(content)
else:
@@ -3021,7 +3041,7 @@ def build_service_message_type(
if source in (SOURCE_BOTH, SOURCE_CLIENT):
# Only add ifdef when we're actually generating content
if ifdef is not None:
hout += f"#ifdef {ifdef}\n"
hout += _make_ifdef_line(ifdef) + "\n"
# Generate receive handler and switch case
func = f"on_{snake}"
has_fields = any(not field.options.deprecated for field in mt.field)
@@ -3302,8 +3322,8 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint
content += "#endif\n"
dump_cpp += "#endif\n"
if enum_ifdef is not None:
content += f"#ifdef {enum_ifdef}\n"
dump_cpp += f"#ifdef {enum_ifdef}\n"
content += _make_ifdef_line(enum_ifdef) + "\n"
dump_cpp += _make_ifdef_line(enum_ifdef) + "\n"
current_ifdef = enum_ifdef
content += s
@@ -3378,9 +3398,9 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint
if dump_cpp:
dump_cpp += "#endif\n"
if msg_ifdef is not None:
content += f"#ifdef {msg_ifdef}\n"
cpp += f"#ifdef {msg_ifdef}\n"
dump_cpp += f"#ifdef {msg_ifdef}\n"
content += _make_ifdef_line(msg_ifdef) + "\n"
cpp += _make_ifdef_line(msg_ifdef) + "\n"
dump_cpp += _make_ifdef_line(msg_ifdef) + "\n"
current_ifdef = msg_ifdef
content += s
@@ -3529,7 +3549,7 @@ static const char *const TAG = "api.service";
for id_ in sorted(ids):
_, ifdef, case_label = RECEIVE_CASES[id_]
if ifdef:
result += f"#ifdef {ifdef}\n"
result += _make_ifdef_line(ifdef) + "\n"
result += f" case {case_label}: {comment}\n"
if ifdef:
result += "#endif\n"
@@ -3572,7 +3592,7 @@ static const char *const TAG = "api.service";
out += " switch (msg_type) {\n"
for i, (case, ifdef, case_label) in cases:
if ifdef is not None:
out += f"#ifdef {ifdef}\n"
out += _make_ifdef_line(ifdef) + "\n"
c = f" case {case_label}: {{\n"
c += indent(case, " ") + "\n"