-
-
Notifications
You must be signed in to change notification settings - Fork 3k
/
space_inside_reference_brackets.rb
140 lines (122 loc) · 4.11 KB
/
space_inside_reference_brackets.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# frozen_string_literal: true
module RuboCop
module Cop
module Layout
# Checks that reference brackets have or don't have
# surrounding space depending on configuration.
#
# @example EnforcedStyle: no_space (default)
# # The `no_space` style enforces that reference brackets have
# # no surrounding space.
#
# # bad
# hash[ :key ]
# array[ index ]
#
# # good
# hash[:key]
# array[index]
#
# @example EnforcedStyle: space
# # The `space` style enforces that reference brackets have
# # surrounding space.
#
# # bad
# hash[:key]
# array[index]
#
# # good
# hash[ :key ]
# array[ index ]
#
#
# @example EnforcedStyleForEmptyBrackets: no_space (default)
# # The `no_space` EnforcedStyleForEmptyBrackets style enforces that
# # empty reference brackets do not contain spaces.
#
# # bad
# foo[ ]
# foo[ ]
#
# # good
# foo[]
#
# @example EnforcedStyleForEmptyBrackets: space
# # The `space` EnforcedStyleForEmptyBrackets style enforces that
# # empty reference brackets contain exactly one space.
#
# # bad
# foo[]
# foo[ ]
#
# # good
# foo[ ]
#
class SpaceInsideReferenceBrackets < Base
include SurroundingSpace
include ConfigurableEnforcedStyle
extend AutoCorrector
MSG = '%<command>s space inside reference brackets.'
EMPTY_MSG = '%<command>s space inside empty reference brackets.'
RESTRICT_ON_SEND = %i[[] []=].freeze
def on_send(node)
return if node.multiline?
tokens = processed_source.tokens_within(node)
left_token = left_ref_bracket(node, tokens)
return unless left_token
right_token = closing_bracket(tokens, left_token)
if empty_brackets?(left_token, right_token)
return empty_offenses(node, left_token, right_token, EMPTY_MSG)
end
if style == :no_space
no_space_offenses(node, left_token, right_token, MSG)
else
space_offenses(node, left_token, right_token, MSG)
end
end
private
def autocorrect(corrector, node)
left, right = reference_brackets(node)
if empty_brackets?(left, right)
SpaceCorrector.empty_corrections(processed_source, corrector, empty_config, left, right)
elsif style == :no_space
SpaceCorrector.remove_space(processed_source, corrector, left, right)
else
SpaceCorrector.add_space(processed_source, corrector, left, right)
end
end
def reference_brackets(node)
tokens = processed_source.tokens_within(node)
left = left_ref_bracket(node, tokens)
[left, closing_bracket(tokens, left)]
end
def left_ref_bracket(node, tokens)
current_token = tokens.reverse.find(&:left_ref_bracket?)
previous_token = previous_token(current_token)
if node.method?(:[]=) ||
previous_token && !previous_token.right_bracket?
tokens.find(&:left_ref_bracket?)
else
current_token
end
end
def closing_bracket(tokens, opening_bracket)
i = tokens.index(opening_bracket)
inner_left_brackets_needing_closure = 0
tokens[i..-1].each do |token|
inner_left_brackets_needing_closure += 1 if token.left_bracket?
inner_left_brackets_needing_closure -= 1 if token.right_bracket?
return token if inner_left_brackets_needing_closure.zero? && token.right_bracket?
end
end
def previous_token(current_token)
index = processed_source.tokens.index(current_token)
index.nil? || index.zero? ? nil : processed_source.tokens[index - 1]
end
def empty_config
cop_config['EnforcedStyleForEmptyBrackets']
end
end
end
end
end