rubocop 0.93.1 → 1.6.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 (199) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -16
  3. data/config/default.yml +276 -82
  4. data/config/obsoletion.yml +196 -0
  5. data/exe/rubocop +1 -1
  6. data/lib/rubocop.rb +31 -2
  7. data/lib/rubocop/cli.rb +5 -1
  8. data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
  9. data/lib/rubocop/cli/command/execute_runner.rb +26 -11
  10. data/lib/rubocop/cli/command/suggest_extensions.rb +80 -0
  11. data/lib/rubocop/cli/command/version.rb +1 -1
  12. data/lib/rubocop/comment_config.rb +1 -1
  13. data/lib/rubocop/config.rb +4 -0
  14. data/lib/rubocop/config_loader.rb +34 -8
  15. data/lib/rubocop/config_loader_resolver.rb +12 -6
  16. data/lib/rubocop/config_obsoletion.rb +65 -247
  17. data/lib/rubocop/config_obsoletion/changed_enforced_styles.rb +33 -0
  18. data/lib/rubocop/config_obsoletion/changed_parameter.rb +21 -0
  19. data/lib/rubocop/config_obsoletion/cop_rule.rb +34 -0
  20. data/lib/rubocop/config_obsoletion/extracted_cop.rb +44 -0
  21. data/lib/rubocop/config_obsoletion/parameter_rule.rb +44 -0
  22. data/lib/rubocop/config_obsoletion/removed_cop.rb +41 -0
  23. data/lib/rubocop/config_obsoletion/renamed_cop.rb +34 -0
  24. data/lib/rubocop/config_obsoletion/rule.rb +41 -0
  25. data/lib/rubocop/config_obsoletion/split_cop.rb +27 -0
  26. data/lib/rubocop/config_regeneration.rb +1 -1
  27. data/lib/rubocop/config_validator.rb +25 -10
  28. data/lib/rubocop/cop/autocorrect_logic.rb +21 -6
  29. data/lib/rubocop/cop/badge.rb +9 -24
  30. data/lib/rubocop/cop/base.rb +33 -16
  31. data/lib/rubocop/cop/bundler/duplicated_gem.rb +26 -6
  32. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  33. data/lib/rubocop/cop/commissioner.rb +37 -23
  34. data/lib/rubocop/cop/cop.rb +2 -2
  35. data/lib/rubocop/cop/corrector.rb +3 -1
  36. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  37. data/lib/rubocop/cop/correctors/string_literal_corrector.rb +6 -8
  38. data/lib/rubocop/cop/force.rb +1 -1
  39. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +3 -3
  40. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +4 -5
  41. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +1 -1
  42. data/lib/rubocop/cop/generator.rb +3 -10
  43. data/lib/rubocop/cop/generator/configuration_injector.rb +1 -1
  44. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +1 -1
  45. data/lib/rubocop/cop/layout/block_alignment.rb +3 -4
  46. data/lib/rubocop/cop/layout/class_structure.rb +22 -3
  47. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  48. data/lib/rubocop/cop/layout/else_alignment.rb +15 -2
  49. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +80 -10
  50. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
  51. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +6 -1
  52. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -1
  53. data/lib/rubocop/cop/layout/end_alignment.rb +3 -3
  54. data/lib/rubocop/cop/layout/end_of_line.rb +5 -5
  55. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -2
  56. data/lib/rubocop/cop/layout/first_argument_indentation.rb +7 -2
  57. data/lib/rubocop/cop/layout/hash_alignment.rb +4 -4
  58. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +12 -0
  59. data/lib/rubocop/cop/layout/line_length.rb +10 -13
  60. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +7 -3
  61. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +24 -18
  62. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  63. data/lib/rubocop/cop/layout/space_around_operators.rb +4 -1
  64. data/lib/rubocop/cop/layout/space_inside_parens.rb +35 -13
  65. data/lib/rubocop/cop/layout/trailing_whitespace.rb +37 -13
  66. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +2 -1
  67. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +26 -2
  68. data/lib/rubocop/cop/lint/debugger.rb +17 -28
  69. data/lib/rubocop/cop/lint/duplicate_branch.rb +93 -0
  70. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +2 -12
  71. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +77 -0
  72. data/lib/rubocop/cop/lint/else_layout.rb +29 -3
  73. data/lib/rubocop/cop/lint/empty_block.rb +82 -0
  74. data/lib/rubocop/cop/lint/empty_class.rb +93 -0
  75. data/lib/rubocop/cop/lint/flip_flop.rb +8 -2
  76. data/lib/rubocop/cop/lint/interpolation_check.rb +7 -2
  77. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +39 -7
  78. data/lib/rubocop/cop/lint/loop.rb +4 -4
  79. data/lib/rubocop/cop/lint/missing_super.rb +7 -4
  80. data/lib/rubocop/cop/lint/nested_percent_literal.rb +14 -0
  81. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +58 -0
  82. data/lib/rubocop/cop/lint/number_conversion.rb +46 -13
  83. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +27 -8
  84. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +19 -16
  85. data/lib/rubocop/cop/lint/shadowed_exception.rb +4 -5
  86. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +13 -0
  87. data/lib/rubocop/cop/lint/to_enum_arguments.rb +86 -0
  88. data/lib/rubocop/cop/lint/to_json.rb +1 -1
  89. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +85 -0
  90. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +199 -0
  91. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  92. data/lib/rubocop/cop/lint/useless_method_definition.rb +2 -4
  93. data/lib/rubocop/cop/lint/useless_setter_call.rb +6 -1
  94. data/lib/rubocop/cop/metrics/abc_size.rb +25 -1
  95. data/lib/rubocop/cop/metrics/block_length.rb +13 -7
  96. data/lib/rubocop/cop/metrics/method_length.rb +7 -2
  97. data/lib/rubocop/cop/metrics/parameter_lists.rb +68 -2
  98. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +20 -10
  99. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +146 -0
  100. data/lib/rubocop/cop/metrics/utils/repeated_csend_discount.rb +6 -1
  101. data/lib/rubocop/cop/migration/department_name.rb +1 -1
  102. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  103. data/lib/rubocop/cop/mixin/configurable_numbering.rb +4 -3
  104. data/lib/rubocop/cop/mixin/enforce_superclass.rb +9 -1
  105. data/lib/rubocop/cop/mixin/ignored_methods.rb +36 -3
  106. data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
  107. data/lib/rubocop/cop/mixin/method_complexity.rb +6 -0
  108. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  109. data/lib/rubocop/cop/mixin/statement_modifier.rb +9 -4
  110. data/lib/rubocop/cop/mixin/string_help.rb +4 -1
  111. data/lib/rubocop/cop/mixin/visibility_help.rb +1 -3
  112. data/lib/rubocop/cop/naming/accessor_method_name.rb +15 -1
  113. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +12 -2
  114. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +11 -5
  115. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +67 -18
  116. data/lib/rubocop/cop/naming/predicate_name.rb +2 -1
  117. data/lib/rubocop/cop/naming/variable_number.rb +100 -8
  118. data/lib/rubocop/cop/offense.rb +3 -3
  119. data/lib/rubocop/cop/security/open.rb +12 -10
  120. data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
  121. data/lib/rubocop/cop/style/and_or.rb +11 -3
  122. data/lib/rubocop/cop/style/arguments_forwarding.rb +142 -0
  123. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +0 -4
  124. data/lib/rubocop/cop/style/case_like_if.rb +0 -4
  125. data/lib/rubocop/cop/style/character_literal.rb +10 -11
  126. data/lib/rubocop/cop/style/class_and_module_children.rb +8 -3
  127. data/lib/rubocop/cop/style/collection_compact.rb +91 -0
  128. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +169 -0
  129. data/lib/rubocop/cop/style/documentation.rb +12 -1
  130. data/lib/rubocop/cop/style/double_negation.rb +6 -1
  131. data/lib/rubocop/cop/style/float_division.rb +44 -1
  132. data/lib/rubocop/cop/style/format_string.rb +8 -3
  133. data/lib/rubocop/cop/style/format_string_token.rb +47 -2
  134. data/lib/rubocop/cop/style/hash_syntax.rb +3 -3
  135. data/lib/rubocop/cop/style/identical_conditional_branches.rb +7 -2
  136. data/lib/rubocop/cop/style/if_inside_else.rb +37 -1
  137. data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -3
  138. data/lib/rubocop/cop/style/if_with_semicolon.rb +39 -4
  139. data/lib/rubocop/cop/style/infinite_loop.rb +4 -0
  140. data/lib/rubocop/cop/style/ip_addresses.rb +1 -1
  141. data/lib/rubocop/cop/style/keyword_parameters_order.rb +12 -0
  142. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +10 -13
  143. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +8 -13
  144. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +7 -11
  145. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -2
  146. data/lib/rubocop/cop/style/mixin_grouping.rb +0 -4
  147. data/lib/rubocop/cop/style/multiple_comparison.rb +55 -7
  148. data/lib/rubocop/cop/style/negated_if_else_condition.rb +106 -0
  149. data/lib/rubocop/cop/style/nil_lambda.rb +52 -0
  150. data/lib/rubocop/cop/style/numeric_literals.rb +14 -11
  151. data/lib/rubocop/cop/style/perl_backrefs.rb +86 -9
  152. data/lib/rubocop/cop/style/raise_args.rb +21 -6
  153. data/lib/rubocop/cop/style/redundant_argument.rb +88 -0
  154. data/lib/rubocop/cop/style/redundant_condition.rb +2 -1
  155. data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -0
  156. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +7 -1
  157. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +24 -8
  158. data/lib/rubocop/cop/style/redundant_self.rb +3 -0
  159. data/lib/rubocop/cop/style/safe_navigation.rb +16 -4
  160. data/lib/rubocop/cop/style/semicolon.rb +3 -0
  161. data/lib/rubocop/cop/style/single_line_block_params.rb +30 -7
  162. data/lib/rubocop/cop/style/sole_nested_conditional.rb +65 -3
  163. data/lib/rubocop/cop/style/special_global_vars.rb +1 -13
  164. data/lib/rubocop/cop/style/static_class.rb +97 -0
  165. data/lib/rubocop/cop/style/string_concatenation.rb +39 -2
  166. data/lib/rubocop/cop/style/string_literals.rb +14 -8
  167. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +4 -3
  168. data/lib/rubocop/cop/style/swap_values.rb +108 -0
  169. data/lib/rubocop/cop/style/symbol_proc.rb +5 -3
  170. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +3 -1
  171. data/lib/rubocop/cop/style/while_until_modifier.rb +9 -0
  172. data/lib/rubocop/cop/team.rb +6 -1
  173. data/lib/rubocop/cop/util.rb +6 -2
  174. data/lib/rubocop/cop/variable_force/branch.rb +1 -1
  175. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  176. data/lib/rubocop/core_ext/hash.rb +20 -0
  177. data/lib/rubocop/ext/regexp_node.rb +36 -11
  178. data/lib/rubocop/ext/regexp_parser.rb +95 -0
  179. data/lib/rubocop/formatter/disabled_config_formatter.rb +21 -6
  180. data/lib/rubocop/formatter/emacs_style_formatter.rb +2 -0
  181. data/lib/rubocop/formatter/formatter_set.rb +2 -1
  182. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +47 -0
  183. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  184. data/lib/rubocop/formatter/simple_text_formatter.rb +2 -0
  185. data/lib/rubocop/formatter/tap_formatter.rb +2 -0
  186. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  187. data/lib/rubocop/lockfile.rb +40 -0
  188. data/lib/rubocop/magic_comment.rb +2 -2
  189. data/lib/rubocop/options.rb +11 -1
  190. data/lib/rubocop/rake_task.rb +2 -2
  191. data/lib/rubocop/rspec/shared_contexts.rb +4 -0
  192. data/lib/rubocop/runner.rb +1 -1
  193. data/lib/rubocop/target_finder.rb +1 -1
  194. data/lib/rubocop/target_ruby.rb +65 -1
  195. data/lib/rubocop/version.rb +56 -6
  196. metadata +50 -9
  197. data/bin/console +0 -10
  198. data/bin/rubocop-profile +0 -32
  199. data/bin/setup +0 -7
@@ -69,6 +69,7 @@ module RuboCop
69
69
  return unless outermost_send
70
70
  return unless outermost_send.loc.end
71
71
  return unless heredoc_arg.first_line != outermost_send.loc.end.line
72
+ return if subsequent_closing_parentheses_in_same_line?(outermost_send)
72
73
 
73
74
  add_offense(outermost_send.loc.end) do |corrector|
74
75
  autocorrect(corrector, outermost_send)
@@ -160,6 +161,17 @@ module RuboCop
160
161
 
161
162
  # Closing parenthesis helpers.
162
163
 
164
+ def subsequent_closing_parentheses_in_same_line?(outermost_send)
165
+ last_arg_of_outer_send = outermost_send.last_argument
166
+ return false unless last_arg_of_outer_send&.loc.respond_to?(:end) &&
167
+ (end_of_last_arg_of_outer_send = last_arg_of_outer_send.loc.end)
168
+
169
+ end_of_outer_send = outermost_send.loc.end
170
+
171
+ end_of_outer_send.line == end_of_last_arg_of_outer_send.line &&
172
+ end_of_outer_send.column == end_of_last_arg_of_outer_send.column + 1
173
+ end
174
+
163
175
  def fix_closing_parenthesis(node, corrector)
164
176
  remove_incorrect_closing_paren(node, corrector)
165
177
  add_correct_closing_paren(node, corrector)
@@ -58,12 +58,13 @@ module RuboCop
58
58
  # bar: "0000000000",
59
59
  # baz: "0000000000",
60
60
  # }
61
- class LineLength < Cop
61
+ class LineLength < Base
62
62
  include CheckLineBreakable
63
63
  include ConfigurableMax
64
64
  include IgnoredPattern
65
65
  include RangeHelp
66
66
  include LineLengthHelp
67
+ extend AutoCorrector
67
68
 
68
69
  MSG = 'Line is too long. [%<length>d/%<max>d]'
69
70
 
@@ -78,26 +79,20 @@ module RuboCop
78
79
  alias on_hash on_potential_breakable_node
79
80
  alias on_send on_potential_breakable_node
80
81
 
81
- def investigate(processed_source)
82
+ def on_new_investigation
82
83
  check_for_breakable_semicolons(processed_source)
83
84
  end
84
85
 
85
- def investigate_post_walk(processed_source)
86
+ def on_investigation_end
86
87
  processed_source.lines.each_with_index do |line, line_index|
87
88
  check_line(line, line_index)
88
89
  end
89
90
  end
90
91
 
91
- def autocorrect(range)
92
- return if range.nil?
93
-
94
- lambda do |corrector|
95
- corrector.insert_before(range, "\n")
96
- end
97
- end
98
-
99
92
  private
100
93
 
94
+ attr_accessor :breakable_range
95
+
101
96
  def check_for_breakable_node(node)
102
97
  breakable_node = extract_breakable_node(node, max)
103
98
  return if breakable_node.nil?
@@ -195,9 +190,11 @@ module RuboCop
195
190
  def register_offense(loc, line, line_index)
196
191
  message = format(MSG, length: line_length(line), max: max)
197
192
 
198
- breakable_range = breakable_range_by_line_index[line_index]
199
- add_offense(breakable_range, location: loc, message: message) do
193
+ self.breakable_range = breakable_range_by_line_index[line_index]
194
+
195
+ add_offense(loc, message: message) do |corrector|
200
196
  self.max = line_length(line)
197
+ corrector.insert_before(breakable_range, "\n") unless breakable_range.nil?
201
198
  end
202
199
  end
203
200
 
@@ -77,7 +77,7 @@ module RuboCop
77
77
 
78
78
  @base = alignment_base(node, rhs, given_style)
79
79
  correct_column = if @base
80
- @base.column + extra_indentation(given_style)
80
+ @base.column + extra_indentation(given_style, node.parent)
81
81
  else
82
82
  indentation(lhs) + correct_indentation(node)
83
83
  end
@@ -85,9 +85,13 @@ module RuboCop
85
85
  rhs if @column_delta.nonzero?
86
86
  end
87
87
 
88
- def extra_indentation(given_style)
88
+ def extra_indentation(given_style, parent)
89
89
  if given_style == :indented_relative_to_receiver
90
- configured_indentation_width
90
+ if parent && (parent.splat_type? || parent.kwsplat_type?)
91
+ configured_indentation_width - parent.loc.operator.length
92
+ else
93
+ configured_indentation_width
94
+ end
91
95
  else
92
96
  0
93
97
  end
@@ -54,17 +54,11 @@ module RuboCop
54
54
  end
55
55
 
56
56
  def check_inside_pipes(arguments)
57
- opening_pipe, closing_pipe = pipes(arguments)
58
-
59
57
  case style
60
58
  when :no_space
61
- check_no_space_style_inside_pipes(arguments.children,
62
- opening_pipe,
63
- closing_pipe)
59
+ check_no_space_style_inside_pipes(arguments)
64
60
  when :space
65
- check_space_style_inside_pipes(arguments.children,
66
- opening_pipe,
67
- closing_pipe)
61
+ check_space_style_inside_pipes(arguments)
68
62
  end
69
63
  end
70
64
 
@@ -76,22 +70,29 @@ module RuboCop
76
70
  closing_pipe, 'after closing `|`')
77
71
  end
78
72
 
79
- def check_no_space_style_inside_pipes(args, opening_pipe, closing_pipe)
73
+ def check_no_space_style_inside_pipes(arguments)
74
+ args = arguments.children
75
+ opening_pipe, closing_pipe = pipes(arguments)
76
+
80
77
  first = args.first.source_range
81
78
  last = args.last.source_range
82
79
 
83
80
  check_no_space(opening_pipe.end_pos, first.begin_pos,
84
81
  'Space before first')
85
- check_no_space(last_end_pos_inside_pipes(last),
82
+ check_no_space(last_end_pos_inside_pipes(arguments, last),
86
83
  closing_pipe.begin_pos, 'Space after last')
87
84
  end
88
85
 
89
- def check_space_style_inside_pipes(args, opening_pipe, closing_pipe)
90
- check_opening_pipe_space(args, opening_pipe)
91
- check_closing_pipe_space(args, closing_pipe)
86
+ def check_space_style_inside_pipes(arguments)
87
+ opening_pipe, closing_pipe = pipes(arguments)
88
+
89
+ check_opening_pipe_space(arguments, opening_pipe)
90
+ check_closing_pipe_space(arguments, closing_pipe)
92
91
  end
93
92
 
94
- def check_opening_pipe_space(args, opening_pipe)
93
+ def check_opening_pipe_space(arguments, opening_pipe)
94
+ args = arguments.children
95
+
95
96
  first_arg = args.first
96
97
  range = first_arg.source_range
97
98
 
@@ -101,9 +102,11 @@ module RuboCop
101
102
  'Extra space before first')
102
103
  end
103
104
 
104
- def check_closing_pipe_space(args, closing_pipe)
105
+ def check_closing_pipe_space(arguments, closing_pipe)
106
+ args = arguments.children
107
+
105
108
  last = args.last.source_range
106
- last_end_pos = last_end_pos_inside_pipes(last)
109
+ last_end_pos = last_end_pos_inside_pipes(arguments, last)
107
110
 
108
111
  check_space(last_end_pos, closing_pipe.begin_pos, last,
109
112
  'after last block parameter')
@@ -111,9 +114,12 @@ module RuboCop
111
114
  'Extra space after last')
112
115
  end
113
116
 
114
- def last_end_pos_inside_pipes(range)
117
+ def last_end_pos_inside_pipes(arguments, range)
115
118
  pos = range.end_pos
116
- range.source_buffer.source[pos] == ',' ? pos + 1 : pos
119
+ num = pos - arguments.source_range.begin_pos
120
+ trailing_comma_index = arguments.source[num..-1].index(',')
121
+
122
+ trailing_comma_index ? pos + trailing_comma_index + 1 : pos
117
123
  end
118
124
 
119
125
  def check_each_arg(args)
@@ -51,7 +51,7 @@ module RuboCop
51
51
  alias on_csend on_send
52
52
 
53
53
  def on_const(node)
54
- return unless node.loc.double_colon
54
+ return unless node.loc.respond_to?(:double_colon) && node.loc.double_colon
55
55
 
56
56
  check_space_after_double_colon(node)
57
57
  end
@@ -5,6 +5,8 @@ module RuboCop
5
5
  module Layout
6
6
  # Checks that operators have space around them, except for ** which
7
7
  # should or shouldn't have surrounding space depending on configuration.
8
+ # It allows vertical alignment consisting of one or more whitespace
9
+ # around operators.
8
10
  #
9
11
  # This cop has `AllowForAlignment` option. When `true`, allows most
10
12
  # uses of extra spacing if the intent is to align with an operator on
@@ -207,7 +209,8 @@ module RuboCop
207
209
  token = Token.new(operator, nil, operator.source)
208
210
  align_preceding = aligned_with_preceding_assignment(token)
209
211
 
210
- return align_preceding == :no unless align_preceding == :none
212
+ return false if align_preceding == :yes ||
213
+ aligned_with_subsequent_assignment(token) == :none
211
214
 
212
215
  aligned_with_subsequent_assignment(token) != :yes
213
216
  end
@@ -11,10 +11,12 @@ module RuboCop
11
11
  # # bad
12
12
  # f( 3)
13
13
  # g = (a + 3 )
14
+ # f( )
14
15
  #
15
16
  # # good
16
17
  # f(3)
17
18
  # g = (a + 3)
19
+ # f()
18
20
  #
19
21
  # @example EnforcedStyle: space
20
22
  # # The `space` style enforces that parentheses have a space at the
@@ -44,11 +46,7 @@ module RuboCop
44
46
  @processed_source = processed_source
45
47
 
46
48
  if style == :space
47
- each_missing_space(processed_source.tokens) do |range|
48
- add_offense(range, message: MSG_SPACE) do |corrector|
49
- corrector.insert_before(range, ' ')
50
- end
51
- end
49
+ process_with_space_style(processed_source)
52
50
  else
53
51
  each_extraneous_space(processed_source.tokens) do |range|
54
52
  add_offense(range) do |corrector|
@@ -60,6 +58,21 @@ module RuboCop
60
58
 
61
59
  private
62
60
 
61
+ def process_with_space_style(processed_source)
62
+ processed_source.tokens.each_cons(2) do |token1, token2|
63
+ each_extraneous_space_in_empty_parens(token1, token2) do |range|
64
+ add_offense(range) do |corrector|
65
+ corrector.remove(range)
66
+ end
67
+ end
68
+ each_missing_space(token1, token2) do |range|
69
+ add_offense(range, message: MSG_SPACE) do |corrector|
70
+ corrector.insert_before(range, ' ')
71
+ end
72
+ end
73
+ end
74
+ end
75
+
63
76
  def each_extraneous_space(tokens)
64
77
  tokens.each_cons(2) do |token1, token2|
65
78
  next unless parens?(token1, token2)
@@ -73,15 +86,21 @@ module RuboCop
73
86
  end
74
87
  end
75
88
 
76
- def each_missing_space(tokens)
77
- tokens.each_cons(2) do |token1, token2|
78
- next if can_be_ignored?(token1, token2)
89
+ def each_extraneous_space_in_empty_parens(token1, token2)
90
+ return unless token1.left_parens? && token2.right_parens?
79
91
 
80
- if token1.left_parens?
81
- yield range_between(token2.begin_pos, token2.begin_pos + 1)
82
- elsif token2.right_parens?
83
- yield range_between(token2.begin_pos, token2.end_pos)
84
- end
92
+ return if range_between(token1.begin_pos, token2.end_pos).source == '()'
93
+
94
+ yield range_between(token1.end_pos, token2.begin_pos)
95
+ end
96
+
97
+ def each_missing_space(token1, token2)
98
+ return if can_be_ignored?(token1, token2)
99
+
100
+ if token1.left_parens?
101
+ yield range_between(token2.begin_pos, token2.begin_pos + 1)
102
+ elsif token2.right_parens?
103
+ yield range_between(token2.begin_pos, token2.end_pos)
85
104
  end
86
105
  end
87
106
 
@@ -96,6 +115,9 @@ module RuboCop
96
115
  def can_be_ignored?(token1, token2)
97
116
  return true unless parens?(token1, token2)
98
117
 
118
+ # Ignore empty parentheses.
119
+ return true if range_between(token1.begin_pos, token2.end_pos).source == '()'
120
+
99
121
  # If the second token is a comment, that means that a line break
100
122
  # follows, and that the rules for space inside don't apply.
101
123
  return true if token2.comment?
@@ -14,14 +14,25 @@ module RuboCop
14
14
  # # good
15
15
  # x = 0
16
16
  #
17
- # @example AllowInHeredoc: false
17
+ # @example AllowInHeredoc: false (default)
18
18
  # # The line in this example contains spaces after the 0.
19
19
  # # bad
20
20
  # code = <<~RUBY
21
21
  # x = 0
22
22
  # RUBY
23
23
  #
24
- # @example AllowInHeredoc: true (default)
24
+ # # ok
25
+ # code = <<~RUBY
26
+ # x = 0 #{}
27
+ # RUBY
28
+ #
29
+ # # good
30
+ # trailing_whitespace = ' '
31
+ # code = <<~RUBY
32
+ # x = 0#{trailing_whitespace}
33
+ # RUBY
34
+ #
35
+ # @example AllowInHeredoc: true
25
36
  # # The line in this example contains spaces after the 0.
26
37
  # # good
27
38
  # code = <<~RUBY
@@ -35,36 +46,49 @@ module RuboCop
35
46
  MSG = 'Trailing whitespace detected.'
36
47
 
37
48
  def on_new_investigation
38
- heredoc_ranges = extract_heredoc_ranges(processed_source.ast)
49
+ @heredocs = extract_heredocs(processed_source.ast)
39
50
  processed_source.lines.each_with_index do |line, index|
40
- lineno = index + 1
41
-
42
51
  next unless line.end_with?(' ', "\t")
43
- next if skip_heredoc? && inside_heredoc?(heredoc_ranges, lineno)
44
52
 
45
- range = offense_range(lineno, line)
46
- add_offense(range) do |corrector|
53
+ process_line(line, index + 1)
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def process_line(line, lineno)
60
+ heredoc = find_heredoc(lineno)
61
+ return if skip_heredoc? && heredoc
62
+
63
+ range = offense_range(lineno, line)
64
+ add_offense(range) do |corrector|
65
+ if heredoc
66
+ corrector.wrap(range, "\#{'", "'}") unless static?(heredoc)
67
+ else
47
68
  corrector.remove(range)
48
69
  end
49
70
  end
50
71
  end
51
72
 
52
- private
73
+ def static?(heredoc)
74
+ heredoc.loc.expression.source.end_with? "'"
75
+ end
53
76
 
54
77
  def skip_heredoc?
55
78
  cop_config.fetch('AllowInHeredoc', false)
56
79
  end
57
80
 
58
- def inside_heredoc?(heredoc_ranges, line_number)
59
- heredoc_ranges.any? { |r| r.include?(line_number) }
81
+ def find_heredoc(line_number)
82
+ @heredocs.each { |node, r| return node if r.include?(line_number) }
83
+ nil
60
84
  end
61
85
 
62
- def extract_heredoc_ranges(ast)
86
+ def extract_heredocs(ast)
63
87
  return [] unless ast
64
88
 
65
89
  ast.each_node(:str, :dstr, :xstr).select(&:heredoc?).map do |node|
66
90
  body = node.location.heredoc_body
67
- (body.first_line...body.last_line)
91
+ [node, body.first_line...body.last_line]
68
92
  end
69
93
  end
70
94
 
@@ -53,7 +53,8 @@ module RuboCop
53
53
  def find_offense_node(node, regexp_receiver)
54
54
  return node unless node.parent
55
55
 
56
- if node.parent.send_type? || method_chain_to_regexp_receiver?(node, regexp_receiver)
56
+ if (node.parent.send_type? && node.receiver) ||
57
+ method_chain_to_regexp_receiver?(node, regexp_receiver)
57
58
  node = find_offense_node(node.parent, regexp_receiver)
58
59
  end
59
60
 
@@ -49,7 +49,21 @@ module RuboCop
49
49
  # const_set(:LIST, [])
50
50
  # end
51
51
  # end
52
+ #
53
+ # @example AllowedMethods: ['enums'] (default)
54
+ # # good
55
+ #
56
+ # # `enums` for Typed Enums via `T::Enum` in Sorbet.
57
+ # # https://sorbet.org/docs/tenum
58
+ # class TestEnum < T::Enum
59
+ # enums do
60
+ # Foo = new("foo")
61
+ # end
62
+ # end
63
+ #
52
64
  class ConstantDefinitionInBlock < Base
65
+ include AllowedMethods
66
+
53
67
  MSG = 'Do not define constants this way within a block.'
54
68
 
55
69
  def_node_matcher :constant_assigned_in_block?, <<~PATTERN
@@ -61,13 +75,23 @@ module RuboCop
61
75
  PATTERN
62
76
 
63
77
  def on_casgn(node)
64
- add_offense(node) if constant_assigned_in_block?(node)
78
+ return if !constant_assigned_in_block?(node) || allowed_method?(method_name(node))
79
+
80
+ add_offense(node)
65
81
  end
66
82
 
67
83
  def on_class(node)
68
- add_offense(node) if module_defined_in_block?(node)
84
+ return if !module_defined_in_block?(node) || allowed_method?(method_name(node))
85
+
86
+ add_offense(node)
69
87
  end
70
88
  alias on_module on_class
89
+
90
+ private
91
+
92
+ def method_name(node)
93
+ node.ancestors.find(&:block_type?).send_node.method_name
94
+ end
71
95
  end
72
96
  end
73
97
  end