Open source contributions
I added push and pop directives to RuboCop, the Ruby linter and formatter, then fixed two bugs in them and an indentation regression. All four pull requests are merged. I also maintain a fork of tree-sitter-ruby, the Ruby grammar for the tree-sitter parser generator.
- Projects
- RuboCop, tree-sitter-ruby
- Merged pull requests
- 4 (RuboCop)
- Merge dates
- Dec 2025 to Jan 2026
- Fork
- tree-sitter-ruby
- Languages
- Ruby, C, JavaScript
| Pull request | Change | Status |
|---|---|---|
| RuboCop #14633 | Push and pop directives | Merged Dec 2025 |
| RuboCop #14774 | Push arguments no longer read as enable comments | Merged Jan 2026 |
| RuboCop #14814 | Nested scopes and department names in push and pop | Merged Jan 2026 |
| RuboCop #14818 | Indentation regression in RuboCop 1.84.0 | Merged Jan 2026 |
Push and pop directives
RuboCop runs checks called cops, and comments switch them off and on for part of a file: # rubocop:disable Style/For, then # rubocop:enable Style/For. These comments are switches, not scopes. An enable turns the cop on whatever its state was before, so a pair placed inside a region where the cop is already off turns it back on too early, and every pair repeats the cop names. Issue #13854, “disable/enable is too imperative”, asked for a stack instead.
With push and pop, push saves the state of the cops and can change some of them on the same line, and pop restores whatever was saved. A - before a cop name disables it and a + enables it. This example is from the RuboCop documentation:
# rubocop:disable Style/For
for x in [1, 2, 3]
puts x
end
# rubocop:push +Style/For -Style/GuardClause
for y in [4, 5, 6] # Style/For is re-enabled here
if y > 0
return y # Style/GuardClause is disabled here
end
end
# rubocop:pop
# Back to original state: Style/For disabled, Style/GuardClause enabledPull request #14633 changed eight files:
- Added
pushandpopto the directive parser, with optional+and-arguments. - Made the analysis of directive comments keep a stack:
pushsaves the state of every cop and applies its arguments,popends the scope and restores the saved state. - Kept
Lint/RedundantCopDisableDirectivefrom reporting push and pop comments, and added the new modes to the message ofLint/CopDirectiveSyntax. - Documented the directives, with nested examples.
- Added specs for ten scenarios, from one disabled cop to nested scopes and inline arguments.
Three follow-up fixes
Two fix push and pop themselves; the third fixes a regression in Layout/IndentationWidth that RuboCop 1.84.0 introduced.
Push arguments read as enable comments
After #14633, Lint/RedundantCopEnableDirective reported # rubocop:push -Style/GuardClause as an unnecessary enabling of a cop named -Style/GuardClause. The method that collects enable comments did not skip push and pop, so the argument took the path of an enable directive. I added a guard that skips them, a regression test, and the changelog entry for #14633.
Nested scopes and department names
My first implementation did not always restore the intermediate state of nested push and pop blocks, and department names such as +Metrics or -Style in push arguments did not work. I reworked the push and pop handling: department names now expand to every cop in the department, each push saves the cops it changes, and pop ends the scope on the line before it and resumes an earlier disabled state from its own line. I updated the specs to check the state of each cop line by line, including nested blocks and departments.
An indentation regression in RuboCop 1.84.0
In RuboCop 1.84.0, Layout/IndentationWidth measured the body of a block that follows a multi-line method chain from the column of the closing brace or end, and reported correctly indented code (issue #14805). I changed the base back to the dot of the chain whenever that dot starts its own line, whatever the EnforcedStyleAlignWith setting, which brings back the indentation from before 1.84.0. I added specs for brace and do blocks after a multi-line chain and for a long receiver, and updated an autocorrect spec.
My tree-sitter-ruby fork
tree-sitter-ruby is the Ruby grammar for tree-sitter, a parser generator that editors use for syntax highlighting and code navigation. My fork, Magikdidi24/tree-sitter-ruby, adds:
- Ruby 3.0+ syntax: endless methods whose body is a command call without parentheses, such as
def a1 = puts 1, lambda parameters with block-local variables, as in->(;a) { a = 1 },returnfollowed by parenthesized values, and a range left open at the end of a line. - Fixes in the hand-written C scanner for heredocs, regular expressions, percent literals, unary arguments and comments inside ERB templates, several of them for issues reported on the original repository.
- A differential check that parses the ruby/spec test suite with both tree-sitter and Prism, Ruby's own parser, and lists where they disagree.
- Build and CI updated for the tree-sitter CLI 0.27.1, and 878 new lines of test cases in the grammar's corpus, which pair a Ruby snippet with the syntax tree the parser must produce.