Skip to content

[bot] Fix Rails/Blank#212

Merged
6[bot] merged 2 commits intomainfrom
fix/rails-blank-23576652976
Mar 26, 2026
Merged

[bot] Fix Rails/Blank#212
6[bot] merged 2 commits intomainfrom
fix/rails-blank-23576652976

Conversation

@6
Copy link
Copy Markdown
Contributor

@6 6 bot commented Mar 26, 2026

Automated fix fix for Rails/Blank corpus conformance.

Refs #160

Details

Cop Rails/Blank
Backend codex / hard
Model gpt-5.4 (xhigh)
Mode fix
Turns 1
Run #108

Result

Updated [blank.rs](/home/runner/work/nitrocop/nitrocop/src/cop/rails/blank.rs#L94) so `Rails/Blank` preserves the original `OrNode` source text in `NilOrEmpty` messages instead of reconstructing everything as `||`. That fixes RuboCop-compatible messaging for `or` and `not` forms like `name.nil? or name.empty?` and `not @params or @params.empty?`. I also corrected and extended the fixture cases in [offense.rb](/home/runner/work/nitrocop/nitrocop/tests/fixtures/cops/rails/blank/offense.rb#L44), including the missing `not @params ...` corpus example.

`cargo test --lib -- cop::rails::blank` passes. I also verified all 14 known FN corpus locations by linting those files explicitly under the corpus config; all 14 now hit. I did run the required `python3 scripts/check_cop.py Rails/Blank --rerun --clone --sample 15`, but I did not commit because that gate still reports `+2 FN` on `liaoziyang__stackneveroverflow__8f4dce2` (`local=55, baseline_nc=57`). The follow-up debugging shows the fixed vendored files are detected when passed explicitly, but the repo-scan count gate excludes `vendor/**/*`, so that remaining mismatch appears to be in repo/file-discovery behavior rather than in [blank.rs](/home/runner/work/nitrocop/nitrocop/src/cop/rails/blank.rs) itself.

Changes

  2 files changed
Agent conversation excerpt

Reading the CI guidance and the Rails/Blank implementation first, then I’ll add an FN fixture that reproduces the missed or cases before touching the cop logic.

Reading the CI guidance and the Rails/Blank implementation first, then I’ll add an FN fixture that reproduces the missed or cases before touching the cop logic.

exec_command: sed -n '1,220p' docs/agent-ci.md

exec_command: sed -n '1,240p' src/cop/rails/blank.rs

exec_command: sed -n '1,240p' tests/fixtures/cops/rails/blank/offense.rb

exec_command: sed -n '1,260p' tests/fixtures/cops/rails/blank/no_offense.rb

exec_command: sed -n '1,240p' vendor/rubocop-rails/lib/rubocop/cop/rails/blank.rb

exec_command: sed -n '1,260p' vendor/rubocop-rails/spec/rubocop/cop/rails/blank_spec.rb

The cop already has the corpus-derived FN snippets in its fixture, so I’m checking whether the current failure is the or parsing path or a narrower AST shape issue in the implementation.

The cop already has the corpus-derived FN snippets in its fixture, so I’m checking whether the current failure is the or parsing path or a narrower AST shape issue in the implementation.

exec_command: sed -n '241,420p' src/cop/rails/blank.rs

exec_command: cargo test --lib -- cop::rails::blank

exec_command: ruby -e 'require "prism"; src=%q{if elements.nil? or elements.empty? then\nend\n}; pp Prism.parse(src).value.statements.body[0].predicate.class; pp Prism.parse(src).value.statements.body[0].predicate.

exec_command: sed -n '421,520p' src/cop/rails/blank.rs

I’ve confirmed Prism parses or into a normal OrNode, so this likely isn’t a parser limitation. Next I’m checking the actual failing assertions to see whether the issue is message/range generation or a missed receiver shape.

I’ve confirmed Prism parses or into a normal OrNode, so this likely isn’t a parser limitation. Next I’m checking the actual failing assertions to see whether the issue is message/range generation or a missed receiver shape.

write_stdin: ``

The current cop is already finding the new or examples, but not with RuboCop-compatible ranges/messages. I’m comparing against RuboCop directly now so the fix targets the exact offense span and preserves or vs || text from source.

The current cop is already finding the new or examples, but not with RuboCop-compatible ranges/messages. I’m comparing against RuboCop directly now so the fix targets the exact offense span and preserves or vs || text from source.

exec_command: printf '%s ' 'if elements.nil? or elements.empty? then' 'end' > /tmp/rails_blank_if_or.rb && rubocop --only Rails/Blank /tmp/rails_blank_if_or.rb

exec_command: printf '%s ' 'return if name.nil? or name.empty?' > /tmp/rails_blank_return_or.rb && rubocop --only Rails/Blank /tmp/rails_blank_return_or.rb

exec_command: printf '%s ' 'abbrev = __is_abbrev(line) unless line.nil? || line.empty?' > /tmp/rails_blank_unless_or.rb && rubocop --only Rails/Blank /tmp/rails_blank_unless_or.rb

exec_command: rg -n "struct Diagnostic|fn diagnostic\(" src -g '*.rs'

exec_command: sed -n '1,220p' src/diagnostic.rs

exec_command: rg -n "\bor\b|\|\|" vendor/rubocop-rails/spec/rubocop/cop/rails/blank_spec.rb

exec_command: sed -n '260,460p' src/testutil.rs

exec_command: bundle exec rubocop --require rubocop-rails --only Rails/Blank /tmp/rails_blank_if_or.rb

exec_command: bundle exec rubocop --require rubocop-rails --only Rails/Blank /tmp/rails_blank_unless_or.rb

Rubocop wasn’t available from the repo root, so I’m using the project’s bundled Ruby environment next. I’ve also confirmed the fixture harness only validates line, column, and message, which fits the location mismatch we’re seeing.

Rubocop wasn’t available from the repo root, so I’m using the project’s bundled Ruby environment next. I’ve also confirmed the fixture harness only validates line, column, and message, which fits the location mismatch we’re seeing.

exec_command: rg --files -g 'Gemfile' -g '.rubocop.yml'

exec_command: cd bench/corpus && BUNDLE_PATH=vendor/bundle bundle exec rubocop --require rubocop-rails --only Rails/Blank /tmp/rails_blank_if_or.rb

exec_command: cd bench/corpus && BUNDLE_PATH=vendor/bundle bundle exec rubocop --require rubocop-rails --only Rails/Blank /tmp/rails_blank_return_or.rb

exec_command: cd bench/corpus && BUNDLE_PATH=vendor/bundle bundle exec rubocop --require rubocop-rails --only Rails/Blank /tmp/rails_blank_unless_or.rb

write_stdin: ``

write_stdin: ``

write_stdin: ``

RuboCop confirms the if ... or ... case should start at the condition column, not column 0, so the fixture snippet in the prompt was only approximate. The remaining real gap is that nitrocop normalizes or to || in messages, which can cause corpus mismatches even when the node is found.

RuboCop confirms the if ... or ... case should start at the condition column, not column 0, so the fixture snippet in the prompt was only approximate. The remaining real gap is that nitrocop normalizes or to || in messages, which can cause corpus mismatches even when the node is found.

exec_command: rg -n "force-default-config|--only|format json|debug" src scripts Cargo.toml

exec_command: cargo run -- --help

exec_command: sed -n '260,340p' src/cop/mod.rs

write_stdin: ``

write_stdin: ``

write_stdin:

I’ve confirmed the main likely logic bug: check_nil_or_empty hardcodes || in its message even when the source uses or. I’m probing a couple of chained cases next, because those are the patterns most likely to explain the remaining 14 corpus misses.

I’ve confirmed the main likely logic bug: check_nil_or_empty hardcodes || in its message even when the source uses or. I’m probing a couple of chained cases next, because those are the patterns most likely to explain the remaining 14 corpus misses.

exec_command: ls target/debug/nitrocop target-linux/debug/nitrocop 2>/dev/null

exec_command: ruby -e 'require "prism"; src=%q{break if rnext.nil? or rnext.empty? or rline.nil? or rline.empty?\n}; node=Prism.parse(src).value.statements.body[0]; pp node.class; pp node.predicate.inspect'

exec_command: cd bench/corpus && BUNDLE_PATH=vendor/bundle ruby -e 'require "rubocop"; require "rubocop-rails"; source = "break if rnext.nil? or rnext.empty? or rline.nil? or rline.empty?\n"; team = RuboCop::Cop::T

exec_command: cd bench/corpus && BUNDLE_PATH=vendor/bundle ruby -e 'require "rubocop"; require "rubocop-rails"; source = "if elements.nil? or elements.empty? then\nend\nreturn if name.nil? or name.empty?\n"; team =

write_stdin: ``

write_stdin: ``

I’ve got RuboCop-confirmed columns for the new or examples already. Next I’m comparing nitrocop and RuboCop on the chained or case and on a temp file with the current binary so I can patch the exact message generation instead of guessing.

I’ve got RuboCop-confirmed columns for the new or examples already. Next I’m comparing nitrocop and RuboCop on the chained or case and on a temp file with the current binary so I can patch the exact message generation instead of guessing.

exec_command: printf '%s ' 'break if rnext.nil? or rnext.empty? or rline.nil? or rline.empty?' > /tmp/rails_blank_chain_or.rb && cd bench/corpus && BUNDLE_PATH=vendor/bundle bundle exec rubocop --plugin rubocop-rai

exec_command: printf '%s ' 'if elements.nil? or elements.empty? then' 'end' 'return if name.nil? or name.empty?' 'words.shift if words[0].nil? or words[0].empty?' 'abbrev = __is_abbrev(line) unless line.nil? || lin

exec_command: sed -n '120,220p' scripts/verify_cop_locations.py

The key discrepancy is now clear: the library test path sees the offense, but the CLI run with default config reports zero. That points to runtime config gating or preview status, not just AST matching, so I’m checking the cop’s default enablement path before editing.

The key discrepancy is now clear: the library test path sees the offense, but the CLI run with default config reports zero. That points to runtime config gating or preview status, not just AST matching, so I’m checking the cop’s default enablement path before editing.

Task prompt (4503 tokens)

Fix Rails/Blank — 0 FP, 14 FN

Instructions

You are fixing ONE cop in nitrocop, a Rust Ruby linter that uses Prism for parsing.

Current state: 6,472 matches, 0 false positives, 14 false negatives.
Focus on: FN (RuboCop flags code nitrocop misses).

⚠ 6,472 existing matches must not regress. Validate with check_cop.py before committing.

Workflow

  1. Read the Pre-diagnostic Results and Corpus FP/FN Examples sections below first
  2. Verify with RuboCop first (for FP fixes): before writing any code, confirm RuboCop's
    behavior on BOTH the specific FP case AND the general pattern:
    echo '<specific FP case>' > /tmp/test.rb && rubocop --only Rails/Blank /tmp/test.rb
    echo '<general pattern>' > /tmp/test.rb && rubocop --only Rails/Blank /tmp/test.rb
    If RuboCop flags the general pattern, your fix must be narrow enough to not suppress it.
  3. Add a test case FIRST:
    • FN fix: add the missed pattern to tests/fixtures/cops/rails/blank/offense.rb with ^ annotation
    • FP fix: add the false-positive pattern to tests/fixtures/cops/rails/blank/no_offense.rb
  4. Verify test fails: cargo test --lib -- cop::rails::blank
  5. Fix src/cop/rails/blank.rs
  6. Verify test passes: cargo test --lib -- cop::rails::blank
  7. Validate against corpus (REQUIRED before committing):
    python3 scripts/check_cop.py Rails/Blank --rerun --clone --sample 15
    If this reports FP or FN regression, your fix is too broad — narrow it down.
  8. Add a /// doc comment on the cop struct documenting what you found and fixed
  9. Commit only your cop's files

Fixture Format

Mark offenses with ^ markers on the line AFTER the offending source line.
The ^ characters must align with the offending columns. The message format is Rails/Blank: <message text>.
See the Current Fixture sections below for real examples from this cop.

If your test passes immediately

If you add a test case and it passes without code changes, the corpus mismatch is
caused by config/context differences, not a detection bug.
Do NOT loop trying to make the test fail. Instead:

  1. Investigate config resolution (Include/Exclude, cop enablement, disable comments)
  2. The fix is likely in src/config/ or the cop's config handling, not detection logic
  3. If you cannot determine the root cause within 5 minutes, document your findings as
    a /// comment on the cop struct and commit

CRITICAL: Avoid regressions in the opposite direction

When fixing FPs, your change MUST NOT suppress legitimate detections. When fixing FNs,
your change MUST NOT flag code that RuboCop accepts. A fix that eliminates a few issues
in one direction but introduces hundreds in the other is a catastrophic regression.

Before exempting a category of patterns, verify with RuboCop that the general case
is still an offense:

rubocop --only Rails/Blank /tmp/test.rb

If RuboCop flags the general pattern but not your specific case, the difference is in
a narrow context (e.g., enclosing structure, receiver type, argument count) — your fix
must target that specific context, not the broad category.

Rule of thumb: if your fix adds an early return or continue that skips a whole
node type, operator class, or naming pattern, it's probably too broad. Prefer adding a
condition that matches the SPECIFIC differentiating context.

Rules

  • Only modify src/cop/rails/blank.rs and tests/fixtures/cops/rails/blank/
  • Run cargo test --lib -- cop::rails::blank to verify your fix (do NOT run the full test suite)
  • Run python3 scripts/check_cop.py Rails/Blank --rerun --clone --sample 15 before committing to catch regressions
  • Do NOT touch unrelated files
  • Do NOT use git stash

Current Fixture: offense.rb

tests/fixtures/cops/rails/blank/offense.rb

!x.present?
^^^^^^^^^^^ Rails/Blank: Use `blank?` instead of `!present?`.

!name.present?
^^^^^^^^^^^^^^ Rails/Blank: Use `blank?` instead of `!present?`.

!user.email.present?
^^^^^^^^^^^^^^^^^^^^ Rails/Blank: Use `blank?` instead of `!present?`.

x.nil? || x.empty?
^^^^^^^^^^^^^^^^^^^ Rails/Blank: Use `x.blank?` instead of `x.nil? || x.empty?`.

name.nil? || name.empty?
^^^^^^^^^^^^^^^^^^^^^^^^ Rails/Blank: Use `name.blank?` instead of `name.nil? || name.empty?`.

foo == nil || foo.empty?
^^^^^^^^^^^^^^^^^^^^^^^^ Rails/Blank: Use `foo.blank?` instead of `foo == nil || foo.empty?`.

something unless foo.present?
          ^^^^^^^^^^^^^^^^^^^ Rails/Blank: Use `if foo.blank?` instead of `unless foo.present?`.

something unless present?
          ^^^^^^^^^^^^^^^ Rails/Blank: Use `if blank?` instead of `unless present?`.

unless foo.present?
^^^^^^^^^^^^^^^^^^^ Rails/Blank: Use `if foo.blank?` instead of `unless foo.present?`.
  something
end

!foo || foo.empty?
^^^^^^^^^^^^^^^^^^ Rails/Blank: Use `foo.blank?` instead of `!foo || foo.empty?`.

!methods || methods.empty?
^^^^^^^^^^^^^^^^^^^^^^^^^^ Rails/Blank: Use `methods.blank?` instead of `!methods || methods.empty?`.

!url || url.empty?
^^^^^^^^^^^^^^^^^^ Rails/Blank: Use `url.blank?` instead of `!url || url.empty?`.

return self if nil? || empty?
               ^^^^^^^^^^^^^^ Rails/Blank: Use `blank?` instead of `nil? || empty?`.
return [] if nil? || empty?
             ^^^^^^^^^^^^^^ Rails/Blank: Use `blank?` instead of `nil? || empty?`.

Current Fixture: no_offense.rb

tests/fixtures/cops/rails/blank/no_offense.rb

x.blank?
x.present?
!x.empty?
x.nil?
name.present? && name.length > 0
x.nil? || y.empty?
x.nil? && x.empty?
x.nil? || x.zero?
something if foo.present?
something unless foo.blank?
def blank?
  !present?
end
unless foo.present?
  something
else
  something_else
end

# present? called with argument (class method style) should NOT be flagged
# RuboCop's NodePattern `(send (send $_ :present?) :!)` requires present? with no arguments
!Helpers.present?(value)
!Vagrant::Util::Presence.present?(directory)
unless Helpers.present?(value)
  do_something
end

# safe navigation on present?/empty? — RuboCop's NodePattern matches send not csend
# so &.present? and &.empty? should NOT be flagged
return [] unless response&.strip&.present?
unless object&.present?
  do_something
end
foo.nil? || foo&.empty?

# pattern match guard: `in pattern unless condition` is not a regular unless
# RuboCop's on_if handler does not visit pattern match guards
case element.name
in "div" unless element.at("div").present?
  element.name = "p"
end

# safe navigation with !present? — semantics differ:
# !pkey_cols&.present? when pkey_cols is nil → !nil → true
# pkey_cols&.blank? when pkey_cols is nil → nil (falsy)
# RuboCop skips this pattern because `(send (send $_ :present?) :!)` doesn't
# match csend (safe navigation).
id_option = if pk_is_also_fk || !pkey_cols&.present?

Key Source Files

  • Rust implementation: src/cop/rails/blank.rs
  • RuboCop Ruby source (ground truth): vendor/rubocop-rails/lib/rubocop/cop/rails/blank.rb
  • RuboCop test excerpts: vendor/rubocop-rails/spec/rubocop/cop/rails/blank_spec.rb

Read these files before making changes.

Start Here

Use the existing corpus data to focus on the most concentrated regressions first.

Helpful local commands:

  • python3 scripts/investigate_cop.py Rails/Blank --repos-only
  • python3 scripts/investigate_cop.py Rails/Blank --context
  • python3 scripts/verify_cop_locations.py Rails/Blank

Top FN repos:

  • databasically__lowdown__d593927 (5 FN) — example vendor/rails/actionmailer/lib/action_mailer/vendor/text-format-0.6.3/text/format.rb:594
  • cjstewart88__Tubalr__f6956c8 (4 FN) — example heroku/ruby/1.9.1/gems/rdoc-3.8/lib/rdoc/parser/c.rb:784
  • pitluga__supply_drop__d64c50c (4 FN) — example examples/vendored-puppet/vendor/puppet-2.7.8/lib/puppet/util/adsi.rb:161

Representative FN examples:

  • cjstewart88__Tubalr__f6956c8: heroku/ruby/1.9.1/gems/rdoc-3.8/lib/rdoc/parser/c.rb:784 — Use elements.blank? instead of elements.nil? or elements.empty?.
  • cjstewart88__Tubalr__f6956c8: heroku/ruby/1.9.1/gems/rdoc-3.8/lib/rdoc/ri/driver.rb:865 — Use name.blank? instead of name.nil? or name.empty?.
  • cjstewart88__Tubalr__f6956c8: heroku/ruby/1.9.1/gems/rdoc-3.9.4/lib/rdoc/parser/c.rb:782 — Use elements.blank? instead of elements.nil? or elements.empty?.

Pre-diagnostic Results

Diagnosis Summary

Each example was tested by running nitrocop on the extracted source in isolation
with --force-default-config to determine if the issue is a code bug or config issue.
Note: source context is truncated and may not parse perfectly. If a diagnosis
seems wrong (e.g., your test passes immediately for a 'CODE BUG'), treat it as
a config/context issue instead.

  • FN: 14 code bug(s), 0 config/context issue(s)

FN #1: cjstewart88__Tubalr__f6956c8: heroku/ruby/1.9.1/gems/rdoc-3.8/lib/rdoc/parser/c.rb:784

NOT DETECTED — CODE BUG
The cop fails to detect this pattern. Fix the detection logic.

Enclosing structure: if branch (line: if type.downcase == 'const' then)
The offense is inside this structure — the cop may need
to handle this context to detect the pattern.

Message: Use elements.blank?instead ofelements.nil? or elements.empty?.

Ready-made test snippet (add to offense.rb, adjust ^ count):

      if elements.nil? or elements.empty? then
^ Rails/Blank: Use `elements.blank?` instead of `elements.nil? or elements.empty?`.

Full source context:

    # In the case of rb_define_const, the definition and comment are in
    # "/* definition: comment */" form.  The literal ':' and '\' characters
    # can be escaped with a backslash.
    if type.downcase == 'const' then
      elements = comment.split ':'

      if elements.nil? or elements.empty? then
        con = RDoc::Constant.new const_name, definition, comment
      else
        new_definition = elements[0..-2].join(':')

        if new_definition.empty? then # Default to literal C definition
          new_definition = definition
        else

FN #2: cjstewart88__Tubalr__f6956c8: heroku/ruby/1.9.1/gems/rdoc-3.8/lib/rdoc/ri/driver.rb:865

NOT DETECTED — CODE BUG
The cop fails to detect this pattern. Fix the detection logic.

Message: Use name.blank?instead ofname.nil? or name.empty?.

Ready-made test snippet (add to offense.rb, adjust ^ count):

      return if name.nil? or name.empty?
^ Rails/Blank: Use `name.blank?` instead of `name.nil? or name.empty?`.

Full source context:

      name = if defined? Readline then
               Readline.readline ">> "
             else
               print ">> "
               $stdin.gets
             end

      return if name.nil? or name.empty?

      name = expand_name name.strip

      begin
        display_name name
      rescue NotFoundError => e
        puts e.message

FN #3: cjstewart88__Tubalr__f6956c8: heroku/ruby/1.9.1/gems/rdoc-3.9.4/lib/rdoc/parser/c.rb:782

NOT DETECTED — CODE BUG
The cop fails to detect this pattern. Fix the detection logic.

Enclosing structure: if branch (line: if type.downcase == 'const' then)
The offense is inside this structure — the cop may need
to handle this context to detect the pattern.

Message: Use elements.blank?instead ofelements.nil? or elements.empty?.

Ready-made test snippet (add to offense.rb, adjust ^ count):

      if elements.nil? or elements.empty? then
^ Rails/Blank: Use `elements.blank?` instead of `elements.nil? or elements.empty?`.

Full source context:

    # In the case of rb_define_const, the definition and comment are in
    # "/* definition: comment */" form.  The literal ':' and '\' characters
    # can be escaped with a backslash.
    if type.downcase == 'const' then
      elements = comment.split ':'

      if elements.nil? or elements.empty? then
        con = RDoc::Constant.new const_name, definition, comment
      else
        new_definition = elements[0..-2].join(':')

        if new_definition.empty? then # Default to literal C definition
          new_definition = definition
        else

FN #4: cjstewart88__Tubalr__f6956c8: heroku/ruby/1.9.1/gems/rdoc-3.9.4/lib/rdoc/ri/driver.rb:878

NOT DETECTED — CODE BUG
The cop fails to detect this pattern. Fix the detection logic.

Message: Use name.blank?instead ofname.nil? or name.empty?.

Ready-made test snippet (add to offense.rb, adjust ^ count):

      return if name.nil? or name.empty?
^ Rails/Blank: Use `name.blank?` instead of `name.nil? or name.empty?`.

Full source context:

      name = if defined? Readline then
               Readline.readline ">> "
             else
               print ">> "
               $stdin.gets
             end

      return if name.nil? or name.empty?

      name = expand_name name.strip

      begin
        display_name name
      rescue NotFoundError => e
        puts e.message

FN #5: databasically__lowdown__d593927: vendor/rails/actionmailer/lib/action_mailer/vendor/text-format-0.6.3/text/format.rb:594

NOT DETECTED — CODE BUG
The cop fails to detect this pattern. Fix the detection logic.

Enclosing structure: method body (line: def __format(to_wrap) #:nodoc:)
The offense is inside this structure — the cop may need
to handle this context to detect the pattern.

Prism AST at offense line: IfNode > OrNode > CallNode > CallNode > LocalVariableReadNode > ArgumentsNode > IntegerNode > CallNode > CallNode > LocalVariableReadNode > ArgumentsNode > IntegerNode > StatementsNode > CallNode > LocalVariableReadNode

Message: Use words[0].blank?instead ofwords[0].nil? or words[0].empty?.

Ready-made test snippet (add to offense.rb, adjust ^ count):

      words.shift if words[0].nil? or words[0].empty?
^ Rails/Blank: Use `words[0].blank?` instead of `words[0].nil? or words[0].empty?`.

Full source context:

  private
    def __do_split_word(word, size) #:nodoc:
      [word[0 .. (size - 1)], word[size .. -1]]
    end

    def __format(to_wrap) #:nodoc:
      words = to_wrap.split(/\s+/).compact
      words.shift if words[0].nil? or words[0].empty?
      to_wrap = []

      abbrev = false
      width = @columns - @first_indent - @left_margin - @right_margin
      indent_str = ' ' * @first_indent
      first_line = true
      line = words.shift

FN #6: databasically__lowdown__d593927: vendor/rails/actionmailer/lib/action_mailer/vendor/text-format-0.6.3/text/format.rb:602

NOT DETECTED — CODE BUG
The cop fails to detect this pattern. Fix the detection logic.

Message: Use line.blank?instead ofline.nil? || line.empty?.

Ready-made test snippet (add to offense.rb, adjust ^ count):

      abbrev = __is_abbrev(line) unless line.nil? || line.empty?
^ Rails/Blank: Use `line.blank?` instead of `line.nil? || line.empty?`.

Full source context:

      to_wrap = []

      abbrev = false
      width = @columns - @first_indent - @left_margin - @right_margin
      indent_str = ' ' * @first_indent
      first_line = true
      line = words.shift
      abbrev = __is_abbrev(line) unless line.nil? || line.empty?

      while w = words.shift
        if (w.size + line.size < (width - 1)) ||
           ((line !~ LEQ_RE || abbrev) && (w.size + line.size < width))
          line << " " if (line =~ LEQ_RE) && (not abbrev)
          line << " #{w}"
        else

FN #7: databasically__lowdown__d593927: vendor/rails/actionmailer/lib/action_mailer/vendor/text-format-0.6.3/text/format.rb:630

NOT DETECTED — CODE BUG
The cop fails to detect this pattern. Fix the detection logic.

Enclosing structure: block (do..end) (line: loop do)
The offense is inside this structure — the cop may need
to handle this context to detect the pattern.

Prism AST at offense line: StatementsNode > IfNode > OrNode > CallNode > LocalVariableReadNode > CallNode > LocalVariableReadNode > StatementsNode > BreakNode

Message: Use line.blank?instead ofline.nil? or line.empty?.

Ready-made test snippet (add to offense.rb, adjust ^ count):

        break if line.nil? or line.empty?
^ Rails/Blank: Use `line.blank?` instead of `line.nil? or line.empty?`.

Full source context:

          line = w
        end

        abbrev = __is_abbrev(w) unless w.nil?
      end

      loop do
        break if line.nil? or line.empty?
        line, w = __do_hyphenate(line, w, width) if @hard_margins
        to_wrap << __make_line(line, indent_str, width, w.nil?)
        line = w
      end

      if (@tag_paragraph && (to_wrap.size > 0)) then
        clr = %r{`(\w+)'}.match([caller(1)].flatten[0])[1]

FN #8: databasically__lowdown__d593927: vendor/rails/actionmailer/lib/action_mailer/vendor/text-format-0.6.3/text/format.rb:790

NOT DETECTED — CODE BUG
The cop fails to detect this pattern. Fix the detection logic.

Enclosing structure: enclosing line: else
The offense is inside this structure — the cop may need
to handle this context to detect the pattern.

Message: Use rnext.blank?instead ofrnext.nil? or rnext.empty?.

Ready-made test snippet (add to offense.rb, adjust ^ count):

          break if rnext.nil? or rnext.empty? or rline.nil? or rline.empty?
^ Rails/Blank: Use `rnext.blank?` instead of `rnext.nil? or rnext.empty?`.

Full source context:

            words[-1] = first
            @split_words << SplitWord.new(word, first, rest)
          end
          rline = words.join(' ').strip
          rnext = "#{rest} #{rnext}".strip
          break
        else
          break if rnext.nil? or rnext.empty? or rline.nil? or rline.empty?
          words = rnext.split(/\s+/)
          word = words.shift
          size = width - rline.size - 1

          if (size <= 0)
            rnext = "#{word} #{words.join(' ')}".strip
            break

Omitted 6 additional diagnosed FN example(s) for brevity.

@6 6 bot force-pushed the fix/rails-blank-23576652976 branch from 7786dc0 to d8b4201 Compare March 26, 2026 04:20
@6 6 bot marked this pull request as ready for review March 26, 2026 04:20
@6 6 bot enabled auto-merge (squash) March 26, 2026 04:20
@6
Copy link
Copy Markdown
Contributor Author

6 bot commented Mar 26, 2026

Cop-check results (8 shards)

Cop Baseline FP Baseline FN New FP New FN Result
Rails/Blank 0 0 0 0
Rails/Blank 0 0 0 0
Rails/Blank 0 0 0 0
Rails/Blank 0 0 0 0
Rails/Blank 0 0 0 0
Rails/Blank 0 0 0 0
Rails/Blank 0 0 0 0
Rails/Blank 0 0 0 0

All shards passed — ready to merge.

Copy link
Copy Markdown
Owner

@6 6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Real fix: uses original OrNode source slice for diagnostic message instead of reconstructing with ||. Fixes 14 FN from or/not forms. Good fixtures.

@6 6 bot merged commit 57bf7c0 into main Mar 26, 2026
14 checks passed
@6 6 bot deleted the fix/rails-blank-23576652976 branch March 26, 2026 12:44
@6 6 bot mentioned this pull request Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant