Stop the generator reading commented-out code - #28
Open
VSN2015 wants to merge 1 commit into
Open
Conversation
VSN2015
commented
Sep 5, 2026
| # `#{}` interpolation, and a permit call inside interpolation IS live code. | ||
| # String CONTENT is deliberately kept: `permit("name")` is a supported | ||
| # spelling, and its keys live in string tokens. | ||
| COMMENT_TOKENS = %i[on_comment on_embdoc on_embdoc_beg on_embdoc_end].freeze |
Owner
Author
There was a problem hiding this comment.
Targeting on_comment, on_embdoc, on_embdoc_beg, and on_embdoc_end handles both standard # comments and =begin/=end documentation blocks.
| tokens = Ripper.lex(source) | ||
| return source if tokens.nil? || tokens.empty? | ||
|
|
||
| tokens.reject { |token| COMMENT_TOKENS.include?(token[1]) }.map { |token| token[2] }.join |
Owner
Author
There was a problem hiding this comment.
Rescuing StandardError and falling back to raw source ensures that files with unusual syntax errors still draft as best as possible rather than failing outright.
A controller keeping a line for reference:
def create
# Legacy: params.require(:admin).permit(:superuser)
params.require(:user).permit(:name)
end
drafted root: :admin and a :superuser field. Both came from a line that
does not execute, and both are wrong — the second in a
security-flavoured way, since the draft then suggests permitting a
privilege escalation parameter. =begin/=end blocks and trailing
comments on live lines had the same effect.
Comments are removed before scanning, with Ripper rather than a
regexp, because `#` is only sometimes a comment. Two consequences the
regexp approach would get wrong, and which specs now pin:
* A permit call inside #{...} interpolation IS live code, and is still
read.
* String CONTENT is deliberately kept. permit("name") is a supported
spelling and its keys live in string tokens, so dropping string
bodies — the obvious next step — would silently lose them.
Ripper is stdlib, so no dependency is added, and a file it cannot lex
falls back to the raw source: a syntactically odd controller scans
exactly as it did before rather than not at all.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
VSN2015
force-pushed
the
fix/generator-ignores-comments
branch
from
September 11, 2026 22:01
5e4bd12 to
4a5cfea
Compare
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.
The bug
A controller keeping a line for reference:
drafted:
Both
:adminand:superusercame from a line that does not execute. The wrong root is annoying; draftingsuperuseras a permitted parameter is the kind of wrong suggestion that shouldn't survive a review, and shouldn't have been offered in the first place.=begin/=endblocks and trailing comments on live lines had the same effect.Why
Ripperand not a regexp#is only sometimes a comment. Two cases a regexp gets wrong, both now pinned by specs:#{...}interpolation is live code and is still read.permit("name")is a supported spelling and its keys live in string tokens — so dropping string bodies, which is the obvious next step after dropping comments, would silently lose them. That one nearly caught me: the first version of this fix droppedon_tstring_contenttoo.Ripperis stdlib, so no dependency is added (the gem's one-runtime-dependency claim is untouched, and #14'sruntime-depsjob would catch it if it weren't).The fallback
A file
Rippercannot lex falls back to the raw source, so a syntactically odd controller scans exactly as it did before rather than not at all. There's a spec for that too.Verification
=begin/=end, a#inside a string, quoted permit keys, and the unlexable fallback