Search code examples
rubyrubocop

Rubocop for catching conditional assignment


We have some code that bit us in production and I am wondering if there is a way to prevent it in the future. We are using ruby and rubocop but I could find a cop to fit my needs.

The code looks like:

a = 1
b = 1
return ((a == 1) || (b = 2)) # should return a boolean, false in  this case

Line 3 is where we had the issue, we missed an equal sign (so it was a single equal instead of a double equal) when calculating a boolean value.

Is there anything off the shelf we could use to catch this error in ruby or rubocop?

Thanks,


Solution

  • These were treated as assignment, it can't ensure and confirm that the user is providing an assignment or he is validating equality.

    i have came accross similar thing (different usecase) and i achieved by creating custom cop extension.

    It is not an appreciatable way to override the exisisting functionality, But however you can achieve this by defining custom cops by creating your own extensions.

    for example You can create a new ruby -rubocop file like assignment_mistake_correction_cop.rb and you can make necessary changes in this file.

    in your yaml file, you can include this file like

    #.rubocop.yml

    require: './assignment_mistake_correction_cop.rb'

    as example changes for the assignment_mistake_correction_cop file, check the code below which i have implemented for some other usecase, this code is updated as per your requirement.

    # assignment_mistake_correction_cop.rb
    require 'rubocop'
    
    module RuboCop
      module Cop
        module CustomWrittenCops
          class AssignmentMistakeCorrectionCop < Cop
    
            MSG = 'Assignment mistake . Use `==` for comparison instead of `=`.'.freeze
    
            def on_send(node)
              receiver, method_name, *args = *node
              return if  !(method_name == :return && args.size == 1)
    
              arg = args.first
    
              receiver, method_name, *args = *arg
    
              arg1, arg2 = args
    
              if assignment_has_a_mistake?(arg1)
                add_offense(arg1, location: :expression)
              elsif assignment_has_a_mistake?(arg2)
                add_offense(arg2, location: :expression)
              end
    
            end
    
            private
    
            def assignment_has_a_mistake?(val)
              val.assignment?
            end
          end
        end
      end
    end
    

    Note: This is a sample code which i modified based on your use case.

    for more references, may be you can look into rubocop/cop/corrector.rb file.

    here the corrector class is responsible for applying the fix (i.e autocorrect fix).