gate-kx11extras: guard namespace blocks using QX11Application

libtaskmanager/virtualdesktopinfo.cpp defines namespace X11Info at namespace
scope in terms of QNativeInterface::QX11Application, which does not exist in a
Qt built without the xcb platform:
  error: 'QX11Application' is not a member of 'QNativeInterface'

All three call sites were already inside #if HAVE_X11 -- only the definition
was exposed -- so wrapping the block changes no reachable behaviour.

Restricted to depth-0 'namespace' blocks whose body names an X11-only native
interface. Narrow on purpose: brace-matching arbitrary function definitions is
much easier to get wrong, and a bad transform here produces invalid C++ rather
than a clean failure.
This commit is contained in:
2026-08-04 21:26:14 +03:00
parent e3b1edacef
commit d8d2ed837c
+58 -1
View File
@@ -403,6 +403,60 @@ def gate_raw_x11_includes(text: str) -> tuple[str, int]:
return "\n".join(out) + ("\n" if text.endswith("\n") else ""), changed
def gate_x11_namespace_blocks(text: str) -> tuple[str, int]:
r"""Guard a namespace block defined in terms of an X11-only Qt interface.
libtaskmanager/virtualdesktopinfo.cpp defines
namespace X11Info
{
[[nodiscard]] inline auto connection()
{
return qGuiApp->nativeInterface<QNativeInterface::QX11Application>()
->connection();
}
}
at namespace scope. QNativeInterface::QX11Application does not exist in a Qt
built without the xcb platform, so this fails to compile even though all
THREE call sites are already inside #if HAVE_X11:
error: 'QX11Application' is not a member of 'QNativeInterface'
Only the definition is exposed, so wrapping the block is sufficient and
changes no reachable behaviour. Restricted to depth-0 `namespace` blocks
whose body names an X11-only native interface -- narrow on purpose, since
brace-matching arbitrary function definitions is far easier to get wrong.
"""
changed = 0
search = 0
while True:
m = re.compile(r"^namespace\s+\w+\s*$", re.M).search(text, search)
if not m:
break
brace = text.find("{", m.end())
if brace < 0:
search = m.end()
continue
end = find_block_end(text, brace)
if end < 0:
search = m.end()
continue
body = text[m.start():end]
if "QX11Application" not in body:
search = end
continue
ls = line_start(text, m.start())
prev_nl = text.rfind("\n", 0, ls - 1)
if text[prev_nl + 1: ls - 1].strip() == GUARD_OPEN:
search = end
continue
new = f"{GUARD_OPEN}\n" + text[ls:end] + f"\n{GUARD_CLOSE}"
text = text[:ls] + new + text[end:]
changed += 1
search = ls + len(new)
return text, changed
def main() -> int:
root = Path(sys.argv[1])
# libtaskmanager's X11 backend is excluded from the build entirely (Wayland
@@ -426,6 +480,8 @@ def main() -> int:
print(f" {path.relative_to(root)}: {n_ifdef} inert #ifdef HAVE_X11 -> #if")
if not any(sym in original for sym in X11_HEADERS):
text, n_raw = gate_raw_x11_includes(original)
text, n_ns = gate_x11_namespace_blocks(text)
n_raw += n_ns
if n_raw:
path.write_text(text)
total_files += 1
@@ -438,7 +494,8 @@ def main() -> int:
text, n_els = gate_else_blocks(text)
text, n_st = gate_statements(text)
text, n_raw = gate_raw_x11_includes(text)
n_blk += n_els + n_st
text, n_ns = gate_x11_namespace_blocks(text)
n_blk += n_els + n_st + n_ns
n_inc += n_raw
if text != original:
path.write_text(text)