rubocop 0.52.0 → 0.52.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -5
  3. data/config/default.yml +1 -11
  4. data/config/disabled.yml +5 -0
  5. data/config/enabled.yml +6 -8
  6. data/lib/rubocop.rb +13 -2
  7. data/lib/rubocop/ast/node.rb +23 -15
  8. data/lib/rubocop/cli.rb +25 -2
  9. data/lib/rubocop/config.rb +23 -8
  10. data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
  11. data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -0
  12. data/lib/rubocop/cop/commissioner.rb +1 -1
  13. data/lib/rubocop/cop/correctors/alignment_corrector.rb +121 -0
  14. data/lib/rubocop/cop/correctors/condition_corrector.rb +28 -0
  15. data/lib/rubocop/cop/correctors/empty_line_corrector.rb +26 -0
  16. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +62 -0
  17. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +44 -0
  18. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +31 -0
  19. data/lib/rubocop/cop/correctors/punctuation_corrector.rb +29 -0
  20. data/lib/rubocop/cop/correctors/space_corrector.rb +34 -0
  21. data/lib/rubocop/cop/correctors/string_literal_corrector.rb +25 -0
  22. data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +31 -0
  23. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
  24. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -0
  25. data/lib/rubocop/cop/generator.rb +18 -87
  26. data/lib/rubocop/cop/generator/require_file_injector.rb +78 -0
  27. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +5 -1
  28. data/lib/rubocop/cop/layout/align_array.rb +5 -1
  29. data/lib/rubocop/cop/layout/align_hash.rb +1 -1
  30. data/lib/rubocop/cop/layout/align_parameters.rb +5 -1
  31. data/lib/rubocop/cop/layout/case_indentation.rb +1 -1
  32. data/lib/rubocop/cop/layout/class_structure.rb +2 -2
  33. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -1
  34. data/lib/rubocop/cop/layout/comment_indentation.rb +5 -1
  35. data/lib/rubocop/cop/layout/else_alignment.rb +5 -1
  36. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +3 -3
  37. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +17 -19
  38. data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +4 -0
  39. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +4 -0
  40. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +4 -0
  41. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +4 -0
  42. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +4 -0
  43. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +4 -0
  44. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +4 -0
  45. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +4 -0
  46. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +4 -0
  47. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
  48. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +6 -2
  49. data/lib/rubocop/cop/layout/indent_array.rb +6 -2
  50. data/lib/rubocop/cop/layout/indent_assignment.rb +6 -2
  51. data/lib/rubocop/cop/layout/indent_hash.rb +5 -1
  52. data/lib/rubocop/cop/layout/indentation_consistency.rb +5 -1
  53. data/lib/rubocop/cop/layout/indentation_width.rb +5 -1
  54. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +4 -0
  55. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +3 -3
  56. data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -2
  57. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +4 -0
  58. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +4 -0
  59. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +6 -2
  60. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
  61. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +6 -2
  62. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -1
  63. data/lib/rubocop/cop/layout/space_after_comma.rb +4 -0
  64. data/lib/rubocop/cop/layout/space_after_semicolon.rb +4 -0
  65. data/lib/rubocop/cop/layout/space_before_comma.rb +4 -0
  66. data/lib/rubocop/cop/layout/space_before_semicolon.rb +4 -0
  67. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +3 -2
  68. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +16 -7
  69. data/lib/rubocop/cop/layout/tab.rb +1 -1
  70. data/lib/rubocop/cop/lint/block_alignment.rb +1 -1
  71. data/lib/rubocop/cop/lint/def_end_alignment.rb +2 -2
  72. data/lib/rubocop/cop/lint/end_alignment.rb +3 -1
  73. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  74. data/lib/rubocop/cop/lint/unused_block_argument.rb +4 -0
  75. data/lib/rubocop/cop/lint/unused_method_argument.rb +6 -0
  76. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -1
  77. data/lib/rubocop/cop/mixin/alignment.rb +70 -0
  78. data/lib/rubocop/cop/mixin/array_hash_indentation.rb +2 -0
  79. data/lib/rubocop/cop/mixin/array_syntax.rb +2 -0
  80. data/lib/rubocop/cop/mixin/code_length.rb +2 -0
  81. data/lib/rubocop/cop/mixin/configurable_max.rb +2 -0
  82. data/lib/rubocop/cop/mixin/def_node.rb +3 -1
  83. data/lib/rubocop/cop/mixin/documentation_comment.rb +2 -2
  84. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +3 -15
  85. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -25
  86. data/lib/rubocop/cop/mixin/enforce_superclass.rb +0 -6
  87. data/lib/rubocop/cop/mixin/first_element_line_break.rb +5 -9
  88. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +2 -2
  89. data/lib/rubocop/cop/mixin/ignored_pattern.rb +2 -0
  90. data/lib/rubocop/cop/mixin/integer_node.rb +2 -0
  91. data/lib/rubocop/cop/mixin/match_range.rb +2 -0
  92. data/lib/rubocop/cop/mixin/min_body_length.rb +2 -0
  93. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -0
  94. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +9 -48
  95. data/lib/rubocop/cop/mixin/negative_conditional.rb +2 -16
  96. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +12 -31
  97. data/lib/rubocop/cop/mixin/parentheses.rb +2 -19
  98. data/lib/rubocop/cop/mixin/percent_literal.rb +3 -3
  99. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +2 -0
  100. data/lib/rubocop/cop/mixin/rescue_node.rb +2 -0
  101. data/lib/rubocop/cop/mixin/safe_assignment.rb +2 -0
  102. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -3
  103. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -3
  104. data/lib/rubocop/cop/mixin/statement_modifier.rb +4 -2
  105. data/lib/rubocop/cop/mixin/string_help.rb +2 -0
  106. data/lib/rubocop/cop/mixin/string_literals_help.rb +2 -13
  107. data/lib/rubocop/cop/mixin/surrounding_space.rb +4 -21
  108. data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -10
  109. data/lib/rubocop/cop/mixin/unused_argument.rb +2 -15
  110. data/lib/rubocop/cop/performance/case_when_splat.rb +1 -1
  111. data/lib/rubocop/cop/rails/action_filter.rb +3 -2
  112. data/lib/rubocop/cop/rails/active_support_aliases.rb +3 -2
  113. data/lib/rubocop/cop/rails/application_job.rb +6 -0
  114. data/lib/rubocop/cop/rails/application_record.rb +6 -0
  115. data/lib/rubocop/cop/rails/blank.rb +10 -9
  116. data/lib/rubocop/cop/rails/date.rb +22 -14
  117. data/lib/rubocop/cop/rails/delegate.rb +1 -1
  118. data/lib/rubocop/cop/rails/dynamic_find_by.rb +3 -2
  119. data/lib/rubocop/cop/rails/enum_uniqueness.rb +4 -2
  120. data/lib/rubocop/cop/rails/environment_comparison.rb +2 -2
  121. data/lib/rubocop/cop/rails/file_path.rb +1 -1
  122. data/lib/rubocop/cop/rails/find_by.rb +2 -2
  123. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +15 -7
  124. data/lib/rubocop/cop/rails/http_positional_arguments.rb +2 -2
  125. data/lib/rubocop/cop/rails/inverse_of.rb +130 -8
  126. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +3 -3
  127. data/lib/rubocop/cop/rails/pluralization_grammar.rb +3 -2
  128. data/lib/rubocop/cop/rails/presence.rb +31 -18
  129. data/lib/rubocop/cop/rails/present.rb +11 -8
  130. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +52 -10
  131. data/lib/rubocop/cop/rails/request_referer.rb +2 -3
  132. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +9 -2
  133. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +38 -10
  134. data/lib/rubocop/cop/style/class_and_module_children.rb +76 -0
  135. data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
  136. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  137. data/lib/rubocop/cop/style/format_string_token.rb +24 -4
  138. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +46 -0
  139. data/lib/rubocop/cop/style/hash_syntax.rb +4 -3
  140. data/lib/rubocop/cop/style/if_unless_modifier.rb +14 -0
  141. data/lib/rubocop/cop/style/method_def_parentheses.rb +79 -0
  142. data/lib/rubocop/cop/style/mixin_usage.rb +13 -2
  143. data/lib/rubocop/cop/style/multiline_if_modifier.rb +1 -1
  144. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +19 -0
  145. data/lib/rubocop/cop/style/negated_if.rb +1 -1
  146. data/lib/rubocop/cop/style/negated_while.rb +6 -4
  147. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
  148. data/lib/rubocop/cop/style/parentheses_around_condition.rb +4 -0
  149. data/lib/rubocop/cop/style/redundant_conditional.rb +1 -1
  150. data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -0
  151. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
  152. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  153. data/lib/rubocop/cop/style/string_literals.rb +4 -0
  154. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +4 -0
  155. data/lib/rubocop/cop/style/trailing_body_on_method_definition.rb +1 -1
  156. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -0
  157. data/lib/rubocop/cop/style/trailing_comma_in_literal.rb +4 -0
  158. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -1
  159. data/lib/rubocop/formatter/disabled_config_formatter.rb +33 -24
  160. data/lib/rubocop/options.rb +33 -10
  161. data/lib/rubocop/path_util.rb +7 -0
  162. data/lib/rubocop/token.rb +4 -0
  163. data/lib/rubocop/version.rb +1 -1
  164. metadata +14 -4
  165. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +0 -149
  166. data/lib/rubocop/cop/style/extend_self.rb +0 -92
@@ -34,7 +34,7 @@ module RuboCop
34
34
  # end
35
35
  # end
36
36
  class LexicallyScopedActionFilter < Cop
37
- MSG = '%s not explicitly defined on the controller.'.freeze
37
+ MSG = '%<action>s not explicitly defined on the controller.'.freeze
38
38
 
39
39
  FILTERS = %w[
40
40
  :after_action
@@ -101,9 +101,9 @@ module RuboCop
101
101
 
102
102
  def message(methods)
103
103
  if methods.size == 1
104
- format(MSG, "`#{methods[0]}` is")
104
+ format(MSG, action: "`#{methods[0]}` is")
105
105
  else
106
- format(MSG, "`#{methods.join('`, `')}` are")
106
+ format(MSG, action: "`#{methods.join('`, `')}` are")
107
107
  end
108
108
  end
109
109
  end
@@ -26,7 +26,7 @@ module RuboCop
26
26
 
27
27
  PLURAL_DURATION_METHODS = SINGULAR_DURATION_METHODS.invert.freeze
28
28
 
29
- MSG = 'Prefer `%s.%s`.'.freeze
29
+ MSG = 'Prefer `%<number>s.%<correct>s`.'.freeze
30
30
 
31
31
  def on_send(node)
32
32
  return unless duration_method?(node.method_name)
@@ -50,7 +50,8 @@ module RuboCop
50
50
  def message(node)
51
51
  number, = *node.receiver
52
52
 
53
- format(MSG, number, correct_method(node.method_name.to_s))
53
+ format(MSG, number: number,
54
+ correct: correct_method(node.method_name.to_s))
54
55
  end
55
56
 
56
57
  def correct_method(method_name)
@@ -45,11 +45,11 @@ module RuboCop
45
45
  (if
46
46
  (send $_recv :present?)
47
47
  _recv
48
- $_false
48
+ $!begin
49
49
  )
50
50
  (if
51
51
  (send $_recv :blank?)
52
- $_true
52
+ $!begin
53
53
  _recv
54
54
  )
55
55
  }
@@ -59,44 +59,57 @@ module RuboCop
59
59
  {
60
60
  (if
61
61
  (send (send $_recv :present?) :!)
62
- $_true
62
+ $!begin
63
63
  _recv
64
64
  )
65
65
  (if
66
66
  (send (send $_recv :blank?) :!)
67
67
  _recv
68
- $_false
68
+ $!begin
69
69
  )
70
70
  }
71
71
  PATTERN
72
72
 
73
73
  def on_if(node)
74
- receiver, other = redundant_receiver_and_other(node)
75
- unless receiver
76
- receiver, other = redundant_negative_receiver_and_other(node)
74
+ redundant_receiver_and_other(node) do |receiver, other|
75
+ unless ignore_other_node?(other)
76
+ add_offense(node, message: message(node, receiver, other))
77
+ end
78
+ end
79
+
80
+ redundant_negative_receiver_and_other(node) do |receiver, other|
81
+ unless ignore_other_node?(other)
82
+ add_offense(node, message: message(node, receiver, other))
83
+ end
77
84
  end
78
- return unless receiver
79
- message = format(MSG,
80
- prefer: replacement(receiver, other),
81
- current: node.source)
82
- add_offense(node, message: message)
83
85
  end
84
86
 
85
87
  def autocorrect(node)
86
88
  lambda do |corrector|
87
- receiver, other = redundant_receiver_and_other(node)
88
- unless receiver
89
- receiver, other = redundant_negative_receiver_and_other(node)
89
+ redundant_receiver_and_other(node) do |receiver, other|
90
+ corrector.replace(node.source_range, replacement(receiver, other))
91
+ end
92
+
93
+ redundant_negative_receiver_and_other(node) do |receiver, other|
94
+ corrector.replace(node.source_range, replacement(receiver, other))
90
95
  end
91
- return unless receiver
92
- corrector.replace(node.source_range, replacement(receiver, other))
93
96
  end
94
97
  end
95
98
 
96
99
  private
97
100
 
101
+ def ignore_other_node?(node)
102
+ node && (node.if_type? || node.rescue_type? || node.while_type?)
103
+ end
104
+
105
+ def message(node, receiver, other)
106
+ format(MSG,
107
+ prefer: replacement(receiver, other),
108
+ current: node.source)
109
+ end
110
+
98
111
  def replacement(receiver, other)
99
- or_source = other.nil_type? ? '' : " || #{other.source}"
112
+ or_source = other.nil? || other.nil_type? ? '' : " || #{other.source}"
100
113
  "#{receiver.source}.presence" + or_source
101
114
  end
102
115
  end
@@ -35,9 +35,11 @@ module RuboCop
35
35
  # # good
36
36
  # something if foo.present?
37
37
  class Present < Cop
38
- MSG_NOT_BLANK = 'Use `%s` instead of `%s`.'.freeze
39
- MSG_EXISTS_AND_NOT_EMPTY = 'Use `%s` instead of `%s`.'.freeze
40
- MSG_UNLESS_BLANK = 'Use `if %s` instead of `%s`.'.freeze
38
+ MSG_NOT_BLANK = 'Use `%<prefer>s` instead of `%<current>s`.'.freeze
39
+ MSG_EXISTS_AND_NOT_EMPTY = 'Use `%<prefer>s` instead of ' \
40
+ '`%<current>s`.'.freeze
41
+ MSG_UNLESS_BLANK = 'Use `if %<prefer>s` instead of ' \
42
+ '`%<current>s`.'.freeze
41
43
 
42
44
  def_node_matcher :exists_and_not_empty?, <<-PATTERN
43
45
  (and
@@ -65,8 +67,8 @@ module RuboCop
65
67
  not_blank?(node) do |receiver|
66
68
  add_offense(node,
67
69
  message: format(MSG_NOT_BLANK,
68
- replacement(receiver),
69
- node.source))
70
+ prefer: replacement(receiver),
71
+ current: node.source))
70
72
  end
71
73
  end
72
74
 
@@ -78,8 +80,8 @@ module RuboCop
78
80
 
79
81
  add_offense(node,
80
82
  message: format(MSG_EXISTS_AND_NOT_EMPTY,
81
- replacement(variable1),
82
- node.source))
83
+ prefer: replacement(variable1),
84
+ current: node.source))
83
85
  end
84
86
  end
85
87
 
@@ -99,7 +101,8 @@ module RuboCop
99
101
 
100
102
  unless_blank?(node) do |method_call, receiver|
101
103
  range = unless_condition(node, method_call)
102
- msg = format(MSG_UNLESS_BLANK, replacement(receiver), range.source)
104
+ msg = format(MSG_UNLESS_BLANK, prefer: replacement(receiver),
105
+ current: range.source)
103
106
  add_offense(node, location: range, message: msg)
104
107
  end
105
108
  end
@@ -26,6 +26,34 @@ module RuboCop
26
26
  # has_many :expenses
27
27
  # end
28
28
  # end
29
+ #
30
+ # @example
31
+ # # bad
32
+ # with_options options: false do |merger|
33
+ # merger.invoke(merger.something)
34
+ # end
35
+ #
36
+ # # good
37
+ # with_options options: false do
38
+ # invoke(something)
39
+ # end
40
+ #
41
+ # # good
42
+ # client = Client.new
43
+ # with_options options: false do |merger|
44
+ # client.invoke(merger.something, something)
45
+ # end
46
+ #
47
+ # # ok
48
+ # # When `with_options` includes a block, all scoping scenarios
49
+ # # cannot be evaluated. Thus, it is ok to include the explicit
50
+ # # receiver.
51
+ # with_options options: false do |merger|
52
+ # merger.invoke
53
+ # with_another_method do |another_receiver|
54
+ # merger.invoke(another_receiver)
55
+ # end
56
+ # end
29
57
  class RedundantReceiverInWithOptions < Cop
30
58
  extend TargetRailsVersion
31
59
 
@@ -38,26 +66,35 @@ module RuboCop
38
66
  (send nil? :with_options
39
67
  (...))
40
68
  (args
41
- (...))
42
- ...)
69
+ $_arg)
70
+ $_body)
43
71
  PATTERN
44
72
 
45
- def_node_search :assoc_has_redundant_receiver, <<-PATTERN
46
- (send
47
- (lvar _) ...)
73
+ def_node_search :all_block_nodes_in, <<-PATTERN
74
+ (block ...)
75
+ PATTERN
76
+
77
+ def_node_search :all_send_nodes_in, <<-PATTERN
78
+ (send ...)
48
79
  PATTERN
49
80
 
50
81
  def on_block(node)
51
- with_options?(node) do
52
- assoc_has_redundant_receiver(node).each do |assoc|
53
- add_offense(assoc, location: assoc.receiver.loc.expression)
82
+ with_options?(node) do |arg, body|
83
+ return unless all_block_nodes_in(body).count.zero?
84
+ send_nodes = all_send_nodes_in(body)
85
+
86
+ if send_nodes.all? { |n| same_value?(arg, n.receiver) }
87
+ send_nodes.each do |send_node|
88
+ receiver = send_node.receiver
89
+ add_offense(send_node, location: receiver.source_range)
90
+ end
54
91
  end
55
92
  end
56
93
  end
57
94
 
58
95
  def autocorrect(node)
59
96
  lambda do |corrector|
60
- corrector.remove(node.receiver.loc.expression)
97
+ corrector.remove(node.receiver.source_range)
61
98
  corrector.remove(node.loc.dot)
62
99
  corrector.remove(block_argument_range(node))
63
100
  end
@@ -66,7 +103,8 @@ module RuboCop
66
103
  private
67
104
 
68
105
  def block_argument_range(node)
69
- block_argument = node.parent.parent.children[1].loc.expression
106
+ block_node = node.each_ancestor(:block).first
107
+ block_argument = block_node.children[1].source_range
70
108
 
71
109
  range_between(
72
110
  search_begin_pos_of_space_before_block_argument(
@@ -85,6 +123,10 @@ module RuboCop
85
123
  begin_pos
86
124
  end
87
125
  end
126
+
127
+ def same_value?(arg_node, recv_node)
128
+ recv_node && recv_node.children[0] == arg_node.children[0]
129
+ end
88
130
  end
89
131
  end
90
132
  end
@@ -6,15 +6,14 @@ module RuboCop
6
6
  # This cop checks for consistent uses of `request.referer` or
7
7
  # `request.referrer`, depending on the cop's configuration.
8
8
  #
9
- # @example
10
- # # EnforcedStyle: referer
9
+ # @example EnforcedStyle: referer (default)
11
10
  # # bad
12
11
  # request.referrer
13
12
  #
14
13
  # # good
15
14
  # request.referer
16
15
  #
17
- # # EnforcedStyle: referrer
16
+ # @example EnforcedStyle: referrer
18
17
  # # bad
19
18
  # request.referer
20
19
  #
@@ -29,8 +29,7 @@ module RuboCop
29
29
 
30
30
  next if node.receiver != target_receiver
31
31
  next if node.method_name != target_method
32
- next if node.parent && node.parent.block_type?
33
- next if node.block_argument?
32
+ next if cleanup?(node)
34
33
 
35
34
  add_offense(node,
36
35
  message: format(MSG,
@@ -38,6 +37,14 @@ module RuboCop
38
37
  method: target_method))
39
38
  end
40
39
  end
40
+
41
+ private
42
+
43
+ def cleanup?(node)
44
+ parent = node.parent
45
+ node.block_argument? ||
46
+ (parent && (parent.block_type? || !parent.lvasgn_type?))
47
+ end
41
48
  end
42
49
  end
43
50
  end
@@ -125,24 +125,52 @@ module RuboCop
125
125
  end
126
126
  end
127
127
 
128
+ # rubocop:disable Metrics/AbcSize
128
129
  def remove_braces_with_whitespace(corrector, node, space)
129
130
  right_brace_and_space = right_brace_and_space(node.loc.end, space)
130
131
 
131
132
  if comment_on_line?(right_brace_and_space.line)
132
- # Removing a line break between a comment and the closing
133
- # parenthesis would cause a syntax error, so we only remove the
134
- # braces in that case.
135
133
  remove_braces(corrector, node)
134
+ elsif node.multiline?
135
+ remove_braces_with_range(corrector,
136
+ left_whole_line_range(node.loc.begin),
137
+ right_whole_line_range(node.loc.end))
136
138
  else
137
- left_brace_and_space =
138
- range_with_surrounding_space(range: node.loc.begin,
139
- side: :right,
140
- newlines: space[:newlines],
141
- whitespace: space[:left])
142
- corrector.remove(left_brace_and_space)
143
- corrector.remove(right_brace_and_space)
139
+ left_brace_and_space = left_brace_and_space(node.loc.begin, space)
140
+ remove_braces_with_range(corrector,
141
+ left_brace_and_space,
142
+ right_brace_and_space)
144
143
  end
145
144
  end
145
+ # rubocop:enable Metrics/AbcSize
146
+
147
+ def remove_braces_with_range(corrector, left_range, right_range)
148
+ corrector.remove(left_range)
149
+ corrector.remove(right_range)
150
+ end
151
+
152
+ def left_whole_line_range(loc_begin)
153
+ if range_by_whole_lines(loc_begin).source.strip == '{'
154
+ range_by_whole_lines(loc_begin, include_final_newline: true)
155
+ else
156
+ loc_begin
157
+ end
158
+ end
159
+
160
+ def right_whole_line_range(loc_end)
161
+ if range_by_whole_lines(loc_end).source.strip == '}'
162
+ range_by_whole_lines(loc_end, include_final_newline: true)
163
+ else
164
+ loc_end
165
+ end
166
+ end
167
+
168
+ def left_brace_and_space(loc_begin, space)
169
+ range_with_surrounding_space(range: loc_begin,
170
+ side: :right,
171
+ newlines: space[:newlines],
172
+ whitespace: space[:left])
173
+ end
146
174
 
147
175
  def right_brace_and_space(loc_end, space)
148
176
  brace_and_space =
@@ -40,8 +40,84 @@ module RuboCop
40
40
  check_style(node, body)
41
41
  end
42
42
 
43
+ def autocorrect(node)
44
+ lambda do |corrector|
45
+ if node.class_type?
46
+ name, superclass, body = *node
47
+ return if superclass && style != :nested
48
+ else
49
+ name, body = *node
50
+ end
51
+ nest_or_compact(corrector, node, name, body)
52
+ end
53
+ end
54
+
43
55
  private
44
56
 
57
+ def nest_or_compact(corrector, node, name, body)
58
+ if style == :nested
59
+ nest_definition(corrector, node)
60
+ else
61
+ compact_definition(corrector, node, name, body)
62
+ end
63
+ end
64
+
65
+ def nest_definition(corrector, node)
66
+ padding = ((' ' * indent_width) + leading_spaces(node)).to_s
67
+ padding_for_trailing_end = padding.sub(' ' * node.loc.end.column, '')
68
+
69
+ replace_keyword_with_module(corrector, node)
70
+ split_on_double_colon(corrector, node, padding)
71
+ add_trailing_end(corrector, node, padding_for_trailing_end)
72
+ end
73
+
74
+ def replace_keyword_with_module(corrector, node)
75
+ corrector.replace(node.loc.keyword, 'module'.freeze)
76
+ end
77
+
78
+ def split_on_double_colon(corrector, node, padding)
79
+ children_definition = node.children.first
80
+ range = range_between(children_definition.loc.double_colon.begin_pos,
81
+ children_definition.loc.double_colon.end_pos)
82
+ replacement = "\n#{padding}#{node.loc.keyword.source} ".freeze
83
+
84
+ corrector.replace(range, replacement)
85
+ end
86
+
87
+ def add_trailing_end(corrector, node, padding)
88
+ replacement = "#{padding}end\n#{leading_spaces(node)}end".freeze
89
+ corrector.replace(node.loc.end, replacement)
90
+ end
91
+
92
+ def compact_definition(corrector, node, name, body)
93
+ compact_node(corrector, node, name, body)
94
+ remove_end(corrector, body)
95
+ end
96
+
97
+ def compact_node(corrector, node, name, body)
98
+ const_name = "#{name.const_name}::#{body.children.first.const_name}"
99
+ replacement = "#{body.type} #{const_name}"
100
+ range = range_between(node.loc.keyword.begin_pos,
101
+ body.loc.name.end_pos)
102
+ corrector.replace(range, replacement)
103
+ end
104
+
105
+ def remove_end(corrector, body)
106
+ range = range_between(
107
+ body.loc.end.begin_pos - leading_spaces(body).size,
108
+ body.loc.end.end_pos + 1
109
+ )
110
+ corrector.remove(range)
111
+ end
112
+
113
+ def leading_spaces(node)
114
+ node.source_range.source_line[/\A\s*/]
115
+ end
116
+
117
+ def indent_width
118
+ @config.for_cop('IndentationWidth')['Width'] || 2
119
+ end
120
+
45
121
  def check_style(node, body)
46
122
  if style == :nested
47
123
  check_nested_style(node)