rubocop 0.75.0 → 0.79.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.
Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/config/default.yml +341 -316
  4. data/lib/rubocop.rb +48 -31
  5. data/lib/rubocop/ast/builder.rb +43 -41
  6. data/lib/rubocop/ast/node.rb +5 -1
  7. data/lib/rubocop/ast/node/block_node.rb +2 -0
  8. data/lib/rubocop/ast/node/def_node.rb +11 -0
  9. data/lib/rubocop/ast/node/forward_args_node.rb +18 -0
  10. data/lib/rubocop/ast/node/return_node.rb +24 -0
  11. data/lib/rubocop/ast/traversal.rb +11 -3
  12. data/lib/rubocop/cli.rb +11 -227
  13. data/lib/rubocop/cli/command.rb +21 -0
  14. data/lib/rubocop/cli/command/auto_genenerate_config.rb +105 -0
  15. data/lib/rubocop/cli/command/base.rb +33 -0
  16. data/lib/rubocop/cli/command/execute_runner.rb +76 -0
  17. data/lib/rubocop/cli/command/init_dotfile.rb +45 -0
  18. data/lib/rubocop/cli/command/show_cops.rb +80 -0
  19. data/lib/rubocop/cli/command/version.rb +17 -0
  20. data/lib/rubocop/cli/environment.rb +21 -0
  21. data/lib/rubocop/comment_config.rb +2 -2
  22. data/lib/rubocop/config.rb +8 -1
  23. data/lib/rubocop/config_loader.rb +20 -20
  24. data/lib/rubocop/config_loader_resolver.rb +2 -1
  25. data/lib/rubocop/config_obsoletion.rb +73 -11
  26. data/lib/rubocop/config_validator.rb +77 -110
  27. data/lib/rubocop/cop/autocorrect_logic.rb +7 -4
  28. data/lib/rubocop/cop/bundler/gem_comment.rb +4 -4
  29. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +2 -2
  30. data/lib/rubocop/cop/commissioner.rb +15 -7
  31. data/lib/rubocop/cop/cop.rb +31 -6
  32. data/lib/rubocop/cop/corrector.rb +8 -7
  33. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
  34. data/lib/rubocop/cop/correctors/space_corrector.rb +1 -2
  35. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  36. data/lib/rubocop/cop/generator.rb +3 -4
  37. data/lib/rubocop/cop/generator/configuration_injector.rb +2 -2
  38. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  39. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +59 -0
  40. data/lib/rubocop/cop/layout/{align_arguments.rb → argument_alignment.rb} +1 -1
  41. data/lib/rubocop/cop/layout/{align_array.rb → array_alignment.rb} +1 -1
  42. data/lib/rubocop/cop/layout/{indent_assignment.rb → assignment_indentation.rb} +3 -2
  43. data/lib/rubocop/cop/layout/comment_indentation.rb +10 -13
  44. data/lib/rubocop/cop/layout/empty_comment.rb +7 -16
  45. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +22 -7
  46. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +2 -2
  47. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +2 -2
  48. data/lib/rubocop/cop/layout/end_of_line.rb +8 -3
  49. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  50. data/lib/rubocop/cop/layout/{indent_first_argument.rb → first_argument_indentation.rb} +14 -12
  51. data/lib/rubocop/cop/layout/{indent_first_array_element.rb → first_array_element_indentation.rb} +4 -4
  52. data/lib/rubocop/cop/layout/{indent_first_hash_element.rb → first_hash_element_indentation.rb} +4 -4
  53. data/lib/rubocop/cop/layout/{indent_first_parameter.rb → first_parameter_indentation.rb} +3 -3
  54. data/lib/rubocop/cop/layout/{align_hash.rb → hash_alignment.rb} +16 -8
  55. data/lib/rubocop/cop/layout/{indent_heredoc.rb → heredoc_indentation.rb} +5 -5
  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 +41 -114
  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_method_argument_line_breaks.rb +1 -1
  61. data/lib/rubocop/cop/layout/{align_parameters.rb → parameter_alignment.rb} +1 -1
  62. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -0
  63. data/lib/rubocop/cop/layout/space_around_keyword.rb +12 -0
  64. data/lib/rubocop/cop/layout/space_around_operators.rb +32 -7
  65. data/lib/rubocop/cop/layout/space_before_block_braces.rb +17 -0
  66. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -7
  67. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +7 -4
  68. data/lib/rubocop/cop/layout/space_inside_parens.rb +6 -6
  69. data/lib/rubocop/cop/layout/{trailing_blank_lines.rb → trailing_empty_lines.rb} +1 -1
  70. data/lib/rubocop/cop/layout/trailing_whitespace.rb +18 -2
  71. data/lib/rubocop/cop/lint/debugger.rb +2 -2
  72. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +1 -1
  73. data/lib/rubocop/cop/lint/{duplicated_key.rb → duplicate_hash_key.rb} +1 -1
  74. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  75. data/lib/rubocop/cop/lint/erb_new_arguments.rb +9 -8
  76. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  77. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +2 -2
  78. data/lib/rubocop/cop/lint/{multiple_compare.rb → multiple_comparison.rb} +1 -1
  79. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +89 -0
  80. data/lib/rubocop/cop/lint/{unneeded_cop_disable_directive.rb → redundant_cop_disable_directive.rb} +26 -26
  81. data/lib/rubocop/cop/lint/{unneeded_cop_enable_directive.rb → redundant_cop_enable_directive.rb} +10 -12
  82. data/lib/rubocop/cop/lint/{unneeded_require_statement.rb → redundant_require_statement.rb} +1 -1
  83. data/lib/rubocop/cop/lint/{unneeded_splat_expansion.rb → redundant_splat_expansion.rb} +6 -6
  84. data/lib/rubocop/cop/lint/{string_conversion_in_interpolation.rb → redundant_string_coercion.rb} +1 -1
  85. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
  86. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  87. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +5 -6
  88. data/lib/rubocop/cop/lint/{handle_exceptions.rb → suppressed_exception.rb} +1 -1
  89. data/lib/rubocop/cop/lint/unused_block_argument.rb +22 -6
  90. data/lib/rubocop/cop/lint/unused_method_argument.rb +23 -5
  91. data/lib/rubocop/cop/lint/useless_access_modifier.rb +57 -23
  92. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
  93. data/lib/rubocop/cop/lint/void.rb +7 -26
  94. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  95. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  96. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +23 -6
  97. data/lib/rubocop/cop/migration/department_name.rb +16 -1
  98. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  99. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -7
  100. data/lib/rubocop/cop/mixin/{hash_alignment.rb → hash_alignment_styles.rb} +1 -1
  101. data/lib/rubocop/cop/mixin/line_length_help.rb +88 -0
  102. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  103. data/lib/rubocop/cop/mixin/nil_methods.rb +4 -4
  104. data/lib/rubocop/cop/mixin/rational_literal.rb +18 -0
  105. data/lib/rubocop/cop/mixin/statement_modifier.rb +7 -4
  106. data/lib/rubocop/cop/mixin/trailing_comma.rb +14 -9
  107. data/lib/rubocop/cop/naming/{uncommunicative_block_param_name.rb → block_parameter_name.rb} +3 -3
  108. data/lib/rubocop/cop/naming/file_name.rb +12 -5
  109. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -5
  110. data/lib/rubocop/cop/naming/{uncommunicative_method_param_name.rb → method_parameter_name.rb} +4 -4
  111. data/lib/rubocop/cop/naming/predicate_name.rb +6 -6
  112. data/lib/rubocop/cop/offense.rb +11 -0
  113. data/lib/rubocop/cop/registry.rb +8 -3
  114. data/lib/rubocop/cop/style/alias.rb +1 -1
  115. data/lib/rubocop/cop/style/array_join.rb +1 -1
  116. data/lib/rubocop/cop/style/attr.rb +10 -2
  117. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +6 -6
  118. data/lib/rubocop/cop/style/comment_annotation.rb +5 -5
  119. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
  120. data/lib/rubocop/cop/style/copyright.rb +11 -7
  121. data/lib/rubocop/cop/style/documentation_method.rb +44 -0
  122. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +2 -2
  123. data/lib/rubocop/cop/style/empty_case_condition.rb +2 -2
  124. data/lib/rubocop/cop/style/empty_literal.rb +2 -2
  125. data/lib/rubocop/cop/style/empty_method.rb +5 -5
  126. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  127. data/lib/rubocop/cop/style/even_odd.rb +1 -1
  128. data/lib/rubocop/cop/style/expand_path_arguments.rb +1 -1
  129. data/lib/rubocop/cop/style/format_string.rb +10 -7
  130. data/lib/rubocop/cop/style/format_string_token.rb +15 -34
  131. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +10 -0
  132. data/lib/rubocop/cop/style/guard_clause.rb +3 -2
  133. data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
  134. data/lib/rubocop/cop/style/if_unless_modifier.rb +45 -3
  135. data/lib/rubocop/cop/style/infinite_loop.rb +5 -4
  136. data/lib/rubocop/cop/style/inverse_methods.rb +19 -13
  137. data/lib/rubocop/cop/style/ip_addresses.rb +4 -4
  138. data/lib/rubocop/cop/style/line_end_concatenation.rb +14 -10
  139. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +24 -227
  140. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +168 -0
  141. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +54 -0
  142. data/lib/rubocop/cop/style/method_def_parentheses.rb +17 -9
  143. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  144. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
  145. data/lib/rubocop/cop/style/multiline_when_then.rb +6 -2
  146. data/lib/rubocop/cop/style/nested_modifier.rb +4 -2
  147. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +5 -5
  148. data/lib/rubocop/cop/style/next.rb +5 -5
  149. data/lib/rubocop/cop/style/non_nil_check.rb +21 -9
  150. data/lib/rubocop/cop/style/numeric_literals.rb +7 -3
  151. data/lib/rubocop/cop/style/numeric_predicate.rb +4 -3
  152. data/lib/rubocop/cop/style/option_hash.rb +3 -3
  153. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +7 -7
  154. data/lib/rubocop/cop/style/{unneeded_capital_w.rb → redundant_capital_w.rb} +1 -1
  155. data/lib/rubocop/cop/style/{unneeded_condition.rb → redundant_condition.rb} +3 -3
  156. data/lib/rubocop/cop/style/{unneeded_interpolation.rb → redundant_interpolation.rb} +1 -1
  157. data/lib/rubocop/cop/style/redundant_parentheses.rb +3 -3
  158. data/lib/rubocop/cop/style/{unneeded_percent_q.rb → redundant_percent_q.rb} +1 -1
  159. data/lib/rubocop/cop/style/redundant_return.rb +39 -29
  160. data/lib/rubocop/cop/style/{unneeded_sort.rb → redundant_sort.rb} +5 -5
  161. data/lib/rubocop/cop/style/safe_navigation.rb +19 -8
  162. data/lib/rubocop/cop/style/semicolon.rb +13 -2
  163. data/lib/rubocop/cop/style/special_global_vars.rb +5 -7
  164. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +7 -1
  165. data/lib/rubocop/cop/style/trivial_accessors.rb +5 -5
  166. data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
  167. data/lib/rubocop/cop/style/yoda_condition.rb +16 -1
  168. data/lib/rubocop/cop/team.rb +5 -0
  169. data/lib/rubocop/cop/util.rb +1 -1
  170. data/lib/rubocop/cop/utils/format_string.rb +10 -18
  171. data/lib/rubocop/cop/variable_force.rb +7 -5
  172. data/lib/rubocop/formatter/base_formatter.rb +2 -2
  173. data/lib/rubocop/formatter/clang_style_formatter.rb +9 -6
  174. data/lib/rubocop/formatter/emacs_style_formatter.rb +22 -12
  175. data/lib/rubocop/formatter/file_list_formatter.rb +1 -1
  176. data/lib/rubocop/formatter/formatter_set.rb +16 -16
  177. data/lib/rubocop/formatter/json_formatter.rb +6 -5
  178. data/lib/rubocop/formatter/pacman_formatter.rb +3 -3
  179. data/lib/rubocop/formatter/simple_text_formatter.rb +7 -3
  180. data/lib/rubocop/formatter/tap_formatter.rb +9 -6
  181. data/lib/rubocop/node_pattern.rb +4 -2
  182. data/lib/rubocop/options.rb +20 -26
  183. data/lib/rubocop/processed_source.rb +1 -1
  184. data/lib/rubocop/rake_task.rb +1 -0
  185. data/lib/rubocop/result_cache.rb +24 -8
  186. data/lib/rubocop/rspec/shared_contexts.rb +5 -0
  187. data/lib/rubocop/runner.rb +50 -29
  188. data/lib/rubocop/target_finder.rb +12 -6
  189. data/lib/rubocop/target_ruby.rb +151 -0
  190. data/lib/rubocop/version.rb +1 -1
  191. metadata +50 -34
  192. data/lib/rubocop/cop/mixin/safe_mode.rb +0 -24
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Layout
6
6
  # This cop checks the indentation of the first key in a hash literal
7
7
  # where the opening brace and the first key are on separate lines. The
8
- # other keys' indentations are handled by the AlignHash cop.
8
+ # other keys' indentations are handled by the HashAlignment cop.
9
9
  #
10
10
  # By default, Hash literals that are arguments in a method call with
11
11
  # parentheses, and where the opening curly brace of the hash is on the
@@ -77,7 +77,7 @@ module RuboCop
77
77
  # and_now_for_something = {
78
78
  # completely: :different
79
79
  # }
80
- class IndentFirstHashElement < Cop
80
+ class FirstHashElementIndentation < Cop
81
81
  include Alignment
82
82
  include ConfigurableEnforcedStyle
83
83
  include MultilineElementIndentation
@@ -113,7 +113,7 @@ module RuboCop
113
113
  first_pair = hash_node.pairs.first
114
114
 
115
115
  if first_pair
116
- return if first_pair.source_range.line == left_brace.line
116
+ return if first_pair.first_line == left_brace.line
117
117
 
118
118
  if separator_style?(first_pair)
119
119
  check_based_on_longest_key(hash_node, left_brace,
@@ -149,7 +149,7 @@ module RuboCop
149
149
  def separator_style?(first_pair)
150
150
  separator = first_pair.loc.operator
151
151
  key = "Enforced#{separator.is?(':') ? 'Colon' : 'HashRocket'}Style"
152
- config.for_cop('Layout/AlignHash')[key] == 'separator'
152
+ config.for_cop('Layout/HashAlignment')[key] == 'separator'
153
153
  end
154
154
 
155
155
  def check_based_on_longest_key(hash_node, left_brace, left_parenthesis)
@@ -5,10 +5,10 @@ module RuboCop
5
5
  module Layout
6
6
  # This cop checks the indentation of the first parameter in a method
7
7
  # definition. Parameters after the first one are checked by
8
- # Layout/AlignParameters, not by this cop.
8
+ # Layout/ParameterAlignment, not by this cop.
9
9
  #
10
10
  # For indenting the first argument of method *calls*, check out
11
- # Layout/IndentFirstArgument, which supports options related to
11
+ # Layout/FirstArgumentIndentation, which supports options related to
12
12
  # nesting that are irrelevant for method *definitions*.
13
13
  #
14
14
  # @example
@@ -41,7 +41,7 @@ module RuboCop
41
41
  # second_param)
42
42
  # 123
43
43
  # end
44
- class IndentFirstParameter < Cop
44
+ class FirstParameterIndentation < Cop
45
45
  include Alignment
46
46
  include ConfigurableEnforcedStyle
47
47
  include MultilineElementIndentation
@@ -175,12 +175,16 @@ module RuboCop
175
175
  # do_something({foo: 1,
176
176
  # bar: 2})
177
177
  #
178
- class AlignHash < Cop
179
- include HashAlignment
178
+ class HashAlignment < Cop
179
+ include HashAlignmentStyles
180
180
  include RangeHelp
181
181
 
182
- MSG = 'Align the elements of a hash literal if they span more than ' \
183
- 'one line.'
182
+ MESSAGES = { KeyAlignment => 'Align the keys of a hash literal if ' \
183
+ 'they span more than one line.',
184
+ SeparatorAlignment => 'Align the separators of a hash ' \
185
+ 'literal if they span more than one line.',
186
+ TableAlignment => 'Align the keys and values of a hash ' \
187
+ 'literal if they span more than one line.' }.freeze
184
188
 
185
189
  def on_send(node)
186
190
  return if double_splat?(node)
@@ -220,14 +224,18 @@ module RuboCop
220
224
 
221
225
  private
222
226
 
227
+ def reset!
228
+ self.offences_by = {}
229
+ self.column_deltas = Hash.new { |hash, key| hash[key] = {} }
230
+ end
231
+
223
232
  def double_splat?(node)
224
233
  node.children.last.is_a?(Symbol)
225
234
  end
226
235
 
227
236
  def check_pairs(node)
228
237
  first_pair = node.pairs.first
229
- self.offences_by = {}
230
- self.column_deltas = Hash.new { |hash, key| hash[key] = {} }
238
+ reset!
231
239
 
232
240
  alignment_for(first_pair).each do |alignment|
233
241
  delta = alignment.deltas_for_first_pair(first_pair, node)
@@ -245,9 +253,9 @@ module RuboCop
245
253
  end
246
254
 
247
255
  def add_offences
248
- _format, offences = offences_by.min_by { |_, v| v.length }
256
+ format, offences = offences_by.min_by { |_, v| v.length }
249
257
  (offences || []).each do |offence|
250
- add_offense offence
258
+ add_offense(offence, message: MESSAGES[format])
251
259
  end
252
260
  end
253
261
 
@@ -8,9 +8,9 @@ module RuboCop
8
8
  # In Ruby 2.3 or newer, squiggly heredocs (`<<~`) should be used. If you
9
9
  # use the older rubies, you should introduce some library to your project
10
10
  # (e.g. ActiveSupport, Powerpack or Unindent).
11
- # Note: When `Metrics/LineLength`'s `AllowHeredoc` is false (not default),
11
+ # Note: When `Layout/LineLength`'s `AllowHeredoc` is false (not default),
12
12
  # this cop does not add any offenses for long here documents to
13
- # avoid `Metrics/LineLength`'s offenses.
13
+ # avoid `Layout/LineLength`'s offenses.
14
14
  #
15
15
  # @example EnforcedStyle: squiggly (default)
16
16
  # # bad
@@ -49,7 +49,7 @@ module RuboCop
49
49
  # something
50
50
  # RUBY
51
51
  #
52
- class IndentHeredoc < Cop
52
+ class HeredocIndentation < Cop
53
53
  include Heredoc
54
54
  include ConfigurableEnforcedStyle
55
55
 
@@ -159,11 +159,11 @@ module RuboCop
159
159
  end
160
160
 
161
161
  def unlimited_heredoc_length?
162
- config.for_cop('Metrics/LineLength')['AllowHeredoc']
162
+ config.for_cop('Layout/LineLength')['AllowHeredoc']
163
163
  end
164
164
 
165
165
  def max_line_length
166
- config.for_cop('Metrics/LineLength')['Max']
166
+ config.for_cop('Layout/LineLength')['Max']
167
167
  end
168
168
 
169
169
  def correct_by_squiggly(node)
@@ -27,7 +27,7 @@ module RuboCop
27
27
  # # good
28
28
  # # (start of file)
29
29
  # # a comment
30
- class LeadingBlankLines < Cop
30
+ class LeadingEmptyLines < Cop
31
31
  MSG = 'Unnecessary blank line at the beginning of the source.'
32
32
 
33
33
  def investigate(processed_source)
@@ -2,10 +2,9 @@
2
2
 
3
3
  require 'uri'
4
4
 
5
- # rubocop:disable Metrics/ClassLength
6
5
  module RuboCop
7
6
  module Cop
8
- module Metrics
7
+ module Layout
9
8
  # This cop checks the length of lines in the source code.
10
9
  # The maximum length is configurable.
11
10
  # The tab size is configured in the `IndentationWidth`
@@ -21,14 +20,14 @@ module RuboCop
21
20
  # If autocorrection is enabled, the following Layout cops
22
21
  # are recommended to further format the broken lines.
23
22
  #
24
- # - AlignArray
25
- # - AlignHash
26
- # - AlignParameters
23
+ # - ParameterAlignment
24
+ # - ArgumentAlignment
27
25
  # - ClosingParenthesisIndentation
28
- # - IndentFirstArgument
29
- # - IndentFirstArrayElement
30
- # - IndentFirstHashElement
31
- # - IndentFirstParameter
26
+ # - FirstArgumentIndentation
27
+ # - FirstArrayElementIndentation
28
+ # - FirstHashElementIndentation
29
+ # - FirstParameterIndentation
30
+ # - HashAlignment
32
31
  # - MultilineArrayLineBreaks
33
32
  # - MultilineHashBraceLayout
34
33
  # - MultilineHashKeyLineBreaks
@@ -58,6 +57,7 @@ module RuboCop
58
57
  include ConfigurableMax
59
58
  include IgnoredPattern
60
59
  include RangeHelp
60
+ include LineLengthHelp
61
61
 
62
62
  MSG = 'Line is too long. [%<length>d/%<max>d]'
63
63
 
@@ -68,6 +68,10 @@ module RuboCop
68
68
  alias on_hash on_potential_breakable_node
69
69
  alias on_send on_potential_breakable_node
70
70
 
71
+ def investigate(processed_source)
72
+ check_for_breakable_semicolons(processed_source)
73
+ end
74
+
71
75
  def investigate_post_walk(processed_source)
72
76
  processed_source.lines.each_with_index do |line, line_index|
73
77
  check_line(line, line_index)
@@ -89,29 +93,41 @@ module RuboCop
89
93
  return if breakable_node.nil?
90
94
 
91
95
  line_index = breakable_node.first_line - 1
92
- breakable_nodes_by_line_index[line_index] = breakable_node
93
- end
96
+ range = breakable_node.source_range
94
97
 
95
- def breakable_nodes_by_line_index
96
- @breakable_nodes_by_line_index ||= {}
97
- end
98
+ existing = breakable_range_by_line_index[line_index]
99
+ return if existing
98
100
 
99
- def heredocs
100
- @heredocs ||= extract_heredocs(processed_source.ast)
101
+ breakable_range_by_line_index[line_index] = range
101
102
  end
102
103
 
103
- def tab_indentation_width
104
- config.for_cop('Layout/Tab')['IndentationWidth']
104
+ def check_for_breakable_semicolons(processed_source)
105
+ tokens = processed_source.tokens.select { |t| t.type == :tSEMI }
106
+ tokens.reverse_each do |token|
107
+ range = breakable_range_after_semicolon(token)
108
+ breakable_range_by_line_index[range.line - 1] = range if range
109
+ end
105
110
  end
106
111
 
107
- def indentation_difference(line)
108
- return 0 unless tab_indentation_width
112
+ def breakable_range_after_semicolon(semicolon_token)
113
+ range = semicolon_token.pos
114
+ end_pos = range.end_pos
115
+ next_range = range_between(end_pos, end_pos + 1)
116
+ return nil unless next_range.line == range.line
117
+
118
+ next_char = next_range.source
119
+ return nil if /[\r\n]/ =~ next_char
120
+ return nil if next_char == ';'
121
+
122
+ next_range
123
+ end
109
124
 
110
- line.match(/^\t*/)[0].size * (tab_indentation_width - 1)
125
+ def breakable_range_by_line_index
126
+ @breakable_range_by_line_index ||= {}
111
127
  end
112
128
 
113
- def line_length(line)
114
- line.length + indentation_difference(line)
129
+ def heredocs
130
+ @heredocs ||= extract_heredocs(processed_source.ast)
115
131
  end
116
132
 
117
133
  def highlight_start(line)
@@ -128,10 +144,7 @@ module RuboCop
128
144
  return check_uri_line(line, line_index) if allow_uri?
129
145
 
130
146
  register_offense(
131
- source_range(
132
- processed_source.buffer, line_index,
133
- highlight_start(line)...line_length(line)
134
- ),
147
+ excess_range(nil, line, line_index),
135
148
  line,
136
149
  line_index
137
150
  )
@@ -150,33 +163,12 @@ module RuboCop
150
163
  def register_offense(loc, line, line_index)
151
164
  message = format(MSG, length: line_length(line), max: max)
152
165
 
153
- breakable_range = breakable_range(line, line_index)
166
+ breakable_range = breakable_range_by_line_index[line_index]
154
167
  add_offense(breakable_range, location: loc, message: message) do
155
168
  self.max = line_length(line)
156
169
  end
157
170
  end
158
171
 
159
- def breakable_range(line, line_index)
160
- return if line_in_heredoc?(line_index + 1)
161
-
162
- semicolon_range = breakable_semicolon_range(line, line_index)
163
- return semicolon_range if semicolon_range
164
-
165
- breakable_node = breakable_nodes_by_line_index[line_index]
166
- return breakable_node.source_range if breakable_node
167
- end
168
-
169
- def breakable_semicolon_range(line, line_index)
170
- semicolon_separated_parts = line.split(';')
171
- return if semicolon_separated_parts.length <= 1
172
-
173
- column = semicolon_separated_parts.first.length + 1
174
- range = source_range(processed_source.buffer, line_index, column, 1)
175
- return if processed_source.commented?(range)
176
-
177
- range
178
- end
179
-
180
172
  def excess_range(uri_range, line, line_index)
181
173
  excessive_position = if uri_range && uri_range.begin < max
182
174
  uri_range.end
@@ -225,53 +217,6 @@ module RuboCop
225
217
  end
226
218
  end
227
219
 
228
- def allow_uri?
229
- cop_config['AllowURI']
230
- end
231
-
232
- def ignore_cop_directives?
233
- cop_config['IgnoreCopDirectives']
234
- end
235
-
236
- def allowed_uri_position?(line, uri_range)
237
- uri_range.begin < max &&
238
- (uri_range.end == line_length(line) ||
239
- uri_range.end == line_length(line) - 1)
240
- end
241
-
242
- def find_excessive_uri_range(line)
243
- last_uri_match = match_uris(line).last
244
- return nil unless last_uri_match
245
-
246
- begin_position, end_position =
247
- last_uri_match.offset(0).map do |pos|
248
- pos + indentation_difference(line)
249
- end
250
- return nil if begin_position < max && end_position < max
251
-
252
- begin_position...end_position
253
- end
254
-
255
- def match_uris(string)
256
- matches = []
257
- string.scan(uri_regexp) do
258
- matches << $LAST_MATCH_INFO if valid_uri?($LAST_MATCH_INFO[0])
259
- end
260
- matches
261
- end
262
-
263
- def valid_uri?(uri_ish_string)
264
- URI.parse(uri_ish_string)
265
- true
266
- rescue URI::InvalidURIError, NoMethodError
267
- false
268
- end
269
-
270
- def uri_regexp
271
- @uri_regexp ||=
272
- URI::DEFAULT_PARSER.make_regexp(cop_config['URISchemes'])
273
- end
274
-
275
220
  def check_directive_line(line, line_index)
276
221
  return if line_length_without_directive(line) <= max
277
222
 
@@ -287,23 +232,6 @@ module RuboCop
287
232
  )
288
233
  end
289
234
 
290
- def directive_on_source_line?(line_index)
291
- source_line_number = line_index + processed_source.buffer.first_line
292
- comment =
293
- processed_source
294
- .comments
295
- .detect { |e| e.location.line == source_line_number }
296
-
297
- return false unless comment
298
-
299
- comment.text.match(CommentConfig::COMMENT_DIRECTIVE_REGEXP)
300
- end
301
-
302
- def line_length_without_directive(line)
303
- before_comment, = line.split(CommentConfig::COMMENT_DIRECTIVE_REGEXP)
304
- before_comment.rstrip.length
305
- end
306
-
307
235
  def check_uri_line(line, line_index)
308
236
  uri_range = find_excessive_uri_range(line)
309
237
  return if uri_range && allowed_uri_position?(line, uri_range)
@@ -318,4 +246,3 @@ module RuboCop
318
246
  end
319
247
  end
320
248
  end
321
- # rubocop:enable Metrics/ClassLength
@@ -43,7 +43,7 @@ module RuboCop
43
43
  'on the same line as the assignment operator `=`.'
44
44
 
45
45
  def check_assignment(node, rhs)
46
- return if node.send_type?
46
+ return if node.send_type? && node.loc.operator&.source != '='
47
47
  return unless rhs
48
48
  return unless supported_types.include?(rhs.type)
49
49
  return if rhs.first_line == rhs.last_line
@@ -97,7 +97,8 @@ module RuboCop
97
97
  def line_break_necessary_in_args?(node)
98
98
  needed_length = node.source_range.column +
99
99
  node.source.lines.first.length +
100
- block_arg_string(node.arguments).length + PIPE_SIZE
100
+ block_arg_string(node, node.arguments).length +
101
+ PIPE_SIZE
101
102
  needed_length > max_line_length
102
103
  end
103
104
 
@@ -115,7 +116,8 @@ module RuboCop
115
116
  newlines: false
116
117
  ).end_pos
117
118
  range = range_between(node.loc.begin.end.begin_pos, end_pos)
118
- corrector.replace(range, " |#{block_arg_string(node.arguments)}|")
119
+ corrector.replace(range,
120
+ " |#{block_arg_string(node, node.arguments)}|")
119
121
  end
120
122
 
121
123
  def autocorrect_body(corrector, node, block_body)
@@ -131,14 +133,21 @@ module RuboCop
131
133
  "\n #{' ' * block_start_col}")
132
134
  end
133
135
 
134
- def block_arg_string(args)
135
- args.children.map do |arg|
136
+ def block_arg_string(node, args)
137
+ arg_string = args.children.map do |arg|
136
138
  if arg.mlhs_type?
137
- "(#{block_arg_string(arg)})"
139
+ "(#{block_arg_string(node, arg)})"
138
140
  else
139
141
  arg.source
140
142
  end
141
143
  end.join(', ')
144
+ arg_string += ',' if include_trailing_comma?(node.arguments)
145
+ arg_string
146
+ end
147
+
148
+ def include_trailing_comma?(args)
149
+ arg_count = args.each_descendant(:arg).to_a.size
150
+ arg_count == 1 && args.source.include?(',')
142
151
  end
143
152
  end
144
153
  end
@@ -26,7 +26,7 @@ module RuboCop
26
26
  'on a separate line.'
27
27
 
28
28
  def on_send(node)
29
- return if node.method_name == :[]=
29
+ return if node.method?(:[]=)
30
30
 
31
31
  args = node.arguments
32
32