Lint
Description
Shows the warnings, notes and hints of the compiler for your sources, and fails on the ones you choose, so it can be used as a gate in a CI. Free Pascal has no standard linter, but with its messages on the compiler already reports uninitialized variables and results, unused units, parameters and variables, unreachable code, lossy conversions and more.
Example:
pasc lint
Building with warnings as errors (-Sew) does not work in a workspace: boss installs the dependencies as sources in modules, and they are compiled with the project, so the build stops in code that is not yours. pasc lint filters the messages by file after the compiler runs instead:
It builds the project in the current folder and its test project, or at the root of a workspace every member and its test project, with
lazbuild -B, so every unit is compiled again and repeats its messages. The output goes to lib/lint, so the normal build is not touched.It keeps the messages for the sources of each member, its folders without lib, backup and modules, and leaves out the ones for the modules and for the units of FPC and Lazarus. Errors are always shown, wherever they are, because they stop the build. The messages of the linker, the assembler and the resources (9000 to 9999) are not about the code and are left out.
Like pasc test lists every test, it lists every source file of the member that was compiled: OK when it has no message, or the kind of its most severe message, with its messages below, by line. A failing message has the whole file:line:col, which editors and terminals turn into a link. Then a summary per member and for the workspace.
Linting apps/cmd
OK cmd.lpr
Warning src/commands/Command.Count.pas
apps/cmd/src/commands/Command.Count.pas:38:19 (5093) function result variable of a managed type does not seem to be initialized
OK src/commands/Command.Greet.pas
OK tests/Testcmd.lpr
OK tests/TestCommandCount.pas
OK tests/TestCommandGreet.pas
Hint tests/TestOutput.pas
25:58 (5024) Parameter "AColor" not used
Summary apps/cmd: 7 files, 5 OK, 1 warning, 1 hint, 1 failing
The exit code is 1 when a message fails or a project could not be built. Then the summary says why, like the first error of the compiler.
Rules
Besides the messages of the compiler, pasc lint has rules of its own, for what the compiler does not report. The sources of each member are parsed with fcl-passrc, the Pascal parser that comes with Free Pascal, also used by fpdoc and pas2js, so they need nothing else. Each rule has an id, and its findings go through the same configuration and output as the messages of the compiler, with the id in place of the number. The parser gives the line of each element but not its column, so a finding is at column 1.
id |
kind |
what it reports |
|---|---|---|
PL001 |
note |
A with statement, which hides where each identifier comes from. |
PL002 |
warning |
An empty except block, or an on handler without statements, which silently ignores the exception. |
PL003 |
warning |
A destructor that does not call inherited, so the parent does not free what it holds. |
PL004 |
hint |
A routine longer than 80 lines, its header included. |
PL005 |
hint |
A routine with more than 6 parameters. |
PL006 |
hint |
Statements nested more than 4 levels deep, in if, case, loops, try and with. Once per routine. |
PL000 |
note |
A source that the parser could not read, with the reason. The compiler still checks it. |
The limits of PL004, PL005 and PL006 are in pasc.json:
"lint": { "rules": { "PL004": { "max": 60 }, "PL006": { "max": 3 } } }
A finding can be turned off in the code with a comment on its line, or on the line above, with the ids of the rules or the numbers of the messages of the compiler:
except // pasc-lint: ignore PL002 // nothing to do: the file may not exist yet end;
Configuration
By default warnings fail, and notes and hints are shown. In the pasc.json of the workspace:
"lint": {
"ignore": [5024],
"fail": ["warning", 5091],
"members": {
"web": { "ignore": [5024, 5023] }
}
}
ignore leaves messages out, by kind (error, warning, note, hint), by number, or by rule, like PL001. Errors can not be ignored.
fail says what makes the command exit with 1, by kind, by number or by rule, so a single hint can fail too. It replaces the default.
rules has the limits of the rules, see above.
members has the configuration of a member, by name or by folder, like apps/web. Its ignore is added to the one of the workspace, its fail, when present, replaces it, and so do its limits. A web app with Horse handlers, for example, has parameters it does not use, required by the signature of the handler, so it can ignore 5024 alone.
The number of each message is in the output, between parentheses, and the complete list is in the Free Pascal documentation, or in the msg folder of the compiler sources.
Report
–report=<file> writes the totals as JSON, for a CI or a badge, without changing the output or the exit code:
pasc lint --report=lint.json
{
"files" : 21,
"ok" : 15,
"errors" : 0,
"warnings" : 1,
"notes" : 0,
"hints" : 8,
"ignored" : 0,
"failing" : 1,
"notLinted" : 0
}
The lint badge of the pasc README is made from this report: its CI writes the kinds with messages, and a color, to the JSON that shields.io reads.
Next New Command |
|---|
Generated by PasDoc 1.0.4.