Rubocop: Safe Navigation Cop fails on accessing hash value

Created on 19 Sep 2017  路  3Comments  路  Source: rubocop-hq/rubocop

When upgrading Rubocop to version 0.50 and running it on our codebase, Rubocop fails with the following stack trace:

undefined method `begin' for nil:NilClass
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/parser-2.4.0.0/lib/parser/source/rewriter.rb:67:in `insert_before'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cop/corrector.rb:78:in `insert_before'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cop/style/safe_navigation.rb:99:in `block in autocorrect'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cop/corrector.rb:56:in `block (2 levels) in rewrite'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/parser-2.4.0.0/lib/parser/source/rewriter.rb:194:in `transaction'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cop/corrector.rb:55:in `block in rewrite'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cop/corrector.rb:53:in `each'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cop/corrector.rb:53:in `rewrite'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cop/team.rb:126:in `autocorrect_all_cops'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cop/team.rb:70:in `autocorrect'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cop/team.rb:98:in `block in offenses'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cop/team.rb:115:in `investigate'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cop/team.rb:94:in `offenses'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cop/team.rb:44:in `inspect_file'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:258:in `inspect_file'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:205:in `block in do_inspection_loop'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:237:in `block in iterate_until_no_changes'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:230:in `loop'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:230:in `iterate_until_no_changes'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:201:in `do_inspection_loop'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:111:in `block in file_offenses'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:121:in `file_offense_cache'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:109:in `file_offenses'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:100:in `process_file'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:78:in `block in each_inspected_file'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:75:in `each'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:75:in `reduce'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:75:in `each_inspected_file'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:67:in `inspect_files'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/runner.rb:39:in `run'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cli.rb:86:in `execute_runner'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/lib/rubocop/cli.rb:32:in `run'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/bin/rubocop:13:in `block in <top (required)>'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/2.4.0/benchmark.rb:308:in `realtime'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/rubocop-0.50.0/bin/rubocop:12:in `<top (required)>'
/Users/maikel.lammers/.rbenv/versions/2.4.1/bin/rubocop:22:in `load'
/Users/maikel.lammers/.rbenv/versions/2.4.1/bin/rubocop:22:in `<top (required)>'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/cli/exec.rb:74:in `load'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/cli/exec.rb:74:in `kernel_load'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/cli/exec.rb:27:in `run'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/cli.rb:362:in `exec'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/cli.rb:22:in `dispatch'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/cli.rb:13:in `start'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/exe/bundle:30:in `block in <top (required)>'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/friendly_errors.rb:121:in `with_friendly_errors'
/Users/maikel.lammers/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/exe/bundle:22:in `<top (required)>'
/Users/maikel.lammers/.rbenv/versions/2.4.1/bin/bundle:22:in `load'
/Users/maikel.lammers/.rbenv/versions/2.4.1/bin/bundle:22:in `<main>'

After some investigation, it seems that the RuboCop::Cop::Style::SafeNavigation cop, fails on the following line of code:

subscriptions << :badge if response_body && response_body["collection"].include?(@user_id)

Expected behavior

RuboCop should first and foremost not raise an exception.

I'm not sure whether RuboCop should try to correct this. One possibility would be:

response_body&.[]("collection")&.include?(@user_id)

Actual behavior

Rubocop raises exception

Steps to reproduce the problem

Step 1: Create class

class RubocopTest
   def safe_navigation
     hash = nil
     result = {}

     result << :something if hash && hash["collection"].include?("a")
   end
end

Step 2: Run Rubocop (version 0.50)
$ rubocop -a rubocop_test.rb

RuboCop version

$ rubocop -V
0.50.0 (using Parser 2.4.0.0, running on ruby 2.4.1 x86_64-darwin16)
bug duplicate

Most helpful comment

You're welcome! We might need to rush the patch release due to this one alone. Affecting a lot of people. 馃槄

All 3 comments

Fixed in #4749. 馃檪

@Drenmi All the better, thank you 馃憤

You're welcome! We might need to rush the patch release due to this one alone. Affecting a lot of people. 馃槄

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tedPen picture tedPen  路  3Comments

bbatsov picture bbatsov  路  3Comments

mikegee picture mikegee  路  3Comments

AndreiMotinga picture AndreiMotinga  路  3Comments

joromir picture joromir  路  3Comments