rubocop 0.76.0 → 0.79.0

Sign up to get free protection for your applications and to get access to all the features.
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