forked from rubocop/rubocop
-
Notifications
You must be signed in to change notification settings - Fork 0
/
multiline_ternary_operator.rb
85 lines (74 loc) · 2.24 KB
/
multiline_ternary_operator.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
# frozen_string_literal: true
module RuboCop
module Cop
module Style
# Checks for multi-line ternary op expressions.
#
# NOTE: `return if ... else ... end` is syntax error. If `return` is used before
# multiline ternary operator expression, it will be autocorrected to single-line
# ternary operator. The same is true for `break`, `next`, and method call.
#
# @example
# # bad
# a = cond ?
# b : c
# a = cond ? b :
# c
# a = cond ?
# b :
# c
#
# return cond ?
# b :
# c
#
# # good
# a = cond ? b : c
# a = if cond
# b
# else
# c
# end
#
# return cond ? b : c
#
class MultilineTernaryOperator < Base
extend AutoCorrector
MSG_IF = 'Avoid multi-line ternary operators, use `if` or `unless` instead.'
MSG_SINGLE_LINE = 'Avoid multi-line ternary operators, use single-line instead.'
SINGLE_LINE_TYPES = %i[return break next send].freeze
def on_if(node)
return unless offense?(node)
message = enforce_single_line_ternary_operator?(node) ? MSG_SINGLE_LINE : MSG_IF
add_offense(node, message: message) do |corrector|
next unless offense?(node)
corrector.replace(node, replacement(node))
end
end
private
def offense?(node)
node.ternary? && node.multiline?
end
def replacement(node)
if enforce_single_line_ternary_operator?(node)
"#{node.condition.source} ? #{node.if_branch.source} : #{node.else_branch.source}"
else
<<~RUBY.chop
if #{node.condition.source}
#{node.if_branch.source}
else
#{node.else_branch.source}
end
RUBY
end
end
def enforce_single_line_ternary_operator?(node)
SINGLE_LINE_TYPES.include?(node.parent&.type) && !use_assignment_method?(node.parent)
end
def use_assignment_method?(node)
node.send_type? && node.assignment_method?
end
end
end
end
end