mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-11-27 02:19:27 +03:00
181 lines
11 KiB
Markdown
181 lines
11 KiB
Markdown
# elm-review suppress
|
|
|
|
This feature comes from the frustration that it can be hard to enable a new rule. There are two choices when attempting to do so:
|
|
1. Fix all reported errors before enabling the rule. This means potentially a lot of work and/or delaying enabling the rule, which can cause new errors to be introduced in the meantime.
|
|
2. Enable the rule, but ignore the errors for the files that are being reported.
|
|
|
|
The suppression system aims to fix this problem.
|
|
|
|
There are several ways to implement this, and different tools have chosen different strategies. This document outlines
|
|
what I believed to be important, and therefore why `suppress` works the way it does. There are a lot of
|
|
trade-offs involved, so it does not get full marks everywhere, but overall I believe works pretty nicely.
|
|
|
|
### Make it easy to discern between purposefully ignored errors and temporarily suppressed errors.
|
|
|
|
This is one of the main goals of the feature. I don't think there's too much to say, except that we know have a
|
|
different system for each:
|
|
- `ignoreRule*` for the purposefully ignored errors
|
|
- the suppression system for temporarily suppressed errors
|
|
|
|
|
|
### Make it hard to introduce new errors
|
|
|
|
`elm-review` has always been very strict about requiring fixing errors that get reported (compared to tools with
|
|
[disable comments](https://jfmengels.net/disable-comments/)), and I'd like it to stay that way.
|
|
|
|
Before the suppression system, we were using the `ignoreRule*` functions for temporarily ignoring some errors,
|
|
but one of its problems was that it was possible for errors to be introduced.
|
|
|
|
The way that this feature is designed, it is at most possible to exchange an error for a rule and file with
|
|
a different error for the same rule and the same file.
|
|
|
|
I don't like that it's now easier than ever to add new suppressions, but I don't think there's a way around that.
|
|
|
|
|
|
### Make it painless to fix errors
|
|
|
|
Fixing errors is ultimately what needs to be done. I want this to be as painless as possible.
|
|
|
|
This translates to the following in practice:
|
|
- Running `elm-review` when you have fixed some errors (and no outstanding errors) will automatically update the
|
|
suppression files.
|
|
|
|
Without doing that, I foresee that the workflow would be something like the following:
|
|
- Run `npm test` (which contains `elm-review`)
|
|
- Wait for `elm-review` to fail the test suite because you fixed stuff
|
|
- Run `elm-review` with a special flag that updates the suppression files
|
|
- Run `npm test` again because you still don't know if the rest of the suite passes
|
|
- Commit and push
|
|
|
|
With the workflow above, fixing errors may feel like a punishment (it sounds like that to me), and I imagine that people
|
|
will avoid fixing issues to avoid having to go through all of this.
|
|
|
|
Instead, with the current workflow, it will more look like this:
|
|
- Run `npm test`, and suppression files get updated automatically
|
|
- At the end of your test suite, if you're running `elm-review suppress --check-after-tests`,
|
|
you are kindly asked to commit, but also notified that you don't need to run the entire suite again, since all tests passed
|
|
- Commit and push
|
|
|
|
The downsides of this approach that I can _imagine_:
|
|
- People forget to run `elm-review` and/or to commit their suppression files, which cause future unrelated PRs from including this change because they did run `elm-review`.
|
|
That's what `--check-after-tests` is for, and I hope that fixes the issue.
|
|
- People get surprised by files being updated. That's fair, but it's not too hard to let people know I'd say? 🤷
|
|
- People want to undo their changes, and therefore also undo the changes to the suppression files. Also fair, but nothing
|
|
that `git restore HEAD review/suppressed` can't solve (and it's not too hard to teach? 🤷).
|
|
|
|
When balancing these up and downsides, I consider this to be the superior approach.
|
|
|
|
|
|
### Make it easy to have an overview of suppressed errors
|
|
|
|
Having suppressed errors are nice and easy, but at some point they need to be fixed, and that will likely need some
|
|
manual work. Once someone decides to tackle the issues, they need to be able to decide how and where to get
|
|
started, meaning they need to have some kind of overview.
|
|
|
|
I decided to make the suppression files be formatted in a way that give an easy overview.
|
|
- Want to know what rules were suppressed? Look at the names of the files in `review/suppressed/`.
|
|
- Want to know in what files rule X was suppressed? Look at the related file.
|
|
- Want to tackle one of the files? Choose the first or the last one, depending on how you prefer tackling these,
|
|
as they are sorted from the most to the least suppressed errors.
|
|
- Want to tackle file Y? Delete the line manually (easy!), and now those errors will be reported.
|
|
|
|
I could have chosen to have the overview be done through CLI subcommands, and I'm not opposed to having that as well if there
|
|
is useful information we can compile for the user, but having it in a file makes it accessible (you can look at it on
|
|
GitHub, even see the history), and even actionable (removing suppressions for a file).
|
|
|
|
|
|
### Make it easy to go fix errors
|
|
|
|
A bit similar to the previous goal, but more about giving you the tools to do the job.
|
|
|
|
This translates to the following in practice:
|
|
- Being able to change the suppression files (as seen before)
|
|
- Several CLI flags to report the suppressed errors: `--unsuppress` and `--unsuppress-rules`
|
|
- The rest of the CLI flags working nicely with this system
|
|
- Running with `--fix` and `--fix-all` give you automatic fix proposals if the errors are unsuppressed (manually or not)
|
|
- Running with `--watch` automatically update the suppression files continuously
|
|
|
|
I think that editors will make this especially nice, which is why `elm-review`
|
|
[provides other tooling](https://github.com/jfmengels/node-elm-review/blob/master/documentation/tooling-integration.md)
|
|
with all the necessary information to lead users towards doing the right thing.
|
|
|
|
|
|
### Make it easy to see when more errors get suppressed
|
|
|
|
One drawback of this system is that it makes it _too_ easy to ignore new errors, and I don't want that to become easy.
|
|
When this happens, I want to push the team to at least have a discussion about whether this suppression makes sense or
|
|
if it was the developer being unnecessarily lazy.
|
|
|
|
This translates to the following in practice:
|
|
- A new line shows up in the Git diff, or the count in a line shows up as higher than before in the diff.
|
|
|
|
I believe that the most important information here is what rule was suppressed, which would be visible in the diff.
|
|
Seeing a teammate ignore `NoUnused.Variables` can be brushed off easily, but noticing them ignore `NoLeakingSecretKeys`
|
|
will likely start a discussion.
|
|
|
|
This could be improved by having the suppressed error (message, details, position, ...) in the suppressed files, as the
|
|
diff would make it clear what new error was suppressed, but that would make the suppression more fragile.
|
|
I think that the rule name is in general enough. Also, the files would become humongous with all that information.
|
|
|
|
|
|
### Celebrate fixing errors
|
|
|
|
I am always happy when I see that I or someone fixed `elm-review` issues, and I want to celebrate that effort or happy accident,
|
|
which I think/hope will make people more inclined to fix issues.
|
|
|
|
This translates to the following in practice:
|
|
- In the CLI, there is a message saying when you fixed errors.
|
|
- In the diff of a PR, you see a difference. It's best visible when all the errors for a rule and file have been fixed.
|
|
|
|
|
|
### Have consistent results
|
|
|
|
Just like pure functions are simple and predictable, I want `elm-review` to feel the same way.
|
|
So if you have the same input (project), you should get the same output (reported errors).
|
|
|
|
(Ok, with the automatically updating of suppression files, maybe we can consider that `elm-review` has a side effect...)
|
|
|
|
|
|
This mostly comes down to the handling of time. [`ember-template-lint`](https://github.com/ember-template-lint/ember-template-lint) has an interesting feature of
|
|
suppressing errors for a certain duration, before being reported [as warnings](https://github.com/jfmengels/elm-review/blob/master/documentation/design/severity-levels.md),
|
|
and before being reported as errors after some more time.
|
|
|
|
While I agree that it may push people towards fixing reported problems, I don't think it
|
|
works out (I have asked some users, but not tried it out myself though), and I imagine the following problems:
|
|
- The CI for the main branch suddenly breaks because warnings have been ignored for too long (no ownership was given) and blocks everyone
|
|
- Reported problems get snoozed like alarm clocks do, because they don't appear at a good time
|
|
- People get used to snoozing/suppressing errors, and they do it more and more when it feels easier to do so
|
|
- People wait until warnings show up to fix them, instead of actively tackling them (may still be better than in `elm-review`'s approach though, who knows)
|
|
- The project has been untouched for a while, and now running the test suite reports a bunch of errors that I need to fix, or suppress again
|
|
If I'm new to the project, I may not know that it's possible (or culturally acceptable) to re-suppress errors
|
|
|
|
Side-note on `ember-template-lint`'s approach: because the location (~line number) is part of the hash (see next section),
|
|
when you move the problematic code (by adding an unrelated import at the top of the file), you need to re-generate the
|
|
suppressions (or fix them), resetting the time it will take before the problem will be reported as a warning. Meaning that for files
|
|
that get changed a lot, it may take a very long time before the errors show up through the postponing mechanism.
|
|
|
|
|
|
### Avoid Git conflicts
|
|
|
|
I want to avoid having the changes in suppression files from causing Git conflicts.
|
|
|
|
This translates to the following in practice:
|
|
- Each file is on its own line.
|
|
|
|
This is probably one of the least successful goals. Suggestions to improve this are welcome.
|
|
|
|
[`ember-template-lint`](https://github.com/ember-template-lint/ember-template-lint) pushed this goal very far, making
|
|
suppressed error (they named them "todo") have their own file, hashed by the contents of the file (which contains error location
|
|
and suppression time, meaning it's unique in practice).
|
|
|
|
The downside I see in this approach is that it makes it really hard to have an overview of the suppressed errors left to
|
|
fix. The hash that changes at every generation of the error suppressions also defeats the consistent results goal.
|
|
|
|
|
|
---
|
|
|
|
|
|
PS: I hope you know, but it is not my intention to bash on the `ember-template-lint` project and choices.
|
|
I compare the approach against theirs because they have made courageous and interesting choices,
|
|
and because they're one of the few projects out there with a similar feature ❤,
|
|
but I want to make it clear why I didn't end up making the same choices that they did. |