lint
Runs the policy checks of the tree, each file read once, with a self-test before each check
lint
lint runs the policy checks of the tree: the rules that the code, the build
files and the documents must follow, each with the spec section that owns it.
It replaces the scripts of integration/lint/, one check at a time.
Usage
lint run every check
lint --check <id>[,<id>...] run the named checks
lint --list [--markdown] list the checks
lint --self-test run the self-test of every check, and nothing else
lint --check <id> --update rewrite the baseline of a check that has one
lint --check <id> --write write what a check writes: the evidence blocks of
parity-citations, the leading whitespace of glsl-style
lint --root <folder> check another checkout
lint --jobs <n> cap the worker threads (default: the processor count)
lint --timings print the time of each check
lint --strict fail on a check that is not judged
lint --with-tests [--kiln <program>] [--compile-db <file>] after the checks, run the guard suites and the kiln check modes
Build and run it from the repository root:
qbs run -p lint -- --check cpp-policy
Without --root, lint checks the checkout that holds the working folder. It
reads the files that git tracks, leaves out the trees that
integration/lint/vendored-paths.txt lists, and reads each file once, on all
processors, for every check that needs it.
What a run reports
Each check gets a block, then the run ends with a summary:
── cpp-policy
note: 9410 non-vendored source file(s) scanned; ...
✓ clean
════════════════════════════════════════════
files read: 10708 of 10708 selected
passed: 1
✓ cpp-policy
A finding names its file and line. A note is good news, such as an allowlist entry that is no longer needed, and never fails the run.
Each check runs its self-test first. The self-test plants a violation and a clean case and checks that the matcher tells them apart. If the self-test fails, the check does not run and the run fails, because a matcher that stopped matching reports the same clean result as a clean tree.
A check that cannot judge, for example because an input file is missing, is
listed as not judged. It does not count as passed. The run fails on it only
with --strict.
The report goes to standard error. --list writes to standard output.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Every check that ran passed |
| 1 | A finding, a failed self-test, an empty run, or, with --strict, a check that is not judged |
| 2 | A wrong command line, such as a check name that does not exist |
| 4 | No checkout, no vendored-paths.txt, or, with --with-tests, no kiln program in the build |
--with-tests
After the checks, lint --with-tests runs the guard suites with
kiln test --prebuilt default --profile gate. It does not build: run
qbs build first.
Then it runs the four check modes of kiln, which hold kiln's description of
the build to what qbs builds: kiln commands --check, kiln sources --check,
kiln keys --check and kiln import-qbs --check. The first two read the
compile database that qbs wrote, release/compile_commands.json unless
--compile-db names another. A mode that lacks its input is listed as
not judged.
By default it runs the kiln program of this checkout's build. A machine that
runs one kiln broker for every checkout refuses a kiln of another build, so
there name the machine's kiln with --kiln <program>. If the program does not
exist, lint exits 4 and says so.
The build step
cpp-policy also runs in the build, as a step of the lint product. A
violation of the exception and RTTI policy fails qbs build. The other checks
run in the guard suites, so a known violation that someone recorded does not
stop a build.
Checks
The table is the output of lint --list --markdown. A test compares the two,
so this page cannot drift from the program.
| ID | Title | Owner | Scope |
|---|---|---|---|
banned-identifiers |
A removed name stays removed: no code names an identifier of banned-identifiers.txt | §SCP-D-2.7 | tree |
build-matrix |
The build-matrix YAML parses, carries its Qt and Windows output schema, and has every leaf | §CF-13 | tree |
ccache-config |
ccache shares its entries between sibling checkouts on this host | §BPC-0 | machine |
clear-colors |
A clear that can reach the screen uses placeholderColor(), not a QColor literal | §WFD-C4 | tree |
core-tier |
A coreTier library's headers include Qt Core and nothing else from Qt | §BSS-T-1 | tree |
cpp-policy |
Our code uses no exceptions and no RTTI, and a product that enables either records why | §EXP-E2 | tree |
debuginfo-follows-install |
Each Application wrapper binds installDebugInformation to install | §WFR-RC-6.3 | tree |
disabled-tests |
A suite is not switched off (excluded category, condition: false, extraCondition: false, requiresCapabilities) without the owner's approval | §TL-T-1 | test tree |
facility-ctor |
An activity that looks up a facility declares the context constructor, and casts the result checked | §AC-3 | tree |
glsl-style |
GLSL indents with tabs, aligns with spaces and holds no tab inside a line, in all three populations | §RRF-C3 | tree |
header-statics |
A first-party header declares no mutable static variable at namespace scope |
§TSR-S-6 | tree |
headless-contradiction |
A suite in a built category does not declare headless: false | §TSR-S-1 | test tree |
hivecluster-mkpath |
libhive makes folders inside a hive with FsUtil::mkpath(), not QDir::mkpath() | §FU-6 | tree |
nice-compliance |
Every process the build spawns takes its priority from lowpriority.js | §BPT-5 | tree |
no-shell |
Every tracked script is listed in exempt-scripts.txt with the reason it stays a script | §SCP-D-12 | tree |
opal-family-registration |
Every OPAL task family is declared or called, and the hand-wired set grows only through its baseline | §OTR-6 | tree |
parity-citations |
Every matrix <ID> citation names one row of one registered matrix, and each generated evidence block is current |
§CIE-C5 | tree |
pragma-once |
A first-party header uses an include guard, not #pragma once, and no two headers share one |
§APD-M17 | tree |
qdoc-file-local |
No QDoc block documents a helper in an anonymous namespace, or main() | §APD-M26 | tree |
product-boundary |
A product compiles only its own files: no files: or prefix: reaches into another product | §KN-K9 | tree |
real-platform-tests |
A suite that skips for want of Vulkan declares requiresRealPlatform: true | §TSR-S-3 | test tree |
rhi-first-policy |
Backend-specific graphics code stays in librhi, and libconstruct guards float targets and SSBOs | §RFC-4 | tree |
root-strays |
The project root holds only its fixed set of tracked entries | §BSS-M-2 | tree |
script-env |
An exempt script uses the environment only where §NEV-A10 allows it, and says so | §NEV-A10 | tree |
section-numbers |
A §-number in a markdown heading addresses one section per file | §BSS-M-2 | tree |
service-level-names |
A ServiceLevel member list names its services with ->name(), never with a string literal | §NCL-C1 | tree |
settings-write-paths |
An apply, push or fallback path never persists a setting | §CIE-C4 | tree |
shared-members |
A suite with shared: true obeys the member rules of SharedTestProbe.qbs | §TSR-B-6 | test tree |
shell-stubs |
A test stubs a program with a program, not a shell script, and names no /tmp/ | §WFD-C5 | test tree |
shortcut-callbacks |
Every id a shortcut callback binds is registered somewhere in the tree | §CFGU-8 | tree |
shutdown-rules |
A QFutureWatcher that libstore makes is parented to qApp | §SL-RS-8 | tree |
signal-id-discipline |
A handler for an id-carrying signal uses the id, or says why it does not | §UC-T5 | tree |
stream-discipline |
Shipped code writes to stdout only where the allowlist records it as data | §SD-V-3 | tree |
test-condition |
A Test binds extraCondition, never a condition that replaces the template's | §KN-F25 | test tree |
test-main |
Every suite enters through OC_TEST_MAIN*, never a raw QTEST_*_MAIN | §TSR-S-2 | test tree |
tick-discipline |
SceneWorkerWidget ticks the worker through the gate, or says why not | §IQD-3 | tree |
unique-connection-lambda |
No connect that names Qt::UniqueConnection carries a lambda | §CIE-T4 | tree |
A tree check reads the source tree. A test tree check reads test/
only and also runs in the testTestHygiene suite. A machine check reads the
configuration of this computer, so it runs from the command line only.