rubocop 1.32.0 → 1.37.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 +104 -16
- data/config/obsoletion.yml +23 -1
- data/lib/rubocop/arguments_env.rb +17 -0
- data/lib/rubocop/arguments_file.rb +17 -0
- data/lib/rubocop/cache_config.rb +29 -0
- data/lib/rubocop/cli/command/{auto_genenerate_config.rb → auto_generate_config.rb} +2 -2
- data/lib/rubocop/cli/command/execute_runner.rb +7 -7
- data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
- data/lib/rubocop/cli/command/suggest_extensions.rb +53 -15
- data/lib/rubocop/config.rb +1 -1
- data/lib/rubocop/config_finder.rb +68 -0
- data/lib/rubocop/config_loader.rb +12 -40
- data/lib/rubocop/config_loader_resolver.rb +1 -5
- data/lib/rubocop/config_obsoletion/changed_parameter.rb +5 -0
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +4 -0
- data/lib/rubocop/config_obsoletion.rb +7 -2
- data/lib/rubocop/cop/cop.rb +1 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +58 -0
- data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
- data/lib/rubocop/cop/generator/require_file_injector.rb +2 -2
- data/lib/rubocop/cop/generator.rb +1 -2
- data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +69 -0
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +62 -0
- data/lib/rubocop/cop/internal_affairs.rb +2 -0
- data/lib/rubocop/cop/layout/block_alignment.rb +16 -12
- data/lib/rubocop/cop/layout/block_end_newline.rb +35 -5
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +2 -0
- data/lib/rubocop/cop/layout/end_of_line.rb +4 -4
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +7 -1
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/indentation_width.rb +6 -2
- data/lib/rubocop/cop/layout/line_length.rb +4 -1
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +25 -9
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +28 -3
- data/lib/rubocop/cop/legacy/corrections_proxy.rb +1 -1
- data/lib/rubocop/cop/legacy/corrector.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +21 -8
- data/lib/rubocop/cop/lint/debugger.rb +26 -16
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
- data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +11 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
- data/lib/rubocop/cop/lint/duplicate_require.rb +1 -1
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/empty_class.rb +3 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +107 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +9 -9
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +4 -0
- data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +25 -6
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +6 -6
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +12 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +24 -8
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +29 -9
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +9 -3
- data/lib/rubocop/cop/lint/redundant_with_index.rb +13 -10
- data/lib/rubocop/cop/lint/redundant_with_object.rb +12 -11
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -2
- data/lib/rubocop/cop/lint/shadowed_exception.rb +15 -10
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +27 -3
- data/lib/rubocop/cop/lint/unreachable_loop.rb +9 -3
- data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +8 -6
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +2 -0
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -1
- data/lib/rubocop/cop/metrics/block_length.rb +6 -7
- data/lib/rubocop/cop/metrics/method_length.rb +8 -8
- data/lib/rubocop/cop/mixin/allowed_methods.rb +20 -1
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +17 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +17 -1
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +82 -4
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -6
- data/lib/rubocop/cop/mixin/method_complexity.rb +8 -13
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/range_help.rb +4 -5
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +6 -5
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +2 -2
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +24 -3
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +97 -1
- data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
- data/lib/rubocop/cop/style/arguments_forwarding.rb +2 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +26 -7
- data/lib/rubocop/cop/style/case_equality.rb +40 -10
- data/lib/rubocop/cop/style/class_and_module_children.rb +4 -4
- data/lib/rubocop/cop/style/class_equality_comparison.rb +32 -7
- data/lib/rubocop/cop/style/class_methods_definitions.rb +2 -1
- data/lib/rubocop/cop/style/collection_compact.rb +6 -1
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -1
- data/lib/rubocop/cop/style/double_negation.rb +2 -0
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +41 -6
- data/lib/rubocop/cop/style/each_with_object.rb +39 -8
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_heredoc.rb +15 -1
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +4 -0
- data/lib/rubocop/cop/style/for.rb +2 -0
- data/lib/rubocop/cop/style/format_string_token.rb +21 -8
- data/lib/rubocop/cop/style/guard_clause.rb +27 -16
- data/lib/rubocop/cop/style/hash_each_methods.rb +3 -1
- data/lib/rubocop/cop/style/hash_except.rb +0 -4
- data/lib/rubocop/cop/style/hash_syntax.rb +17 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +8 -6
- data/lib/rubocop/cop/style/magic_comment_format.rb +307 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +15 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -7
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -6
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +4 -1
- data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -1
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
- data/lib/rubocop/cop/style/next.rb +3 -5
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +16 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +28 -8
- data/lib/rubocop/cop/style/object_then.rb +2 -0
- data/lib/rubocop/cop/style/operator_method_call.rb +39 -0
- data/lib/rubocop/cop/style/perl_backrefs.rb +22 -1
- data/lib/rubocop/cop/style/proc.rb +4 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +3 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +24 -6
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
- data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +19 -22
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
- data/lib/rubocop/cop/style/redundant_self.rb +2 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +21 -6
- data/lib/rubocop/cop/style/redundant_sort_by.rb +24 -8
- data/lib/rubocop/cop/style/redundant_string_escape.rb +173 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +4 -2
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +14 -5
- data/lib/rubocop/cop/style/static_class.rb +32 -1
- data/lib/rubocop/cop/style/symbol_array.rb +3 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +38 -12
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -13
- data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -1
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +3 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/ext/range.rb +15 -0
- data/lib/rubocop/feature_loader.rb +94 -0
- data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +9 -3
- data/lib/rubocop/formatter/html_formatter.rb +3 -3
- data/lib/rubocop/formatter/markdown_formatter.rb +1 -1
- data/lib/rubocop/formatter/tap_formatter.rb +1 -1
- data/lib/rubocop/options.rb +13 -13
- data/lib/rubocop/result_cache.rb +22 -20
- data/lib/rubocop/rspec/shared_contexts.rb +13 -1
- data/lib/rubocop/runner.rb +4 -0
- data/lib/rubocop/server/cache.rb +41 -2
- data/lib/rubocop/server/cli.rb +26 -2
- data/lib/rubocop/server/client_command/exec.rb +5 -0
- data/lib/rubocop/server/core.rb +2 -1
- data/lib/rubocop/server/socket_reader.rb +5 -1
- data/lib/rubocop/server.rb +1 -1
- data/lib/rubocop/version.rb +8 -2
- data/lib/rubocop.rb +8 -3
- metadata +20 -9
- data/lib/rubocop/cop/mixin/ignored_methods.rb +0 -52
@@ -141,7 +141,7 @@ module RuboCop
|
|
141
141
|
|
142
142
|
corrector.remove(begin_range(node, body))
|
143
143
|
corrector.remove(end_range(node, body))
|
144
|
-
corrector.insert_before(method_call.loc.dot, '&')
|
144
|
+
corrector.insert_before(method_call.loc.dot, '&') unless method_call.safe_navigation?
|
145
145
|
handle_comments(corrector, node, method_call)
|
146
146
|
|
147
147
|
add_safe_nav_to_all_methods_in_chain(corrector, method_call, body)
|
@@ -250,7 +250,9 @@ module RuboCop
|
|
250
250
|
end
|
251
251
|
|
252
252
|
def unsafe_method?(send_node)
|
253
|
-
negated?(send_node) ||
|
253
|
+
negated?(send_node) ||
|
254
|
+
send_node.assignment? ||
|
255
|
+
(!send_node.dot? && !send_node.safe_navigation?)
|
254
256
|
end
|
255
257
|
|
256
258
|
def negated?(send_node)
|
@@ -148,7 +148,18 @@ module RuboCop
|
|
148
148
|
)
|
149
149
|
corrector.replace(range, and_operator)
|
150
150
|
corrector.remove(range_by_whole_lines(node.loc.end, include_final_newline: true))
|
151
|
-
|
151
|
+
|
152
|
+
wrap_condition(corrector, if_branch.condition)
|
153
|
+
end
|
154
|
+
|
155
|
+
def wrap_condition(corrector, condition)
|
156
|
+
# Handle `send` and `block` nodes that need to be wrapped in parens
|
157
|
+
# FIXME: autocorrection prevents syntax errors by wrapping the entire node in parens,
|
158
|
+
# but wrapping the argument list would be a more ergonomic correction.
|
159
|
+
node_to_check = condition&.block_type? ? condition.send_node : condition
|
160
|
+
return unless wrap_condition?(node_to_check)
|
161
|
+
|
162
|
+
corrector.wrap(condition, '(', ')')
|
152
163
|
end
|
153
164
|
|
154
165
|
def correct_for_outer_condition_modify_form_style(corrector, node, if_branch)
|
@@ -162,8 +173,6 @@ module RuboCop
|
|
162
173
|
end
|
163
174
|
|
164
175
|
def correct_for_comment(corrector, node, if_branch)
|
165
|
-
return if config.for_cop('Style/IfUnlessModifier')['Enabled']
|
166
|
-
|
167
176
|
comments = processed_source.ast_with_comments[if_branch]
|
168
177
|
comment_text = comments.map(&:text).join("\n") << "\n"
|
169
178
|
|
@@ -207,7 +216,7 @@ module RuboCop
|
|
207
216
|
end
|
208
217
|
|
209
218
|
def require_parentheses?(condition)
|
210
|
-
condition.
|
219
|
+
condition.call_type? && !condition.arguments.empty? && !condition.parenthesized? &&
|
211
220
|
!condition.comparison_method?
|
212
221
|
end
|
213
222
|
|
@@ -219,7 +228,7 @@ module RuboCop
|
|
219
228
|
|
220
229
|
def wrap_condition?(node)
|
221
230
|
node.and_type? || node.or_type? ||
|
222
|
-
(node.
|
231
|
+
(node.call_type? && node.arguments.any? && !node.parenthesized?)
|
223
232
|
end
|
224
233
|
|
225
234
|
def replace_condition(condition)
|
@@ -44,18 +44,49 @@ module RuboCop
|
|
44
44
|
# end
|
45
45
|
#
|
46
46
|
class StaticClass < Base
|
47
|
+
include RangeHelp
|
47
48
|
include VisibilityHelp
|
49
|
+
extend AutoCorrector
|
48
50
|
|
49
51
|
MSG = 'Prefer modules to classes with only class methods.'
|
50
52
|
|
51
53
|
def on_class(class_node)
|
52
54
|
return if class_node.parent_class
|
55
|
+
return unless class_convertible_to_module?(class_node)
|
53
56
|
|
54
|
-
add_offense(class_node)
|
57
|
+
add_offense(class_node) do |corrector|
|
58
|
+
autocorrect(corrector, class_node)
|
59
|
+
end
|
55
60
|
end
|
56
61
|
|
57
62
|
private
|
58
63
|
|
64
|
+
def autocorrect(corrector, class_node)
|
65
|
+
corrector.replace(class_node.loc.keyword, 'module')
|
66
|
+
corrector.insert_after(class_node.loc.name, "\nmodule_function\n")
|
67
|
+
|
68
|
+
class_elements(class_node).each do |node|
|
69
|
+
if node.defs_type?
|
70
|
+
autocorrect_def(corrector, node)
|
71
|
+
elsif node.sclass_type?
|
72
|
+
autocorrect_sclass(corrector, node)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def autocorrect_def(corrector, node)
|
78
|
+
corrector.remove(
|
79
|
+
range_between(node.receiver.source_range.begin_pos, node.loc.name.begin_pos)
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
def autocorrect_sclass(corrector, node)
|
84
|
+
corrector.remove(
|
85
|
+
range_between(node.loc.keyword.begin_pos, node.identifier.source_range.end_pos)
|
86
|
+
)
|
87
|
+
corrector.remove(node.loc.end)
|
88
|
+
end
|
89
|
+
|
59
90
|
def class_convertible_to_module?(class_node)
|
60
91
|
nodes = class_elements(class_node)
|
61
92
|
return false if nodes.empty?
|
@@ -65,11 +65,13 @@ module RuboCop
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def build_bracketed_array(node)
|
68
|
+
return '[]' if node.children.empty?
|
69
|
+
|
68
70
|
syms = node.children.map do |c|
|
69
71
|
if c.dsym_type?
|
70
72
|
string_literal = to_string_literal(c.source)
|
71
73
|
|
72
|
-
":#{
|
74
|
+
":#{trim_string_interpolation_escape_character(string_literal)}"
|
73
75
|
else
|
74
76
|
to_symbol_literal(c.value.to_s)
|
75
77
|
end
|
@@ -7,14 +7,15 @@ module RuboCop
|
|
7
7
|
#
|
8
8
|
# If you prefer a style that allows block for method with arguments,
|
9
9
|
# please set `true` to `AllowMethodsWithArguments`.
|
10
|
-
# respond_to , and `define_method?` methods are
|
11
|
-
# These are customizable with `
|
10
|
+
# respond_to , and `define_method?` methods are allowed by default.
|
11
|
+
# These are customizable with `AllowedMethods` option.
|
12
12
|
#
|
13
13
|
# @safety
|
14
|
-
# This cop is unsafe because
|
15
|
-
#
|
16
|
-
#
|
17
|
-
# an `ArgumentError
|
14
|
+
# This cop is unsafe because there is a difference that a `Proc`
|
15
|
+
# generated from `Symbol#to_proc` behaves as a lambda, while
|
16
|
+
# a `Proc` generated from a block does not.
|
17
|
+
# For example, a lambda will raise an `ArgumentError` if the
|
18
|
+
# number of arguments is wrong, but a non-lambda `Proc` will not.
|
18
19
|
#
|
19
20
|
# For example:
|
20
21
|
#
|
@@ -71,15 +72,25 @@ module RuboCop
|
|
71
72
|
# # some comment
|
72
73
|
# end
|
73
74
|
#
|
74
|
-
# @example
|
75
|
+
# @example AllowedMethods: [respond_to, define_method] (default)
|
75
76
|
# # good
|
76
77
|
# respond_to { |foo| foo.bar }
|
77
78
|
# define_method(:foo) { |foo| foo.bar }
|
78
79
|
#
|
80
|
+
#
|
81
|
+
# @example AllowedPatterns: [] (default)
|
82
|
+
# # bad
|
83
|
+
# something.map { |s| s.upcase }
|
84
|
+
#
|
85
|
+
# @example AllowedPatterns: ['map'] (default)
|
86
|
+
# # good
|
87
|
+
# something.map { |s| s.upcase }
|
88
|
+
#
|
79
89
|
class SymbolProc < Base
|
80
90
|
include CommentsHelp
|
81
91
|
include RangeHelp
|
82
|
-
include
|
92
|
+
include AllowedMethods
|
93
|
+
include AllowedPattern
|
83
94
|
extend AutoCorrector
|
84
95
|
|
85
96
|
MSG = 'Pass `&:%<method>s` as an argument to `%<block_method>s` instead of a block.'
|
@@ -103,15 +114,17 @@ module RuboCop
|
|
103
114
|
[Layout::SpaceBeforeBlockBraces]
|
104
115
|
end
|
105
116
|
|
106
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
117
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
107
118
|
def on_block(node)
|
108
119
|
symbol_proc?(node) do |dispatch_node, arguments_node, method_name|
|
109
120
|
# TODO: Rails-specific handling that we should probably make
|
110
121
|
# configurable - https://github.com/rubocop/rubocop/issues/1485
|
111
|
-
# we should
|
122
|
+
# we should allow lambdas & procs
|
112
123
|
return if proc_node?(dispatch_node)
|
124
|
+
return if unsafe_hash_usage?(dispatch_node)
|
125
|
+
return if unsafe_array_usage?(dispatch_node)
|
113
126
|
return if %i[lambda proc].include?(dispatch_node.method_name)
|
114
|
-
return if
|
127
|
+
return if allowed_method_name?(dispatch_node.method_name)
|
115
128
|
return if allow_if_method_has_argument?(node.send_node)
|
116
129
|
return if node.block_type? && destructuring_block_argument?(arguments_node)
|
117
130
|
return if allow_comments? && contains_comments?(node)
|
@@ -119,7 +132,7 @@ module RuboCop
|
|
119
132
|
register_offense(node, method_name, dispatch_node.method_name)
|
120
133
|
end
|
121
134
|
end
|
122
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
135
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
123
136
|
alias on_numblock on_block
|
124
137
|
|
125
138
|
def destructuring_block_argument?(argument_node)
|
@@ -128,6 +141,19 @@ module RuboCop
|
|
128
141
|
|
129
142
|
private
|
130
143
|
|
144
|
+
# See: https://github.com/rubocop/rubocop/issues/10864
|
145
|
+
def unsafe_hash_usage?(node)
|
146
|
+
node.receiver&.hash_type? && %i[reject select].include?(node.method_name)
|
147
|
+
end
|
148
|
+
|
149
|
+
def unsafe_array_usage?(node)
|
150
|
+
node.receiver&.array_type? && %i[min max].include?(node.method_name)
|
151
|
+
end
|
152
|
+
|
153
|
+
def allowed_method_name?(name)
|
154
|
+
allowed_method?(name) || matches_allowed_pattern?(name)
|
155
|
+
end
|
156
|
+
|
131
157
|
def register_offense(node, method_name, block_method_name)
|
132
158
|
block_start = node.loc.begin.begin_pos
|
133
159
|
block_end = node.loc.end.end_pos
|
@@ -71,7 +71,7 @@ module RuboCop
|
|
71
71
|
|
72
72
|
return if only_closing_parenthesis_is_last_line?(condition)
|
73
73
|
return if condition_as_parenthesized_one_line_pattern_matching?(condition)
|
74
|
-
return unless node.ternary? &&
|
74
|
+
return unless node.ternary? && offense?(node)
|
75
75
|
|
76
76
|
message = message(node)
|
77
77
|
|
@@ -166,22 +166,10 @@ module RuboCop
|
|
166
166
|
style == :require_parentheses_when_complex
|
167
167
|
end
|
168
168
|
|
169
|
-
def redundant_parentheses_enabled?
|
170
|
-
@config.for_cop('Style/RedundantParentheses').fetch('Enabled')
|
171
|
-
end
|
172
|
-
|
173
169
|
def parenthesized?(node)
|
174
170
|
node.begin_type?
|
175
171
|
end
|
176
172
|
|
177
|
-
# When this cop is configured to enforce parentheses and the
|
178
|
-
# `RedundantParentheses` cop is enabled, it will cause an infinite loop
|
179
|
-
# as they compete to add and remove the parentheses respectively.
|
180
|
-
def infinite_loop?
|
181
|
-
(require_parentheses? || require_parentheses_when_complex?) &&
|
182
|
-
redundant_parentheses_enabled?
|
183
|
-
end
|
184
|
-
|
185
173
|
def unsafe_autocorrect?(condition)
|
186
174
|
condition.children.any? do |child|
|
187
175
|
unparenthesized_method_call?(child) || below_ternary_precedence?(child)
|
@@ -63,6 +63,8 @@ module RuboCop
|
|
63
63
|
add_offense(node)
|
64
64
|
end
|
65
65
|
|
66
|
+
alias on_numblock on_block
|
67
|
+
|
66
68
|
private
|
67
69
|
|
68
70
|
def top_level_method_definition?(node)
|
@@ -75,7 +77,7 @@ module RuboCop
|
|
75
77
|
|
76
78
|
# @!method define_method_block?(node)
|
77
79
|
def_node_matcher :define_method_block?, <<~PATTERN
|
78
|
-
(block (send _ {:define_method} _) ...)
|
80
|
+
({block numblock} (send _ {:define_method} _) ...)
|
79
81
|
PATTERN
|
80
82
|
end
|
81
83
|
end
|
@@ -64,7 +64,7 @@ module RuboCop
|
|
64
64
|
|
65
65
|
MSG = 'Useless trailing comma present in block arguments.'
|
66
66
|
|
67
|
-
def on_block(node)
|
67
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
68
68
|
# lambda literal (`->`) never has block arguments.
|
69
69
|
return if node.send_node.lambda_literal?
|
70
70
|
return unless useless_trailing_comma?(node)
|
@@ -83,11 +83,13 @@ module RuboCop
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def build_bracketed_array(node)
|
86
|
+
return '[]' if node.children.empty?
|
87
|
+
|
86
88
|
words = node.children.map do |word|
|
87
89
|
if word.dstr_type?
|
88
90
|
string_literal = to_string_literal(word.source)
|
89
91
|
|
90
|
-
|
92
|
+
trim_string_interpolation_escape_character(string_literal)
|
91
93
|
else
|
92
94
|
to_string_literal(word.children[0])
|
93
95
|
end
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Ext
|
5
|
+
# Extensions to Parser::Source::Range
|
6
|
+
module Range
|
7
|
+
# Adds `Range#single_line?` to parallel `Node#single_line?`
|
8
|
+
def single_line?
|
9
|
+
first_line == last_line
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Parser::Source::Range.include RuboCop::Ext::Range
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
# This class handles loading files (a.k.a. features in Ruby) specified
|
5
|
+
# by `--require` command line option and `require` directive in the config.
|
6
|
+
#
|
7
|
+
# Normally, the given string is directly passed to `require`. If a string
|
8
|
+
# beginning with `.` is given, it is assumed to be relative to the given
|
9
|
+
# directory.
|
10
|
+
#
|
11
|
+
# If a string containing `-` is given, it will be used as is, but if we
|
12
|
+
# cannot find the file to load, we will replace `-` with `/` and try it
|
13
|
+
# again as when Bundler loads gems.
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
class FeatureLoader
|
17
|
+
class << self
|
18
|
+
# @param [String] config_directory_path
|
19
|
+
# @param [String] feature
|
20
|
+
def load(config_directory_path:, feature:)
|
21
|
+
new(config_directory_path: config_directory_path, feature: feature).load
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [String] config_directory_path
|
26
|
+
# @param [String] feature
|
27
|
+
def initialize(config_directory_path:, feature:)
|
28
|
+
@config_directory_path = config_directory_path
|
29
|
+
@feature = feature
|
30
|
+
end
|
31
|
+
|
32
|
+
def load
|
33
|
+
# Don't use `::Kernel.require(target)` to prevent the following error:
|
34
|
+
# https://github.com/rubocop/rubocop/issues/10893
|
35
|
+
require(target)
|
36
|
+
rescue ::LoadError => e
|
37
|
+
raise if e.path != target
|
38
|
+
|
39
|
+
begin
|
40
|
+
# Don't use `::Kernel.require(target)` to prevent the following error:
|
41
|
+
# https://github.com/rubocop/rubocop/issues/10893
|
42
|
+
require(namespaced_target)
|
43
|
+
rescue ::LoadError => error_for_namespaced_target
|
44
|
+
# NOTE: This wrap is necessary due to JRuby 9.3.4.0 incompatibility:
|
45
|
+
# https://github.com/jruby/jruby/issues/7316
|
46
|
+
raise LoadError, e if error_for_namespaced_target.path == namespaced_target
|
47
|
+
|
48
|
+
raise error_for_namespaced_target
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
# @return [String]
|
55
|
+
def namespaced_feature
|
56
|
+
@feature.tr('-', '/')
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [String]
|
60
|
+
def namespaced_target
|
61
|
+
if relative?
|
62
|
+
relative(namespaced_feature)
|
63
|
+
else
|
64
|
+
namespaced_feature
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# @param [String]
|
69
|
+
# @return [String]
|
70
|
+
def relative(feature)
|
71
|
+
::File.join(@config_directory_path, feature)
|
72
|
+
end
|
73
|
+
|
74
|
+
# @return [Boolean]
|
75
|
+
def relative?
|
76
|
+
@feature.start_with?('.')
|
77
|
+
end
|
78
|
+
|
79
|
+
# @param [LoadError] error
|
80
|
+
# @return [Boolean]
|
81
|
+
def seems_cannot_load_such_file_error?(error)
|
82
|
+
error.path == target
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [String]
|
86
|
+
def target
|
87
|
+
if relative?
|
88
|
+
relative(@feature)
|
89
|
+
else
|
90
|
+
@feature
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -70,7 +70,9 @@ module RuboCop
|
|
70
70
|
|
71
71
|
command += ' --auto-gen-only-exclude' if @options[:auto_gen_only_exclude]
|
72
72
|
|
73
|
-
if
|
73
|
+
if no_exclude_limit?
|
74
|
+
command += ' --no-exclude-limit'
|
75
|
+
elsif @exclude_limit_option
|
74
76
|
command += format(' --exclude-limit %<limit>d', limit: Integer(@exclude_limit_option))
|
75
77
|
end
|
76
78
|
command += ' --no-offense-counts' unless show_offense_counts?
|
@@ -161,7 +163,7 @@ module RuboCop
|
|
161
163
|
next unless value.is_a?(Array)
|
162
164
|
next if value.empty?
|
163
165
|
|
164
|
-
output_buffer.puts "# #{param}: #{value.join(', ')}"
|
166
|
+
output_buffer.puts "# #{param}: #{value.uniq.join(', ')}"
|
165
167
|
end
|
166
168
|
end
|
167
169
|
|
@@ -187,7 +189,7 @@ module RuboCop
|
|
187
189
|
return unless cfg.empty?
|
188
190
|
|
189
191
|
offending_files = @files_with_offenses[cop_name].sort
|
190
|
-
if offending_files.count > @exclude_limit
|
192
|
+
if !no_exclude_limit? && offending_files.count > @exclude_limit
|
191
193
|
output_buffer.puts ' Enabled: false'
|
192
194
|
else
|
193
195
|
output_exclude_list(output_buffer, offending_files, cop_name)
|
@@ -245,6 +247,10 @@ module RuboCop
|
|
245
247
|
def safe_autocorrect?(config)
|
246
248
|
config.fetch('Safe', true) && config.fetch('SafeAutoCorrect', true)
|
247
249
|
end
|
250
|
+
|
251
|
+
def no_exclude_limit?
|
252
|
+
@options[:no_exclude_limit] == false
|
253
|
+
end
|
248
254
|
end
|
249
255
|
end
|
250
256
|
end
|
@@ -93,12 +93,12 @@ module RuboCop
|
|
93
93
|
|
94
94
|
def highlighted_source_line(offense)
|
95
95
|
source_before_highlight(offense) +
|
96
|
-
|
96
|
+
highlight_source_tag(offense) +
|
97
97
|
source_after_highlight(offense) +
|
98
98
|
possible_ellipses(offense.location)
|
99
99
|
end
|
100
100
|
|
101
|
-
def
|
101
|
+
def highlight_source_tag(offense)
|
102
102
|
"<span class=\"highlight #{offense.severity}\">" \
|
103
103
|
"#{escape(offense.highlighted_area.source)}" \
|
104
104
|
'</span>'
|
@@ -115,7 +115,7 @@ module RuboCop
|
|
115
115
|
end
|
116
116
|
|
117
117
|
def possible_ellipses(location)
|
118
|
-
location.
|
118
|
+
location.single_line? ? '' : " #{ELLIPSES}"
|
119
119
|
end
|
120
120
|
|
121
121
|
def escape(string)
|
data/lib/rubocop/options.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'optparse'
|
4
|
-
|
4
|
+
require_relative 'arguments_env'
|
5
|
+
require_relative 'arguments_file'
|
5
6
|
|
6
7
|
module RuboCop
|
7
8
|
class IncorrectCopNameError < StandardError; end
|
@@ -24,7 +25,10 @@ module RuboCop
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def parse(command_line_args)
|
28
|
+
args_from_file = ArgumentsFile.read_as_arguments
|
29
|
+
args_from_env = ArgumentsEnv.read_as_arguments
|
27
30
|
args = args_from_file.concat(args_from_env).concat(command_line_args)
|
31
|
+
|
28
32
|
define_options.parse!(args)
|
29
33
|
|
30
34
|
@validator.validate_compatibility
|
@@ -45,18 +49,6 @@ module RuboCop
|
|
45
49
|
|
46
50
|
private
|
47
51
|
|
48
|
-
def args_from_file
|
49
|
-
if File.exist?('.rubocop') && !File.directory?('.rubocop')
|
50
|
-
File.read('.rubocop').shellsplit
|
51
|
-
else
|
52
|
-
[]
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def args_from_env
|
57
|
-
Shellwords.split(ENV.fetch('RUBOCOP_OPTS', ''))
|
58
|
-
end
|
59
|
-
|
60
52
|
def define_options
|
61
53
|
OptionParser.new do |opts|
|
62
54
|
opts.banner = rainbow.wrap('Usage: rubocop [options] [file1, file2, ...]').bright
|
@@ -169,6 +161,7 @@ module RuboCop
|
|
169
161
|
end
|
170
162
|
|
171
163
|
option(opts, '--exclude-limit COUNT') { @validator.validate_exclude_limit_option }
|
164
|
+
option(opts, '--no-exclude-limit')
|
172
165
|
|
173
166
|
option(opts, '--[no-]offense-counts')
|
174
167
|
option(opts, '--[no-]auto-gen-only-exclude')
|
@@ -400,6 +393,12 @@ module RuboCop
|
|
400
393
|
end
|
401
394
|
|
402
395
|
def validate_autocorrect
|
396
|
+
if @options.key?(:safe_autocorrect) && @options.key?(:autocorrect_all)
|
397
|
+
message = Rainbow(<<~MESSAGE).red
|
398
|
+
Error: Both safe and unsafe autocorrect options are specified, use only one.
|
399
|
+
MESSAGE
|
400
|
+
raise OptionArgumentError, message
|
401
|
+
end
|
403
402
|
return if @options.key?(:autocorrect)
|
404
403
|
return unless @options.key?(:disable_uncorrectable)
|
405
404
|
|
@@ -497,6 +496,7 @@ module RuboCop
|
|
497
496
|
disable_uncorrectable: ['Used with --autocorrect to annotate any',
|
498
497
|
'offenses that do not support autocorrect',
|
499
498
|
'with `rubocop:todo` comments.'],
|
499
|
+
no_exclude_limit: ['Do not set the limit for how many files to exclude.'],
|
500
500
|
force_exclusion: ['Any files excluded by `Exclude` in configuration',
|
501
501
|
'files will be excluded, even if given explicitly',
|
502
502
|
'as arguments.'],
|