-
-
Notifications
You must be signed in to change notification settings - Fork 3
Description
What the rule should do:
Report usages of specific values/functions/types/modules by name.
What problems does it solve:
Making it much easier to forbid the usage of certain elements, lowering the entry to use elm-review
.
Example of things the rule would report:
Given configuration like
RuleNameTBD.rule
[ { value = "Html.img"
, message = "Use Accessibility.img or Accessibility.decorativeImg instead of Html.img"
, details = [ "...some explanations as to why..." ]
}
]
then this rule would report references to Html.img
with the message and details defined above.
When (not) to enable this rule:
When you don't have specific things you want to forbid or move away from.
I am looking for:
I have plenty of questions around this rule, and could use a lot of feedback!
- Collision with
NoDeprecated
The NoDeprecated
rule in this same package has quite a bit of overlap with this proposal. For instance, you can forbid a function defined in your codebase by either tagging it as deprecated, or by using this rule by explicitly targeting the function by name.
Which one to use becomes a bit of an unclear decision. We can probably merge the two ideas, but then it shouldn't be called NoDeprecated
. There is definitely some overlap, but it's also not a perfect overlap.
- Need for exceptions
A common use-case for this rule is to forbid something in favor of a custom solution. For instance, you could define a new Button
module and then forbid the Html.button
function. But you would still want to support the usage of Html.button
in this one module. So each restriction likely needs to be configured with exceptions. Except that you can't use the existing Review.Rule.ignoreErrorsFor*
functions as that would make the exceptions apply to unrelated forbidden elements.
Unless you use the rule multiple times, which is possible (but potentially confusing for people who come from ESLint where that's not possible because redefining a rule overrides it).
- Suppressions
One thing that I've noticed with NoDeprecated
is that when you're using elm-review
's suppression system (which the rule is pretty much meant to), you can get a large amount of suppressions (we have over a 1000 at work), and it can be a bit hard to figure out which deprecated functions are responsible for most suppressed usages. I have a proof of concept to use --extract
to help give that insight, which could help a bit.
I'm thinking that if we have one rule with plenty of these restrictions and we suppress that, then once again it would be hard to tell which functions are still used a lot and which ones don't have any issues.
-
There probably needs quite a few configuration options to forbid functions vs types (and especially record type constructors) vs modules vs dependencies vs other things. The proposed API above only works for functions and/or types, but depending on the scope, we might want more.
These could also be split into multiple new rules. -
Maybe I'm overthinking or over-engineering this rule, and it would be nice to have a simpler rule (or way of writing this rule), for instance that would only forbid a single element. But that then becomes annoying if you have plenty of related functions you want to forbid.
-
I also need a good rule name.
I'm thinking NoForbiddenReferences
or something. I do find the double negation a bit confusing though, so maybe only ForbiddenReferences
.
ESLint has multiple "no-restricted-*" rules, like "no-restrict-syntax" and "no-restricted-globals" which are close. But I have found the name very confusing for years.
That said, if we decide to limit this rule to forbidding a single element, then the rule name should likely be configurable by the user of the rule, as that is a somewhat important part of an elm-review
error. But the module containing this rule would still need to be named 😄
- I'm thinking I could in the documentation of the rule show the entire implementation of the rule, so that if someone wants to extend the rule a bit, then they can easily do so with that example as the source code. Does that sound like a good idea?
Thoughts and ideas welcome 🙏