Hey all,
Last weekend I’ve written two little packages that may be useful for others in the audience:
diagnostics.pl and flymake-swi-prolog.el
diagnostics.pl
is a SWI-Prolog packge providing a simple and
extensible interface for linting Prolog source code and emitting
diagnostic messages. It builds upon the comprehensive analysis
performed by the built-in prolog_colourise_stream/3
and
xref_source/1
to diagnose issues in a given source file.
This package is intended to further expose the detailed diagnosis that is available
to the user when working with the SWI-Prolog built-in IDE to be
consumed by different targets for different needs.
The default diagnosis provided can be extended and customized by defining the
multifile
predicate diagnostics:diagnosis_hook/3
(refer to the documentation
for the specifics). Moreover, diagnostics are reported via
print_message/2 and can thus be intercepted and handled in arbitrary
manners via the built-in message_hook/3.
The two main use-cases of diagnostics.pl
are:
Linting code in CI
diagnostics.pl
can be executed from the command line to diagnose and
report on issues during CI. Let’s say we have the following code in a file called /tmp/spam.pl
:
:- module(foo, [bar/2]).
bar(A, A) :-
baz(A).
bar(_).
Note the typo in the body of bar/2
- we want to call bar/1
but we
accidentally typed baz
instead of bar
.
We can run diagnostics.pl
to catch such issues by running:
➜ swipl -q -g "use_module(library(diagnostics))" -t halt -- /tmp/spam.pl
ERROR: /tmp/spam.pl:3:
ERROR: /tmp/spam.pl:43:3: Undefined predicate baz/1
Warning: /tmp/spam.pl:6:
Warning: /tmp/spam.pl:52:3: Unreferenced definition for bar/1
For an example of incorporating such a step in CI, check out the CI process of
ropes.pl
which
uses diagnostics.pl
to check for errors whenever a new commit is
pushed to the package’s repository.
One can run swipl
with the --on-error=status
and --on-warning=status
command line options set to have the process to fail (potentially failing the CI run) when diagnostics are
reported.
Diagnosing issues within an IDE during development
The other major use case for diagnostics.pl
is allowing different user
interfaces to consume and display diagnostics on the fly in a way that
mirrors the SWI-Prolog built-in IDE, which brings us to the other
package mentioned above - flymake-swi-prolog.el
.
flymake-swi-prolog
is an Emacs Lisp package I’ve written along with
diagnostics.pl
to integrate the Prolog diagnostic messages with
Flymake, the built-in diagnostics infrastructure in GNU Emacs.
Here’s what the aforementioned erroneous code looks like with flymake-swi-prolog
enabled:
And here’s how it looks immediately after fixing the typo:
flymake-swi-prolog
is available from the Emacs package archive
MELPA, so installation is trivial, check out the project’s README for more
information.
Important note: on-the-fly diagnostics for IDEs can also
be obtained from an LSP server, and some are indeed provided by
lsp_server – diagnostics.pl
does not aim to compete with such servers, instead, it aims to be a
layer that the LSP server and other programs can build upon.
Cheers