rubocop 0.76.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 (129) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/config/default.yml +290 -264
  4. data/lib/rubocop/ast/builder.rb +43 -42
  5. data/lib/rubocop/ast/node/block_node.rb +2 -0
  6. data/lib/rubocop/ast/node/def_node.rb +11 -0
  7. data/lib/rubocop/ast/node/forward_args_node.rb +18 -0
  8. data/lib/rubocop/ast/node.rb +1 -1
  9. data/lib/rubocop/ast/traversal.rb +11 -3
  10. data/lib/rubocop/cli/command/auto_genenerate_config.rb +105 -0
  11. data/lib/rubocop/cli/command/base.rb +33 -0
  12. data/lib/rubocop/cli/command/execute_runner.rb +76 -0
  13. data/lib/rubocop/cli/command/init_dotfile.rb +45 -0
  14. data/lib/rubocop/cli/command/show_cops.rb +80 -0
  15. data/lib/rubocop/cli/command/version.rb +17 -0
  16. data/lib/rubocop/cli/command.rb +21 -0
  17. data/lib/rubocop/cli/environment.rb +21 -0
  18. data/lib/rubocop/cli.rb +11 -230
  19. data/lib/rubocop/config.rb +1 -1
  20. data/lib/rubocop/config_loader.rb +19 -19
  21. data/lib/rubocop/config_obsoletion.rb +65 -12
  22. data/lib/rubocop/config_validator.rb +56 -98
  23. data/lib/rubocop/cop/autocorrect_logic.rb +7 -4
  24. data/lib/rubocop/cop/bundler/gem_comment.rb +4 -4
  25. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +2 -2
  26. data/lib/rubocop/cop/cop.rb +21 -0
  27. data/lib/rubocop/cop/correctors/space_corrector.rb +1 -2
  28. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  29. data/lib/rubocop/cop/generator/configuration_injector.rb +1 -1
  30. data/lib/rubocop/cop/generator.rb +3 -4
  31. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +59 -0
  32. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  33. data/lib/rubocop/cop/layout/{align_arguments.rb → argument_alignment.rb} +1 -1
  34. data/lib/rubocop/cop/layout/{align_array.rb → array_alignment.rb} +1 -1
  35. data/lib/rubocop/cop/layout/{indent_assignment.rb → assignment_indentation.rb} +1 -1
  36. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  37. data/lib/rubocop/cop/layout/{indent_first_argument.rb → first_argument_indentation.rb} +5 -5
  38. data/lib/rubocop/cop/layout/{indent_first_array_element.rb → first_array_element_indentation.rb} +4 -4
  39. data/lib/rubocop/cop/layout/{indent_first_hash_element.rb → first_hash_element_indentation.rb} +3 -3
  40. data/lib/rubocop/cop/layout/{indent_first_parameter.rb → first_parameter_indentation.rb} +3 -3
  41. data/lib/rubocop/cop/layout/{align_hash.rb → hash_alignment.rb} +10 -6
  42. data/lib/rubocop/cop/layout/{indent_heredoc.rb → heredoc_indentation.rb} +5 -5
  43. data/lib/rubocop/cop/layout/{leading_blank_lines.rb → leading_empty_lines.rb} +1 -1
  44. data/lib/rubocop/cop/{metrics → layout}/line_length.rb +40 -110
  45. data/lib/rubocop/cop/layout/multiline_block_layout.rb +14 -5
  46. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +1 -1
  47. data/lib/rubocop/cop/layout/{align_parameters.rb → parameter_alignment.rb} +1 -1
  48. data/lib/rubocop/cop/layout/space_around_keyword.rb +12 -0
  49. data/lib/rubocop/cop/layout/space_around_operators.rb +32 -7
  50. data/lib/rubocop/cop/layout/space_before_block_braces.rb +17 -0
  51. data/lib/rubocop/cop/layout/{trailing_blank_lines.rb → trailing_empty_lines.rb} +1 -1
  52. data/lib/rubocop/cop/lint/debugger.rb +2 -2
  53. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +1 -1
  54. data/lib/rubocop/cop/lint/{duplicated_key.rb → duplicate_hash_key.rb} +1 -1
  55. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  56. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  57. data/lib/rubocop/cop/lint/{multiple_compare.rb → multiple_comparison.rb} +1 -1
  58. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +89 -0
  59. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +3 -3
  60. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +4 -4
  61. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  62. data/lib/rubocop/cop/lint/{string_conversion_in_interpolation.rb → redundant_string_coercion.rb} +1 -1
  63. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
  64. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  65. data/lib/rubocop/cop/lint/{handle_exceptions.rb → suppressed_exception.rb} +1 -1
  66. data/lib/rubocop/cop/lint/useless_access_modifier.rb +57 -23
  67. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
  68. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  69. data/lib/rubocop/cop/migration/department_name.rb +16 -1
  70. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  71. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -7
  72. data/lib/rubocop/cop/mixin/{hash_alignment.rb → hash_alignment_styles.rb} +1 -1
  73. data/lib/rubocop/cop/mixin/line_length_help.rb +88 -0
  74. data/lib/rubocop/cop/mixin/nil_methods.rb +4 -4
  75. data/lib/rubocop/cop/mixin/rational_literal.rb +18 -0
  76. data/lib/rubocop/cop/mixin/statement_modifier.rb +2 -2
  77. data/lib/rubocop/cop/mixin/trailing_comma.rb +6 -3
  78. data/lib/rubocop/cop/naming/{uncommunicative_block_param_name.rb → block_parameter_name.rb} +3 -3
  79. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -5
  80. data/lib/rubocop/cop/naming/{uncommunicative_method_param_name.rb → method_parameter_name.rb} +4 -4
  81. data/lib/rubocop/cop/naming/predicate_name.rb +6 -6
  82. data/lib/rubocop/cop/offense.rb +11 -0
  83. data/lib/rubocop/cop/registry.rb +7 -2
  84. data/lib/rubocop/cop/style/alias.rb +1 -1
  85. data/lib/rubocop/cop/style/array_join.rb +1 -1
  86. data/lib/rubocop/cop/style/attr.rb +8 -0
  87. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
  88. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  89. data/lib/rubocop/cop/style/even_odd.rb +1 -1
  90. data/lib/rubocop/cop/style/guard_clause.rb +3 -2
  91. data/lib/rubocop/cop/style/if_unless_modifier.rb +38 -3
  92. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  93. data/lib/rubocop/cop/style/ip_addresses.rb +4 -4
  94. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +168 -0
  95. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +54 -0
  96. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +4 -207
  97. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  98. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
  99. data/lib/rubocop/cop/style/multiline_when_then.rb +5 -1
  100. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +5 -5
  101. data/lib/rubocop/cop/style/next.rb +5 -5
  102. data/lib/rubocop/cop/style/numeric_literals.rb +7 -3
  103. data/lib/rubocop/cop/style/numeric_predicate.rb +4 -3
  104. data/lib/rubocop/cop/style/option_hash.rb +3 -3
  105. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +7 -7
  106. data/lib/rubocop/cop/style/redundant_parentheses.rb +3 -3
  107. data/lib/rubocop/cop/style/redundant_return.rb +2 -8
  108. data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
  109. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +7 -1
  110. data/lib/rubocop/cop/style/trivial_accessors.rb +5 -5
  111. data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
  112. data/lib/rubocop/cop/style/yoda_condition.rb +16 -1
  113. data/lib/rubocop/cop/team.rb +5 -0
  114. data/lib/rubocop/formatter/base_formatter.rb +2 -2
  115. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -3
  116. data/lib/rubocop/formatter/json_formatter.rb +6 -5
  117. data/lib/rubocop/formatter/tap_formatter.rb +1 -3
  118. data/lib/rubocop/node_pattern.rb +1 -1
  119. data/lib/rubocop/options.rb +8 -8
  120. data/lib/rubocop/processed_source.rb +1 -1
  121. data/lib/rubocop/rake_task.rb +1 -0
  122. data/lib/rubocop/result_cache.rb +23 -7
  123. data/lib/rubocop/rspec/shared_contexts.rb +5 -0
  124. data/lib/rubocop/runner.rb +18 -2
  125. data/lib/rubocop/target_ruby.rb +151 -0
  126. data/lib/rubocop/version.rb +1 -1
  127. data/lib/rubocop.rb +38 -22
  128. metadata +40 -25
  129. data/lib/rubocop/cop/mixin/safe_mode.rb +0 -24
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # This cop checks for uses of "*" as a substitute for *join*.
6
+ # This cop checks for uses of "\*" as a substitute for *join*.
7
7
  #
8
8
  # Not all cases can reliably checked, due to Ruby's dynamic
9
9
  # types, so we consider only cases when the first argument is an
@@ -21,6 +21,10 @@ module RuboCop
21
21
 
22
22
  def on_send(node)
23
23
  return unless node.command?(:attr) && node.arguments?
24
+ # check only for method definitions in class/module body
25
+ return if node.parent &&
26
+ !node.parent.class_type? &&
27
+ !class_eval?(node.parent)
24
28
 
25
29
  add_offense(node, location: :selector)
26
30
  end
@@ -56,6 +60,10 @@ module RuboCop
56
60
  'attr_reader'
57
61
  end
58
62
  end
63
+
64
+ def_node_matcher :class_eval?, <<~PATTERN
65
+ (block (send _ {:class_eval :module_eval}) ...)
66
+ PATTERN
59
67
  end
60
68
  end
61
69
  end
@@ -212,7 +212,7 @@ module RuboCop
212
212
  %i[casgn cvasgn gvasgn ivasgn lvasgn].freeze
213
213
  ASSIGNMENT_TYPES = VARIABLE_ASSIGNMENT_TYPES +
214
214
  %i[and_asgn or_asgn op_asgn masgn].freeze
215
- LINE_LENGTH = 'Metrics/LineLength'
215
+ LINE_LENGTH = 'Layout/LineLength'
216
216
  INDENTATION_WIDTH = 'Layout/IndentationWidth'
217
217
  ENABLED = 'Enabled'
218
218
  MAX = 'Max'
@@ -376,7 +376,7 @@ module RuboCop
376
376
  assignment_types_match?(*statements)
377
377
  end
378
378
 
379
- # If `Metrics/LineLength` is enabled, we do not want to introduce an
379
+ # If `Layout/LineLength` is enabled, we do not want to introduce an
380
380
  # offense by auto-correcting this cop. Find the max configured line
381
381
  # length. Find the longest line of condition. Remove the assignment
382
382
  # from lines that contain the offending assignment because after
@@ -85,7 +85,7 @@ module RuboCop
85
85
  # FIXME: It's a Style/ConditionalAssignment's false positive.
86
86
  # rubocop:disable Style/ConditionalAssignment
87
87
  def with_lineno?(node)
88
- if node.method_name == :eval
88
+ if node.method?(:eval)
89
89
  node.arguments.size == 4
90
90
  else
91
91
  node.arguments.size == 3
@@ -23,7 +23,7 @@ module RuboCop
23
23
  {(send $_ :% (int 2))
24
24
  (begin (send $_ :% (int 2)))}
25
25
  ${:== :!=}
26
- (int ${0 1 2}))
26
+ (int ${0 1}))
27
27
  PATTERN
28
28
 
29
29
  def on_send(node)
@@ -49,8 +49,9 @@ module RuboCop
49
49
 
50
50
  if body.if_type?
51
51
  check_ending_if(body)
52
- elsif body.begin_type? && body.children.last.if_type?
53
- check_ending_if(body.children.last)
52
+ elsif body.begin_type?
53
+ final_expression = body.children.last
54
+ check_ending_if(final_expression) if final_expression&.if_type?
54
55
  end
55
56
  end
56
57
  alias on_defs on_def
@@ -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) &&
@@ -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)
@@ -0,0 +1,168 @@
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
+ node.parent &&
78
+ (logical_operator?(node.parent) ||
79
+ node.parent.send_type? &&
80
+ node.parent.arguments.any?(&method(:logical_operator?)))
81
+ end
82
+
83
+ def call_in_optional_arguments?(node)
84
+ node.parent &&
85
+ (node.parent.optarg_type? || node.parent.kwoptarg_type?)
86
+ end
87
+
88
+ def call_with_ambiguous_arguments?(node)
89
+ call_with_braced_block?(node) ||
90
+ call_as_argument_or_chain?(node) ||
91
+ hash_literal_in_arguments?(node) ||
92
+ node.descendants.any? do |n|
93
+ ambigious_literal?(n) || logical_operator?(n) ||
94
+ call_with_braced_block?(n)
95
+ end
96
+ end
97
+
98
+ def call_with_braced_block?(node)
99
+ (node.send_type? || node.super_type?) &&
100
+ node.block_node && node.block_node.braces?
101
+ end
102
+
103
+ def call_as_argument_or_chain?(node)
104
+ node.parent &&
105
+ (node.parent.send_type? && !assigned_before?(node.parent, node) ||
106
+ node.parent.csend_type? || node.parent.super_type?)
107
+ end
108
+
109
+ def hash_literal_in_arguments?(node)
110
+ node.arguments.any? do |n|
111
+ hash_literal?(n) ||
112
+ n.send_type? && node.descendants.any?(&method(:hash_literal?))
113
+ end
114
+ end
115
+
116
+ def allowed_multiline_call_with_parentheses?(node)
117
+ cop_config['AllowParenthesesInMultilineCall'] && node.multiline?
118
+ end
119
+
120
+ def allowed_chained_call_with_parentheses?(node)
121
+ return false unless cop_config['AllowParenthesesInChaining']
122
+
123
+ previous = node.descendants.first
124
+ return false unless previous&.send_type?
125
+
126
+ previous.parenthesized? ||
127
+ allowed_chained_call_with_parentheses?(previous)
128
+ end
129
+
130
+ def ambigious_literal?(node)
131
+ splat?(node) || ternary_if?(node) || regexp_slash_literal?(node) ||
132
+ unary_literal?(node)
133
+ end
134
+
135
+ def splat?(node)
136
+ node.splat_type? || node.kwsplat_type? || node.block_pass_type?
137
+ end
138
+
139
+ def ternary_if?(node)
140
+ node.if_type? && node.ternary?
141
+ end
142
+
143
+ def logical_operator?(node)
144
+ (node.and_type? || node.or_type?) && node.logical_operator?
145
+ end
146
+
147
+ def hash_literal?(node)
148
+ node.hash_type? && node.braces?
149
+ end
150
+
151
+ def regexp_slash_literal?(node)
152
+ node.regexp_type? && node.loc.begin.source == '/'
153
+ end
154
+
155
+ def unary_literal?(node)
156
+ node.numeric_type? && node.sign? ||
157
+ node.parent&.send_type? && node.parent&.unary_operation?
158
+ end
159
+
160
+ def assigned_before?(node, target)
161
+ node.assignment? &&
162
+ node.loc.operator.begin < target.loc.begin
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ class MethodCallWithArgsParentheses
7
+ # Style require_parentheses
8
+ module RequireParentheses
9
+ def on_send(node)
10
+ return if ignored_method?(node.method_name)
11
+ return if matches_ignored_pattern?(node.method_name)
12
+ return if eligible_for_parentheses_omission?(node)
13
+ return unless node.arguments? && !node.parenthesized?
14
+
15
+ add_offense(node)
16
+ end
17
+ alias on_csend on_send
18
+ alias on_super on_send
19
+ alias on_yield on_send
20
+
21
+ def autocorrect(node)
22
+ lambda do |corrector|
23
+ corrector.replace(args_begin(node), '(')
24
+
25
+ unless args_parenthesized?(node)
26
+ corrector.insert_after(args_end(node), ')')
27
+ end
28
+ end
29
+ end
30
+
31
+ def message(_node = nil)
32
+ 'Use parentheses for method calls with arguments.'
33
+ end
34
+
35
+ private
36
+
37
+ def eligible_for_parentheses_omission?(node)
38
+ node.operator_method? || node.setter_method? || ignored_macro?(node)
39
+ end
40
+
41
+ def included_macros_list
42
+ cop_config.fetch('IncludedMacros', []).map(&:to_sym)
43
+ end
44
+
45
+ def ignored_macro?(node)
46
+ cop_config['IgnoreMacros'] &&
47
+ node.macro? &&
48
+ !included_macros_list.include?(node.method_name)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -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,18 @@ module RuboCop
150
148
  include IgnoredMethods
151
149
  include IgnoredPattern
152
150
 
153
- TRAILING_WHITESPACE_REGEX = /\s+\Z/.freeze
154
-
155
- def on_send(node)
156
- case style
157
- when :require_parentheses
158
- add_offense_for_require_parentheses(node)
159
- when :omit_parentheses
160
- add_offense_for_omit_parentheses(node)
161
- end
162
- end
163
- alias on_csend on_send
164
- alias on_super on_send
165
- alias on_yield on_send
166
-
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)
151
+ def initialize(*)
152
+ super
177
153
  case style
178
154
  when :require_parentheses
179
- 'Use parentheses for method calls with arguments.'
155
+ extend RequireParentheses
180
156
  when :omit_parentheses
181
- 'Omit parentheses for method calls with arguments.'
157
+ extend OmitParentheses
182
158
  end
183
159
  end
184
160
 
185
161
  private
186
162
 
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
163
  def args_begin(node)
242
164
  loc = node.loc
243
165
  selector =
@@ -257,132 +179,7 @@ module RuboCop
257
179
  first_node = node.arguments.first
258
180
  first_node.begin_type? && first_node.parenthesized_call?
259
181
  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
182
  end
385
183
  end
386
184
  end
387
185
  end
388
- # rubocop:enable Metrics/ClassLength
@@ -103,7 +103,7 @@ module RuboCop
103
103
  .select(&:macro?)
104
104
 
105
105
  siblings.select do |sibling_node|
106
- sibling_node.method_name == send_node.method_name
106
+ sibling_node.method?(send_node.method_name)
107
107
  end
108
108
  end
109
109
 
@@ -53,7 +53,7 @@ module RuboCop
53
53
  end
54
54
 
55
55
  def max_line_length
56
- config.for_cop('Metrics/LineLength')['Max'] || 80
56
+ config.for_cop('Layout/LineLength')['Max'] || 80
57
57
  end
58
58
  end
59
59
  end