rubocop 0.90.0 → 0.93.1

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.
Files changed (201) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/config/default.yml +79 -3
  4. data/lib/rubocop.rb +20 -5
  5. data/lib/rubocop/cached_data.rb +2 -1
  6. data/lib/rubocop/cli/command/execute_runner.rb +8 -0
  7. data/lib/rubocop/comment_config.rb +9 -5
  8. data/lib/rubocop/config_loader.rb +3 -3
  9. data/lib/rubocop/config_regeneration.rb +33 -0
  10. data/lib/rubocop/config_store.rb +3 -3
  11. data/lib/rubocop/cop/bundler/duplicated_gem.rb +5 -1
  12. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -0
  13. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +2 -0
  14. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
  15. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +10 -10
  16. data/lib/rubocop/cop/generator.rb +1 -1
  17. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +1 -0
  18. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -0
  19. data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +1 -0
  20. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -0
  21. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -0
  22. data/lib/rubocop/cop/layout/array_alignment.rb +1 -0
  23. data/lib/rubocop/cop/layout/begin_end_alignment.rb +77 -0
  24. data/lib/rubocop/cop/layout/case_indentation.rb +4 -7
  25. data/lib/rubocop/cop/layout/class_structure.rb +1 -1
  26. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  27. data/lib/rubocop/cop/layout/dot_position.rb +6 -9
  28. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +2 -2
  29. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +4 -12
  30. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +13 -8
  31. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +2 -2
  32. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -2
  33. data/lib/rubocop/cop/layout/end_alignment.rb +5 -10
  34. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +26 -4
  35. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +4 -13
  36. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +7 -7
  37. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +0 -4
  38. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +6 -21
  39. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +3 -8
  40. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +2 -2
  41. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -0
  42. data/lib/rubocop/cop/lint/ambiguous_operator.rb +2 -0
  43. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +18 -1
  44. data/lib/rubocop/cop/lint/big_decimal_new.rb +1 -2
  45. data/lib/rubocop/cop/lint/boolean_symbol.rb +3 -0
  46. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +74 -0
  47. data/lib/rubocop/cop/lint/debugger.rb +2 -3
  48. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -3
  49. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -4
  50. data/lib/rubocop/cop/lint/duplicate_require.rb +7 -2
  51. data/lib/rubocop/cop/lint/duplicate_rescue_exception.rb +2 -4
  52. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -0
  53. data/lib/rubocop/cop/lint/empty_file.rb +1 -4
  54. data/lib/rubocop/cop/lint/erb_new_arguments.rb +2 -0
  55. data/lib/rubocop/cop/lint/float_comparison.rb +2 -2
  56. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  57. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +37 -0
  58. data/lib/rubocop/cop/lint/identity_comparison.rb +51 -0
  59. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +2 -5
  60. data/lib/rubocop/cop/lint/inherit_exception.rb +2 -2
  61. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  62. data/lib/rubocop/cop/lint/multiple_comparison.rb +3 -1
  63. data/lib/rubocop/cop/lint/number_conversion.rb +1 -0
  64. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -2
  65. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  66. data/lib/rubocop/cop/lint/raise_exception.rb +1 -0
  67. data/lib/rubocop/cop/lint/rand_one.rb +2 -1
  68. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +22 -12
  69. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +14 -4
  70. data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -0
  71. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +78 -0
  72. data/lib/rubocop/cop/lint/rescue_type.rb +0 -1
  73. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +3 -1
  74. data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -6
  75. data/lib/rubocop/cop/lint/struct_new_override.rb +1 -0
  76. data/lib/rubocop/cop/lint/to_json.rb +16 -5
  77. data/lib/rubocop/cop/lint/unreachable_loop.rb +3 -6
  78. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +3 -1
  79. data/lib/rubocop/cop/lint/uri_regexp.rb +2 -1
  80. data/lib/rubocop/cop/lint/useless_access_modifier.rb +3 -9
  81. data/lib/rubocop/cop/lint/useless_method_definition.rb +20 -27
  82. data/lib/rubocop/cop/lint/useless_times.rb +106 -0
  83. data/lib/rubocop/cop/metrics/block_length.rb +3 -1
  84. data/lib/rubocop/cop/metrics/class_length.rb +14 -6
  85. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +25 -16
  86. data/lib/rubocop/cop/mixin/comments_help.rb +3 -9
  87. data/lib/rubocop/cop/mixin/configurable_naming.rb +2 -2
  88. data/lib/rubocop/cop/mixin/configurable_numbering.rb +3 -3
  89. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +9 -0
  90. data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -2
  91. data/lib/rubocop/cop/mixin/rescue_node.rb +1 -0
  92. data/lib/rubocop/cop/mixin/statement_modifier.rb +9 -3
  93. data/lib/rubocop/cop/mixin/visibility_help.rb +4 -16
  94. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  95. data/lib/rubocop/cop/naming/file_name.rb +1 -1
  96. data/lib/rubocop/cop/offense.rb +15 -2
  97. data/lib/rubocop/cop/security/eval.rb +1 -0
  98. data/lib/rubocop/cop/security/json_load.rb +1 -0
  99. data/lib/rubocop/cop/security/marshal_load.rb +1 -0
  100. data/lib/rubocop/cop/security/open.rb +1 -0
  101. data/lib/rubocop/cop/security/yaml_load.rb +1 -0
  102. data/lib/rubocop/cop/style/access_modifier_declarations.rb +7 -11
  103. data/lib/rubocop/cop/style/accessor_grouping.rb +3 -0
  104. data/lib/rubocop/cop/style/alias.rb +2 -0
  105. data/lib/rubocop/cop/style/array_coercion.rb +4 -0
  106. data/lib/rubocop/cop/style/array_join.rb +1 -0
  107. data/lib/rubocop/cop/style/attr.rb +1 -0
  108. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +2 -0
  109. data/lib/rubocop/cop/style/case_equality.rb +3 -0
  110. data/lib/rubocop/cop/style/case_like_if.rb +20 -4
  111. data/lib/rubocop/cop/style/class_and_module_children.rb +2 -0
  112. data/lib/rubocop/cop/style/class_check.rb +6 -9
  113. data/lib/rubocop/cop/style/class_equality_comparison.rb +64 -0
  114. data/lib/rubocop/cop/style/class_methods_definitions.rb +42 -16
  115. data/lib/rubocop/cop/style/class_vars.rb +1 -2
  116. data/lib/rubocop/cop/style/combinable_loops.rb +13 -11
  117. data/lib/rubocop/cop/style/comment_annotation.rb +6 -0
  118. data/lib/rubocop/cop/style/commented_keyword.rb +7 -8
  119. data/lib/rubocop/cop/style/conditional_assignment.rb +49 -60
  120. data/lib/rubocop/cop/style/date_time.rb +12 -1
  121. data/lib/rubocop/cop/style/dir.rb +1 -0
  122. data/lib/rubocop/cop/style/double_negation.rb +1 -0
  123. data/lib/rubocop/cop/style/empty_literal.rb +3 -1
  124. data/lib/rubocop/cop/style/eval_with_location.rb +1 -3
  125. data/lib/rubocop/cop/style/even_odd.rb +1 -0
  126. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -2
  127. data/lib/rubocop/cop/style/explicit_block_argument.rb +7 -3
  128. data/lib/rubocop/cop/style/float_division.rb +2 -0
  129. data/lib/rubocop/cop/style/for.rb +0 -4
  130. data/lib/rubocop/cop/style/format_string.rb +1 -4
  131. data/lib/rubocop/cop/style/format_string_token.rb +1 -1
  132. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +24 -5
  133. data/lib/rubocop/cop/style/hash_transform_keys.rb +5 -11
  134. data/lib/rubocop/cop/style/hash_transform_values.rb +5 -11
  135. data/lib/rubocop/cop/style/if_unless_modifier.rb +0 -4
  136. data/lib/rubocop/cop/style/implicit_runtime_error.rb +1 -0
  137. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -6
  138. data/lib/rubocop/cop/style/lambda_call.rb +3 -1
  139. data/lib/rubocop/cop/style/method_def_parentheses.rb +0 -4
  140. data/lib/rubocop/cop/style/mixin_usage.rb +8 -27
  141. data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -2
  142. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +14 -1
  143. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -0
  144. data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -0
  145. data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
  146. data/lib/rubocop/cop/style/non_nil_check.rb +2 -0
  147. data/lib/rubocop/cop/style/not.rb +1 -0
  148. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -3
  149. data/lib/rubocop/cop/style/one_line_conditional.rb +3 -1
  150. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +12 -1
  151. data/lib/rubocop/cop/style/preferred_hash_methods.rb +2 -0
  152. data/lib/rubocop/cop/style/raise_args.rb +2 -3
  153. data/lib/rubocop/cop/style/random_with_offset.rb +4 -3
  154. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -9
  155. data/lib/rubocop/cop/style/redundant_begin.rb +36 -8
  156. data/lib/rubocop/cop/style/redundant_condition.rb +5 -1
  157. data/lib/rubocop/cop/style/redundant_conditional.rb +4 -5
  158. data/lib/rubocop/cop/style/redundant_exception.rb +1 -3
  159. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -0
  160. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -1
  161. data/lib/rubocop/cop/style/redundant_interpolation.rb +6 -1
  162. data/lib/rubocop/cop/style/redundant_parentheses.rb +14 -6
  163. data/lib/rubocop/cop/style/redundant_percent_q.rb +9 -11
  164. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +39 -24
  165. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -15
  166. data/lib/rubocop/cop/style/redundant_return.rb +17 -17
  167. data/lib/rubocop/cop/style/redundant_self.rb +7 -9
  168. data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -2
  169. data/lib/rubocop/cop/style/redundant_sort.rb +12 -29
  170. data/lib/rubocop/cop/style/redundant_sort_by.rb +5 -9
  171. data/lib/rubocop/cop/style/rescue_standard_error.rb +20 -16
  172. data/lib/rubocop/cop/style/safe_navigation.rb +5 -0
  173. data/lib/rubocop/cop/style/sample.rb +2 -1
  174. data/lib/rubocop/cop/style/send.rb +2 -3
  175. data/lib/rubocop/cop/style/signal_exception.rb +2 -0
  176. data/lib/rubocop/cop/style/single_argument_dig.rb +1 -0
  177. data/lib/rubocop/cop/style/slicing_with_range.rb +2 -1
  178. data/lib/rubocop/cop/style/stderr_puts.rb +1 -0
  179. data/lib/rubocop/cop/style/string_concatenation.rb +17 -3
  180. data/lib/rubocop/cop/style/strip.rb +1 -0
  181. data/lib/rubocop/cop/style/ternary_parentheses.rb +2 -3
  182. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +4 -3
  183. data/lib/rubocop/cop/style/unpack_first.rb +1 -0
  184. data/lib/rubocop/cop/style/zero_length_predicate.rb +1 -5
  185. data/lib/rubocop/cop/util.rb +0 -1
  186. data/lib/rubocop/cop/variable_force/branch.rb +0 -4
  187. data/lib/rubocop/core_ext/string.rb +1 -1
  188. data/lib/rubocop/directive_comment.rb +32 -0
  189. data/lib/rubocop/ext/regexp_node.rb +23 -7
  190. data/lib/rubocop/formatter/disabled_config_formatter.rb +12 -5
  191. data/lib/rubocop/options.rb +37 -17
  192. data/lib/rubocop/result_cache.rb +38 -15
  193. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  194. data/lib/rubocop/rspec/expect_offense.rb +5 -5
  195. data/lib/rubocop/runner.rb +37 -18
  196. data/lib/rubocop/target_finder.rb +27 -26
  197. data/lib/rubocop/target_ruby.rb +1 -1
  198. data/lib/rubocop/version.rb +6 -1
  199. metadata +19 -18
  200. data/lib/rubocop/cop/mixin/regexp_literal_help.rb +0 -43
  201. data/lib/rubocop/cop/tokens_util.rb +0 -84
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop enforces the use of `Object#instance_of?` instead of class comparison
7
+ # for equality.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # var.class == Date
12
+ # var.class.equal?(Date)
13
+ # var.class.eql?(Date)
14
+ # var.class.name == 'Date'
15
+ #
16
+ # # good
17
+ # var.instance_of?(Date)
18
+ #
19
+ class ClassEqualityComparison < Base
20
+ include RangeHelp
21
+ include IgnoredMethods
22
+ extend AutoCorrector
23
+
24
+ MSG = 'Use `instance_of?(%<class_name>s)` instead of comparing classes.'
25
+
26
+ RESTRICT_ON_SEND = %i[== equal? eql?].freeze
27
+
28
+ def_node_matcher :class_comparison_candidate?, <<~PATTERN
29
+ (send
30
+ {$(send _ :class) (send $(send _ :class) :name)}
31
+ {:== :equal? :eql?} $_)
32
+ PATTERN
33
+
34
+ def on_send(node)
35
+ def_node = node.each_ancestor(:def, :defs).first
36
+ return if def_node && ignored_method?(def_node.method_name)
37
+
38
+ class_comparison_candidate?(node) do |receiver_node, class_node|
39
+ range = offense_range(receiver_node, node)
40
+ class_name = class_name(class_node, node)
41
+
42
+ add_offense(range, message: format(MSG, class_name: class_name)) do |corrector|
43
+ corrector.replace(range, "instance_of?(#{class_name})")
44
+ end
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def class_name(class_node, node)
51
+ if node.children.first.method?(:name)
52
+ class_node.source.delete('"').delete("'")
53
+ else
54
+ class_node.source
55
+ end
56
+ end
57
+
58
+ def offense_range(receiver_node, node)
59
+ range_between(receiver_node.loc.selector.begin_pos, node.source_range.end_pos)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -62,22 +62,19 @@ module RuboCop
62
62
  include ConfigurableEnforcedStyle
63
63
  include CommentsHelp
64
64
  include VisibilityHelp
65
+ include RangeHelp
65
66
  extend AutoCorrector
66
67
 
67
- MSG = 'Use `%<preferred>s` to define class method.'
68
+ MSG = 'Use `%<preferred>s` to define a class method.'
69
+ MSG_SCLASS = 'Do not define public methods within class << self.'
68
70
 
69
71
  def on_sclass(node)
70
72
  return unless def_self_style?
71
73
  return unless node.identifier.source == 'self'
72
- return if contains_non_public_methods?(node)
74
+ return unless all_methods_public?(node)
73
75
 
74
- def_nodes(node).each do |def_node|
75
- next unless node_visibility(def_node) == :public
76
-
77
- message = format(MSG, preferred: "def self.#{def_node.method_name}")
78
- add_offense(def_node, message: message) do |corrector|
79
- extract_def_from_sclass(def_node, node, corrector)
80
- end
76
+ add_offense(node, message: MSG_SCLASS) do |corrector|
77
+ autocorrect_sclass(node, corrector)
81
78
  end
82
79
  end
83
80
 
@@ -94,8 +91,11 @@ module RuboCop
94
91
  style == :def_self
95
92
  end
96
93
 
97
- def contains_non_public_methods?(sclass_node)
98
- def_nodes(sclass_node).any? { |def_node| node_visibility(def_node) != :public }
94
+ def all_methods_public?(sclass_node)
95
+ def_nodes = def_nodes(sclass_node)
96
+ return false if def_nodes.empty?
97
+
98
+ def_nodes.all? { |def_node| node_visibility(def_node) == :public }
99
99
  end
100
100
 
101
101
  def def_nodes(sclass_node)
@@ -111,19 +111,45 @@ module RuboCop
111
111
  end
112
112
  end
113
113
 
114
- def extract_def_from_sclass(def_node, sclass_node, corrector)
114
+ def autocorrect_sclass(node, corrector)
115
+ rewritten_defs = []
116
+
117
+ def_nodes(node).each do |def_node|
118
+ next unless node_visibility(def_node) == :public
119
+
120
+ range, source = extract_def_from_sclass(def_node, node)
121
+
122
+ corrector.remove(range)
123
+ rewritten_defs << source
124
+ end
125
+
126
+ if sclass_only_has_methods?(node)
127
+ corrector.remove(node)
128
+ rewritten_defs.first&.strip!
129
+ else
130
+ corrector.insert_after(node, "\n")
131
+ end
132
+
133
+ corrector.insert_after(node, rewritten_defs.join("\n"))
134
+ end
135
+
136
+ def sclass_only_has_methods?(node)
137
+ node.body.def_type? || node.body.each_child_node.all?(&:def_type?)
138
+ end
139
+
140
+ def extract_def_from_sclass(def_node, sclass_node)
115
141
  range = source_range_with_comment(def_node)
116
142
  source = range.source.sub!(
117
143
  "def #{def_node.method_name}",
118
144
  "def self.#{def_node.method_name}"
119
145
  )
120
146
 
121
- corrector.insert_before(sclass_node, "#{source}\n#{indent(sclass_node)}")
122
- corrector.remove(range)
147
+ source = source.gsub(/^ {#{indentation_diff(def_node, sclass_node)}}/, '')
148
+ [range, source.chomp]
123
149
  end
124
150
 
125
- def indent(node)
126
- ' ' * node.loc.column
151
+ def indentation_diff(node1, node2)
152
+ node1.loc.column - node2.loc.column
127
153
  end
128
154
  end
129
155
  end
@@ -47,14 +47,13 @@ module RuboCop
47
47
  #
48
48
  class ClassVars < Base
49
49
  MSG = 'Replace class var %<class_var>s with a class instance var.'
50
+ RESTRICT_ON_SEND = %i[class_variable_set].freeze
50
51
 
51
52
  def on_cvasgn(node)
52
53
  add_offense(node.loc.name, message: format(MSG, class_var: node.children.first))
53
54
  end
54
55
 
55
56
  def on_send(node)
56
- return unless node.method?(:class_variable_set)
57
-
58
57
  add_offense(
59
58
  node.first_argument, message: format(MSG, class_var: node.first_argument.source)
60
59
  )
@@ -49,18 +49,26 @@ module RuboCop
49
49
  # end
50
50
  # end
51
51
  #
52
+ # # good
53
+ # def method
54
+ # each_slice(2) { |slice| do_something(slice) }
55
+ # each_slice(3) { |slice| do_something(slice) }
56
+ # end
57
+ #
52
58
  class CombinableLoops < Base
53
59
  MSG = 'Combine this loop with the previous loop.'
54
60
 
55
61
  def on_block(node)
62
+ return unless node.parent&.begin_type?
56
63
  return unless collection_looping_method?(node)
57
64
 
58
- sibling = left_sibling_of(node)
59
- add_offense(node) if same_collection_looping?(node, sibling)
65
+ add_offense(node) if same_collection_looping?(node, node.left_sibling)
60
66
  end
61
67
 
62
68
  def on_for(node)
63
- sibling = left_sibling_of(node)
69
+ return unless node.parent&.begin_type?
70
+
71
+ sibling = node.left_sibling
64
72
  add_offense(node) if sibling&.for_type? && node.collection == sibling.collection
65
73
  end
66
74
 
@@ -71,17 +79,11 @@ module RuboCop
71
79
  method_name.match?(/^each/) || method_name.match?(/_each$/)
72
80
  end
73
81
 
74
- def left_sibling_of(node)
75
- return unless node.parent&.begin_type?
76
-
77
- index = node.sibling_index - 1
78
- node.parent.children[index] if index >= 0
79
- end
80
-
81
82
  def same_collection_looping?(node, sibling)
82
83
  sibling&.block_type? &&
83
84
  sibling.send_node.method?(node.method_name) &&
84
- sibling.send_node.receiver == node.send_node.receiver
85
+ sibling.send_node.receiver == node.send_node.receiver &&
86
+ sibling.send_node.arguments == node.send_node.arguments
85
87
  end
86
88
  end
87
89
  end
@@ -6,6 +6,12 @@ module RuboCop
6
6
  # This cop checks that comment annotation keywords are written according
7
7
  # to guidelines.
8
8
  #
9
+ # NOTE: With a multiline comment block (where each line is only a
10
+ # comment), only the first line will be able to register an offense, even
11
+ # if an annotation keyword starts another line. This is done to prevent
12
+ # incorrect registering of keywords (eg. `review`) inside a paragraph as an
13
+ # annotation.
14
+ #
9
15
  # @example
10
16
  # # bad
11
17
  # # TODO make better
@@ -33,13 +33,17 @@ module RuboCop
33
33
  # class X # :nodoc:
34
34
  # y
35
35
  # end
36
- class CommentedKeyword < Cop
36
+ class CommentedKeyword < Base
37
37
  MSG = 'Do not place comments on the same line as the ' \
38
38
  '`%<keyword>s` keyword.'
39
39
 
40
- def investigate(processed_source)
40
+ def on_new_investigation
41
41
  processed_source.comments.each do |comment|
42
- add_offense(comment) if offensive?(comment)
42
+ next unless (match = line(comment).match(/(?<keyword>\S+).*#/))
43
+
44
+ if offensive?(comment)
45
+ add_offense(comment, message: format(MSG, keyword: match[:keyword]))
46
+ end
43
47
  end
44
48
  end
45
49
 
@@ -62,11 +66,6 @@ module RuboCop
62
66
  ALLOWED_COMMENT_REGEXES.none? { |r| r.match?(line) }
63
67
  end
64
68
 
65
- def message(comment)
66
- keyword = line(comment).match(/(\S+).*#/)[1]
67
- format(MSG, keyword: keyword)
68
- end
69
-
70
69
  def line(comment)
71
70
  comment.location.expression.source_line
72
71
  end
@@ -208,10 +208,11 @@ module RuboCop
208
208
  # some_other_method
209
209
  # bar = 2
210
210
  # end
211
- class ConditionalAssignment < Cop
211
+ class ConditionalAssignment < Base
212
212
  include ConditionalAssignmentHelper
213
213
  include ConfigurableEnforcedStyle
214
214
  include IgnoredNode
215
+ extend AutoCorrector
215
216
 
216
217
  MSG = 'Use the return of the conditional for variable assignment ' \
217
218
  'and comparison.'
@@ -275,14 +276,6 @@ module RuboCop
275
276
  check_node(node, branches)
276
277
  end
277
278
 
278
- def autocorrect(node)
279
- if assignment_type?(node)
280
- move_assignment_inside_condition(node)
281
- else
282
- move_assignment_outside_condition(node)
283
- end
284
- end
285
-
286
279
  private
287
280
 
288
281
  def check_assignment_to_condition(node)
@@ -298,7 +291,9 @@ module RuboCop
298
291
  return unless else_branch
299
292
  return if allowed_single_line?([*branches, else_branch])
300
293
 
301
- add_offense(node, message: ASSIGN_TO_CONDITION_MSG)
294
+ add_offense(node, message: ASSIGN_TO_CONDITION_MSG) do |corrector|
295
+ autocorrect(corrector, node)
296
+ end
302
297
  end
303
298
 
304
299
  def candidate_node?(node)
@@ -326,25 +321,25 @@ module RuboCop
326
321
  assignment
327
322
  end
328
323
 
329
- def move_assignment_outside_condition(node)
324
+ def move_assignment_outside_condition(corrector, node)
330
325
  if node.case_type?
331
- CaseCorrector.correct(self, node)
326
+ CaseCorrector.correct(corrector, self, node)
332
327
  elsif node.ternary?
333
- TernaryCorrector.correct(node)
328
+ TernaryCorrector.correct(corrector, node)
334
329
  elsif node.if? || node.unless?
335
- IfCorrector.correct(self, node)
330
+ IfCorrector.correct(corrector, self, node)
336
331
  end
337
332
  end
338
333
 
339
- def move_assignment_inside_condition(node)
334
+ def move_assignment_inside_condition(corrector, node)
340
335
  *_assignment, condition = *node
341
336
 
342
337
  if ternary_condition?(condition)
343
- TernaryCorrector.move_assignment_inside_condition(node)
338
+ TernaryCorrector.move_assignment_inside_condition(corrector, node)
344
339
  elsif condition.case_type?
345
- CaseCorrector.move_assignment_inside_condition(node)
340
+ CaseCorrector.move_assignment_inside_condition(corrector, node)
346
341
  elsif condition.if_type?
347
- IfCorrector.move_assignment_inside_condition(node)
342
+ IfCorrector.move_assignment_inside_condition(corrector, node)
348
343
  end
349
344
  end
350
345
 
@@ -371,7 +366,17 @@ module RuboCop
371
366
  return if allowed_single_line?(branches)
372
367
  return if correction_exceeds_line_limit?(node, branches)
373
368
 
374
- add_offense(node)
369
+ add_offense(node) do |corrector|
370
+ autocorrect(corrector, node)
371
+ end
372
+ end
373
+
374
+ def autocorrect(corrector, node)
375
+ if assignment_type?(node)
376
+ move_assignment_inside_condition(corrector, node)
377
+ else
378
+ move_assignment_outside_condition(corrector, node)
379
+ end
375
380
  end
376
381
 
377
382
  def allowed_statements?(branches)
@@ -499,24 +504,20 @@ module RuboCop
499
504
  include ConditionalAssignmentHelper
500
505
  include ConditionalCorrectorHelper
501
506
 
502
- def correct(node)
503
- lambda do |corrector|
504
- corrector.replace(node, correction(node))
505
- end
507
+ def correct(corrector, node)
508
+ corrector.replace(node, correction(node))
506
509
  end
507
510
 
508
- def move_assignment_inside_condition(node)
511
+ def move_assignment_inside_condition(corrector, node)
509
512
  *_var, rhs = *node
510
513
  if_branch, else_branch = extract_branches(node)
511
514
  assignment = assignment(node)
512
515
 
513
- lambda do |corrector|
514
- remove_parentheses(corrector, rhs) if Util.parentheses?(rhs)
515
- corrector.remove(assignment)
516
+ remove_parentheses(corrector, rhs) if Util.parentheses?(rhs)
517
+ corrector.remove(assignment)
516
518
 
517
- move_branch_inside_condition(corrector, if_branch, assignment)
518
- move_branch_inside_condition(corrector, else_branch, assignment)
519
- end
519
+ move_branch_inside_condition(corrector, if_branch, assignment)
520
+ move_branch_inside_condition(corrector, else_branch, assignment)
520
521
  end
521
522
 
522
523
  private
@@ -565,22 +566,19 @@ module RuboCop
565
566
  include ConditionalAssignmentHelper
566
567
  include ConditionalCorrectorHelper
567
568
 
568
- def correct(cop, node)
569
- ->(corrector) { correct_if_branches(corrector, cop, node) }
569
+ def correct(corrector, cop, node)
570
+ correct_if_branches(corrector, cop, node)
570
571
  end
571
572
 
572
- def move_assignment_inside_condition(node)
573
+ def move_assignment_inside_condition(corrector, node)
573
574
  column = node.loc.expression.column
574
575
  *_var, condition = *node
575
576
  assignment = assignment(node)
576
577
 
577
- lambda do |corrector|
578
- corrector.remove(assignment)
578
+ corrector.remove(assignment)
579
579
 
580
- condition.branches.flatten.each do |branch|
581
- move_branch_inside_condition(corrector, branch, condition,
582
- assignment, column)
583
- end
580
+ condition.branches.flatten.each do |branch|
581
+ move_branch_inside_condition(corrector, branch, condition, assignment, column)
584
582
  end
585
583
  end
586
584
 
@@ -614,31 +612,25 @@ module RuboCop
614
612
  include ConditionalAssignmentHelper
615
613
  include ConditionalCorrectorHelper
616
614
 
617
- def correct(cop, node)
615
+ def correct(corrector, cop, node)
618
616
  when_branches, else_branch = extract_tail_branches(node)
619
617
 
620
- lambda do |corrector|
621
- corrector.insert_before(node, lhs(else_branch))
622
- correct_branches(corrector, when_branches)
623
- replace_branch_assignment(corrector, else_branch)
618
+ corrector.insert_before(node, lhs(else_branch))
619
+ correct_branches(corrector, when_branches)
620
+ replace_branch_assignment(corrector, else_branch)
624
621
 
625
- corrector.insert_before(node.loc.end,
626
- indent(cop, lhs(else_branch)))
627
- end
622
+ corrector.insert_before(node.loc.end, indent(cop, lhs(else_branch)))
628
623
  end
629
624
 
630
- def move_assignment_inside_condition(node)
625
+ def move_assignment_inside_condition(corrector, node)
631
626
  column = node.loc.expression.column
632
627
  *_var, condition = *node
633
628
  assignment = assignment(node)
634
629
 
635
- lambda do |corrector|
636
- corrector.remove(assignment)
630
+ corrector.remove(assignment)
637
631
 
638
- extract_branches(condition).flatten.each do |branch|
639
- move_branch_inside_condition(corrector, branch, condition,
640
- assignment, column)
641
- end
632
+ extract_branches(condition).flatten.each do |branch|
633
+ move_branch_inside_condition(corrector, branch, condition, assignment, column)
642
634
  end
643
635
  end
644
636
 
@@ -656,17 +648,14 @@ module RuboCop
656
648
  [when_branches, case_node.else_branch]
657
649
  end
658
650
 
659
- def move_branch_inside_condition(corrector, branch, condition,
660
- assignment, column)
651
+ def move_branch_inside_condition(corrector, branch, condition, assignment, column)
661
652
  branch_assignment = tail(branch)
662
- corrector.insert_before(branch_assignment,
663
- assignment.source)
653
+ corrector.insert_before(branch_assignment, assignment.source)
664
654
 
665
655
  remove_whitespace_in_branches(corrector, branch, condition, column)
666
656
 
667
657
  parent_keyword = branch.parent.loc.keyword
668
- corrector.remove_preceding(parent_keyword,
669
- parent_keyword.column - column)
658
+ corrector.remove_preceding(parent_keyword, parent_keyword.column - column)
670
659
  end
671
660
  end
672
661
  end