rubocop 0.79.0 → 0.83.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/LICENSE.txt +1 -1
- data/README.md +5 -5
- data/config/default.yml +184 -50
- data/lib/rubocop.rb +15 -5
- data/lib/rubocop/ast/builder.rb +2 -0
- data/lib/rubocop/ast/node.rb +12 -19
- data/lib/rubocop/ast/node/array_node.rb +13 -0
- data/lib/rubocop/ast/node/block_node.rb +5 -1
- data/lib/rubocop/ast/node/case_match_node.rb +56 -0
- data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +8 -0
- data/lib/rubocop/ast/node/regexp_node.rb +2 -4
- data/lib/rubocop/ast/node/send_node.rb +4 -0
- data/lib/rubocop/ast/traversal.rb +20 -9
- data/lib/rubocop/cli.rb +11 -5
- data/lib/rubocop/comment_config.rb +6 -1
- data/lib/rubocop/config.rb +40 -10
- data/lib/rubocop/config_loader.rb +43 -33
- data/lib/rubocop/config_loader_resolver.rb +28 -1
- data/lib/rubocop/config_obsoletion.rb +4 -1
- data/lib/rubocop/config_validator.rb +18 -1
- data/lib/rubocop/cop/badge.rb +5 -5
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +1 -1
- data/lib/rubocop/cop/corrector.rb +48 -24
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -2
- data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +3 -3
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/string_literal_corrector.rb +2 -2
- data/lib/rubocop/cop/generator.rb +3 -2
- data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/array_alignment.rb +53 -10
- data/lib/rubocop/cop/layout/block_end_newline.rb +5 -3
- data/lib/rubocop/cop/layout/condition_position.rb +12 -2
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/else_alignment.rb +8 -0
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +68 -0
- data/lib/rubocop/cop/layout/end_of_line.rb +2 -2
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +16 -10
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/{tab.rb → indentation_style.rb} +48 -6
- data/lib/rubocop/cop/layout/leading_comment_space.rb +34 -3
- data/lib/rubocop/cop/layout/line_length.rb +36 -4
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +0 -4
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +13 -4
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +3 -3
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +133 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +37 -2
- data/lib/rubocop/cop/layout/space_before_first_arg.rb +8 -0
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -2
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -9
- data/lib/rubocop/cop/layout/space_inside_range_literal.rb +2 -2
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +2 -2
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +38 -0
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +14 -0
- data/lib/rubocop/cop/lint/boolean_symbol.rb +12 -0
- data/lib/rubocop/cop/lint/debugger.rb +2 -2
- data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -5
- data/lib/rubocop/cop/lint/empty_when.rb +29 -6
- data/lib/rubocop/cop/lint/ensure_return.rb +18 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
- data/lib/rubocop/cop/lint/inherit_exception.rb +1 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +1 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +10 -13
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/loop.rb +6 -4
- data/lib/rubocop/cop/lint/multiple_comparison.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +2 -2
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +21 -9
- data/lib/rubocop/cop/lint/percent_string_array.rb +2 -2
- data/lib/rubocop/cop/lint/raise_exception.rb +75 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +1 -6
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +12 -7
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -1
- data/lib/rubocop/cop/lint/struct_new_override.rb +58 -0
- data/lib/rubocop/cop/lint/suppressed_exception.rb +12 -28
- data/lib/rubocop/cop/lint/unified_integer.rb +0 -2
- data/lib/rubocop/cop/lint/unused_method_argument.rb +32 -6
- data/lib/rubocop/cop/lint/uri_regexp.rb +4 -4
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +12 -0
- data/lib/rubocop/cop/lint/useless_assignment.rb +3 -2
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +5 -0
- data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -0
- data/lib/rubocop/cop/migration/department_name.rb +36 -10
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +4 -0
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +6 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +16 -1
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +178 -0
- data/lib/rubocop/cop/mixin/line_length_help.rb +2 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +5 -0
- data/lib/rubocop/cop/mixin/parser_diagnostic.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +7 -22
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +5 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -10
- data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +2 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +1 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/naming/method_name.rb +26 -0
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
- data/lib/rubocop/cop/registry.rb +11 -4
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +26 -6
- data/lib/rubocop/cop/style/alias.rb +4 -4
- data/lib/rubocop/cop/style/and_or.rb +5 -6
- data/lib/rubocop/cop/style/array_join.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +60 -1
- data/lib/rubocop/cop/style/case_equality.rb +24 -1
- data/lib/rubocop/cop/style/character_literal.rb +2 -2
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +8 -8
- data/lib/rubocop/cop/style/copyright.rb +1 -1
- data/lib/rubocop/cop/style/dir.rb +1 -1
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +49 -0
- data/lib/rubocop/cop/style/documentation.rb +43 -5
- data/lib/rubocop/cop/style/double_cop_disable_directive.rb +1 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/each_with_object.rb +3 -3
- data/lib/rubocop/cop/style/empty_method.rb +1 -5
- data/lib/rubocop/cop/style/end_block.rb +6 -0
- data/lib/rubocop/cop/style/even_odd.rb +1 -1
- data/lib/rubocop/cop/style/expand_path_arguments.rb +3 -3
- data/lib/rubocop/cop/style/exponential_notation.rb +119 -0
- data/lib/rubocop/cop/style/format_string.rb +2 -2
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +89 -11
- data/lib/rubocop/cop/style/guard_clause.rb +25 -2
- data/lib/rubocop/cop/style/hash_each_methods.rb +89 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +3 -5
- data/lib/rubocop/cop/style/hash_transform_keys.rb +83 -0
- data/lib/rubocop/cop/style/hash_transform_values.rb +80 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +23 -3
- data/lib/rubocop/cop/style/if_with_semicolon.rb +16 -0
- data/lib/rubocop/cop/style/inverse_methods.rb +9 -5
- data/lib/rubocop/cop/style/lambda.rb +3 -2
- data/lib/rubocop/cop/style/lambda_call.rb +1 -21
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +5 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +5 -4
- data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
- data/lib/rubocop/cop/style/module_function.rb +58 -12
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +1 -1
- data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +16 -1
- data/lib/rubocop/cop/style/mutable_constant.rb +2 -4
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +4 -4
- data/lib/rubocop/cop/style/next.rb +2 -2
- data/lib/rubocop/cop/style/nil_comparison.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +4 -4
- data/lib/rubocop/cop/style/not.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
- data/lib/rubocop/cop/style/one_line_conditional.rb +4 -3
- data/lib/rubocop/cop/style/optional_arguments.rb +1 -1
- data/lib/rubocop/cop/style/or_assignment.rb +4 -3
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- data/lib/rubocop/cop/style/perl_backrefs.rb +2 -2
- data/lib/rubocop/cop/style/proc.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +18 -6
- data/lib/rubocop/cop/style/redundant_conditional.rb +1 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +3 -3
- data/lib/rubocop/cop/style/redundant_interpolation.rb +2 -2
- data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -2
- data/lib/rubocop/cop/style/redundant_return.rb +5 -7
- data/lib/rubocop/cop/style/redundant_self.rb +1 -1
- data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
- data/lib/rubocop/cop/style/return_nil.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/slicing_with_range.rb +39 -0
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -4
- data/lib/rubocop/cop/style/string_hash_keys.rb +1 -1
- data/lib/rubocop/cop/style/symbol_array.rb +3 -3
- data/lib/rubocop/cop/style/symbol_literal.rb +2 -2
- data/lib/rubocop/cop/style/ternary_parentheses.rb +2 -3
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +35 -22
- data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +41 -0
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +88 -0
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +44 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/unpack_first.rb +0 -4
- data/lib/rubocop/cop/style/variable_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +1 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +1 -1
- data/lib/rubocop/cop/util.rb +24 -0
- data/lib/rubocop/cop/variable_force.rb +4 -1
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -0
- data/lib/rubocop/cop/variable_force/scope.rb +1 -0
- data/lib/rubocop/cop/variable_force/variable.rb +1 -0
- data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/formatter/junit_formatter.rb +74 -0
- data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
- data/lib/rubocop/formatter/tap_formatter.rb +1 -1
- data/lib/rubocop/name_similarity.rb +12 -9
- data/lib/rubocop/node_pattern.rb +96 -10
- data/lib/rubocop/options.rb +18 -5
- data/lib/rubocop/processed_source.rb +1 -4
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +1 -1
- data/lib/rubocop/rspec/shared_contexts.rb +0 -4
- data/lib/rubocop/runner.rb +7 -2
- data/lib/rubocop/target_finder.rb +6 -4
- data/lib/rubocop/target_ruby.rb +2 -2
- data/lib/rubocop/version.rb +1 -1
- metadata +35 -25
- data/lib/rubocop/cop/lint/end_in_method.rb +0 -40
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +0 -209
- data/lib/rubocop/formatter/disabled_lines_formatter.rb +0 -57
- data/lib/rubocop/string_util.rb +0 -14
@@ -38,9 +38,34 @@ module RuboCop
|
|
38
38
|
# def do_something(unused)
|
39
39
|
# end
|
40
40
|
#
|
41
|
+
# @example IgnoreNotImplementedMethods: true (default)
|
42
|
+
# # good
|
43
|
+
# def do_something(unused)
|
44
|
+
# raise NotImplementedError
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# def do_something_else(unused)
|
48
|
+
# fail "TODO"
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# @example IgnoreNotImplementedMethods: false
|
52
|
+
# # bad
|
53
|
+
# def do_something(unused)
|
54
|
+
# raise NotImplementedError
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# def do_something_else(unused)
|
58
|
+
# fail "TODO"
|
59
|
+
# end
|
60
|
+
#
|
41
61
|
class UnusedMethodArgument < Cop
|
42
62
|
include UnusedArgument
|
43
63
|
|
64
|
+
def_node_matcher :not_implemented?, <<~PATTERN
|
65
|
+
{(send nil? :raise (const nil? :NotImplementedError))
|
66
|
+
(send nil? :fail ...)}
|
67
|
+
PATTERN
|
68
|
+
|
44
69
|
def autocorrect(node)
|
45
70
|
UnusedArgCorrector.correct(processed_source, node)
|
46
71
|
end
|
@@ -51,16 +76,17 @@ module RuboCop
|
|
51
76
|
return unless variable.method_argument?
|
52
77
|
return if variable.keyword_argument? &&
|
53
78
|
cop_config['AllowUnusedKeywordArguments']
|
54
|
-
|
55
|
-
if cop_config['IgnoreEmptyMethods']
|
56
|
-
body = variable.scope.node.body
|
57
|
-
|
58
|
-
return if body.nil?
|
59
|
-
end
|
79
|
+
return if ignored_method?(variable.scope.node.body)
|
60
80
|
|
61
81
|
super
|
62
82
|
end
|
63
83
|
|
84
|
+
def ignored_method?(body)
|
85
|
+
cop_config['IgnoreEmptyMethods'] && body.nil? ||
|
86
|
+
cop_config['IgnoreNotImplementedMethods'] &&
|
87
|
+
not_implemented?(body)
|
88
|
+
end
|
89
|
+
|
64
90
|
def message(variable)
|
65
91
|
message = +"Unused method argument - `#{variable.name}`."
|
66
92
|
|
@@ -21,7 +21,7 @@ module RuboCop
|
|
21
21
|
def_node_matcher :uri_regexp_with_argument?, <<~PATTERN
|
22
22
|
(send
|
23
23
|
(const ${nil? cbase} :URI) :regexp
|
24
|
-
(str
|
24
|
+
${(str _) (array ...)})
|
25
25
|
PATTERN
|
26
26
|
|
27
27
|
def_node_matcher :uri_regexp_without_argument?, <<~PATTERN
|
@@ -32,7 +32,7 @@ module RuboCop
|
|
32
32
|
def on_send(node)
|
33
33
|
uri_regexp_with_argument?(node) do |double_colon, arg|
|
34
34
|
register_offense(
|
35
|
-
node, top_level: double_colon ? '::' : '', arg: "(
|
35
|
+
node, top_level: double_colon ? '::' : '', arg: "(#{arg.source})"
|
36
36
|
)
|
37
37
|
end
|
38
38
|
|
@@ -51,10 +51,10 @@ module RuboCop
|
|
51
51
|
double_colon, arg = captured_values
|
52
52
|
|
53
53
|
top_level = double_colon ? '::' : ''
|
54
|
-
argument = arg ? "(
|
54
|
+
argument = arg ? "(#{arg.source})" : ''
|
55
55
|
|
56
56
|
corrector.replace(
|
57
|
-
node
|
57
|
+
node,
|
58
58
|
"#{top_level}URI::DEFAULT_PARSER.make_regexp#{argument}"
|
59
59
|
)
|
60
60
|
end
|
@@ -125,6 +125,8 @@ module RuboCop
|
|
125
125
|
# delegate :method_a, to: :method_b
|
126
126
|
# end
|
127
127
|
class UselessAccessModifier < Cop
|
128
|
+
include RangeHelp
|
129
|
+
|
128
130
|
MSG = 'Useless `%<current>s` access modifier.'
|
129
131
|
|
130
132
|
def on_class(node)
|
@@ -145,6 +147,16 @@ module RuboCop
|
|
145
147
|
check_node(node.children[1]) # singleton class body
|
146
148
|
end
|
147
149
|
|
150
|
+
def autocorrect(node)
|
151
|
+
lambda do |corrector|
|
152
|
+
range = range_by_whole_lines(
|
153
|
+
node.source_range, include_final_newline: true
|
154
|
+
)
|
155
|
+
|
156
|
+
corrector.remove(range)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
148
160
|
private
|
149
161
|
|
150
162
|
def_node_matcher :static_method_definition?, <<~PATTERN
|
@@ -31,7 +31,6 @@ module RuboCop
|
|
31
31
|
# do_something(some_var)
|
32
32
|
# end
|
33
33
|
class UselessAssignment < Cop
|
34
|
-
include NameSimilarity
|
35
34
|
MSG = 'Useless assignment to variable - `%<variable>s`.'
|
36
35
|
|
37
36
|
def join_force?(force_class)
|
@@ -94,7 +93,9 @@ module RuboCop
|
|
94
93
|
end
|
95
94
|
|
96
95
|
def similar_name_message(variable)
|
97
|
-
|
96
|
+
variable_like_names = collect_variable_like_names(variable.scope)
|
97
|
+
similar_name = NameSimilarity.find_similar_name(variable.name,
|
98
|
+
variable_like_names)
|
98
99
|
" Did you mean `#{similar_name}`?" if similar_name
|
99
100
|
end
|
100
101
|
|
@@ -40,6 +40,11 @@ module RuboCop
|
|
40
40
|
diagnostic.reason == :useless_else
|
41
41
|
end
|
42
42
|
|
43
|
+
def find_offense_node_by(diagnostic)
|
44
|
+
# TODO: When implementing auto-correction, this method should return
|
45
|
+
# an offense node passed as first argument of `add_offense` method.
|
46
|
+
end
|
47
|
+
|
43
48
|
def alternative_message(_diagnostic)
|
44
49
|
MSG
|
45
50
|
end
|
@@ -6,6 +6,10 @@ module RuboCop
|
|
6
6
|
# This cop checks for setter call to local variable as the final
|
7
7
|
# expression of a function definition.
|
8
8
|
#
|
9
|
+
# Note: There are edge cases in which the local variable references a
|
10
|
+
# value that is also accessible outside the local scope. This is not
|
11
|
+
# detected by the cop, and it can yield a false positive.
|
12
|
+
#
|
9
13
|
# @example
|
10
14
|
#
|
11
15
|
# # bad
|
@@ -14,19 +14,24 @@ module RuboCop
|
|
14
14
|
/\A(# *rubocop *: *((dis|en)able|todo) +)(.*)/.freeze
|
15
15
|
|
16
16
|
# The token that makes up a disable comment.
|
17
|
-
# The
|
18
|
-
#
|
19
|
-
DISABLING_COPS_CONTENT_TOKEN = %r{[A-z
|
17
|
+
# The allowed specification for comments after `# rubocop: disable` is
|
18
|
+
# `DepartmentName/CopName` or` all`.
|
19
|
+
DISABLING_COPS_CONTENT_TOKEN = %r{[A-z]+/[A-z]+|all}.freeze
|
20
20
|
|
21
21
|
def investigate(processed_source)
|
22
22
|
processed_source.each_comment do |comment|
|
23
23
|
next if comment.text !~ DISABLE_COMMENT_FORMAT
|
24
24
|
|
25
25
|
offset = Regexp.last_match(1).length
|
26
|
-
Regexp.last_match(4).scan(%r{[\w/]+|\W+}) do |name|
|
27
|
-
break unless valid_content_token?(name.strip)
|
28
26
|
|
29
|
-
|
27
|
+
Regexp.last_match(4).scan(/[^,]+|[\W]+/) do |name|
|
28
|
+
trimmed_name = name.strip
|
29
|
+
|
30
|
+
break if contain_plain_comment?(trimmed_name)
|
31
|
+
|
32
|
+
unless valid_content_token?(trimmed_name)
|
33
|
+
check_cop_name(trimmed_name, comment, offset)
|
34
|
+
end
|
30
35
|
|
31
36
|
offset += name.length
|
32
37
|
end
|
@@ -35,23 +40,44 @@ module RuboCop
|
|
35
40
|
|
36
41
|
def autocorrect(range)
|
37
42
|
shall_warn = false
|
38
|
-
|
43
|
+
cop_name = range.source
|
44
|
+
qualified_cop_name = Cop.registry.qualified_cop_name(cop_name,
|
39
45
|
nil, shall_warn)
|
46
|
+
unless qualified_cop_name.include?('/')
|
47
|
+
qualified_cop_name = qualified_legacy_cop_name(cop_name)
|
48
|
+
end
|
49
|
+
|
40
50
|
->(corrector) { corrector.replace(range, qualified_cop_name) }
|
41
51
|
end
|
42
52
|
|
43
53
|
private
|
44
54
|
|
45
|
-
def
|
46
|
-
|
55
|
+
def disable_comment_offset
|
56
|
+
Regexp.last_match(1).length
|
57
|
+
end
|
47
58
|
|
59
|
+
def check_cop_name(name, comment, offset)
|
48
60
|
start = comment.location.expression.begin_pos + offset
|
49
61
|
range = range_between(start, start + name.length)
|
62
|
+
|
50
63
|
add_offense(range, location: range)
|
51
64
|
end
|
52
65
|
|
53
66
|
def valid_content_token?(content_token)
|
54
|
-
|
67
|
+
!/\W+/.match(content_token).nil? ||
|
68
|
+
!DISABLING_COPS_CONTENT_TOKEN.match(content_token).nil?
|
69
|
+
end
|
70
|
+
|
71
|
+
def contain_plain_comment?(name)
|
72
|
+
name == '#'
|
73
|
+
end
|
74
|
+
|
75
|
+
def qualified_legacy_cop_name(cop_name)
|
76
|
+
legacy_cop_names = RuboCop::ConfigObsoletion::OBSOLETE_COPS.keys
|
77
|
+
|
78
|
+
legacy_cop_names.detect do |legacy_cop_name|
|
79
|
+
legacy_cop_name.split('/')[1] == cop_name
|
80
|
+
end
|
55
81
|
end
|
56
82
|
end
|
57
83
|
end
|
@@ -60,6 +60,10 @@ module RuboCop
|
|
60
60
|
alias conflicting_styles_detected no_acceptable_style!
|
61
61
|
alias unrecognized_style_detected no_acceptable_style!
|
62
62
|
|
63
|
+
def style_configured?
|
64
|
+
cop_config.key?(style_parameter_name)
|
65
|
+
end
|
66
|
+
|
63
67
|
def style
|
64
68
|
@style ||= begin
|
65
69
|
s = cop_config[style_parameter_name].to_sym
|
@@ -20,7 +20,7 @@ module RuboCop
|
|
20
20
|
return if ignored_node?(node)
|
21
21
|
|
22
22
|
end_loc = node.loc.end
|
23
|
-
return
|
23
|
+
return if accept_end_kw_alignment?(end_loc)
|
24
24
|
|
25
25
|
matching = matching_ranges(end_loc, align_ranges)
|
26
26
|
|
@@ -49,6 +49,11 @@ module RuboCop
|
|
49
49
|
add_offense(node, location: end_loc, message: msg)
|
50
50
|
end
|
51
51
|
|
52
|
+
def accept_end_kw_alignment?(end_loc)
|
53
|
+
end_loc.nil? || # Discard modifier forms of if/while/until.
|
54
|
+
processed_source.lines[end_loc.line - 1] !~ /\A[ \t]*end/
|
55
|
+
end
|
56
|
+
|
52
57
|
def style_parameter_name
|
53
58
|
'EnforcedStyleAlignWith'
|
54
59
|
end
|
@@ -39,8 +39,23 @@ module RuboCop
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
def frozen_string_literal_specified?
|
43
|
+
leading_comment_lines.any? do |line|
|
44
|
+
MagicComment.parse(line).frozen_string_literal_specified?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
42
48
|
def leading_comment_lines
|
43
|
-
processed_source.
|
49
|
+
first_non_comment_token = processed_source.tokens.find do |token|
|
50
|
+
!token.comment?
|
51
|
+
end
|
52
|
+
|
53
|
+
if first_non_comment_token
|
54
|
+
# `line` is 1-indexed so we need to subtract 1 to get the array index
|
55
|
+
processed_source.lines[0...first_non_comment_token.line - 1]
|
56
|
+
else
|
57
|
+
processed_source.lines
|
58
|
+
end
|
44
59
|
end
|
45
60
|
end
|
46
61
|
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common functionality for Style/HashTransformKeys and
|
6
|
+
# Style/HashTransformValues
|
7
|
+
module HashTransformMethod
|
8
|
+
def on_block(node)
|
9
|
+
on_bad_each_with_object(node) do |*match|
|
10
|
+
handle_possible_offense(node, match, 'each_with_object')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_send(node)
|
15
|
+
on_bad_hash_brackets_map(node) do |*match|
|
16
|
+
handle_possible_offense(node, match, 'Hash[_.map {...}]')
|
17
|
+
end
|
18
|
+
on_bad_map_to_h(node) do |*match|
|
19
|
+
handle_possible_offense(node, match, 'map {...}.to_h')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_csend(node)
|
24
|
+
on_bad_map_to_h(node) do |*match|
|
25
|
+
handle_possible_offense(node, match, 'map {...}.to_h')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def autocorrect(node)
|
30
|
+
lambda do |corrector|
|
31
|
+
correction = prepare_correction(node)
|
32
|
+
execute_correction(corrector, node, correction)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# @abstract Implemented with `def_node_matcher`
|
39
|
+
def on_bad_each_with_object(_node)
|
40
|
+
raise NotImplementedError
|
41
|
+
end
|
42
|
+
|
43
|
+
# @abstract Implemented with `def_node_matcher`
|
44
|
+
def on_bad_hash_brackets_map(_node)
|
45
|
+
raise NotImplementedError
|
46
|
+
end
|
47
|
+
|
48
|
+
# @abstract Implemented with `def_node_matcher`
|
49
|
+
def on_bad_map_to_h(_node)
|
50
|
+
raise NotImplementedError
|
51
|
+
end
|
52
|
+
|
53
|
+
def handle_possible_offense(node, match, match_desc)
|
54
|
+
captures = extract_captures(match)
|
55
|
+
|
56
|
+
# If key didn't actually change either, this is most likely a false
|
57
|
+
# positive (receiver isn't a hash).
|
58
|
+
return if captures.noop_transformation?
|
59
|
+
|
60
|
+
# Can't `transform_keys` if key transformation uses value, or
|
61
|
+
# `transform_values` if value transformation uses key.
|
62
|
+
return if captures.transformation_uses_both_args?
|
63
|
+
|
64
|
+
add_offense(
|
65
|
+
node,
|
66
|
+
message: "Prefer `#{new_method_name}` over `#{match_desc}`."
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @abstract
|
71
|
+
#
|
72
|
+
# @return [Captures]
|
73
|
+
def extract_captures(_match)
|
74
|
+
raise NotImplementedError
|
75
|
+
end
|
76
|
+
|
77
|
+
# @abstract
|
78
|
+
#
|
79
|
+
# @return [String]
|
80
|
+
def new_method_name
|
81
|
+
raise NotImplementedError
|
82
|
+
end
|
83
|
+
|
84
|
+
def prepare_correction(node)
|
85
|
+
if (match = on_bad_each_with_object(node))
|
86
|
+
Autocorrection.from_each_with_object(node, match)
|
87
|
+
elsif (match = on_bad_hash_brackets_map(node))
|
88
|
+
Autocorrection.from_hash_brackets_map(node, match)
|
89
|
+
elsif (match = on_bad_map_to_h(node))
|
90
|
+
Autocorrection.from_map_to_h(node, match)
|
91
|
+
else
|
92
|
+
raise 'unreachable'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def execute_correction(corrector, node, correction)
|
97
|
+
correction.strip_prefix_and_suffix(node, corrector)
|
98
|
+
correction.set_new_method_name(new_method_name, corrector)
|
99
|
+
|
100
|
+
captures = extract_captures(correction.match)
|
101
|
+
correction.set_new_arg_name(captures.transformed_argname, corrector)
|
102
|
+
correction.set_new_body_expression(
|
103
|
+
captures.transforming_body_expr,
|
104
|
+
corrector
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Internal helper class to hold match data
|
109
|
+
Captures = Struct.new(
|
110
|
+
:transformed_argname,
|
111
|
+
:transforming_body_expr,
|
112
|
+
:unchanged_body_expr
|
113
|
+
) do
|
114
|
+
def noop_transformation?
|
115
|
+
transforming_body_expr.lvar_type? &&
|
116
|
+
transforming_body_expr.children == [transformed_argname]
|
117
|
+
end
|
118
|
+
|
119
|
+
def transformation_uses_both_args?
|
120
|
+
transforming_body_expr.descendants.include?(unchanged_body_expr)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Internal helper class to hold autocorrect data
|
125
|
+
Autocorrection = Struct.new(:match, :block_node, :leading, :trailing) do # rubocop:disable Metrics/BlockLength
|
126
|
+
def self.from_each_with_object(node, match)
|
127
|
+
new(match, node, 0, 0)
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.from_hash_brackets_map(node, match)
|
131
|
+
new(match, node.children.last, 'Hash['.length, ']'.length)
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.from_map_to_h(node, match)
|
135
|
+
strip_trailing_chars = 0
|
136
|
+
|
137
|
+
unless node.parent&.block_type?
|
138
|
+
map_range = node.children.first.source_range
|
139
|
+
node_range = node.source_range
|
140
|
+
strip_trailing_chars = node_range.end_pos - map_range.end_pos
|
141
|
+
end
|
142
|
+
|
143
|
+
new(match, node.children.first, 0, strip_trailing_chars)
|
144
|
+
end
|
145
|
+
|
146
|
+
def strip_prefix_and_suffix(node, corrector)
|
147
|
+
expression = node.loc.expression
|
148
|
+
corrector.remove_leading(expression, leading)
|
149
|
+
corrector.remove_trailing(expression, trailing)
|
150
|
+
end
|
151
|
+
|
152
|
+
def set_new_method_name(new_method_name, corrector)
|
153
|
+
range = block_node.send_node.loc.selector
|
154
|
+
if (send_end = block_node.send_node.loc.end)
|
155
|
+
# If there are arguments (only true in the `each_with_object`
|
156
|
+
# case)
|
157
|
+
range = range.begin.join(send_end)
|
158
|
+
end
|
159
|
+
corrector.replace(range, new_method_name)
|
160
|
+
end
|
161
|
+
|
162
|
+
def set_new_arg_name(transformed_argname, corrector)
|
163
|
+
corrector.replace(
|
164
|
+
block_node.arguments.loc.expression,
|
165
|
+
"|#{transformed_argname}|"
|
166
|
+
)
|
167
|
+
end
|
168
|
+
|
169
|
+
def set_new_body_expression(transforming_body_expr, corrector)
|
170
|
+
corrector.replace(
|
171
|
+
block_node.body,
|
172
|
+
transforming_body_expr.loc.expression.source
|
173
|
+
)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|