forked from rubocop/rubocop
/
empty_case_condition.rb
109 lines (89 loc) · 2.89 KB
/
empty_case_condition.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# frozen_string_literal: true
module RuboCop
module Cop
module Style
# This cop checks for case statements with an empty condition.
#
# @example
#
# # bad:
# case
# when x == 0
# puts 'x is 0'
# when y == 0
# puts 'y is 0'
# else
# puts 'neither is 0'
# end
#
# # good:
# if x == 0
# puts 'x is 0'
# elsif y == 0
# puts 'y is 0'
# else
# puts 'neither is 0'
# end
#
# # good: (the case condition node is not empty)
# case n
# when 0
# puts 'zero'
# when 1
# puts 'one'
# else
# puts 'more'
# end
class EmptyCaseCondition < Cop
include RangeHelp
MSG = 'Do not use empty `case` condition, instead use an `if` '\
'expression.'
def on_case(case_node)
return if case_node.condition
branch_bodies = [
*case_node.when_branches.map(&:body),
case_node.else_branch
].compact
return if branch_bodies.any? do |body|
body.return_type? ||
body.each_descendant.any?(&:return_type?)
end
add_offense(case_node, location: :keyword)
end
def autocorrect(case_node)
when_branches = case_node.when_branches
lambda do |corrector|
correct_case_when(corrector, case_node, when_branches)
correct_when_conditions(corrector, when_branches)
end
end
private
def correct_case_when(corrector, case_node, when_nodes)
case_range = case_node.loc.keyword.join(when_nodes.first.loc.keyword)
corrector.replace(case_range, 'if')
keep_first_when_comment(case_node, when_nodes.first, corrector)
when_nodes[1..-1].each do |when_node|
corrector.replace(when_node.loc.keyword, 'elsif')
end
end
def correct_when_conditions(corrector, when_nodes)
when_nodes.each do |when_node|
conditions = when_node.conditions
next unless conditions.size > 1
range = range_between(conditions.first.source_range.begin_pos,
conditions.last.source_range.end_pos)
corrector.replace(range, conditions.map(&:source).join(' || '))
end
end
def keep_first_when_comment(case_node, first_when_node, corrector)
comment = processed_source.comments_before_line(
first_when_node.loc.keyword.line
).map(&:text).join("\n")
line = range_by_whole_lines(case_node.source_range)
corrector.insert_before(line, "#{comment}\n") if !comment.empty? &&
!case_node.parent
end
end
end
end
end