Fix TLetCorrection corrupting files with interior heredocs - #387
Open
dduugg wants to merge 2 commits into
Open
Conversation
…ior heredocs TLetCorrection re-appended every heredoc in the value when unwrapping T.let. That is only correct for a heredoc at the tail of the value, whose body sits past the value node's source range. An interior heredoc — one followed by more of the value, e.g. `Foo.new(a: <<~X, b: 2)` — already lives inside `value_node.source`, so re-appending duplicated its body and corrupted the file. Only reattach tail heredocs.
Shorten the tail_heredocs and interior-heredoc test comments to match the concise, 2-3 line style used by sibling comments elsewhere in this file and the surrounding test file.
dduugg
marked this pull request as ready for review
July 20, 2026 23:15
KaanOzkan
reviewed
Jul 27, 2026
| def replace_t_let(corrector, t_let_node, value_node) | ||
| heredocs = value_node.each_node(:any_str).select(&:heredoc?) | ||
| heredocs = tail_heredocs(value_node) | ||
| return corrector.replace(t_let_node, value_node.source) if heredocs.empty? |
Contributor
There was a problem hiding this comment.
Nit: if heredocs.empty? reads funny. Can we either change the variable name (heredocs_to_reattach?) or add a comment to indicate these heredocs require special handling.
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.
Problem
TLetCorrection(shared bySorbet/RedundantTLetandSorbet/RedundantTLetForLiteral) corrupts files when theT.letvalue contains an interior heredoc — one that is followed by more of the value's own source.The mixin was written for heredocs at the tail of the value, where
value_node.sourcestops at the marker and the body must be reattached. But when a heredoc sits in the interior of a larger value (e.g. a constructor call that continues after the heredoc),value_node.sourcealready contains the heredoc body inline, so reattaching it duplicates the body.Minimal repro:
Autocorrect currently produces a duplicated, syntactically broken body:
Fix
Only reattach heredocs whose body/terminator extend past the value node's own source range (the tail heredocs). Interior heredocs already live inside
value_node.source, so the plaincorrector.replace(t_let_node, value_node.source)path handles them correctly.Tests
Added
test_offense_on_constant_constructor_with_interior_heredoccovering the case above. Full suite green (bundle exec rake test).