class RuboCop::Cop::Style::ConditionalAssignment
Check for ‘if` and `case` statements where each branch is used for both the assignment and comparison of the same variable when using the return of the condition can be used instead.
@example EnforcedStyle: assign_to_condition (default)
# bad if foo bar = 1 else bar = 2 end case foo when 'a' bar += 1 else bar += 2 end if foo some_method bar = 1 else some_other_method bar = 2 end # good bar = if foo 1 else 2 end bar += case foo when 'a' 1 else 2 end bar << if foo some_method 1 else some_other_method 2 end
@example EnforcedStyle: assign_inside_condition
# bad bar = if foo 1 else 2 end bar += case foo when 'a' 1 else 2 end bar << if foo some_method 1 else some_other_method 2 end # good if foo bar = 1 else bar = 2 end case foo when 'a' bar += 1 else bar += 2 end if foo some_method bar = 1 else some_other_method bar = 2 end
Constants
- ASSIGNMENT_TYPES
- ASSIGN_TO_CONDITION_MSG
- ENABLED
- LINE_LENGTH
- MAX
- MSG
- SINGLE_LINE_CONDITIONS_ONLY
- VARIABLE_ASSIGNMENT_TYPES
Public Instance Methods
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 260 def on_case(node) return unless style == :assign_to_condition return unless node.else_branch when_branches = expand_when_branches(node.when_branches) branches = [*when_branches, node.else_branch] check_node(node, branches) end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 270 def on_case_match(node) return unless style == :assign_to_condition return unless node.else_branch in_pattern_branches = expand_when_branches(node.in_pattern_branches) branches = [*in_pattern_branches, node.else_branch] check_node(node, branches) end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 246 def on_if(node) return unless style == :assign_to_condition return if node.elsif? else_branch = node.else_branch elsif_branches, else_branch = expand_elses(else_branch) return unless else_branch branches = [node.if_branch, *elsif_branches, else_branch] check_node(node, branches) end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 240 def on_send(node) return unless assignment_type?(node) check_assignment_to_condition(node) end
Private Instance Methods
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 311 def allowed_single_line?(branches) single_line_conditions_only? && branches.compact.any?(&:begin_type?) end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 385 def allowed_statements?(branches) return false unless branches.all? statements = branches.filter_map { |branch| tail(branch) } lhs_all_match?(statements) && statements.none?(&:masgn_type?) && assignment_types_match?(*statements) end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 307 def allowed_ternary?(assignment) assignment.if_type? && assignment.ternary? && !include_ternary? end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 315 def assignment_node(node) assignment = node.send_type? ? node.last_argument : node.expression return unless assignment # ignore pseudo-assignments without rhs in for nodes return if node.parent&.for_type? if assignment.begin_type? && assignment.children.one? assignment = assignment.children.first end assignment end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 362 def assignment_types_match?(*nodes) return false unless assignment_type?(nodes.first) nodes.map(&:type).uniq.one? end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 377 def autocorrect(corrector, node) if assignment_type?(node) move_assignment_inside_condition(corrector, node) else move_assignment_outside_condition(corrector, node) end end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 300 def candidate_node?(node) style == :assign_inside_condition && assignment_rhs_exist?(node) end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 282 def check_assignment_to_condition(node) return unless candidate_node?(node) ignore_node(node) assignment = assignment_node(node) return unless candidate_condition?(assignment) _condition, *branches, else_branch = *assignment return unless else_branch return if allowed_single_line?([*branches, else_branch]) add_offense(node, message: ASSIGN_TO_CONDITION_MSG) do |corrector| autocorrect(corrector, node) end end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 368 def check_node(node, branches) return if allowed_ternary?(node) return unless allowed_statements?(branches) return if allowed_single_line?(branches) return if correction_exceeds_line_limit?(node, branches) add_offense(node) { |corrector| autocorrect(corrector, node) } end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 401 def correction_exceeds_line_limit?(node, branches) return false unless line_length_cop_enabled? assignment = lhs(tail(branches[0])) longest_line_exceeds_line_limit?(node, assignment) end
If ‘Layout/LineLength` is enabled, we do not want to introduce an offense by autocorrecting this cop. Find the max configured line length. Find the longest line of condition. Remove the assignment from lines that contain the offending assignment because after correcting, this will not be on the line anymore. Check if the length of the longest line + the length of the corrected assignment is greater than the max configured line length
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 432 def include_ternary? cop_config['IncludeTernaryExpressions'] end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 355 def lhs_all_match?(branches) return true if branches.empty? first_lhs = lhs(branches.first) branches.all? { |branch| lhs(branch) == first_lhs } end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 420 def line_length_cop_enabled? config.for_cop(LINE_LENGTH)[ENABLED] end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 413 def longest_line(node, assignment) assignment_regex = /\s*#{Regexp.escape(assignment).gsub('\ ', '\s*')}/ lines = node.source.lines.map { |line| line.chomp.sub(assignment_regex, '') } longest_line = lines.max_by(&:length) assignment + longest_line end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 409 def longest_line_exceeds_line_limit?(node, assignment) longest_line(node, assignment).length > max_line_length end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 424 def max_line_length config.for_cop(LINE_LENGTH)[MAX] end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 339 def move_assignment_inside_condition(corrector, node) condition = node.send_type? ? node.last_argument : node.expression if ternary_condition?(condition) TernaryCorrector.move_assignment_inside_condition(corrector, node) elsif condition.type?(:case, :case_match) CaseCorrector.move_assignment_inside_condition(corrector, node) elsif condition.if_type? IfCorrector.move_assignment_inside_condition(corrector, node) end end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 329 def move_assignment_outside_condition(corrector, node) if node.type?(:case, :case_match) CaseCorrector.correct(corrector, self, node) elsif node.ternary? TernaryCorrector.correct(corrector, node) elsif node.if? || node.unless? IfCorrector.correct(corrector, self, node) end end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 428 def single_line_conditions_only? cop_config[SINGLE_LINE_CONDITIONS_ONLY] end
Source
# File lib/rubocop/cop/style/conditional_assignment.rb, line 351 def ternary_condition?(node) [node, node.children.first].compact.any? { |n| n.if_type? && n.ternary? } end