testkit/qt/ci: clear the clang-tidy debt in the two AUTOMOC self-including TUs, and drop a deleted workflow from a docstring (fixes #646, fixes #643) - #653
Conversation
…luding TUs now report (fixes #646) #647 made the clang-tidy job build `ladder_common_tests_autogen` and `morph_forms_qml_tests_autogen`, so `examples/common/testkit/test_qml_surface.cpp` and `src/qt/forms/tests/tst_main.cpp` parse for the first time and are analysed. Nothing was broken -- clang-tidy-diff reports only changed lines -- but the first PR to touch one of those lines would have inherited findings that were not its own. Re-measured on 0067b5b with the clang-tidy job's own configure flags and clang-tidy 22.1.8 (CI's pinned major), both AUTOMOC targets built first: 81 findings in test_qml_surface.cpp (73 misc-const-correctness, 3 readability-convert-member-functions-to-static, 2 readability-inconsistent-declaration-parameter-name, 2 readability-identifier-length, 1 bugprone-easily-swappable-parameters) and 3 in tst_main.cpp. That reproduces the #647 lane's figure at c55ea5b exactly. 77 of the 84 are fixed rather than suppressed: * 73 `misc-const-correctness` -- local `QTemporaryDir` and fixture-bridge declarations that are never mutated. Applied with clang-tidy --fix, then rewritten to the west-const spelling the rest of the file uses. * 2 `readability-identifier-length` -- `id` -> `rowId`, `ok` -> `okay`. Safe: QmlSurfaceAudit reads `QMetaMethod::name()` and `parameterCount()` and never a parameter name, and the QML fixture text is unchanged. * 1 `misc-use-internal-linkage` -- `MorphFormsQmlTestSetup` moves into an anonymous namespace; QUICK_TEST_MAIN_WITH_SETUP expands in the same TU. * 1 `readability-redundant-access-specifiers` -- the explicitly defaulted default constructor and its `public:` are removed, which also removes the redundancy, since Q_OBJECT ends in `private:`. The remaining 7 get individually reasoned NOLINTNEXTLINEs, reason above the directive (#631/#627's rule) -- no NOLINT sweep and no new `.clang-tidy` entry, which is what #632 was about: * 4 `readability-convert-member-functions-to-static` on Q_PROPERTY readers, a Q_INVOKABLE and a Qt Quick Test setup slot. The reason is shape, not legality: the static form was measured to compile and moc registers the same property, but no bridge these fixtures stand in for has a static property reader, and a Qt slot is a member function by definition. * 2 `readability-inconsistent-declaration-parameter-name` on the two signals. moc's generated definitions name the parameters `_t1`/`_t2`, so no edit to the declarations can remove the mismatch; the finding reaches these files only because the classes are declared in a .cpp. * 1 `bugprone-easily-swappable-parameters` on the file-local `writeQml` helper's two adjacent `const QString&`. Verified, not asserted: * Both files are in this configure's compile_commands.json (703 entries, 695 in-workspace, 270 under examples/ -- above #649's 600/200 floors). * clang-tidy exits 0 on both files afterwards, and with every NOLINTNEXTLINE line stripped it exits 1 reporting exactly the 6 + 1 suppressed findings again. Each directive is load-bearing and the TUs are really analysed, rather than clean because nothing looked at them. * `ladder_common_tests "[qml-surface]"`: 182 assertions in 36 test cases, all passing. * `morph_forms_qml_tests -input src/qt/forms/tests`: 292 passed, 0 failed, the two corpus-reading suites among them -- which is what proves the setup slot still runs after the anonymous-namespace move. * clang-format 22.1.8 clean; check_nolint_directives.sh, check_bidi_controls.py, check_tidy_suppression_scope.sh, check_automoc_includes.sh, check_catch_test_names.sh all pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VptDWG2fKr2vBnLSJcgzgW
…string (fixes #643) #635 deleted .github/workflows/suppression-guard.yml; the checker's "## Scope" paragraph still named it as one of the single-job workflows the gate skips. It was the last reference to that file in the tree: $ git grep -n "suppression-guard" -- . scripts/check_workflow_job_banners.py:50:suppression-guard.yml and the two wasm workflows are single-job files that have Gate behaviour was never affected and is not affected now -- the skip is derived per file, not read from that list. Measured on 0067b5b, over the five workflows with zero banners: ok: .github/workflows/docs.yml: no section banners, not in the banner style ok: .github/workflows/mutation.yml: no section banners, not in the banner style ok: .github/workflows/spec-sync.yml: no section banners, not in the banner style ok: .github/workflows/wasm-demo.yml: no section banners, not in the banner style ok: .github/workflows/wasm-ladder.yml: no section banners, not in the banner style ok: all 24 section banner(s) introduce the job they describe So the name is deleted rather than swapped for another: with it gone the sentence enumerates exactly the five files a run reports as skipped, and there is no sixth current example to put in its place. A second paragraph says so explicitly -- the list is an illustration with a shelf life, nothing reads it, and the run's own output is the current list -- so the next workflow deletion dates one sentence instead of producing a third round of this. Verified: `python3 scripts/check_workflow_job_banners.py .` and `bash scripts/test_check_workflow_job_banners.sh` both pass; the five skipped files and their single-job counts were enumerated from the tree with the checker's own BANNER_RE/JOB_KEY_RE rather than read off the docstring. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VptDWG2fKr2vBnLSJcgzgW
Runner verificationMy brief was wrong on #643 and the lane checked rather than complying. I told it that replacing Exactly five, so "docs.yml, mutation.yml, spec-sync.yml and the two wasm workflows" is exact once the stale name is gone. Deleting was right. The added paragraph is better than either option I offered — it marks the list as an illustration with a shelf life and points the reader at the run's own Diff shape matches the report exactly: three files, no The east-const rewrite checks out and the reason for it is sound. What I could not verify: the branch's load-bearing claim — that clang-tidy exits 0 on both files because they were analysed and are clean, not because the invocation missed them. That rests on the lane's mutation probe (strip every The best thing in this report is a reason the lane refused to use. It probed whether moc rejects a static #652 is the same class as #632 and worth its own look: Not merged: CI incomplete at hand-off. Next sweep counts the checks. 🤖 Generated with Claude Code |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Two tickets, one commit each.
#646 — the 84 findings #647 made reachable
#647 taught the
clang-tidyjob to buildladder_common_tests_autogenandmorph_forms_qml_tests_autogen, soexamples/common/testkit/test_qml_surface.cppand
src/qt/forms/tests/tst_main.cppparse and are analysed for the firsttime. Nothing was broken —
clang-tidy-diffreports only changed lines — butthe first PR to touch one of those lines would have inherited findings that
were not its own.
Re-measured, not quoted
The ticket carried the #647 lane's figure from
c55ea5b7, and the triagecomment explicitly declined to repeat it as fact. Re-derived here on
0067b5bfwith the job's own configure flags and clang-tidy 22.1.8 (CI'spinned major), both AUTOMOC targets built first:
test_qml_surface.cppmisc-const-correctness, 3readability-convert-member-functions-to-static, 2readability-inconsistent-declaration-parameter-name, 2readability-identifier-length, 1bugprone-easily-swappable-parameterstst_main.cppmisc-use-internal-linkage,readability-redundant-access-specifiers,readability-convert-member-functions-to-staticThat reproduces the reported 81 / 73 / 3 exactly. The ticket is not an
artefact of the pre-#647 parse failure; it stands.
77 of 84 fixed, 7 suppressed with an argument
Fixed:
misc-const-correctness— localQTemporaryDirand fixture-bridgedeclarations never mutated. Applied with
clang-tidy --fix, then rewrittenfrom the tool's east-const output to the west-const spelling the rest of the
file uses (
.clang-formatsets noQualifierAlignment, so the formatterwould have left
QTemporaryDir const dir;standing).readability-identifier-length—id→rowId,ok→okay. Safebecause
QmlSurfaceAuditreadsQMetaMethod::name()andparameterCount()and never a parameter name (
examples/common/testkit/qml_surface.cpp:145-158);the QML fixture text is untouched.
misc-use-internal-linkage—MorphFormsQmlTestSetupmoves into ananonymous namespace.
QUICK_TEST_MAIN_WITH_SETUPexpands in the same TU(
quicktest.hconstructsQuickTestSetupClass setup;and passes&setup),so internal linkage is enough.
readability-redundant-access-specifiers— the explicitly defaulteddefault constructor and its
public:are removed.Q_OBJECTends inprivate:, sopublic Q_SLOTS:following it directly is not redundant; thefinding existed only because of the
public:section above it.Suppressed, one reasoned
NOLINTNEXTLINEper site, reason above thedirective so #627/#631's wrapped-reason trap cannot apply. No
NOLINTsweep,no new or edited
.clang-tidy— which is what #632 andscripts/check_tidy_suppression_scope.share about:readability-convert-member-functions-to-staticon twoQ_PROPERTYreaders, a
Q_INVOKABLE, and a Qt Quick Test setup slot. The reason givenis shape, not legality, because legality was measured and the honest
answer is that the static form works: with the three fixture methods made
static, moc emits_t->title()exactly as for a member function,registers the same property and invokable, and the TU compiles. It is
declined because no bridge these fixtures stand in for has a static property
reader, and a Qt slot is a member function by definition — the same argument
tests/.clang-tidyalready records for this check over its stubexecutemethods.
readability-inconsistent-declaration-parameter-nameon the twosignals. moc's generated definitions name the parameters positionally —
SurfaceFixtureBridge::listed(const QVariantList & _t1, bool _t2)intest_qml_surface.moc:155— so no edit to the declarations can remove themismatch. Leaving them unnamed would trade it for
readability-named-parameterand take the Doxygen with it. These findingsreach a first-party file only because the classes are declared in a
.cpp,which is what puts moc's output inside the translation unit.
bugprone-easily-swappable-parameterson the file-localwriteQmlhelper's two adjacent
const QString&, across 40 call sites that all pass aQStringLiteral("….qml")first and a generated body second.Verification — the specific trap this leg had
A clean clang-tidy run proves nothing unless the TUs were analysed. Four
independent checks:
entries, 695 in-workspace, 270 under
examples/— above core/ladder: retire IBackend's four async twins and move the examples' prose onto the structural surface (fixes #570, fixes #571) #649's 600 / 200floors, and matching the figures in
ci.yml's own comment. Both targetfiles resolve inside it, so core/ladder: retire IBackend's four async twins and move the examples' prose onto the structural surface (fixes #570, fixes #571) #649's filter does not drop them.
NOLINTNEXTLINEline stripped and nothingelse changed, clang-tidy exits 1 and reports exactly the 6 + 1 suppressed
findings again:
findings that were fixed rather than suppressed do not come back, which
is the other half of the same probe.
clang-tidy-diff.pyover this branch's own diff againstorigin/master,with the job's flags: 2 TUs analysed, exit 0.
ladder_common_tests "[qml-surface]"— 182assertions in 36 test cases.
morph_forms_qml_tests -input src/qt/forms/tests(the command
add_testregisters) — 292 passed, 0 failed, the twocorpus-reading QML suites among them, which is what proves the setup slot
still runs after the anonymous-namespace move rather than silently
injecting nothing.
Also run green:
clang-format 22.1.8 --dry-run -Werror,check_nolint_directives.sh(171 directives),check_bidi_controls.py,check_tidy_suppression_scope.sh,check_automoc_includes.sh,check_catch_test_names.sh.#643 — a stale name in a docstring
scripts/check_workflow_job_banners.py's## Scopeparagraph namedsuppression-guard.yml, deleted by #635. It was the only surviving referencein the tree.
The name is deleted rather than swapped for another example, against the
ticket's suggestion, because there is no sixth current example to put in its
place: enumerating the tree with the checker's own
BANNER_RE/JOB_KEY_REgives exactly five bannerless workflows, all single-job —
docs.yml,mutation.yml,spec-sync.yml,wasm-demo.yml,wasm-ladder.yml— which isprecisely "docs.yml, mutation.yml, spec-sync.yml and the two wasm workflows".
With
suppression-guard.ymlremoved the sentence is exact, not short.A second paragraph then says the list is an illustration with a shelf life,
that nothing reads it, and that a run's own
no section banners, not in the banner stylelines are the current list — sothe next workflow deletion dates one sentence instead of producing a third
round of this. Gate behaviour is unchanged either way: the skip is recomputed
per file.
Verified:
python3 scripts/check_workflow_job_banners.py .(24 banners) andbash scripts/test_check_workflow_job_banners.shboth pass, as docheck_bidi_controls.pyandcheck_workflow_option_coverage.py.Filed, not folded
#652 —
examples/common/testkit/.clang-tidysays "Checks suppressedinside this test directory only" and "a hand-written
a < b < cin the codeunder test is still reported", but that directory also holds the
morph_ladder_testkitlibrary (fault_proxy.cpp,qml_surface.cpp), so thesuppression governs those two TUs as well. Reproduced with a probe line, with
both runs' output in the issue. Narrow in practice —
-Wparenthesescatchesthat exact shape anyway and only one check is subtracted — but it is a false
claim in a file whose value is the accuracy of its claims, the same class as
#632. Not folded here; this PR is about two unrelated files.
Review notes
Reasoned inline rather than through
/code-review, as instructed.clang-tidyexits 0 on both filesbecause they were analysed and are clean, not because the invocation missed
them. Check 2 above is what carries it — strip the directives and the
exact seven findings return, at the expected lines and checks.
tst_main.cppcould have broken Qt Quick Test's setup-hook lookup silently(it would have injected empty corpora, and the QML side fails loudly on
that, which is why 292/0 is the evidence and not just a green build). The
73
consts are tool-generated; they were reviewed as a diff and the suiteexercises them.
const SurfaceFixtureBridge bridge;binds toQmlSurfaceAudit::bind(const QString&, const QObject&), so the audit's view of the fixture is unchanged.Not verified
CI. Reporting at push time as instructed, without waiting.
Fixes #646
Fixes #643
🤖 Generated with Claude Code
https://claude.ai/code/session_01VptDWG2fKr2vBnLSJcgzgW