rubocop 0.75.1 → 0.80.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +4 -4
  4. data/config/default.yml +374 -335
  5. data/lib/rubocop.rb +53 -32
  6. data/lib/rubocop/ast/builder.rb +43 -41
  7. data/lib/rubocop/ast/node.rb +5 -13
  8. data/lib/rubocop/ast/node/block_node.rb +2 -0
  9. data/lib/rubocop/ast/node/def_node.rb +11 -0
  10. data/lib/rubocop/ast/node/forward_args_node.rb +18 -0
  11. data/lib/rubocop/ast/node/regexp_node.rb +2 -4
  12. data/lib/rubocop/ast/node/return_node.rb +24 -0
  13. data/lib/rubocop/ast/traversal.rb +20 -3
  14. data/lib/rubocop/cli.rb +11 -227
  15. data/lib/rubocop/cli/command.rb +21 -0
  16. data/lib/rubocop/cli/command/auto_genenerate_config.rb +105 -0
  17. data/lib/rubocop/cli/command/base.rb +33 -0
  18. data/lib/rubocop/cli/command/execute_runner.rb +76 -0
  19. data/lib/rubocop/cli/command/init_dotfile.rb +45 -0
  20. data/lib/rubocop/cli/command/show_cops.rb +80 -0
  21. data/lib/rubocop/cli/command/version.rb +17 -0
  22. data/lib/rubocop/cli/environment.rb +21 -0
  23. data/lib/rubocop/comment_config.rb +8 -3
  24. data/lib/rubocop/config.rb +8 -1
  25. data/lib/rubocop/config_loader.rb +20 -20
  26. data/lib/rubocop/config_loader_resolver.rb +2 -1
  27. data/lib/rubocop/config_obsoletion.rb +73 -10
  28. data/lib/rubocop/config_validator.rb +77 -110
  29. data/lib/rubocop/cop/autocorrect_logic.rb +7 -4
  30. data/lib/rubocop/cop/bundler/gem_comment.rb +4 -4
  31. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +2 -2
  32. data/lib/rubocop/cop/commissioner.rb +15 -7
  33. data/lib/rubocop/cop/cop.rb +31 -6
  34. data/lib/rubocop/cop/corrector.rb +8 -7
  35. data/lib/rubocop/cop/correctors/space_corrector.rb +1 -2
  36. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  37. data/lib/rubocop/cop/generator.rb +3 -4
  38. data/lib/rubocop/cop/generator/configuration_injector.rb +2 -2
  39. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  40. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +59 -0
  41. data/lib/rubocop/cop/layout/{align_arguments.rb → argument_alignment.rb} +1 -1
  42. data/lib/rubocop/cop/layout/{align_array.rb → array_alignment.rb} +1 -1
  43. data/lib/rubocop/cop/layout/{indent_assignment.rb → assignment_indentation.rb} +1 -1
  44. data/lib/rubocop/cop/layout/comment_indentation.rb +10 -13
  45. data/lib/rubocop/cop/layout/empty_comment.rb +7 -16
  46. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
  47. data/lib/rubocop/cop/layout/end_of_line.rb +8 -3
  48. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  49. data/lib/rubocop/cop/layout/{indent_first_argument.rb → first_argument_indentation.rb} +14 -12
  50. data/lib/rubocop/cop/layout/{indent_first_array_element.rb → first_array_element_indentation.rb} +4 -4
  51. data/lib/rubocop/cop/layout/{indent_first_hash_element.rb → first_hash_element_indentation.rb} +4 -4
  52. data/lib/rubocop/cop/layout/{indent_first_parameter.rb → first_parameter_indentation.rb} +3 -3
  53. data/lib/rubocop/cop/layout/{align_hash.rb → hash_alignment.rb} +16 -8
  54. data/lib/rubocop/cop/layout/{indent_heredoc.rb → heredoc_indentation.rb} +5 -5
  55. data/lib/rubocop/cop/layout/leading_comment_space.rb +33 -2
  56. data/lib/rubocop/cop/layout/{leading_blank_lines.rb → leading_empty_lines.rb} +1 -1
  57. data/lib/rubocop/cop/{metrics → layout}/line_length.rb +68 -112
  58. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
  59. data/lib/rubocop/cop/layout/multiline_block_layout.rb +14 -5
  60. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +0 -4
  61. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +1 -1
  62. data/lib/rubocop/cop/layout/{align_parameters.rb → parameter_alignment.rb} +1 -1
  63. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -0
  64. data/lib/rubocop/cop/layout/space_around_keyword.rb +12 -0
  65. data/lib/rubocop/cop/layout/space_around_operators.rb +50 -7
  66. data/lib/rubocop/cop/layout/space_before_block_braces.rb +17 -0
  67. data/lib/rubocop/cop/layout/space_before_first_arg.rb +8 -0
  68. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -7
  69. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +7 -4
  70. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -9
  71. data/lib/rubocop/cop/layout/space_inside_parens.rb +6 -6
  72. data/lib/rubocop/cop/layout/{trailing_blank_lines.rb → trailing_empty_lines.rb} +1 -1
  73. data/lib/rubocop/cop/layout/trailing_whitespace.rb +18 -2
  74. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  75. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +1 -1
  76. data/lib/rubocop/cop/lint/{duplicated_key.rb → duplicate_hash_key.rb} +1 -1
  77. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  78. data/lib/rubocop/cop/lint/erb_new_arguments.rb +9 -8
  79. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  80. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +2 -2
  81. data/lib/rubocop/cop/lint/{multiple_compare.rb → multiple_comparison.rb} +1 -1
  82. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +89 -0
  83. data/lib/rubocop/cop/lint/{unneeded_cop_disable_directive.rb → redundant_cop_disable_directive.rb} +26 -26
  84. data/lib/rubocop/cop/lint/{unneeded_cop_enable_directive.rb → redundant_cop_enable_directive.rb} +18 -15
  85. data/lib/rubocop/cop/lint/{unneeded_require_statement.rb → redundant_require_statement.rb} +1 -1
  86. data/lib/rubocop/cop/lint/{unneeded_splat_expansion.rb → redundant_splat_expansion.rb} +6 -6
  87. data/lib/rubocop/cop/lint/{string_conversion_in_interpolation.rb → redundant_string_coercion.rb} +1 -1
  88. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
  89. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  90. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +5 -6
  91. data/lib/rubocop/cop/lint/{handle_exceptions.rb → suppressed_exception.rb} +1 -1
  92. data/lib/rubocop/cop/lint/useless_access_modifier.rb +57 -23
  93. data/lib/rubocop/cop/lint/useless_setter_call.rb +5 -1
  94. data/lib/rubocop/cop/lint/void.rb +4 -4
  95. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  96. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  97. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +23 -6
  98. data/lib/rubocop/cop/migration/department_name.rb +30 -2
  99. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  100. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +4 -0
  101. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +7 -7
  102. data/lib/rubocop/cop/mixin/{hash_alignment.rb → hash_alignment_styles.rb} +1 -1
  103. data/lib/rubocop/cop/mixin/hash_transform_method.rb +172 -0
  104. data/lib/rubocop/cop/mixin/line_length_help.rb +88 -0
  105. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  106. data/lib/rubocop/cop/mixin/nil_methods.rb +4 -4
  107. data/lib/rubocop/cop/mixin/rational_literal.rb +18 -0
  108. data/lib/rubocop/cop/mixin/statement_modifier.rb +7 -4
  109. data/lib/rubocop/cop/mixin/trailing_comma.rb +16 -18
  110. data/lib/rubocop/cop/naming/{uncommunicative_block_param_name.rb → block_parameter_name.rb} +3 -3
  111. data/lib/rubocop/cop/naming/file_name.rb +12 -5
  112. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -5
  113. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  114. data/lib/rubocop/cop/naming/{uncommunicative_method_param_name.rb → method_parameter_name.rb} +4 -4
  115. data/lib/rubocop/cop/naming/predicate_name.rb +6 -6
  116. data/lib/rubocop/cop/offense.rb +11 -0
  117. data/lib/rubocop/cop/registry.rb +8 -3
  118. data/lib/rubocop/cop/style/alias.rb +1 -1
  119. data/lib/rubocop/cop/style/array_join.rb +1 -1
  120. data/lib/rubocop/cop/style/attr.rb +10 -2
  121. data/lib/rubocop/cop/style/block_delimiters.rb +60 -1
  122. data/lib/rubocop/cop/style/comment_annotation.rb +5 -5
  123. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
  124. data/lib/rubocop/cop/style/copyright.rb +11 -7
  125. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +2 -2
  126. data/lib/rubocop/cop/style/empty_case_condition.rb +2 -2
  127. data/lib/rubocop/cop/style/empty_literal.rb +2 -2
  128. data/lib/rubocop/cop/style/empty_method.rb +5 -5
  129. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  130. data/lib/rubocop/cop/style/even_odd.rb +1 -1
  131. data/lib/rubocop/cop/style/format_string.rb +10 -7
  132. data/lib/rubocop/cop/style/format_string_token.rb +2 -0
  133. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +99 -11
  134. data/lib/rubocop/cop/style/guard_clause.rb +3 -2
  135. data/lib/rubocop/cop/style/hash_each_methods.rb +87 -0
  136. data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
  137. data/lib/rubocop/cop/style/hash_transform_keys.rb +79 -0
  138. data/lib/rubocop/cop/style/hash_transform_values.rb +79 -0
  139. data/lib/rubocop/cop/style/if_unless_modifier.rb +45 -3
  140. data/lib/rubocop/cop/style/infinite_loop.rb +5 -4
  141. data/lib/rubocop/cop/style/inverse_methods.rb +19 -13
  142. data/lib/rubocop/cop/style/ip_addresses.rb +4 -4
  143. data/lib/rubocop/cop/style/line_end_concatenation.rb +14 -10
  144. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -205
  145. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +169 -0
  146. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +54 -0
  147. data/lib/rubocop/cop/style/method_def_parentheses.rb +17 -9
  148. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  149. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
  150. data/lib/rubocop/cop/style/multiline_when_then.rb +6 -2
  151. data/lib/rubocop/cop/style/nested_modifier.rb +4 -2
  152. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +5 -5
  153. data/lib/rubocop/cop/style/next.rb +5 -5
  154. data/lib/rubocop/cop/style/non_nil_check.rb +21 -9
  155. data/lib/rubocop/cop/style/numeric_literals.rb +7 -3
  156. data/lib/rubocop/cop/style/numeric_predicate.rb +4 -3
  157. data/lib/rubocop/cop/style/option_hash.rb +3 -3
  158. data/lib/rubocop/cop/style/or_assignment.rb +3 -2
  159. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +7 -7
  160. data/lib/rubocop/cop/style/{unneeded_capital_w.rb → redundant_capital_w.rb} +1 -1
  161. data/lib/rubocop/cop/style/{unneeded_condition.rb → redundant_condition.rb} +3 -3
  162. data/lib/rubocop/cop/style/{unneeded_interpolation.rb → redundant_interpolation.rb} +1 -1
  163. data/lib/rubocop/cop/style/redundant_parentheses.rb +3 -3
  164. data/lib/rubocop/cop/style/{unneeded_percent_q.rb → redundant_percent_q.rb} +1 -1
  165. data/lib/rubocop/cop/style/redundant_return.rb +27 -29
  166. data/lib/rubocop/cop/style/{unneeded_sort.rb → redundant_sort.rb} +5 -5
  167. data/lib/rubocop/cop/style/safe_navigation.rb +13 -10
  168. data/lib/rubocop/cop/style/semicolon.rb +2 -2
  169. data/lib/rubocop/cop/style/special_global_vars.rb +5 -7
  170. data/lib/rubocop/cop/style/symbol_array.rb +2 -2
  171. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  172. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +0 -22
  173. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +7 -1
  174. data/lib/rubocop/cop/style/trivial_accessors.rb +5 -5
  175. data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
  176. data/lib/rubocop/cop/style/yoda_condition.rb +16 -1
  177. data/lib/rubocop/cop/team.rb +5 -0
  178. data/lib/rubocop/cop/util.rb +1 -1
  179. data/lib/rubocop/cop/utils/format_string.rb +10 -18
  180. data/lib/rubocop/cop/variable_force.rb +11 -6
  181. data/lib/rubocop/formatter/base_formatter.rb +2 -2
  182. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -3
  183. data/lib/rubocop/formatter/formatter_set.rb +1 -0
  184. data/lib/rubocop/formatter/json_formatter.rb +6 -5
  185. data/lib/rubocop/formatter/junit_formatter.rb +63 -0
  186. data/lib/rubocop/formatter/tap_formatter.rb +1 -3
  187. data/lib/rubocop/node_pattern.rb +100 -12
  188. data/lib/rubocop/options.rb +17 -11
  189. data/lib/rubocop/processed_source.rb +1 -1
  190. data/lib/rubocop/rake_task.rb +1 -0
  191. data/lib/rubocop/result_cache.rb +24 -8
  192. data/lib/rubocop/rspec/shared_contexts.rb +5 -0
  193. data/lib/rubocop/runner.rb +50 -29
  194. data/lib/rubocop/target_finder.rb +12 -6
  195. data/lib/rubocop/target_ruby.rb +151 -0
  196. data/lib/rubocop/version.rb +1 -1
  197. metadata +69 -35
  198. data/lib/rubocop/cop/mixin/safe_mode.rb +0 -24
  199. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +0 -209
@@ -49,8 +49,9 @@ module RuboCop
49
49
 
50
50
  if body.if_type?
51
51
  check_ending_if(body)
52
- elsif body.begin_type? && body.children.last.if_type?
53
- check_ending_if(body.children.last)
52
+ elsif body.begin_type?
53
+ final_expression = body.children.last
54
+ check_ending_if(final_expression) if final_expression&.if_type?
54
55
  end
55
56
  end
56
57
  alias on_defs on_def
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for uses of `each_key` and `each_value` Hash methods.
7
+ #
8
+ # Note: If you have an array of two-element arrays, you can put
9
+ # parentheses around the block arguments to indicate that you're not
10
+ # working with a hash, and suppress RuboCop offenses.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # hash.keys.each { |k| p k }
15
+ # hash.values.each { |v| p v }
16
+ #
17
+ # # good
18
+ # hash.each_key { |k| p k }
19
+ # hash.each_value { |v| p v }
20
+ class HashEachMethods < Cop
21
+ include Lint::UnusedArgument
22
+
23
+ MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
24
+
25
+ def_node_matcher :kv_each, <<~PATTERN
26
+ (block $(send (send _ ${:keys :values}) :each) ...)
27
+ PATTERN
28
+
29
+ def on_block(node)
30
+ register_kv_offense(node)
31
+ end
32
+
33
+ def autocorrect(node)
34
+ lambda do |corrector|
35
+ correct_key_value_each(node, corrector)
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def register_kv_offense(node)
42
+ kv_each(node) do |target, method|
43
+ msg = format(message, prefer: "each_#{method[0..-2]}",
44
+ current: "#{method}.each")
45
+
46
+ add_offense(target, location: kv_range(target), message: msg)
47
+ end
48
+ end
49
+
50
+ def check_argument(variable)
51
+ return unless variable.block_argument?
52
+
53
+ (@block_args ||= []).push(variable)
54
+ end
55
+
56
+ def used?(arg)
57
+ @block_args.find { |var| var.declaration_node.loc == arg.loc }.used?
58
+ end
59
+
60
+ def correct_implicit(node, corrector, method_name)
61
+ corrector.replace(node.loc.expression, method_name)
62
+ correct_args(node, corrector)
63
+ end
64
+
65
+ def correct_key_value_each(node, corrector)
66
+ receiver = node.receiver.receiver
67
+ name = "each_#{node.receiver.method_name.to_s.chop}"
68
+ return correct_implicit(node, corrector, name) unless receiver
69
+
70
+ new_source = receiver.source + ".#{name}"
71
+ corrector.replace(node.loc.expression, new_source)
72
+ end
73
+
74
+ def correct_args(node, corrector)
75
+ args = node.parent.arguments
76
+ name, = *args.children.find { |arg| used?(arg) }
77
+
78
+ corrector.replace(args.source_range, "|#{name}|")
79
+ end
80
+
81
+ def kv_range(outer_node)
82
+ outer_node.receiver.loc.selector.join(outer_node.loc.selector)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -168,10 +168,10 @@ module RuboCop
168
168
  end
169
169
 
170
170
  def autocorrect_ruby19(corrector, pair_node)
171
- key = pair_node.key
171
+ key = pair_node.key.source_range
172
172
  op = pair_node.loc.operator
173
173
 
174
- range = range_between(key.source_range.begin_pos, op.end_pos)
174
+ range = key.join(op)
175
175
  range = range_with_surrounding_space(range: range, side: :right)
176
176
 
177
177
  space = argument_without_space?(pair_node.parent) ? ' ' : ''
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop looks for uses of `_.each_with_object({}) {...}`,
7
+ # `_.map {...}.to_h`, and `Hash[_.map {...}]` that are actually just
8
+ # transforming the keys of a hash, and tries to use a simpler & faster
9
+ # call to `transform_keys` instead.
10
+ #
11
+ # This can produce false positives if we are transforming an enumerable
12
+ # of key-value-like pairs that isn't actually a hash, e.g.:
13
+ # `[[k1, v1], [k2, v2], ...]`
14
+ #
15
+ # This cop should only be enabled on Ruby version 2.5 or newer
16
+ # (`transform_keys` was added in Ruby 2.5.)
17
+ #
18
+ # @example
19
+ # # bad
20
+ # {a: 1, b: 2}.each_with_object({}) { |(k, v), h| h[foo(k)] = v }
21
+ # {a: 1, b: 2}.map { |k, v| [k.to_s, v] }
22
+ #
23
+ # # good
24
+ # {a: 1, b: 2}.transform_keys { |k| foo(k) }
25
+ # {a: 1, b: 2}.transform_keys { |k| k.to_s }
26
+ class HashTransformKeys < Cop
27
+ extend TargetRubyVersion
28
+ include HashTransformMethod
29
+
30
+ minimum_target_ruby_version 2.5
31
+
32
+ def_node_matcher :on_bad_each_with_object, <<~PATTERN
33
+ (block
34
+ ({send csend} !(send _ :each_with_index) :each_with_object (hash))
35
+ (args
36
+ (mlhs
37
+ (arg $_)
38
+ (arg _val))
39
+ (arg _memo))
40
+ ({send csend} (lvar _memo) :[]= $_ $(lvar _val)))
41
+ PATTERN
42
+
43
+ def_node_matcher :on_bad_hash_brackets_map, <<~PATTERN
44
+ (send
45
+ (const _ :Hash)
46
+ :[]
47
+ (block
48
+ ({send csend} !(send _ :each_with_index) {:map :collect})
49
+ (args
50
+ (arg $_)
51
+ (arg _val))
52
+ (array $_ $(lvar _val))))
53
+ PATTERN
54
+
55
+ def_node_matcher :on_bad_map_to_h, <<~PATTERN
56
+ ({send csend}
57
+ (block
58
+ ({send csend} !(send _ :each_with_index) {:map :collect})
59
+ (args
60
+ (arg $_)
61
+ (arg _val))
62
+ (array $_ $(lvar _val)))
63
+ :to_h)
64
+ PATTERN
65
+
66
+ private
67
+
68
+ def extract_captures(match)
69
+ key_argname, key_body_expr, val_body_expr = *match
70
+ Captures.new(key_argname, key_body_expr, val_body_expr)
71
+ end
72
+
73
+ def new_method_name
74
+ 'transform_keys'
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop looks for uses of `_.each_with_object({}) {...}`,
7
+ # `_.map {...}.to_h`, and `Hash[_.map {...}]` that are actually just
8
+ # transforming the values of a hash, and tries to use a simpler & faster
9
+ # call to `transform_values` instead.
10
+ #
11
+ # This can produce false positives if we are transforming an enumerable
12
+ # of key-value-like pairs that isn't actually a hash, e.g.:
13
+ # `[[k1, v1], [k2, v2], ...]`
14
+ #
15
+ # This cop should only be enabled on Ruby version 2.4 or newer
16
+ # (`transform_values` was added in Ruby 2.4.)
17
+ #
18
+ # @example
19
+ # # bad
20
+ # {a: 1, b: 2}.each_with_object({}) { |(k, v), h| h[k] = foo(v) }
21
+ # {a: 1, b: 2}.map { |k, v| [k, v * v] }
22
+ #
23
+ # # good
24
+ # {a: 1, b: 2}.transform_values { |v| foo(v) }
25
+ # {a: 1, b: 2}.transform_values { |v| v * v }
26
+ class HashTransformValues < Cop
27
+ extend TargetRubyVersion
28
+ include HashTransformMethod
29
+
30
+ minimum_target_ruby_version 2.4
31
+
32
+ def_node_matcher :on_bad_each_with_object, <<~PATTERN
33
+ (block
34
+ ({send csend} !(send _ :each_with_index) :each_with_object (hash))
35
+ (args
36
+ (mlhs
37
+ (arg _key)
38
+ (arg $_))
39
+ (arg _memo))
40
+ ({send csend} (lvar _memo) :[]= $(lvar _key) $_))
41
+ PATTERN
42
+
43
+ def_node_matcher :on_bad_hash_brackets_map, <<~PATTERN
44
+ (send
45
+ (const _ :Hash)
46
+ :[]
47
+ (block
48
+ ({send csend} !(send _ :each_with_index) {:map :collect})
49
+ (args
50
+ (arg _key)
51
+ (arg $_))
52
+ (array $(lvar _key) $_)))
53
+ PATTERN
54
+
55
+ def_node_matcher :on_bad_map_to_h, <<~PATTERN
56
+ ({send csend}
57
+ (block
58
+ ({send csend} !(send _ :each_with_index) {:map :collect})
59
+ (args
60
+ (arg _key)
61
+ (arg $_))
62
+ (array $(lvar _key) $_))
63
+ :to_h)
64
+ PATTERN
65
+
66
+ private
67
+
68
+ def extract_captures(match)
69
+ val_argname, key_body_expr, val_body_expr = *match
70
+ Captures.new(val_argname, val_body_expr, key_body_expr)
71
+ end
72
+
73
+ def new_method_name
74
+ 'transform_values'
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -7,7 +7,7 @@ module RuboCop
7
7
  # written as modifier `if`/`unless`. The cop also checks for modifier
8
8
  # `if`/`unless` lines that exceed the maximum line length.
9
9
  #
10
- # The maximum line length is configured in the `Metrics/LineLength`
10
+ # The maximum line length is configured in the `Layout/LineLength`
11
11
  # cop. The tab size is configured in the `IndentationWidth` of the
12
12
  # `Layout/Tab` cop.
13
13
  #
@@ -32,6 +32,8 @@ module RuboCop
32
32
  # end
33
33
  class IfUnlessModifier < Cop
34
34
  include StatementModifier
35
+ include LineLengthHelp
36
+ include IgnoredPattern
35
37
 
36
38
  MSG_USE_MODIFIER = 'Favor modifier `%<keyword>s` usage when having a ' \
37
39
  'single-line body. Another good alternative is ' \
@@ -66,12 +68,52 @@ module RuboCop
66
68
 
67
69
  private
68
70
 
71
+ def ignored_patterns
72
+ config.for_cop('Layout/LineLength')['IgnoredPatterns'] || []
73
+ end
74
+
69
75
  def too_long_single_line?(node)
70
76
  return false unless max_line_length
71
77
 
72
78
  range = node.source_range
73
- range.first_line == range.last_line &&
74
- range.last_column > max_line_length
79
+ return false unless range.first_line == range.last_line
80
+ return false unless line_length_enabled_at_line?(range.first_line)
81
+
82
+ line = range.source_line
83
+ return false if line_length(line) <= max_line_length
84
+
85
+ too_long_line_based_on_config?(range, line)
86
+ end
87
+
88
+ def too_long_line_based_on_config?(range, line)
89
+ return false if matches_ignored_pattern?(line)
90
+
91
+ too_long = too_long_line_based_on_ignore_cop_directives?(range, line)
92
+ return too_long unless too_long == :undetermined
93
+
94
+ too_long_line_based_on_allow_uri?(line)
95
+ end
96
+
97
+ def too_long_line_based_on_ignore_cop_directives?(range, line)
98
+ if ignore_cop_directives? && directive_on_source_line?(range.line - 1)
99
+ return line_length_without_directive(line) > max_line_length
100
+ end
101
+
102
+ :undetermined
103
+ end
104
+
105
+ def too_long_line_based_on_allow_uri?(line)
106
+ if allow_uri?
107
+ uri_range = find_excessive_uri_range(line)
108
+ return false if uri_range && allowed_uri_position?(line, uri_range)
109
+ end
110
+
111
+ true
112
+ end
113
+
114
+ def line_length_enabled_at_line?(line)
115
+ processed_source.comment_config
116
+ .cop_enabled_at_line?('Layout/LineLength', line)
75
117
  end
76
118
 
77
119
  def named_capture_in_condition?(node)
@@ -58,7 +58,7 @@ module RuboCop
58
58
  # `loop do` without further modification. The reason is that a
59
59
  # variable that's introduced inside a while/until loop is in scope
60
60
  # outside of that loop too, but a variable that's assigned for the
61
- # first time inside a block can not be accessed after the block. In
61
+ # first time inside a block cannot be accessed after the block. In
62
62
  # those more complicated cases we don't report an offense.
63
63
  return if @variables.any? do |var|
64
64
  assigned_inside_loop?(var, range) &&
@@ -97,12 +97,13 @@ module RuboCop
97
97
  end
98
98
 
99
99
  def modifier_replacement(node)
100
+ body = node.body
100
101
  if node.single_line?
101
- 'loop { ' + node.body.source + ' }'
102
+ 'loop { ' + body.source + ' }'
102
103
  else
103
- indentation = node.body.loc.expression.source_line[LEADING_SPACE]
104
+ indentation = body.source_range.source_line[LEADING_SPACE]
104
105
 
105
- ['loop do', node.body.source.gsub(/^/, configured_indent),
106
+ ['loop do', body.source.gsub(/^/, configured_indent),
106
107
  'end'].join("\n#{indentation}")
107
108
  end
108
109
  end
@@ -94,20 +94,25 @@ module RuboCop
94
94
  end
95
95
 
96
96
  def autocorrect(node)
97
+ if node.block_type?
98
+ correct_inverse_block(node)
99
+ elsif node.send_type?
100
+ correct_inverse_method(node)
101
+ end
102
+ end
103
+
104
+ def correct_inverse_method(node)
97
105
  method_call, _lhs, method, _rhs = inverse_candidate?(node)
106
+ return unless method_call && method
98
107
 
99
- if method_call && method
100
- lambda do |corrector|
101
- corrector.remove(not_to_receiver(node, method_call))
102
- corrector.replace(method_call.loc.selector,
103
- inverse_methods[method].to_s)
108
+ lambda do |corrector|
109
+ corrector.remove(not_to_receiver(node, method_call))
110
+ corrector.replace(method_call.loc.selector,
111
+ inverse_methods[method].to_s)
104
112
 
105
- if EQUALITY_METHODS.include?(method)
106
- corrector.remove(end_parentheses(node, method_call))
107
- end
113
+ if EQUALITY_METHODS.include?(method)
114
+ corrector.remove(end_parentheses(node, method_call))
108
115
  end
109
- else
110
- correct_inverse_block(node)
111
116
  end
112
117
  end
113
118
 
@@ -122,18 +127,19 @@ module RuboCop
122
127
  end
123
128
 
124
129
  def correct_inverse_selector(block, corrector)
125
- selector = block.loc.selector.source
130
+ selector_loc = block.loc.selector
131
+ selector = selector_loc.source
126
132
 
127
133
  if NEGATED_EQUALITY_METHODS.include?(selector.to_sym)
128
134
  selector[0] = '='
129
- corrector.replace(block.loc.selector, selector)
135
+ corrector.replace(selector_loc, selector)
130
136
  else
131
137
  if block.loc.dot
132
138
  range = dot_range(block.loc)
133
139
  corrector.remove(range)
134
140
  end
135
141
 
136
- corrector.remove(block.loc.selector)
142
+ corrector.remove(selector_loc)
137
143
  end
138
144
  end
139
145
 
@@ -28,7 +28,7 @@ module RuboCop
28
28
  contents = node.source[1...-1]
29
29
  return false if contents.empty?
30
30
 
31
- return false if whitelist.include?(contents.downcase)
31
+ return false if allowed_addresses.include?(contents.downcase)
32
32
 
33
33
  # To try to avoid doing two regex checks on every string,
34
34
  # shortcut out if the string does not look like an IP address
@@ -47,9 +47,9 @@ module RuboCop
47
47
 
48
48
  private
49
49
 
50
- def whitelist
51
- whitelist = cop_config['Whitelist']
52
- Array(whitelist).map(&:downcase)
50
+ def allowed_addresses
51
+ allowed_addresses = cop_config['AllowedAddresses']
52
+ Array(allowed_addresses).map(&:downcase)
53
53
  end
54
54
 
55
55
  def could_be_ip?(str)