[Feature] Allow rule to be disabled by comment#249
Conversation
f9b67b2 to
0bb0edd
Compare
This comment was marked as outdated.
This comment was marked as outdated.
0bb0edd to
b7c8b67
Compare
koddsson
left a comment
There was a problem hiding this comment.
This is really cool!
@rafaelfranca; what do you think about this change? I know @khiga8 wants to clean it up a bit more if this is something we want to merge so comments and feedback on an approach would be really cool.
|
Feature makes sense to me. Do you want to bring this to the finish line? |
|
Sure, I'd love to bring it to finish line. I will probably just clean up the messy code in Does the current approach seem ok? I prioritized making non-breaking changes, so there are some inefficiencies. I also want to get your thoughts on the disable comment placement and format. Currently it's set up so the disable comment can be placed on preceding line or any part of offending line: 1. Comment on offending lines<hr /> <%# erblint:disable SelfClosingTag %>2. Comment on previous line<%# erblint:disable SelfClosingTag %>
<hr />I just had a look at rubocop disable comment guide, and eslint disable comment guide, both of which take different disable comment approaches. Do we want to align with either of those? Can you think of any weirdness that could emerge from this format approach, especially when considering we might want to support something like file-level disables? |
|
@rafaelfranca This is ready for another look 🙇♀️ |
|
I think we should align with rubocop in this case. |
|
I decided to remove support for comment on previous lines, so we only have support for disable comment on any part of the offending lines. This is somewhat similar to Rubocop:
However, with, we may have offenses that span more than one line, so we allow comment to be on any part of the offending lines. Rubocop has support for formats like This is ready for another review! cc: @rafaelfranca |
This comment was marked as resolved.
This comment was marked as resolved.
9e4f8b0 to
85fe954
Compare
This commit introduces a `run_and_clear_ignored_offenses` method which
filters out offenses which may include a comment in the format
```
<%# erblint:disable #{offense.linter.simple_class_name} %>
```
as either part of the offending lines, or as a comment in the previous line.
This commit adds support for the no_unused_disable linter. This can be configured in `erb-lint.yml`. If there are any unnecessary disable statements, these will be reported. This is a special linter that must run after all other linters.
| end | ||
| end | ||
|
|
||
| context "with --disable-inline-configs" do |
There was a problem hiding this comment.
I introduced a new config.
|
Made the following updates since the last time this was formally reviewed.
I would like there to be a command we can run to automate adding inline disables in the relevant places but I think that should be done in a separate PR. This is ready for another review! |
spec/spec_helper.rb
Outdated
|
|
||
| require "erb_lint/all" | ||
|
|
||
| def source_range_for_code(processed_source, code) |
There was a problem hiding this comment.
This is adding this method to all objects. Let's add it to a module and call it from the module instead
|
The only thing that I don't think I understood is why we are using |
I think the distinction helps when turning off a rule for the whole file vs, just on a line. Having the extra functionality of file/line would let us also support this case: I was thinking in a follow up, we could add |
What @jonrohan said! If you have a different suggestion or would like to talk this through, let me know! |
|
erblint is modelled after rubocop. Rubocop uses the same disable directive for line and block. Did you find any reason why we need two different directives for line and block disabling? |
Ah, ok. Deep down I felt like the eslint system was more flexible/functional, but didn't have an understanding on rubocop's stance on this. I found this PR/thread that the rubocop contributors responded to and now I feel like it's best to stick with what they do. 👍🏻 Sorry for the code review flip flopping here @khiga8 |
I'm fine aligning with Rubocop too. Swapped it back to |
This PR makes possible to disable a rule in a erb line. The implementation follows the [Standard way](https://github.com/standardrb/standard?tab=readme-ov-file#ignoring-errors) to disable rules, in the same way that [ERBLint allows to disable rules inline](https://github.com/Shopify/erb_lint?tab=readme-ov-file#disable-rule-at-offense-level). The implementation is very similar this [pull request](Shopify/erb_lint#249). The strategy consist of 1. Use a regex to see which line skipped rules with the `<%# herb:disable some-rule %>` syntax 2. Partition the offenses collected by the visitor based on the rules that where disabled for each line. 3. Report in the reporters the number of offenses. Here is a screenshot of how the implementation looks in the Linter CLI. ```erb <div> <h1 class="<%= classes %>"> <%= title %> </h1> <DIV>hello</DIV> <DIV>hello</DIV> <%# herb:disable html-tag-name-lowercase %> <% %> <%# herb:disable erb-no-empty-tags %> </div> ``` <img width="790" height="620" alt="image" src="https://github.com/user-attachments/assets/e38c35bd-f96c-455a-b4a1-5818c05c5c3a" /> Future work: - Be able to skip the skipped lines (useful when we want to find where are the rules skipped). - Allow the LSP to make a code action with an autocorrect that adds the line skipping. - Allow disable multiple rules in one line (this should be pretty straightforward in a follow up PR). - Add another linter rule to avoid putting disable comments that not disable anything (like erb_lint NoUnusedDisable). Resolves #270
…th#531) This PR makes possible to disable a rule in a erb line. The implementation follows the [Standard way](https://github.com/standardrb/standard?tab=readme-ov-file#ignoring-errors) to disable rules, in the same way that [ERBLint allows to disable rules inline](https://github.com/Shopify/erb_lint?tab=readme-ov-file#disable-rule-at-offense-level). The implementation is very similar this [pull request](Shopify/erb_lint#249). The strategy consist of 1. Use a regex to see which line skipped rules with the `<%# herb:disable some-rule %>` syntax 2. Partition the offenses collected by the visitor based on the rules that where disabled for each line. 3. Report in the reporters the number of offenses. Here is a screenshot of how the implementation looks in the Linter CLI. ```erb <div> <h1 class="<%= classes %>"> <%= title %> </h1> <DIV>hello</DIV> <DIV>hello</DIV> <%# herb:disable html-tag-name-lowercase %> <% %> <%# herb:disable erb-no-empty-tags %> </div> ``` <img width="790" height="620" alt="image" src="https://github.com/user-attachments/assets/e38c35bd-f96c-455a-b4a1-5818c05c5c3a" /> Future work: - Be able to skip the skipped lines (useful when we want to find where are the rules skipped). - Allow the LSP to make a code action with an autocorrect that adds the line skipping. - Allow disable multiple rules in one line (this should be pretty straightforward in a follow up PR). - Add another linter rule to avoid putting disable comments that not disable anything (like erb_lint NoUnusedDisable). Resolves marcoroth#270

Fixes: #243
Context
For codebases with a lot of violations of a certain rule, it would be helpful to allow rules to be disabled on a per violation basis so that the violations can be progressively addressed while preventing new violations from being introduced.
For example, rubocop allows rules to be disabled with comments:
Proposal
We allow offenses to be ignored when there is a disable comment appearing as part of the lines spanning the reported offense.
examples
Offenses that include a disable comment on offending lines will be ignored.
We also allow multiple rule disables:
This also introduces
NoUnusedDisablelint rule which can be configured to detect any unused disable comments.Approach
This PR aims for backward compatibility. Consequently, we only update
linter.rbandrunner.rbso no changes should be required for existing custom rules that consumers may have created following how rules have been defined in this repo.We introduce
run_and_set_offense_statusmethod which will be called by theERBLint::Runnerinstead ofrun. This method will calllinter.runand then set status ofoffensebased on comment criteria described above.When
NoUnusedDisableis enabled, it runs inrunner.rbafter all other linters have ran. Then it will go through the file and report any unused disable comments.What should reviewers focus on?
I went with what seems like a backward-compatible approach though it may not be the most efficient. Open to thoughts. I'd appreciate any feedback. Is the logic for how we decide to ignore an offense sufficient?
To do