rubocop 0.76.0 → 0.79.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/config/default.yml +290 -264
- data/lib/rubocop/ast/builder.rb +43 -42
- data/lib/rubocop/ast/node/block_node.rb +2 -0
- data/lib/rubocop/ast/node/def_node.rb +11 -0
- data/lib/rubocop/ast/node/forward_args_node.rb +18 -0
- data/lib/rubocop/ast/node.rb +1 -1
- data/lib/rubocop/ast/traversal.rb +11 -3
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +105 -0
- data/lib/rubocop/cli/command/base.rb +33 -0
- data/lib/rubocop/cli/command/execute_runner.rb +76 -0
- data/lib/rubocop/cli/command/init_dotfile.rb +45 -0
- data/lib/rubocop/cli/command/show_cops.rb +80 -0
- data/lib/rubocop/cli/command/version.rb +17 -0
- data/lib/rubocop/cli/command.rb +21 -0
- data/lib/rubocop/cli/environment.rb +21 -0
- data/lib/rubocop/cli.rb +11 -230
- data/lib/rubocop/config.rb +1 -1
- data/lib/rubocop/config_loader.rb +19 -19
- data/lib/rubocop/config_obsoletion.rb +65 -12
- data/lib/rubocop/config_validator.rb +56 -98
- data/lib/rubocop/cop/autocorrect_logic.rb +7 -4
- data/lib/rubocop/cop/bundler/gem_comment.rb +4 -4
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +2 -2
- data/lib/rubocop/cop/cop.rb +21 -0
- data/lib/rubocop/cop/correctors/space_corrector.rb +1 -2
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
- data/lib/rubocop/cop/generator/configuration_injector.rb +1 -1
- data/lib/rubocop/cop/generator.rb +3 -4
- data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +59 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/{align_arguments.rb → argument_alignment.rb} +1 -1
- data/lib/rubocop/cop/layout/{align_array.rb → array_alignment.rb} +1 -1
- data/lib/rubocop/cop/layout/{indent_assignment.rb → assignment_indentation.rb} +1 -1
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/{indent_first_argument.rb → first_argument_indentation.rb} +5 -5
- data/lib/rubocop/cop/layout/{indent_first_array_element.rb → first_array_element_indentation.rb} +4 -4
- data/lib/rubocop/cop/layout/{indent_first_hash_element.rb → first_hash_element_indentation.rb} +3 -3
- data/lib/rubocop/cop/layout/{indent_first_parameter.rb → first_parameter_indentation.rb} +3 -3
- data/lib/rubocop/cop/layout/{align_hash.rb → hash_alignment.rb} +10 -6
- data/lib/rubocop/cop/layout/{indent_heredoc.rb → heredoc_indentation.rb} +5 -5
- data/lib/rubocop/cop/layout/{leading_blank_lines.rb → leading_empty_lines.rb} +1 -1
- data/lib/rubocop/cop/{metrics → layout}/line_length.rb +40 -110
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +14 -5
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +1 -1
- data/lib/rubocop/cop/layout/{align_parameters.rb → parameter_alignment.rb} +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +12 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +32 -7
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +17 -0
- data/lib/rubocop/cop/layout/{trailing_blank_lines.rb → trailing_empty_lines.rb} +1 -1
- data/lib/rubocop/cop/lint/debugger.rb +2 -2
- data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +1 -1
- data/lib/rubocop/cop/lint/{duplicated_key.rb → duplicate_hash_key.rb} +1 -1
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
- data/lib/rubocop/cop/lint/{multiple_compare.rb → multiple_comparison.rb} +1 -1
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +89 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +3 -3
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +4 -4
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
- data/lib/rubocop/cop/lint/{string_conversion_in_interpolation.rb → redundant_string_coercion.rb} +1 -1
- data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
- data/lib/rubocop/cop/lint/{handle_exceptions.rb → suppressed_exception.rb} +1 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +57 -23
- data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +1 -1
- data/lib/rubocop/cop/migration/department_name.rb +16 -1
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -7
- data/lib/rubocop/cop/mixin/{hash_alignment.rb → hash_alignment_styles.rb} +1 -1
- data/lib/rubocop/cop/mixin/line_length_help.rb +88 -0
- data/lib/rubocop/cop/mixin/nil_methods.rb +4 -4
- data/lib/rubocop/cop/mixin/rational_literal.rb +18 -0
- data/lib/rubocop/cop/mixin/statement_modifier.rb +2 -2
- data/lib/rubocop/cop/mixin/trailing_comma.rb +6 -3
- data/lib/rubocop/cop/naming/{uncommunicative_block_param_name.rb → block_parameter_name.rb} +3 -3
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -5
- data/lib/rubocop/cop/naming/{uncommunicative_method_param_name.rb → method_parameter_name.rb} +4 -4
- data/lib/rubocop/cop/naming/predicate_name.rb +6 -6
- data/lib/rubocop/cop/offense.rb +11 -0
- data/lib/rubocop/cop/registry.rb +7 -2
- data/lib/rubocop/cop/style/alias.rb +1 -1
- data/lib/rubocop/cop/style/array_join.rb +1 -1
- data/lib/rubocop/cop/style/attr.rb +8 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
- data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
- data/lib/rubocop/cop/style/even_odd.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +3 -2
- data/lib/rubocop/cop/style/if_unless_modifier.rb +38 -3
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/ip_addresses.rb +4 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +168 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +54 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +4 -207
- data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +5 -1
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +5 -5
- data/lib/rubocop/cop/style/next.rb +5 -5
- data/lib/rubocop/cop/style/numeric_literals.rb +7 -3
- data/lib/rubocop/cop/style/numeric_predicate.rb +4 -3
- data/lib/rubocop/cop/style/option_hash.rb +3 -3
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +7 -7
- data/lib/rubocop/cop/style/redundant_parentheses.rb +3 -3
- data/lib/rubocop/cop/style/redundant_return.rb +2 -8
- data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +7 -1
- data/lib/rubocop/cop/style/trivial_accessors.rb +5 -5
- data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +16 -1
- data/lib/rubocop/cop/team.rb +5 -0
- data/lib/rubocop/formatter/base_formatter.rb +2 -2
- data/lib/rubocop/formatter/clang_style_formatter.rb +1 -3
- data/lib/rubocop/formatter/json_formatter.rb +6 -5
- data/lib/rubocop/formatter/tap_formatter.rb +1 -3
- data/lib/rubocop/node_pattern.rb +1 -1
- data/lib/rubocop/options.rb +8 -8
- data/lib/rubocop/processed_source.rb +1 -1
- data/lib/rubocop/rake_task.rb +1 -0
- data/lib/rubocop/result_cache.rb +23 -7
- data/lib/rubocop/rspec/shared_contexts.rb +5 -0
- data/lib/rubocop/runner.rb +18 -2
- data/lib/rubocop/target_ruby.rb +151 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +38 -22
- metadata +40 -25
- data/lib/rubocop/cop/mixin/safe_mode.rb +0 -24
@@ -8,9 +8,9 @@ module RuboCop
|
|
8
8
|
# In Ruby 2.3 or newer, squiggly heredocs (`<<~`) should be used. If you
|
9
9
|
# use the older rubies, you should introduce some library to your project
|
10
10
|
# (e.g. ActiveSupport, Powerpack or Unindent).
|
11
|
-
# Note: When `
|
11
|
+
# Note: When `Layout/LineLength`'s `AllowHeredoc` is false (not default),
|
12
12
|
# this cop does not add any offenses for long here documents to
|
13
|
-
# avoid `
|
13
|
+
# avoid `Layout/LineLength`'s offenses.
|
14
14
|
#
|
15
15
|
# @example EnforcedStyle: squiggly (default)
|
16
16
|
# # bad
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
49
49
|
# something
|
50
50
|
# RUBY
|
51
51
|
#
|
52
|
-
class
|
52
|
+
class HeredocIndentation < Cop
|
53
53
|
include Heredoc
|
54
54
|
include ConfigurableEnforcedStyle
|
55
55
|
|
@@ -159,11 +159,11 @@ module RuboCop
|
|
159
159
|
end
|
160
160
|
|
161
161
|
def unlimited_heredoc_length?
|
162
|
-
config.for_cop('
|
162
|
+
config.for_cop('Layout/LineLength')['AllowHeredoc']
|
163
163
|
end
|
164
164
|
|
165
165
|
def max_line_length
|
166
|
-
config.for_cop('
|
166
|
+
config.for_cop('Layout/LineLength')['Max']
|
167
167
|
end
|
168
168
|
|
169
169
|
def correct_by_squiggly(node)
|
@@ -2,10 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'uri'
|
4
4
|
|
5
|
-
# rubocop:disable Metrics/ClassLength
|
6
5
|
module RuboCop
|
7
6
|
module Cop
|
8
|
-
module
|
7
|
+
module Layout
|
9
8
|
# This cop checks the length of lines in the source code.
|
10
9
|
# The maximum length is configurable.
|
11
10
|
# The tab size is configured in the `IndentationWidth`
|
@@ -21,14 +20,14 @@ module RuboCop
|
|
21
20
|
# If autocorrection is enabled, the following Layout cops
|
22
21
|
# are recommended to further format the broken lines.
|
23
22
|
#
|
24
|
-
# -
|
25
|
-
# -
|
26
|
-
# - AlignParameters
|
23
|
+
# - ParameterAlignment
|
24
|
+
# - ArgumentAlignment
|
27
25
|
# - ClosingParenthesisIndentation
|
28
|
-
# -
|
29
|
-
# -
|
30
|
-
# -
|
31
|
-
# -
|
26
|
+
# - FirstArgumentIndentation
|
27
|
+
# - FirstArrayElementIndentation
|
28
|
+
# - FirstHashElementIndentation
|
29
|
+
# - FirstParameterIndentation
|
30
|
+
# - HashAlignment
|
32
31
|
# - MultilineArrayLineBreaks
|
33
32
|
# - MultilineHashBraceLayout
|
34
33
|
# - MultilineHashKeyLineBreaks
|
@@ -58,6 +57,7 @@ module RuboCop
|
|
58
57
|
include ConfigurableMax
|
59
58
|
include IgnoredPattern
|
60
59
|
include RangeHelp
|
60
|
+
include LineLengthHelp
|
61
61
|
|
62
62
|
MSG = 'Line is too long. [%<length>d/%<max>d]'
|
63
63
|
|
@@ -68,6 +68,10 @@ module RuboCop
|
|
68
68
|
alias on_hash on_potential_breakable_node
|
69
69
|
alias on_send on_potential_breakable_node
|
70
70
|
|
71
|
+
def investigate(processed_source)
|
72
|
+
check_for_breakable_semicolons(processed_source)
|
73
|
+
end
|
74
|
+
|
71
75
|
def investigate_post_walk(processed_source)
|
72
76
|
processed_source.lines.each_with_index do |line, line_index|
|
73
77
|
check_line(line, line_index)
|
@@ -89,29 +93,41 @@ module RuboCop
|
|
89
93
|
return if breakable_node.nil?
|
90
94
|
|
91
95
|
line_index = breakable_node.first_line - 1
|
92
|
-
|
93
|
-
end
|
96
|
+
range = breakable_node.source_range
|
94
97
|
|
95
|
-
|
96
|
-
|
97
|
-
end
|
98
|
+
existing = breakable_range_by_line_index[line_index]
|
99
|
+
return if existing
|
98
100
|
|
99
|
-
|
100
|
-
@heredocs ||= extract_heredocs(processed_source.ast)
|
101
|
+
breakable_range_by_line_index[line_index] = range
|
101
102
|
end
|
102
103
|
|
103
|
-
def
|
104
|
-
|
104
|
+
def check_for_breakable_semicolons(processed_source)
|
105
|
+
tokens = processed_source.tokens.select { |t| t.type == :tSEMI }
|
106
|
+
tokens.reverse_each do |token|
|
107
|
+
range = breakable_range_after_semicolon(token)
|
108
|
+
breakable_range_by_line_index[range.line - 1] = range if range
|
109
|
+
end
|
105
110
|
end
|
106
111
|
|
107
|
-
def
|
108
|
-
|
112
|
+
def breakable_range_after_semicolon(semicolon_token)
|
113
|
+
range = semicolon_token.pos
|
114
|
+
end_pos = range.end_pos
|
115
|
+
next_range = range_between(end_pos, end_pos + 1)
|
116
|
+
return nil unless next_range.line == range.line
|
117
|
+
|
118
|
+
next_char = next_range.source
|
119
|
+
return nil if /[\r\n]/ =~ next_char
|
120
|
+
return nil if next_char == ';'
|
109
121
|
|
110
|
-
|
122
|
+
next_range
|
111
123
|
end
|
112
124
|
|
113
|
-
def
|
114
|
-
|
125
|
+
def breakable_range_by_line_index
|
126
|
+
@breakable_range_by_line_index ||= {}
|
127
|
+
end
|
128
|
+
|
129
|
+
def heredocs
|
130
|
+
@heredocs ||= extract_heredocs(processed_source.ast)
|
115
131
|
end
|
116
132
|
|
117
133
|
def highlight_start(line)
|
@@ -147,33 +163,12 @@ module RuboCop
|
|
147
163
|
def register_offense(loc, line, line_index)
|
148
164
|
message = format(MSG, length: line_length(line), max: max)
|
149
165
|
|
150
|
-
breakable_range =
|
166
|
+
breakable_range = breakable_range_by_line_index[line_index]
|
151
167
|
add_offense(breakable_range, location: loc, message: message) do
|
152
168
|
self.max = line_length(line)
|
153
169
|
end
|
154
170
|
end
|
155
171
|
|
156
|
-
def breakable_range(line, line_index)
|
157
|
-
return if line_in_heredoc?(line_index + 1)
|
158
|
-
|
159
|
-
semicolon_range = breakable_semicolon_range(line, line_index)
|
160
|
-
return semicolon_range if semicolon_range
|
161
|
-
|
162
|
-
breakable_node = breakable_nodes_by_line_index[line_index]
|
163
|
-
return breakable_node.source_range if breakable_node
|
164
|
-
end
|
165
|
-
|
166
|
-
def breakable_semicolon_range(line, line_index)
|
167
|
-
semicolon_separated_parts = line.split(';')
|
168
|
-
return if semicolon_separated_parts.length <= 1
|
169
|
-
|
170
|
-
column = semicolon_separated_parts.first.length + 1
|
171
|
-
range = source_range(processed_source.buffer, line_index, column, 1)
|
172
|
-
return if processed_source.commented?(range)
|
173
|
-
|
174
|
-
range
|
175
|
-
end
|
176
|
-
|
177
172
|
def excess_range(uri_range, line, line_index)
|
178
173
|
excessive_position = if uri_range && uri_range.begin < max
|
179
174
|
uri_range.end
|
@@ -222,53 +217,6 @@ module RuboCop
|
|
222
217
|
end
|
223
218
|
end
|
224
219
|
|
225
|
-
def allow_uri?
|
226
|
-
cop_config['AllowURI']
|
227
|
-
end
|
228
|
-
|
229
|
-
def ignore_cop_directives?
|
230
|
-
cop_config['IgnoreCopDirectives']
|
231
|
-
end
|
232
|
-
|
233
|
-
def allowed_uri_position?(line, uri_range)
|
234
|
-
uri_range.begin < max &&
|
235
|
-
(uri_range.end == line_length(line) ||
|
236
|
-
uri_range.end == line_length(line) - 1)
|
237
|
-
end
|
238
|
-
|
239
|
-
def find_excessive_uri_range(line)
|
240
|
-
last_uri_match = match_uris(line).last
|
241
|
-
return nil unless last_uri_match
|
242
|
-
|
243
|
-
begin_position, end_position =
|
244
|
-
last_uri_match.offset(0).map do |pos|
|
245
|
-
pos + indentation_difference(line)
|
246
|
-
end
|
247
|
-
return nil if begin_position < max && end_position < max
|
248
|
-
|
249
|
-
begin_position...end_position
|
250
|
-
end
|
251
|
-
|
252
|
-
def match_uris(string)
|
253
|
-
matches = []
|
254
|
-
string.scan(uri_regexp) do
|
255
|
-
matches << $LAST_MATCH_INFO if valid_uri?($LAST_MATCH_INFO[0])
|
256
|
-
end
|
257
|
-
matches
|
258
|
-
end
|
259
|
-
|
260
|
-
def valid_uri?(uri_ish_string)
|
261
|
-
URI.parse(uri_ish_string)
|
262
|
-
true
|
263
|
-
rescue URI::InvalidURIError, NoMethodError
|
264
|
-
false
|
265
|
-
end
|
266
|
-
|
267
|
-
def uri_regexp
|
268
|
-
@uri_regexp ||=
|
269
|
-
URI::DEFAULT_PARSER.make_regexp(cop_config['URISchemes'])
|
270
|
-
end
|
271
|
-
|
272
220
|
def check_directive_line(line, line_index)
|
273
221
|
return if line_length_without_directive(line) <= max
|
274
222
|
|
@@ -284,23 +232,6 @@ module RuboCop
|
|
284
232
|
)
|
285
233
|
end
|
286
234
|
|
287
|
-
def directive_on_source_line?(line_index)
|
288
|
-
source_line_number = line_index + processed_source.buffer.first_line
|
289
|
-
comment =
|
290
|
-
processed_source
|
291
|
-
.comments
|
292
|
-
.detect { |e| e.location.line == source_line_number }
|
293
|
-
|
294
|
-
return false unless comment
|
295
|
-
|
296
|
-
comment.text.match(CommentConfig::COMMENT_DIRECTIVE_REGEXP)
|
297
|
-
end
|
298
|
-
|
299
|
-
def line_length_without_directive(line)
|
300
|
-
before_comment, = line.split(CommentConfig::COMMENT_DIRECTIVE_REGEXP)
|
301
|
-
before_comment.rstrip.length
|
302
|
-
end
|
303
|
-
|
304
235
|
def check_uri_line(line, line_index)
|
305
236
|
uri_range = find_excessive_uri_range(line)
|
306
237
|
return if uri_range && allowed_uri_position?(line, uri_range)
|
@@ -315,4 +246,3 @@ module RuboCop
|
|
315
246
|
end
|
316
247
|
end
|
317
248
|
end
|
318
|
-
# rubocop:enable Metrics/ClassLength
|
@@ -97,7 +97,8 @@ module RuboCop
|
|
97
97
|
def line_break_necessary_in_args?(node)
|
98
98
|
needed_length = node.source_range.column +
|
99
99
|
node.source.lines.first.length +
|
100
|
-
block_arg_string(node.arguments).length +
|
100
|
+
block_arg_string(node, node.arguments).length +
|
101
|
+
PIPE_SIZE
|
101
102
|
needed_length > max_line_length
|
102
103
|
end
|
103
104
|
|
@@ -115,7 +116,8 @@ module RuboCop
|
|
115
116
|
newlines: false
|
116
117
|
).end_pos
|
117
118
|
range = range_between(node.loc.begin.end.begin_pos, end_pos)
|
118
|
-
corrector.replace(range,
|
119
|
+
corrector.replace(range,
|
120
|
+
" |#{block_arg_string(node, node.arguments)}|")
|
119
121
|
end
|
120
122
|
|
121
123
|
def autocorrect_body(corrector, node, block_body)
|
@@ -131,14 +133,21 @@ module RuboCop
|
|
131
133
|
"\n #{' ' * block_start_col}")
|
132
134
|
end
|
133
135
|
|
134
|
-
def block_arg_string(args)
|
135
|
-
args.children.map do |arg|
|
136
|
+
def block_arg_string(node, args)
|
137
|
+
arg_string = args.children.map do |arg|
|
136
138
|
if arg.mlhs_type?
|
137
|
-
"(#{block_arg_string(arg)})"
|
139
|
+
"(#{block_arg_string(node, arg)})"
|
138
140
|
else
|
139
141
|
arg.source
|
140
142
|
end
|
141
143
|
end.join(', ')
|
144
|
+
arg_string += ',' if include_trailing_comma?(node.arguments)
|
145
|
+
arg_string
|
146
|
+
end
|
147
|
+
|
148
|
+
def include_trailing_comma?(args)
|
149
|
+
arg_count = args.each_descendant(:arg).to_a.size
|
150
|
+
arg_count == 1 && args.source.include?(',')
|
142
151
|
end
|
143
152
|
end
|
144
153
|
end
|
@@ -30,10 +30,12 @@ module RuboCop
|
|
30
30
|
|
31
31
|
DO = 'do'
|
32
32
|
SAFE_NAVIGATION = '&.'
|
33
|
+
NAMESPACE_OPERATOR = '::'
|
33
34
|
ACCEPT_LEFT_PAREN =
|
34
35
|
%w[break defined? next not rescue return super yield].freeze
|
35
36
|
ACCEPT_LEFT_SQUARE_BRACKET =
|
36
37
|
%w[super yield].freeze
|
38
|
+
ACCEPT_NAMESPACE_OPERATOR = 'super'
|
37
39
|
|
38
40
|
def on_and(node)
|
39
41
|
check(node, [:operator].freeze) if node.keyword?
|
@@ -193,6 +195,8 @@ module RuboCop
|
|
193
195
|
|
194
196
|
return false if accepted_opening_delimiter?(range, char)
|
195
197
|
return false if safe_navigation_call?(range, pos)
|
198
|
+
return false if accept_namespace_operator?(range) &&
|
199
|
+
namespace_operator?(range, pos)
|
196
200
|
|
197
201
|
char !~ /[\s;,#\\\)\}\]\.]/
|
198
202
|
end
|
@@ -212,10 +216,18 @@ module RuboCop
|
|
212
216
|
ACCEPT_LEFT_SQUARE_BRACKET.include?(range.source)
|
213
217
|
end
|
214
218
|
|
219
|
+
def accept_namespace_operator?(range)
|
220
|
+
ACCEPT_NAMESPACE_OPERATOR == range.source
|
221
|
+
end
|
222
|
+
|
215
223
|
def safe_navigation_call?(range, pos)
|
216
224
|
range.source_buffer.source[pos, 2].start_with?(SAFE_NAVIGATION)
|
217
225
|
end
|
218
226
|
|
227
|
+
def namespace_operator?(range, pos)
|
228
|
+
range.source_buffer.source[pos, 2].start_with?(NAMESPACE_OPERATOR)
|
229
|
+
end
|
230
|
+
|
219
231
|
def preceded_by_operator?(node, _range)
|
220
232
|
# regular dotted method calls bind more tightly than operators
|
221
233
|
# so we need to climb up the AST past them
|
@@ -3,24 +3,37 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Layout
|
6
|
-
# Checks that operators have space around them, except for **
|
7
|
-
#
|
6
|
+
# Checks that operators have space around them, except for ** which
|
7
|
+
# should or shouldn't have surrounding space depending on configuration.
|
8
8
|
#
|
9
9
|
# @example
|
10
10
|
# # bad
|
11
11
|
# total = 3*4
|
12
12
|
# "apple"+"juice"
|
13
13
|
# my_number = 38/4
|
14
|
-
# a ** b
|
15
14
|
#
|
16
15
|
# # good
|
17
16
|
# total = 3 * 4
|
18
17
|
# "apple" + "juice"
|
19
18
|
# my_number = 38 / 4
|
19
|
+
#
|
20
|
+
# @example EnforcedStyleForExponentOperator: no_space (default)
|
21
|
+
# # bad
|
22
|
+
# a ** b
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# a**b
|
26
|
+
#
|
27
|
+
# @example EnforcedStyleForExponentOperator: space
|
28
|
+
# # bad
|
20
29
|
# a**b
|
30
|
+
#
|
31
|
+
# # good
|
32
|
+
# a ** b
|
21
33
|
class SpaceAroundOperators < Cop
|
22
34
|
include PrecedingFollowingAlignment
|
23
35
|
include RangeHelp
|
36
|
+
include RationalLiteral
|
24
37
|
|
25
38
|
IRREGULAR_METHODS = %i[[] ! []=].freeze
|
26
39
|
EXCESSIVE_SPACE = ' '
|
@@ -53,6 +66,8 @@ module RuboCop
|
|
53
66
|
end
|
54
67
|
|
55
68
|
def on_send(node)
|
69
|
+
return if rational_literal?(node)
|
70
|
+
|
56
71
|
if node.setter_method?
|
57
72
|
on_special_asgn(node)
|
58
73
|
elsif regular_operator?(node)
|
@@ -101,7 +116,7 @@ module RuboCop
|
|
101
116
|
|
102
117
|
def autocorrect(range)
|
103
118
|
lambda do |corrector|
|
104
|
-
if range.source =~ /\*\*/
|
119
|
+
if range.source =~ /\*\*/ && !space_around_exponent_operator?
|
105
120
|
corrector.replace(range, '**')
|
106
121
|
elsif range.source.end_with?("\n")
|
107
122
|
corrector.replace(range, " #{range.source.strip}\n")
|
@@ -138,8 +153,10 @@ module RuboCop
|
|
138
153
|
end
|
139
154
|
|
140
155
|
def offense_message(type, operator, with_space, right_operand)
|
141
|
-
if
|
142
|
-
|
156
|
+
if should_not_have_surrounding_space?(operator)
|
157
|
+
return if with_space.is?(operator.source)
|
158
|
+
|
159
|
+
"Space around operator `#{operator.source}` detected."
|
143
160
|
elsif with_space.source !~ /^\s.*\s$/
|
144
161
|
"Surrounding space missing for operator `#{operator.source}`."
|
145
162
|
elsif excess_leading_space?(type, operator, with_space) ||
|
@@ -169,13 +186,21 @@ module RuboCop
|
|
169
186
|
end
|
170
187
|
|
171
188
|
def align_hash_cop_config
|
172
|
-
config.for_cop('Layout/
|
189
|
+
config.for_cop('Layout/HashAlignment')
|
173
190
|
end
|
174
191
|
|
175
192
|
def hash_table_style?
|
176
193
|
align_hash_cop_config &&
|
177
194
|
align_hash_cop_config['EnforcedHashRocketStyle'] == 'table'
|
178
195
|
end
|
196
|
+
|
197
|
+
def space_around_exponent_operator?
|
198
|
+
cop_config['EnforcedStyleForExponentOperator'] == 'space'
|
199
|
+
end
|
200
|
+
|
201
|
+
def should_not_have_surrounding_space?(operator)
|
202
|
+
operator.is?('**') ? !space_around_exponent_operator? : false
|
203
|
+
end
|
179
204
|
end
|
180
205
|
end
|
181
206
|
end
|
@@ -41,6 +41,14 @@ module RuboCop
|
|
41
41
|
def on_block(node)
|
42
42
|
return if node.keywords?
|
43
43
|
|
44
|
+
# Do not register an offense for multi-line braces when specifying
|
45
|
+
# `EnforcedStyle: no_space`. It will conflict with auto-correction
|
46
|
+
# by `EnforcedStyle: line_count_based` of `Style/BlockDelimiters` cop.
|
47
|
+
# That means preventing auto-correction to incorrect auto-corrected
|
48
|
+
# code.
|
49
|
+
# See: https://github.com/rubocop-hq/rubocop/issues/7534
|
50
|
+
return if conflict_with_block_delimiters?(node)
|
51
|
+
|
44
52
|
left_brace = node.loc.begin
|
45
53
|
space_plus_brace = range_with_surrounding_space(range: left_brace)
|
46
54
|
used_style =
|
@@ -110,6 +118,15 @@ module RuboCop
|
|
110
118
|
end
|
111
119
|
end
|
112
120
|
|
121
|
+
def conflict_with_block_delimiters?(node)
|
122
|
+
block_delimiters_style == 'line_count_based' &&
|
123
|
+
style == :no_space && node.multiline?
|
124
|
+
end
|
125
|
+
|
126
|
+
def block_delimiters_style
|
127
|
+
config.for_cop('Style/BlockDelimiters')['EnforcedStyle']
|
128
|
+
end
|
129
|
+
|
113
130
|
def empty_braces?(loc)
|
114
131
|
loc.begin.end_pos == loc.end.begin_pos
|
115
132
|
end
|
@@ -43,9 +43,9 @@ module RuboCop
|
|
43
43
|
PATTERN
|
44
44
|
|
45
45
|
def_node_matcher :debugger_call?, <<~PATTERN
|
46
|
-
{(send {nil? #kernel?} {:debugger :byebug :remote_byebug} ...)
|
46
|
+
{(send {nil? #kernel?} {:debugger :byebug :remote_byebug :console} ...)
|
47
47
|
(send (send {#kernel? nil?} :binding)
|
48
|
-
{:pry :remote_pry :pry_remote} ...)
|
48
|
+
{:pry :remote_pry :pry_remote :console} ...)
|
49
49
|
(send (const {nil? (cbase)} :Pry) :rescue ...)
|
50
50
|
(send nil? {:save_and_open_page
|
51
51
|
:save_and_open_screenshot
|
@@ -22,7 +22,7 @@ module RuboCop
|
|
22
22
|
# num = 0
|
23
23
|
# sum = numbers.each_with_object(num) { |e, a| a += e }
|
24
24
|
class EachWithObjectArgument < Cop
|
25
|
-
MSG = 'The argument to each_with_object
|
25
|
+
MSG = 'The argument to each_with_object cannot be immutable.'
|
26
26
|
|
27
27
|
def_node_matcher :each_with_object?, <<~PATTERN
|
28
28
|
({send csend} _ :each_with_object $_)
|
@@ -117,7 +117,7 @@ module RuboCop
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def correct_visibility?(node, modifier, ignored_methods)
|
120
|
-
return true if modifier.nil? || modifier.
|
120
|
+
return true if modifier.nil? || modifier.method?(:public)
|
121
121
|
|
122
122
|
ignored_methods.include?(node.method_name)
|
123
123
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# `Dir[...]` and `Dir.glob(...)` do not make any guarantees about
|
7
|
+
# the order in which files are returned. The final order is
|
8
|
+
# determined by the operating system and file system.
|
9
|
+
# This means that using them in cases where the order matters,
|
10
|
+
# such as requiring files, can lead to intermittent failures
|
11
|
+
# that are hard to debug. To ensure this doesn't happen,
|
12
|
+
# always sort the list.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
#
|
16
|
+
# # bad
|
17
|
+
# Dir["./lib/**/*.rb"].each do |file|
|
18
|
+
# require file
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# Dir["./lib/**/*.rb"].sort.each do |file|
|
23
|
+
# require file
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
#
|
28
|
+
# # bad
|
29
|
+
# Dir.glob(Rails.root.join(__dir__, 'test', '*.rb')) do |file|
|
30
|
+
# require file
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# # good
|
34
|
+
# Dir.glob(Rails.root.join(__dir__, 'test', '*.rb')).sort.each do |file|
|
35
|
+
# require file
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
class NonDeterministicRequireOrder < Cop
|
39
|
+
MSG = 'Sort files before requiring them.'
|
40
|
+
|
41
|
+
def on_block(node)
|
42
|
+
return unless node.body
|
43
|
+
return unless unsorted_dir_loop?(node.send_node)
|
44
|
+
|
45
|
+
loop_variable(node.arguments) do |var_name|
|
46
|
+
return unless var_is_required?(node.body, var_name)
|
47
|
+
|
48
|
+
add_offense(node.send_node)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def autocorrect(node)
|
53
|
+
if unsorted_dir_block?(node)
|
54
|
+
lambda do |corrector|
|
55
|
+
corrector.replace(node.loc.expression, "#{node.source}.sort.each")
|
56
|
+
end
|
57
|
+
else
|
58
|
+
lambda do |corrector|
|
59
|
+
source = node.receiver.source
|
60
|
+
corrector.replace(node.loc.expression, "#{source}.sort.each")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def unsorted_dir_loop?(node)
|
68
|
+
unsorted_dir_block?(node) || unsorted_dir_each?(node)
|
69
|
+
end
|
70
|
+
|
71
|
+
def_node_matcher :unsorted_dir_block?, <<~PATTERN
|
72
|
+
(send (const nil? :Dir) :glob ...)
|
73
|
+
PATTERN
|
74
|
+
|
75
|
+
def_node_matcher :unsorted_dir_each?, <<~PATTERN
|
76
|
+
(send (send (const nil? :Dir) {:[] :glob} ...) :each)
|
77
|
+
PATTERN
|
78
|
+
|
79
|
+
def_node_matcher :loop_variable, <<~PATTERN
|
80
|
+
(args (arg $_))
|
81
|
+
PATTERN
|
82
|
+
|
83
|
+
def_node_search :var_is_required?, <<~PATTERN
|
84
|
+
(send nil? :require (lvar %1))
|
85
|
+
PATTERN
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|