rubocop 0.76.0 → 0.80.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 (155) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +4 -4
  4. data/config/default.yml +325 -283
  5. data/lib/rubocop.rb +43 -23
  6. data/lib/rubocop/ast/builder.rb +43 -42
  7. data/lib/rubocop/ast/node.rb +1 -13
  8. data/lib/rubocop/ast/node/block_node.rb +2 -0
  9. data/lib/rubocop/ast/node/def_node.rb +11 -0
  10. data/lib/rubocop/ast/node/forward_args_node.rb +18 -0
  11. data/lib/rubocop/ast/node/regexp_node.rb +2 -4
  12. data/lib/rubocop/ast/traversal.rb +20 -3
  13. data/lib/rubocop/cli.rb +11 -230
  14. data/lib/rubocop/cli/command.rb +21 -0
  15. data/lib/rubocop/cli/command/auto_genenerate_config.rb +105 -0
  16. data/lib/rubocop/cli/command/base.rb +33 -0
  17. data/lib/rubocop/cli/command/execute_runner.rb +76 -0
  18. data/lib/rubocop/cli/command/init_dotfile.rb +45 -0
  19. data/lib/rubocop/cli/command/show_cops.rb +80 -0
  20. data/lib/rubocop/cli/command/version.rb +17 -0
  21. data/lib/rubocop/cli/environment.rb +21 -0
  22. data/lib/rubocop/comment_config.rb +6 -1
  23. data/lib/rubocop/config.rb +28 -10
  24. data/lib/rubocop/config_loader.rb +19 -19
  25. data/lib/rubocop/config_obsoletion.rb +65 -11
  26. data/lib/rubocop/config_validator.rb +56 -98
  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/cop.rb +21 -0
  31. data/lib/rubocop/cop/correctors/space_corrector.rb +1 -2
  32. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  33. data/lib/rubocop/cop/generator.rb +3 -4
  34. data/lib/rubocop/cop/generator/configuration_injector.rb +1 -1
  35. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  36. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +59 -0
  37. data/lib/rubocop/cop/layout/{align_arguments.rb → argument_alignment.rb} +1 -1
  38. data/lib/rubocop/cop/layout/{align_array.rb → array_alignment.rb} +1 -1
  39. data/lib/rubocop/cop/layout/{indent_assignment.rb → assignment_indentation.rb} +1 -1
  40. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
  41. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  42. data/lib/rubocop/cop/layout/{indent_first_argument.rb → first_argument_indentation.rb} +5 -5
  43. data/lib/rubocop/cop/layout/{indent_first_array_element.rb → first_array_element_indentation.rb} +4 -4
  44. data/lib/rubocop/cop/layout/{indent_first_hash_element.rb → first_hash_element_indentation.rb} +3 -3
  45. data/lib/rubocop/cop/layout/{indent_first_parameter.rb → first_parameter_indentation.rb} +3 -3
  46. data/lib/rubocop/cop/layout/{align_hash.rb → hash_alignment.rb} +10 -6
  47. data/lib/rubocop/cop/layout/{indent_heredoc.rb → heredoc_indentation.rb} +5 -5
  48. data/lib/rubocop/cop/layout/leading_comment_space.rb +33 -2
  49. data/lib/rubocop/cop/layout/{leading_blank_lines.rb → leading_empty_lines.rb} +1 -1
  50. data/lib/rubocop/cop/{metrics → layout}/line_length.rb +67 -108
  51. data/lib/rubocop/cop/layout/multiline_block_layout.rb +14 -5
  52. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +0 -4
  53. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +1 -1
  54. data/lib/rubocop/cop/layout/{align_parameters.rb → parameter_alignment.rb} +1 -1
  55. data/lib/rubocop/cop/layout/space_around_keyword.rb +12 -0
  56. data/lib/rubocop/cop/layout/space_around_operators.rb +50 -7
  57. data/lib/rubocop/cop/layout/space_before_block_braces.rb +17 -0
  58. data/lib/rubocop/cop/layout/space_before_first_arg.rb +8 -0
  59. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -9
  60. data/lib/rubocop/cop/layout/{trailing_blank_lines.rb → trailing_empty_lines.rb} +1 -1
  61. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  62. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +1 -1
  63. data/lib/rubocop/cop/lint/{duplicated_key.rb → duplicate_hash_key.rb} +1 -1
  64. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  65. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  66. data/lib/rubocop/cop/lint/{multiple_compare.rb → multiple_comparison.rb} +1 -1
  67. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +89 -0
  68. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +3 -3
  69. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +13 -8
  70. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  71. data/lib/rubocop/cop/lint/{string_conversion_in_interpolation.rb → redundant_string_coercion.rb} +1 -1
  72. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
  73. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  74. data/lib/rubocop/cop/lint/{handle_exceptions.rb → suppressed_exception.rb} +1 -1
  75. data/lib/rubocop/cop/lint/useless_access_modifier.rb +57 -23
  76. data/lib/rubocop/cop/lint/useless_setter_call.rb +5 -1
  77. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  78. data/lib/rubocop/cop/migration/department_name.rb +30 -2
  79. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  80. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +4 -0
  81. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +7 -7
  82. data/lib/rubocop/cop/mixin/{hash_alignment.rb → hash_alignment_styles.rb} +1 -1
  83. data/lib/rubocop/cop/mixin/hash_transform_method.rb +171 -0
  84. data/lib/rubocop/cop/mixin/line_length_help.rb +88 -0
  85. data/lib/rubocop/cop/mixin/nil_methods.rb +4 -4
  86. data/lib/rubocop/cop/mixin/rational_literal.rb +18 -0
  87. data/lib/rubocop/cop/mixin/statement_modifier.rb +2 -2
  88. data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -12
  89. data/lib/rubocop/cop/naming/{uncommunicative_block_param_name.rb → block_parameter_name.rb} +3 -3
  90. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -5
  91. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  92. data/lib/rubocop/cop/naming/{uncommunicative_method_param_name.rb → method_parameter_name.rb} +4 -4
  93. data/lib/rubocop/cop/naming/predicate_name.rb +6 -6
  94. data/lib/rubocop/cop/offense.rb +11 -0
  95. data/lib/rubocop/cop/registry.rb +7 -2
  96. data/lib/rubocop/cop/style/alias.rb +1 -1
  97. data/lib/rubocop/cop/style/array_join.rb +1 -1
  98. data/lib/rubocop/cop/style/attr.rb +8 -0
  99. data/lib/rubocop/cop/style/block_delimiters.rb +60 -1
  100. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
  101. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  102. data/lib/rubocop/cop/style/even_odd.rb +1 -1
  103. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +89 -11
  104. data/lib/rubocop/cop/style/guard_clause.rb +3 -2
  105. data/lib/rubocop/cop/style/hash_each_methods.rb +87 -0
  106. data/lib/rubocop/cop/style/hash_transform_keys.rb +79 -0
  107. data/lib/rubocop/cop/style/hash_transform_values.rb +79 -0
  108. data/lib/rubocop/cop/style/if_unless_modifier.rb +38 -3
  109. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  110. data/lib/rubocop/cop/style/inverse_methods.rb +8 -4
  111. data/lib/rubocop/cop/style/ip_addresses.rb +4 -4
  112. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -205
  113. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +169 -0
  114. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +54 -0
  115. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  116. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
  117. data/lib/rubocop/cop/style/multiline_when_then.rb +5 -1
  118. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +7 -7
  119. data/lib/rubocop/cop/style/next.rb +5 -5
  120. data/lib/rubocop/cop/style/numeric_literals.rb +7 -3
  121. data/lib/rubocop/cop/style/numeric_predicate.rb +4 -3
  122. data/lib/rubocop/cop/style/option_hash.rb +3 -3
  123. data/lib/rubocop/cop/style/or_assignment.rb +3 -2
  124. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +7 -7
  125. data/lib/rubocop/cop/style/redundant_condition.rb +17 -4
  126. data/lib/rubocop/cop/style/redundant_parentheses.rb +3 -3
  127. data/lib/rubocop/cop/style/redundant_return.rb +2 -8
  128. data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
  129. data/lib/rubocop/cop/style/symbol_array.rb +2 -2
  130. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  131. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +0 -22
  132. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +7 -1
  133. data/lib/rubocop/cop/style/trivial_accessors.rb +5 -5
  134. data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
  135. data/lib/rubocop/cop/style/yoda_condition.rb +16 -1
  136. data/lib/rubocop/cop/team.rb +5 -0
  137. data/lib/rubocop/cop/variable_force.rb +4 -1
  138. data/lib/rubocop/formatter/base_formatter.rb +2 -2
  139. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -3
  140. data/lib/rubocop/formatter/formatter_set.rb +1 -0
  141. data/lib/rubocop/formatter/json_formatter.rb +6 -5
  142. data/lib/rubocop/formatter/junit_formatter.rb +63 -0
  143. data/lib/rubocop/formatter/tap_formatter.rb +1 -3
  144. data/lib/rubocop/node_pattern.rb +97 -11
  145. data/lib/rubocop/options.rb +8 -8
  146. data/lib/rubocop/processed_source.rb +1 -1
  147. data/lib/rubocop/rake_task.rb +1 -0
  148. data/lib/rubocop/result_cache.rb +23 -7
  149. data/lib/rubocop/rspec/shared_contexts.rb +5 -0
  150. data/lib/rubocop/runner.rb +18 -2
  151. data/lib/rubocop/target_ruby.rb +151 -0
  152. data/lib/rubocop/version.rb +1 -1
  153. metadata +60 -27
  154. data/lib/rubocop/cop/mixin/safe_mode.rb +0 -24
  155. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +0 -209
@@ -7,7 +7,7 @@ module RuboCop
7
7
  # written as modifier `if`/`unless`. The cop also checks for modifier
8
8
  # `if`/`unless` lines that exceed the maximum line length.
9
9
  #
10
- # The maximum line length is configured in the `Metrics/LineLength`
10
+ # The maximum line length is configured in the `Layout/LineLength`
11
11
  # cop. The tab size is configured in the `IndentationWidth` of the
12
12
  # `Layout/Tab` cop.
13
13
  #
@@ -32,6 +32,8 @@ module RuboCop
32
32
  # end
33
33
  class IfUnlessModifier < Cop
34
34
  include StatementModifier
35
+ include LineLengthHelp
36
+ include IgnoredPattern
35
37
 
36
38
  MSG_USE_MODIFIER = 'Favor modifier `%<keyword>s` usage when having a ' \
37
39
  'single-line body. Another good alternative is ' \
@@ -66,6 +68,10 @@ module RuboCop
66
68
 
67
69
  private
68
70
 
71
+ def ignored_patterns
72
+ config.for_cop('Layout/LineLength')['IgnoredPatterns'] || []
73
+ end
74
+
69
75
  def too_long_single_line?(node)
70
76
  return false unless max_line_length
71
77
 
@@ -73,12 +79,41 @@ module RuboCop
73
79
  return false unless range.first_line == range.last_line
74
80
  return false unless line_length_enabled_at_line?(range.first_line)
75
81
 
76
- range.last_column > max_line_length
82
+ line = range.source_line
83
+ return false if line_length(line) <= max_line_length
84
+
85
+ too_long_line_based_on_config?(range, line)
86
+ end
87
+
88
+ def too_long_line_based_on_config?(range, line)
89
+ return false if matches_ignored_pattern?(line)
90
+
91
+ too_long = too_long_line_based_on_ignore_cop_directives?(range, line)
92
+ return too_long unless too_long == :undetermined
93
+
94
+ too_long_line_based_on_allow_uri?(line)
95
+ end
96
+
97
+ def too_long_line_based_on_ignore_cop_directives?(range, line)
98
+ if ignore_cop_directives? && directive_on_source_line?(range.line - 1)
99
+ return line_length_without_directive(line) > max_line_length
100
+ end
101
+
102
+ :undetermined
103
+ end
104
+
105
+ def too_long_line_based_on_allow_uri?(line)
106
+ if allow_uri?
107
+ uri_range = find_excessive_uri_range(line)
108
+ return false if uri_range && allowed_uri_position?(line, uri_range)
109
+ end
110
+
111
+ true
77
112
  end
78
113
 
79
114
  def line_length_enabled_at_line?(line)
80
115
  processed_source.comment_config
81
- .cop_enabled_at_line?('Metrics/LineLength', line)
116
+ .cop_enabled_at_line?('Layout/LineLength', line)
82
117
  end
83
118
 
84
119
  def named_capture_in_condition?(node)
@@ -58,7 +58,7 @@ module RuboCop
58
58
  # `loop do` without further modification. The reason is that a
59
59
  # variable that's introduced inside a while/until loop is in scope
60
60
  # outside of that loop too, but a variable that's assigned for the
61
- # first time inside a block can not be accessed after the block. In
61
+ # first time inside a block cannot be accessed after the block. In
62
62
  # those more complicated cases we don't report an offense.
63
63
  return if @variables.any? do |var|
64
64
  assigned_inside_loop?(var, range) &&
@@ -109,10 +109,7 @@ module RuboCop
109
109
  corrector.remove(not_to_receiver(node, method_call))
110
110
  corrector.replace(method_call.loc.selector,
111
111
  inverse_methods[method].to_s)
112
-
113
- if EQUALITY_METHODS.include?(method)
114
- corrector.remove(end_parentheses(node, method_call))
115
- end
112
+ remove_end_parenthesis(corrector, node, method, method_call)
116
113
  end
117
114
  end
118
115
 
@@ -187,6 +184,13 @@ module RuboCop
187
184
  def dot_range(loc)
188
185
  range_between(loc.dot.begin_pos, loc.expression.end_pos)
189
186
  end
187
+
188
+ def remove_end_parenthesis(corrector, node, method, method_call)
189
+ return unless EQUALITY_METHODS.include?(method) ||
190
+ method_call.parent.begin_type?
191
+
192
+ corrector.remove(end_parentheses(node, method_call))
193
+ end
190
194
  end
191
195
  end
192
196
  end
@@ -28,7 +28,7 @@ module RuboCop
28
28
  contents = node.source[1...-1]
29
29
  return false if contents.empty?
30
30
 
31
- return false if whitelist.include?(contents.downcase)
31
+ return false if allowed_addresses.include?(contents.downcase)
32
32
 
33
33
  # To try to avoid doing two regex checks on every string,
34
34
  # shortcut out if the string does not look like an IP address
@@ -47,9 +47,9 @@ module RuboCop
47
47
 
48
48
  private
49
49
 
50
- def whitelist
51
- whitelist = cop_config['Whitelist']
52
- Array(whitelist).map(&:downcase)
50
+ def allowed_addresses
51
+ allowed_addresses = cop_config['AllowedAddresses']
52
+ Array(allowed_addresses).map(&:downcase)
53
53
  end
54
54
 
55
55
  def could_be_ip?(str)
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rubocop:disable Metrics/ClassLength
4
3
  module RuboCop
5
4
  module Cop
6
5
  module Style
@@ -43,7 +42,6 @@ module RuboCop
43
42
  #
44
43
  # @example EnforcedStyle: require_parentheses (default)
45
44
  #
46
- #
47
45
  # # bad
48
46
  # array.delete e
49
47
  #
@@ -150,94 +148,23 @@ module RuboCop
150
148
  include IgnoredMethods
151
149
  include IgnoredPattern
152
150
 
153
- TRAILING_WHITESPACE_REGEX = /\s+\Z/.freeze
151
+ def initialize(*)
152
+ super
153
+ return unless style_configured?
154
154
 
155
- def on_send(node)
156
155
  case style
157
156
  when :require_parentheses
158
- add_offense_for_require_parentheses(node)
157
+ extend RequireParentheses
159
158
  when :omit_parentheses
160
- add_offense_for_omit_parentheses(node)
159
+ extend OmitParentheses
161
160
  end
162
161
  end
163
- alias on_csend on_send
164
- alias on_super on_send
165
- alias on_yield on_send
166
162
 
167
- def autocorrect(node)
168
- case style
169
- when :require_parentheses
170
- autocorrect_for_require_parentheses(node)
171
- when :omit_parentheses
172
- autocorrect_for_omit_parentheses(node)
173
- end
174
- end
175
-
176
- def message(_node = nil)
177
- case style
178
- when :require_parentheses
179
- 'Use parentheses for method calls with arguments.'
180
- when :omit_parentheses
181
- 'Omit parentheses for method calls with arguments.'
182
- end
183
- end
163
+ # @abstract Overridden in style modules
164
+ def autocorrect(_node); end
184
165
 
185
166
  private
186
167
 
187
- def add_offense_for_require_parentheses(node)
188
- return if ignored_method?(node.method_name)
189
- return if matches_ignored_pattern?(node.method_name)
190
- return if eligible_for_parentheses_omission?(node)
191
- return unless node.arguments? && !node.parenthesized?
192
-
193
- add_offense(node)
194
- end
195
-
196
- def add_offense_for_omit_parentheses(node)
197
- return unless node.parenthesized?
198
- return if node.implicit_call?
199
- return if super_call_without_arguments?(node)
200
- return if allowed_camel_case_method_call?(node)
201
- return if legitimate_call_with_parentheses?(node)
202
-
203
- add_offense(node, location: node.loc.begin.join(node.loc.end))
204
- end
205
-
206
- def autocorrect_for_require_parentheses(node)
207
- lambda do |corrector|
208
- corrector.replace(args_begin(node), '(')
209
-
210
- unless args_parenthesized?(node)
211
- corrector.insert_after(args_end(node), ')')
212
- end
213
- end
214
- end
215
-
216
- def autocorrect_for_omit_parentheses(node)
217
- lambda do |corrector|
218
- if parentheses_at_the_end_of_multiline_call?(node)
219
- corrector.replace(args_begin(node), ' \\')
220
- else
221
- corrector.replace(args_begin(node), ' ')
222
- end
223
- corrector.remove(node.loc.end)
224
- end
225
- end
226
-
227
- def eligible_for_parentheses_omission?(node)
228
- node.operator_method? || node.setter_method? || ignored_macro?(node)
229
- end
230
-
231
- def included_macros_list
232
- cop_config.fetch('IncludedMacros', []).map(&:to_sym)
233
- end
234
-
235
- def ignored_macro?(node)
236
- cop_config['IgnoreMacros'] &&
237
- node.macro? &&
238
- !included_macros_list.include?(node.method_name)
239
- end
240
-
241
168
  def args_begin(node)
242
169
  loc = node.loc
243
170
  selector =
@@ -257,132 +184,7 @@ module RuboCop
257
184
  first_node = node.arguments.first
258
185
  first_node.begin_type? && first_node.parenthesized_call?
259
186
  end
260
-
261
- def parentheses_at_the_end_of_multiline_call?(node)
262
- node.multiline? &&
263
- node.loc.begin.source_line
264
- .gsub(TRAILING_WHITESPACE_REGEX, '')
265
- .end_with?('(')
266
- end
267
-
268
- def super_call_without_arguments?(node)
269
- node.super_type? && node.arguments.none?
270
- end
271
-
272
- def allowed_camel_case_method_call?(node)
273
- node.camel_case_method? &&
274
- (node.arguments.none? ||
275
- cop_config['AllowParenthesesInCamelCaseMethod'])
276
- end
277
-
278
- def legitimate_call_with_parentheses?(node)
279
- call_in_literals?(node) ||
280
- call_with_ambiguous_arguments?(node) ||
281
- call_in_logical_operators?(node) ||
282
- call_in_optional_arguments?(node) ||
283
- allowed_multiline_call_with_parentheses?(node) ||
284
- allowed_chained_call_with_parentheses?(node)
285
- end
286
-
287
- def call_in_literals?(node)
288
- node.parent &&
289
- (node.parent.pair_type? ||
290
- node.parent.array_type? ||
291
- node.parent.range_type? ||
292
- splat?(node.parent) ||
293
- ternary_if?(node.parent))
294
- end
295
-
296
- def call_in_logical_operators?(node)
297
- node.parent &&
298
- (logical_operator?(node.parent) ||
299
- node.parent.send_type? &&
300
- node.parent.arguments.any?(&method(:logical_operator?)))
301
- end
302
-
303
- def call_in_optional_arguments?(node)
304
- node.parent &&
305
- (node.parent.optarg_type? || node.parent.kwoptarg_type?)
306
- end
307
-
308
- def call_with_ambiguous_arguments?(node)
309
- call_with_braced_block?(node) ||
310
- call_as_argument_or_chain?(node) ||
311
- hash_literal_in_arguments?(node) ||
312
- node.descendants.any? do |n|
313
- ambigious_literal?(n) || logical_operator?(n) ||
314
- call_with_braced_block?(n)
315
- end
316
- end
317
-
318
- def call_with_braced_block?(node)
319
- (node.send_type? || node.super_type?) &&
320
- node.block_node && node.block_node.braces?
321
- end
322
-
323
- def call_as_argument_or_chain?(node)
324
- node.parent &&
325
- (node.parent.send_type? && !assigned_before?(node.parent, node) ||
326
- node.parent.csend_type? || node.parent.super_type?)
327
- end
328
-
329
- def hash_literal_in_arguments?(node)
330
- node.arguments.any? do |n|
331
- hash_literal?(n) ||
332
- n.send_type? && node.descendants.any?(&method(:hash_literal?))
333
- end
334
- end
335
-
336
- def allowed_multiline_call_with_parentheses?(node)
337
- cop_config['AllowParenthesesInMultilineCall'] && node.multiline?
338
- end
339
-
340
- def allowed_chained_call_with_parentheses?(node)
341
- return false unless cop_config['AllowParenthesesInChaining']
342
-
343
- previous = node.descendants.first
344
- return false unless previous&.send_type?
345
-
346
- previous.parenthesized? ||
347
- allowed_chained_call_with_parentheses?(previous)
348
- end
349
-
350
- def ambigious_literal?(node)
351
- splat?(node) || ternary_if?(node) || regexp_slash_literal?(node) ||
352
- unary_literal?(node)
353
- end
354
-
355
- def splat?(node)
356
- node.splat_type? || node.kwsplat_type? || node.block_pass_type?
357
- end
358
-
359
- def ternary_if?(node)
360
- node.if_type? && node.ternary?
361
- end
362
-
363
- def logical_operator?(node)
364
- (node.and_type? || node.or_type?) && node.logical_operator?
365
- end
366
-
367
- def hash_literal?(node)
368
- node.hash_type? && node.braces?
369
- end
370
-
371
- def regexp_slash_literal?(node)
372
- node.regexp_type? && node.loc.begin.source == '/'
373
- end
374
-
375
- def unary_literal?(node)
376
- node.numeric_type? && node.sign? ||
377
- node.parent&.send_type? && node.parent&.unary_operation?
378
- end
379
-
380
- def assigned_before?(node, target)
381
- node.assignment? &&
382
- node.loc.operator.begin < target.loc.begin
383
- end
384
187
  end
385
188
  end
386
189
  end
387
190
  end
388
- # rubocop:enable Metrics/ClassLength
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ class MethodCallWithArgsParentheses
7
+ # Style omit_parentheses
8
+ module OmitParentheses
9
+ TRAILING_WHITESPACE_REGEX = /\s+\Z/.freeze
10
+
11
+ def on_send(node)
12
+ return unless node.parenthesized?
13
+ return if node.implicit_call?
14
+ return if super_call_without_arguments?(node)
15
+ return if allowed_camel_case_method_call?(node)
16
+ return if legitimate_call_with_parentheses?(node)
17
+
18
+ add_offense(node, location: node.loc.begin.join(node.loc.end))
19
+ end
20
+ alias on_csend on_send
21
+ alias on_super on_send
22
+ alias on_yield on_send
23
+
24
+ def autocorrect(node)
25
+ lambda do |corrector|
26
+ if parentheses_at_the_end_of_multiline_call?(node)
27
+ corrector.replace(args_begin(node), ' \\')
28
+ else
29
+ corrector.replace(args_begin(node), ' ')
30
+ end
31
+ corrector.remove(node.loc.end)
32
+ end
33
+ end
34
+
35
+ def message(_node = nil)
36
+ 'Omit parentheses for method calls with arguments.'
37
+ end
38
+
39
+ private
40
+
41
+ def super_call_without_arguments?(node)
42
+ node.super_type? && node.arguments.none?
43
+ end
44
+
45
+ def allowed_camel_case_method_call?(node)
46
+ node.camel_case_method? &&
47
+ (node.arguments.none? ||
48
+ cop_config['AllowParenthesesInCamelCaseMethod'])
49
+ end
50
+
51
+ def parentheses_at_the_end_of_multiline_call?(node)
52
+ node.multiline? &&
53
+ node.loc.begin.source_line
54
+ .gsub(TRAILING_WHITESPACE_REGEX, '')
55
+ .end_with?('(')
56
+ end
57
+
58
+ def legitimate_call_with_parentheses?(node)
59
+ call_in_literals?(node) ||
60
+ call_with_ambiguous_arguments?(node) ||
61
+ call_in_logical_operators?(node) ||
62
+ call_in_optional_arguments?(node) ||
63
+ allowed_multiline_call_with_parentheses?(node) ||
64
+ allowed_chained_call_with_parentheses?(node)
65
+ end
66
+
67
+ def call_in_literals?(node)
68
+ node.parent &&
69
+ (node.parent.pair_type? ||
70
+ node.parent.array_type? ||
71
+ node.parent.range_type? ||
72
+ splat?(node.parent) ||
73
+ ternary_if?(node.parent))
74
+ end
75
+
76
+ def call_in_logical_operators?(node)
77
+ parent = node.parent&.block_type? ? node.parent.parent : node.parent
78
+ parent &&
79
+ (logical_operator?(parent) ||
80
+ parent.send_type? &&
81
+ parent.arguments.any?(&method(:logical_operator?)))
82
+ end
83
+
84
+ def call_in_optional_arguments?(node)
85
+ node.parent &&
86
+ (node.parent.optarg_type? || node.parent.kwoptarg_type?)
87
+ end
88
+
89
+ def call_with_ambiguous_arguments?(node)
90
+ call_with_braced_block?(node) ||
91
+ call_as_argument_or_chain?(node) ||
92
+ hash_literal_in_arguments?(node) ||
93
+ node.descendants.any? do |n|
94
+ ambigious_literal?(n) || logical_operator?(n) ||
95
+ call_with_braced_block?(n)
96
+ end
97
+ end
98
+
99
+ def call_with_braced_block?(node)
100
+ (node.send_type? || node.super_type?) &&
101
+ node.block_node && node.block_node.braces?
102
+ end
103
+
104
+ def call_as_argument_or_chain?(node)
105
+ node.parent &&
106
+ (node.parent.send_type? && !assigned_before?(node.parent, node) ||
107
+ node.parent.csend_type? || node.parent.super_type?)
108
+ end
109
+
110
+ def hash_literal_in_arguments?(node)
111
+ node.arguments.any? do |n|
112
+ hash_literal?(n) ||
113
+ n.send_type? && node.descendants.any?(&method(:hash_literal?))
114
+ end
115
+ end
116
+
117
+ def allowed_multiline_call_with_parentheses?(node)
118
+ cop_config['AllowParenthesesInMultilineCall'] && node.multiline?
119
+ end
120
+
121
+ def allowed_chained_call_with_parentheses?(node)
122
+ return false unless cop_config['AllowParenthesesInChaining']
123
+
124
+ previous = node.descendants.first
125
+ return false unless previous&.send_type?
126
+
127
+ previous.parenthesized? ||
128
+ allowed_chained_call_with_parentheses?(previous)
129
+ end
130
+
131
+ def ambigious_literal?(node)
132
+ splat?(node) || ternary_if?(node) || regexp_slash_literal?(node) ||
133
+ unary_literal?(node)
134
+ end
135
+
136
+ def splat?(node)
137
+ node.splat_type? || node.kwsplat_type? || node.block_pass_type?
138
+ end
139
+
140
+ def ternary_if?(node)
141
+ node.if_type? && node.ternary?
142
+ end
143
+
144
+ def logical_operator?(node)
145
+ (node.and_type? || node.or_type?) && node.logical_operator?
146
+ end
147
+
148
+ def hash_literal?(node)
149
+ node.hash_type? && node.braces?
150
+ end
151
+
152
+ def regexp_slash_literal?(node)
153
+ node.regexp_type? && node.loc.begin.source == '/'
154
+ end
155
+
156
+ def unary_literal?(node)
157
+ node.numeric_type? && node.sign? ||
158
+ node.parent&.send_type? && node.parent&.unary_operation?
159
+ end
160
+
161
+ def assigned_before?(node, target)
162
+ node.assignment? &&
163
+ node.loc.operator.begin < target.loc.begin
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end