[api_protobuf] Support compound ifdef conditions in proto generator (#15930)
This commit is contained in:
1 parent
36720c8495
commit
70b1d9a087
1 file changed
+31
-11
@@ -65,11 +65,31 @@ _enum_max_values: dict[str, int] = {}
|
|||||||
_message_desc_map: dict[str, Any] = {}
|
_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]:
|
def indent_list(text: str, padding: str = " ") -> list[str]:
|
||||||
"""Indent each line of the given text with the specified padding."""
|
"""Indent each line of the given text with the specified padding."""
|
||||||
lines = []
|
lines = []
|
||||||
for line in text.splitlines():
|
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 = ""
|
p = ""
|
||||||
else:
|
else:
|
||||||
p = padding
|
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]:
|
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:
|
Args:
|
||||||
content: Single string or list of strings to wrap
|
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]
|
||||||
return content
|
return content
|
||||||
|
|
||||||
result = [f"#ifdef {ifdef}"]
|
result = [_make_ifdef_line(ifdef)]
|
||||||
if isinstance(content, str):
|
if isinstance(content, str):
|
||||||
result.append(content)
|
result.append(content)
|
||||||
else:
|
else:
|
||||||
@@ -3021,7 +3041,7 @@ def build_service_message_type(
|
|||||||
if source in (SOURCE_BOTH, SOURCE_CLIENT):
|
if source in (SOURCE_BOTH, SOURCE_CLIENT):
|
||||||
# Only add ifdef when we're actually generating content
|
# Only add ifdef when we're actually generating content
|
||||||
if ifdef is not None:
|
if ifdef is not None:
|
||||||
hout += f"#ifdef {ifdef}\n"
|
hout += _make_ifdef_line(ifdef) + "\n"
|
||||||
# Generate receive handler and switch case
|
# Generate receive handler and switch case
|
||||||
func = f"on_{snake}"
|
func = f"on_{snake}"
|
||||||
has_fields = any(not field.options.deprecated for field in mt.field)
|
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"
|
content += "#endif\n"
|
||||||
dump_cpp += "#endif\n"
|
dump_cpp += "#endif\n"
|
||||||
if enum_ifdef is not None:
|
if enum_ifdef is not None:
|
||||||
content += f"#ifdef {enum_ifdef}\n"
|
content += _make_ifdef_line(enum_ifdef) + "\n"
|
||||||
dump_cpp += f"#ifdef {enum_ifdef}\n"
|
dump_cpp += _make_ifdef_line(enum_ifdef) + "\n"
|
||||||
current_ifdef = enum_ifdef
|
current_ifdef = enum_ifdef
|
||||||
|
|
||||||
content += s
|
content += s
|
||||||
@@ -3378,9 +3398,9 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint
|
|||||||
if dump_cpp:
|
if dump_cpp:
|
||||||
dump_cpp += "#endif\n"
|
dump_cpp += "#endif\n"
|
||||||
if msg_ifdef is not None:
|
if msg_ifdef is not None:
|
||||||
content += f"#ifdef {msg_ifdef}\n"
|
content += _make_ifdef_line(msg_ifdef) + "\n"
|
||||||
cpp += f"#ifdef {msg_ifdef}\n"
|
cpp += _make_ifdef_line(msg_ifdef) + "\n"
|
||||||
dump_cpp += f"#ifdef {msg_ifdef}\n"
|
dump_cpp += _make_ifdef_line(msg_ifdef) + "\n"
|
||||||
current_ifdef = msg_ifdef
|
current_ifdef = msg_ifdef
|
||||||
|
|
||||||
content += s
|
content += s
|
||||||
@@ -3529,7 +3549,7 @@ static const char *const TAG = "api.service";
|
|||||||
for id_ in sorted(ids):
|
for id_ in sorted(ids):
|
||||||
_, ifdef, case_label = RECEIVE_CASES[id_]
|
_, ifdef, case_label = RECEIVE_CASES[id_]
|
||||||
if ifdef:
|
if ifdef:
|
||||||
result += f"#ifdef {ifdef}\n"
|
result += _make_ifdef_line(ifdef) + "\n"
|
||||||
result += f" case {case_label}: {comment}\n"
|
result += f" case {case_label}: {comment}\n"
|
||||||
if ifdef:
|
if ifdef:
|
||||||
result += "#endif\n"
|
result += "#endif\n"
|
||||||
@@ -3572,7 +3592,7 @@ static const char *const TAG = "api.service";
|
|||||||
out += " switch (msg_type) {\n"
|
out += " switch (msg_type) {\n"
|
||||||
for i, (case, ifdef, case_label) in cases:
|
for i, (case, ifdef, case_label) in cases:
|
||||||
if ifdef is not None:
|
if ifdef is not None:
|
||||||
out += f"#ifdef {ifdef}\n"
|
out += _make_ifdef_line(ifdef) + "\n"
|
||||||
|
|
||||||
c = f" case {case_label}: {{\n"
|
c = f" case {case_label}: {{\n"
|
||||||
c += indent(case, " ") + "\n"
|
c += indent(case, " ") + "\n"
|
||||||
|
|||||||
Reference in new issue
Block a user