2 Checking a package
2.1 raco dover check
raco dover check ‹options› ‹pkg› ...
For each installed ‹pkg›, Dover finds the package’s modules, collects the bindings they export at phase 0, and looks each binding up in the installed documentation. It prints the bindings that are missing documentation, grouped by module, followed by a coverage summary and any documentation warnings.
Valid flags for ‹options›:
--include-private —
also check modules in "private" directories and modules listed in dover-consider-private. --ignore ‹module› or --ignore ‹module›:‹id› —
ignore every binding from ‹module›, or just the binding ‹id›. The ‹module› can be any checked module that exports the binding, or the one that defines it. This flag can be given more than once. --min ‹percent› —
exit with status 1 if coverage is below ‹percent›. Overrides dover-min-coverage. --strict —
exit with status 1 if there are any documentation warnings. --show-reexported —
also list the bindings re-exported from other packages, which don’t affect the score (see Which bindings count). The JSON output always includes them. -f ‹format› or --format ‹format› —
where ‹format› is one of: text (the default) —
a human-readable report, in color when the output is a terminal. Set the NO_COLOR environment variable to turn color off, or FORCE_COLOR to turn it on for output that is not a terminal; json —
a JSON object with totals per module (for scored bindings) or per package (for unscored ones), the missing bindings with the modules that export them, and the documentation warnings with their suggested fixes; stubs —
a defproc or defform stub for each missing binding, ready to paste into a Scribble file and fill in. The stubs are grouped by the module they are reported under: under a new defmodule if that module has no docs yet, or after a comment suggesting the existing defmodule or declare-exporting to add them under. Since a module’s docs can span several sections, Dover also suggests adding each stub near the docs for other bindings defined in the same module, naming up to three of them. Stubs that get the same suggestion are listed together; when a module’s stubs get different suggestions, each group comes after a separator line.
2.2 Which modules are checked
By default, Dover checks every ".rkt" file in the package’s collections, except:
files in directories that are named "private", "compiled" or "scribblings", or whose names start with .;
"info.rkt" files and "lang/reader.rkt" modules;
paths excluded by a compile-omit-paths field in any "info.rkt", since raco setup does not compile them either.
To treat other modules as private, list them in the dover-consider-private field of "info.rkt". Use this for internal modules that are not in a "private" directory. Dover skips private modules, but still counts the bindings that checked modules re-export from them.
Use --include-private to check all private modules too, or list specific private modules that Dover should always check in the dover-never-ignore field of "info.rkt". To replace module discovery altogether, list the modules in dover-modules.
Dover declares each module but does not instantiate it, so checking a package does not run its code.
2.3 Which bindings count
Dover follows each re-exported binding back to the module where it is originally defined, and scores it according to which package that module belongs to:
A binding defined in one of the packages being checked counts toward the score. This includes bindings defined in private modules and re-exported by public ones.
A binding re-exported from another package does not affect the score. The text report lists these bindings, grouped by the package that defines them, only if you give --show-reexported.
A binding re-exported from Racket’s main collections (such as racket/list) is skipped.
A binding is counted once, however many checked modules export it. It is documented if Scribble can find its documentation from at least one of those modules, and missing otherwise. Only documented bindings count as covered.
2.4 Where bindings are reported
Dover reports each scored binding under exactly one of the checked modules that export it:
A documented binding goes under the first module that its documentation says exports it (as given by defmodule or declare-exporting) and that does export it. For example, after (declare-exporting mypkg/element mypkg/core), the bindings in that section are reported under mypkg/element.
A missing binding that has siblings (documented bindings defined in the same module) is reported under the module that most of them are reported under, if that module also exports it. So if mypkg/private/impl defines several bindings that are documented under mypkg, a missing one that mypkg also exports is reported under mypkg, next to the others.
Any other binding goes under the checked module nearest to its definition. If the module that defines it is checked, that is the module; otherwise it is the first checked module that re-exports it, working outward from the definition. So a missing binding defined in mypkg/private/impl and re-exported by mypkg/element (which is in turn re-exported by mypkg) is reported under mypkg/element, which is probably where its documentation belongs.
When two modules are equally near, or have equally many siblings, the one that sorts first wins.
2.5 Documentation warnings
Besides missing documentation, Dover reports two problems with documented bindings, each with a suggested fix. Warnings do not affect the coverage score, and they affect the exit status only when you give --strict.
Binding doesn’t connect to its docs. A documented binding should connect to its documentation as exported by every checked module that exports it, so that a program requiring any of those modules gets links to the docs. To find the docs for a binding as exported by a module, Scribble follows its re-exports from that module toward the definition, looking for the module the docs are keyed to. If the docs use (defmodule mypkg/a) but mypkg/b re-exports the binding straight from the module that defines it, that path never passes through mypkg/a, so the binding as exported by mypkg/b doesn’t connect to its docs.
To fix it, add the defining module to the #:use-sources of the defmodule or declare-exporting, which keys the docs to the definition so that every re-export connects to them. See When public modules share a private module. (Adding mypkg/b to declare-exporting does not help.) If mypkg/b is an internal module that users should not require, list it in dover-consider-private instead.
Scribble matches #:use-sources modules by name, so when a binding is renamed on its way to a public module, Dover suggests the module on that path that exports it under the name the docs use. Two kinds of rename can’t be fixed that way:
If each public module gives the binding its public name itself, as with (provide (rename-out [%make-widget make-widget])) in both mypkg/a and mypkg/b, no module between mypkg/b and the definition exports it as make-widget. Give it that name in one module that both re-export it from, and add that module to the #:use-sources; or have mypkg/b re-export it from mypkg/a.
If mypkg/b exports the binding under a different name than the docs use, that name needs its own docs, for example with deftogether.
Incorrect export claim. The docs say a checked module exports a binding (through defmodule or declare-exporting), but the module doesn’t. Either remove the module from the declaration or export the binding from it.
2.6 Configuration in "info.rkt"
Dover reads the following fields from the package’s top-level "info.rkt", and also from the "info.rkt" of each package that has its docs (see Configuration in split lib/doc packages). All are optional.
dover-ignore —
a list of bindings to leave out of the check. Each element is either a module path, which ignores every binding exported from or defined in that module, or a list of a module path followed by identifiers, which ignores only those identifiers. (define dover-ignore '(mypkg/tests (mypkg/form ~error ~errors))) Typical candidates are bindings that exist only to produce better syntax errors, and internals that are exported for use by other modules in the same package.
dover-consider-private —
a list of modules to treat as private, in addition to the modules in "private" directories. Dover does not check them unless --include-private is given, but bindings that checked modules re-export from them still count. (define dover-consider-private '(mypkg/components/email))
Unlike dover-ignore, this does not remove any bindings from the check: a binding defined in mypkg/components/email and re-exported by mypkg is still counted, and still needs documentation.
dover-never-ignore —
a list of modules that Dover always checks, even if they are in a "private" directory or listed in dover-consider-private. (define dover-never-ignore '(mypkg/private/public-api))
dover-modules —
a list of the modules to check. When present, Dover skips module discovery and dover-never-ignore and checks exactly these modules, minus any in dover-consider-private (unless --include-private is given). dover-min-coverage —
a number from 0 to 100. When coverage is below it, raco dover check exits with status 1. The --min flag overrides it.
2.6.1 Configuration in split lib/doc packages
When a package’s docs are in another package, such as a -doc package, you can put these fields in either package’s "info.rkt". Before it checks a package, Dover looks up the defmodule for each of the package’s modules in the installed docs, and reads the fields of each other package that has one of those defmodules. (A module documented only with declare-exporting doesn’t lead Dover to a package.)
Dover combines the fields from both packages:
It uses all the entries in dover-ignore and dover-consider-private.
From the package that has the docs, it uses only the entries in dover-modules and dover-never-ignore for modules in the package being checked. A package that has docs can also document other packages, or have modules of its own.
A dover-min-coverage in the package being checked wins.
The text report starts with a line that names each package with docs whose fields Dover used. The JSON report lists in config_packages each package whose fields Dover used.
2.7 Using Dover in CI
After installing your package and building its docs, run:
raco dover check --strict --min 100 mypkg-lib
For a package split into -lib and -doc packages, this command must check the -lib package since that is where the bindings are defined. Ensure the -doc package is installed before the check, so that its docs are built. The Dover fields can go in the "info.rkt" of either package; see Configuration in split lib/doc packages.