rubywarningslvaluetargetnullvalue

Detecting a missing sub!, sort!, map!, etc


After returning to Ruby from a long stint coding in another language, I regularly assume that foo.sort, foo.map {...}, foo.sub /bar/, 'zip' will change foo. Of course I meant foo.sort!, etc. But that usually takes 3 or 4 debugging potshots before I notice. Meanwhile, the sort is calculated, but then isn't assigned to anything. Can I make ruby warn about that missing lvalue, like a C compiler warns of a function's ignored return value?


Solution

  • Here's a very basic parser :

    @forgetful_methods = %w(sort map sub)
    
    Dir['*.rb'].each do |script|
      File.readlines(script).each.with_index(1) do |line, i|
        @forgetful_methods.each do |method|
          if line =~ /\.#{method}(?!!)/ && $` !~ /(=|\b(puts|print|return)\b|^#)/
            puts format('%-25s (%3d) : %s', script, i, line.strip)
          end
        end
      end
    end
    
    # =>
    # brace_globbing.rb         ( 13) : subpatterns.map{|subpattern| explode_extglob(match.pre_match+subpattern+match.post_match)}.flatten
    # delegate.rb               ( 11) : @targets.map { |t| t.send(m, *args) }
    

    It checks every ruby script in the current directory for sort, map or sub without ! that aren't preceded by =, puts, print or return.

    It's just a start, but maybe it could help you find some of the low hanging fruits. There are many false positives, though.

    A more complex version could use abstract syntax trees, for example with Ripper.