feat: make test-ui checks the UI files with blueprint-compiler

The interface is hand-written GtkBuilder XML and nothing in the build can see a mistake in it: a
property a class does not have, or a child a container does not accept, is a Gtk-ERROR when the
window is built -- and Gtk-ERROR aborts the process, so a typo in a .ui takes the application down
rather than failing to open a dialog. xml-stripblanks catches malformed XML and nothing else, and
the probes catch the rest only for the windows they open. Three of those aborts happened during
this refactor.

tools/check_ui.py round-trips each file through blueprint-compiler: decompile to blueprint, then
compile that, which type-checks every property and child type against the GIR. The XML stays the
source of truth and stays hand-written -- this is a check, not a compiler, and nothing here is
needed to build the application. Which is why the target is opt-in (no ALL) and the tool is looked
for at configure time rather than required: without it the target is absent, not silently passing.

    $ make -C build test-ui
    check_ui: 5 files in src/ui
      ok    help.ui ... source-form.ui
    check_ui: 5 ok, 0 failed

Injected the exact mistake that cost a run earlier (an AdwEntryRow subtitle) and the check caught
it, with the caret and the "did you mean title?" hint, exiting non-zero. --lint prints the linter's
advice separately: it is advice, and the linter has opinions this project does not share.
This commit is contained in:
Martino Ferrari committed 2026-10-12 10:41:25 +02:00
1 parent 8073e7b3fd
commit 7a982da6c4
4 files changed
+190 -17

No files matched your search

+18
View File
@@ -34,6 +34,24 @@ deliberate: the entry then always launches exactly the binary that was last buil
`StartupWMClass` is needed — GTK takes the WM class from the application ID, and the desktop
file's basename is that same string, which is what associates a running window with the entry.
The interface files can be checked without building anything or opening a window:
```sh
cmake --build build --target test-ui # or: make -C build test-ui
```
That round-trips every `.ui` through `blueprint-compiler` — `decompile` turns it into blueprint, and
compiling *that* type-checks every property and child type against the GIR — printing one line per file.
It exists because the alternative is what happens otherwise: a property a class does not have is a
`Gtk-ERROR` when the window is built, and `Gtk-ERROR` **aborts the process**, so a typo in a `.ui` takes
the application down rather than failing to open a dialog. `preprocess="xml-stripblanks"` catches
malformed XML and nothing else, and the probes catch the rest only for the windows they open.
The XML stays the source of truth and stays hand-written: this is a check, not a compiler, and nothing
here is needed to *build* the application. `blueprint-compiler` and `python3` are found at configure
time; without them the target is absent rather than silently passing. `tools/check_ui.py --lint` also
prints the linter's advice, which is advice and deliberately not a gate.
Options: `--server`, `--port`, `--multicast`, `--interface`, `--buffer-mb` (per
buffer, default 200), `--max-window`, `--holdoff`, `--recv-buffer`, `--plots` (the row
count to *start* with, 1..`RowSet::kMaxRows`; the layout editor owns it afterwards),