Repository navigation
fix(ruby): keep a wrapped chain indented inside a block that is a hash value - #43
Merged
Merged
Conversation
…h value RuboCop 1.84 through 1.91 make Layout/MultilineMethodCallIndentation search upward for an enclosing hash pair without stopping at a block, so a chain inside a lambda, proc, do block, begin, if or loop that is a hash value is aligned as if it were the value itself - flush under its receiver. A boot-time patch stops that search where the body starts, which restores the indent RuboCop 1.82 gave these chains, and leaves a chain that is itself the hash value aligned exactly as stock 1.91 aligns it. Tests cover the reported shape, each body the patch handles, the case it must leave alone, a version guard on the RuboCop it was derived from, and a conformance check that native RuboCop still flattens these shapes while we differ from it only in that indentation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XSYkhEutUrPqAdCqYSZ9vv
…oCop 1.84.1 RuboCop 1.84.0 still indents a chain inside a block that is a hash value; the regression arrived in 1.84.1 with the fix for rubocop/rubocop#11513.
The MultilineMethodCallIndentation regression the patch works around is reported as rubocop/rubocop#15761, which is what to watch before retiring it.
cameronrohani
approved these changes
Sep 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
The RuboCop 1.91.0 bump (#40) introduced a regression in the Layout pass. A wrapped method chain inside a block that is a hash value lost the indentation on every continuation line:
The cause is upstream. Since 1.84.1,
Layout/MultilineMethodCallIndentationsearches upward from a chain for an enclosing hash pair, and that search doesn't stop at a block body. So the chain inside the lambda is treated as the value ofrun:and aligned with its receiver. It still reproduces on RuboCop's current master. It's reported as rubocop/rubocop#15761, with the same fix proposed upstream.This PR adds
packages/ruby/src/rubocop-patch.ts, which is applied at VM boot the same way as the existing syntax_tree fixes. The artifact itself is not rebuilt.begin,if/elseor loop body starts. Those chains go back to the indentation RuboCop 1.84.0 gave them.key: foo.barwrapped onto the next line) is still aligned exactly as stock 1.91.0 aligns it.caseanddefbodies are deliberately left to stock. On the fallback path RuboCop has an older, separate misalignment there, so routing them to it would look worse.Which packages
packages/ruby, plus the rootREADME.md.Exactness
The reference tool is still RuboCop 1.91.0. This adds one output-changing fix, so the README status moves from
exact +3 fixestoexact +4 fixes, and both READMEs describe what diverges and why. The divergence is held narrow in three ways:test/rubocop-conformance.test.tsstill asserts byte-identical output against the nativerubocop1.91.0 binary for every other sample. That includes two new ones where the chain is the hash value, which the patch must leave alone.src/rubocop-patch.test.tsfails if the VM reports any RuboCop other than 1.91.0. That way a pin bump can't leave a stale copy of the method overriding the new gem.I also ran syntax_tree's output of 1,238 files through native
rubocop --autocorrect --only Layoutwith and without the patch: rubocop 1.91's lib and specs, rubocop-ast, syntax_tree, parser and regexp_parser. Every file came out the same both ways. The patch only fires on the nested-body shapes above.How it was validated
bun run check(the only warnings are 3 that were already onmain)bun run types:checkbun run test: all packages pass. Ruby's 89 tests include the native syntax_tree and RuboCop conformance tests against native gems at the pinned versions.bun run test:node: ran forpackages/rubyonly. Its entry points and exports haven't changed, but the boot now evaluates one more patch.Each new test fails with the patch disabled, except the one that checks a chain that is itself the hash value, which passes either way by design.
Changeset
@scalar/ruby-fmt: patch)Generated by Claude Code