Open bbc2 opened 2 years ago
Thanks for reporting this!
Am I using the feature the way it was meant to be used? Perhaps linters produced by ppxlib are supposed to be used differently with Dune?
That's a very good question. One other way to use PPX linters would probably be to consider them normal preprocessors (using the (preprocess (pps linter))
stanza) and to see the possible warnings captured by the linter every time you build your project. Have you already tried that? Or would that break with your workflow?
Anyways, it's also a very good question why dune passes the -null
flag to the linter when using the lint
stanza. I will try to find out.
One other way to use PPX linters would probably be to consider them normal preprocessors (using the (preprocess (pps linter)) stanza) and to see the possible warnings captured by the linter every time you build your project. Have you already tried that? Or would that break with your workflow?
That's a good point. I have tried it and it works. Perhaps it's a little weird to have a linter listed along PPXs which are actually needed for compilation but that shouldn't be a big deal. In any case, I'm still interested in how the lint
stanza is supposed to be used.
We now have some more information about your question here. So I think the lint_impl
and lint_intf
arguments of the ppxlib driver are unrelated to dune's lint
stanza. My understanding now is the following:
lint_impl
and lint_intf
allow you to write a PPX that lints your code during compilation. Via them, you can generate warnings that aren't offered by the ocaml compiler. Such lint PPXs are added to the build configuration just like any other PPX: with the preprocess
stanza.
The dune lint
stanza allows you to lint a given PPX (or possibly also something else) on your code. When used, the @lint
alias will check if the PPX can be run on your code; it exits successfully returning nothing if yes and raises the first error otherwise.
I hope I've understood that correctly! If not, @jeremiedimino, please let us know.
Thank you, it makes a lot more sense to me now.
If I understand correctly, Dune lets the user choose between applying a PPX as part of the compilation (with a preprocess
stanza) or as a separate task (with the lint
stanza).
ppxlib, on the other hand, notably enables the creation of PPXs which don't transform the code but just emit warnings, with the lint_impl
and lint_intf
parameters.
I suppose that, in theory, those linters should be usable with either Dune use case (compilation or lint task). While the first use case definitely works, the second currently doesn't because ppxlib linters emit warnings and ppxlib, as pointed out in the other issue, instructs Dune to use the -null
argument for the lint
task, which silences those warnings.
While my problem is solved (I'll use Dune's preprocess
stanza), I have to wonder why ppxlib would have to tell Dune to use that -null
argument. I understand the fact that a ppxlib linter doesn't have to be used with dune build @lint
and that this @lint
target can be used with regular PPXs (not just linters), but it does seem like combining @lint
and lint_impl
/lint_intf
would be a convenient use case.
to use the
-null
argument for thelint
task, which silences those warnings.
In fact the -null
argument silences everything, not just warnings. When passing in -null
, the ppxlib driver won't do anything; as in, it won't return anything, but it will still choke on an exception.
I have to wonder why ppxlib would have to tell Dune to use that
-null
argument
If not passing in -null
, ppxlib would return the whole AST, also containing the created warnings. But when running the @lint
task, dune doesn't want anyone to process such an AST further (whereas in the @build
task it asks the compiler to do so); it just wants to know if the driver would succeed or not.
Does that resolve the doubt?
Hi there,
Just chiming in to give a bit of context. When I added the (lint ...)
field in Dune, I had two uses cases in mind:
type t [@@deriving_inline sexp] ... [@@@end]
. I did that for the Base library, so that we could benefit from ppx rewriters without having a hard dependency of ppxIf you are already using ppx rewriters, then you might as well put your linters in the preprocess
field. This way the properties are checked all the time, not just when building @lint
. But if you want to avoid a hard dependency on ppx, then the lint field comes in handy.
In this world, a linter is a pass over the AST that should just emit errors, warnings and corrections. There is no output AST: just errors, warnings and corrections. That's why we pass -null
in the lint flags.
In fact the -null argument silences everything, not just warnings. When passing in -null, the ppxlib driver won't do anything; as in, it won't return anything, but it will still choke on an exception.
Ah, so warnings being silenced by linters is not what was initially intended. Looking back at it, I should probably have used a more specific flag for linters instead of -null
.
Thanks for the context! It's very good to understand that the idea for the dune (lint ...)
field is to avoid PPX as a hard dependency. By the way, how do you reflect that in the opam file? Do you simply use with-test
? I've just had a look and there doesn't seem to be any with-lint
variable or similar.
a linter is a pass over the AST that should just emit errors, warnings and corrections.
You're right about corrections! It also emits corrections (which I didn't think about when writing my comment above). The reason why warnings get lost is that ppxlib doesn't print them itself, but it embedds them as warning attributes in the AST (which with -null
is thrown away). It shouldn't be much work though to implement a distinguishing logic that depending on the use case either puts the warnings on stderr
(which seems like should be done when using dune's (lint ...)
) or embeds the warnings into the AST (as is done currently always).
I'm not sure if this problem is most related to ppxlib or Dune but here it is. I'm trying to make a linter to be used with
dune build @lint
. I made a minimal example that I'm going to show here.Here's the dune file for the linter:
Its implementation:
The dune file of the library I'm trying to apply the linter to:
The content of
foo.ml
:When I run
dune build --verbose @lint
, I can see that the linter is indeed used:But no error is reported by Dune (exit code 0 and no output).
I noticed that Dune passes the
-null
argument to the linter, which means that only errors are shown. However, if I run the same command without the-null
argument, I get the error I expected output as a warning:Am I using the feature the way it was meant to be used? Perhaps linters produced by ppxlib are supposed to be used differently with Dune? Perhaps linters should output errors, not warnings? Perhaps Dune shouldn't add the
-null
argument?While searching for similar issues, I realized that this feature might not be quite stable yet, so maybe what I'm experiencing is currently to be expected and that there's already a plan to fix it.
Versions used: