rubocop 1.70.0 → 1.71.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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +17 -0
  4. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  5. data/lib/rubocop/comment_config.rb +1 -1
  6. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  7. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  8. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  9. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +2 -1
  10. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  11. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  12. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  13. data/lib/rubocop/cop/layout/class_structure.rb +7 -7
  14. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  15. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
  16. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  17. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  18. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +1 -0
  19. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
  20. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
  21. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  22. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  23. data/lib/rubocop/cop/lint/duplicate_set_element.rb +1 -1
  24. data/lib/rubocop/cop/lint/float_comparison.rb +5 -2
  25. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  26. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +12 -2
  27. data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
  28. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  29. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +12 -17
  30. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
  31. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  32. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  33. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  34. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +7 -0
  35. data/lib/rubocop/cop/lint/shared_mutable_default.rb +3 -3
  36. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  37. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  38. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  39. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  40. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  41. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  42. data/lib/rubocop/cop/mixin/hash_subset.rb +170 -0
  43. data/lib/rubocop/cop/mixin/statement_modifier.rb +7 -2
  44. data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -2
  45. data/lib/rubocop/cop/security/compound_hash.rb +1 -0
  46. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  47. data/lib/rubocop/cop/style/block_delimiters.rb +6 -19
  48. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  49. data/lib/rubocop/cop/style/conditional_assignment.rb +3 -1
  50. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  51. data/lib/rubocop/cop/style/exact_regexp_match.rb +1 -1
  52. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  53. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  54. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -1
  55. data/lib/rubocop/cop/style/hash_except.rb +5 -131
  56. data/lib/rubocop/cop/style/hash_slice.rb +65 -0
  57. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  58. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
  59. data/lib/rubocop/cop/style/mutable_constant.rb +1 -1
  60. data/lib/rubocop/cop/style/open_struct_use.rb +4 -4
  61. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  62. data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
  63. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
  64. data/lib/rubocop/cop/style/redundant_line_continuation.rb +27 -10
  65. data/lib/rubocop/cop/style/redundant_parentheses.rb +3 -0
  66. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  67. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  68. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  69. data/lib/rubocop/cop/style/sole_nested_conditional.rb +1 -1
  70. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  71. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
  72. data/lib/rubocop/cops_documentation_generator.rb +13 -13
  73. data/lib/rubocop/directive_comment.rb +9 -8
  74. data/lib/rubocop/options.rb +2 -1
  75. data/lib/rubocop/result_cache.rb +13 -13
  76. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  77. data/lib/rubocop/target_finder.rb +1 -0
  78. data/lib/rubocop/version.rb +1 -1
  79. data/lib/rubocop.rb +3 -0
  80. metadata +9 -8
@@ -12,7 +12,7 @@ module RuboCop
12
12
  # are handled by Lint/UselessNumericOperation.
13
13
  #
14
14
  # NOTE: This cop doesn't detect offenses for the `-` and `%` operator because it
15
- # can't determine the type of `x`. If `x` is an Array or String, it doesn't perform
15
+ # can't determine the type of `x`. If `x` is an `Array` or `String`, it doesn't perform
16
16
  # a numeric operation.
17
17
  #
18
18
  # @example
@@ -50,43 +50,38 @@ module RuboCop
50
50
 
51
51
  # @!method operation_with_constant_result?(node)
52
52
  def_node_matcher :operation_with_constant_result?,
53
- '(send (send nil? $_) $_ ({int | send nil?} $_))'
53
+ '(call (call nil? $_lhs) $_operation ({int | call nil?} $_rhs))'
54
54
 
55
55
  # @!method abbreviated_assignment_with_constant_result?(node)
56
56
  def_node_matcher :abbreviated_assignment_with_constant_result?,
57
- '(op-asgn (lvasgn $_) $_ ({int | lvar} $_))'
57
+ '(op-asgn (lvasgn $_lhs) $_operation ({int lvar} $_rhs))'
58
58
 
59
59
  def on_send(node)
60
- return unless operation_with_constant_result?(node)
61
-
62
- variable, operation, number = operation_with_constant_result?(node)
63
- result = constant_result?(variable, operation, number)
64
- return unless result
60
+ return unless (lhs, operation, rhs = operation_with_constant_result?(node))
61
+ return unless (result = constant_result?(lhs, operation, rhs))
65
62
 
66
63
  add_offense(node) do |corrector|
67
64
  corrector.replace(node, result.to_s)
68
65
  end
69
66
  end
67
+ alias on_csend on_send
70
68
 
71
69
  def on_op_asgn(node)
72
- return unless abbreviated_assignment_with_constant_result?(node)
73
-
74
- variable, operation, number = abbreviated_assignment_with_constant_result?(node)
75
- result = constant_result?(variable, operation, number)
76
- return unless result
70
+ return unless (lhs, operation, rhs = abbreviated_assignment_with_constant_result?(node))
71
+ return unless (result = constant_result?(lhs, operation, rhs))
77
72
 
78
73
  add_offense(node) do |corrector|
79
- corrector.replace(node, "#{variable} = #{result}")
74
+ corrector.replace(node, "#{lhs} = #{result}")
80
75
  end
81
76
  end
82
77
 
83
78
  private
84
79
 
85
- def constant_result?(variable, operation, number)
86
- if number.to_s == '0'
80
+ def constant_result?(lhs, operation, rhs)
81
+ if rhs.to_s == '0'
87
82
  return 0 if operation == :*
88
83
  return 1 if operation == :**
89
- elsif number == variable
84
+ elsif rhs == lhs
90
85
  return 1 if operation == :/
91
86
  end
92
87
  # If we weren't able to find any matches, return false so we can bail out.
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Looks for references of Regexp captures that are out of range
6
+ # Looks for references of `Regexp` captures that are out of range
7
7
  # and thus always returns nil.
8
8
  #
9
9
  # @safety
@@ -61,6 +61,7 @@ module RuboCop
61
61
  check_regexp(node.receiver)
62
62
  end
63
63
  end
64
+ alias after_csend after_send
64
65
 
65
66
  def on_when(node)
66
67
  regexp_conditions = node.conditions.select(&:regexp_type?)
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for redundant quantifiers inside Regexp literals.
6
+ # Checks for redundant quantifiers inside `Regexp` literals.
7
7
  #
8
8
  # It is always allowed when interpolation is used in a regexp literal,
9
9
  # because it's unknown what kind of string will be expanded as a result:
@@ -29,7 +29,7 @@ module RuboCop
29
29
  RESTRICT_ON_SEND = %i[print puts warn].freeze
30
30
 
31
31
  # @!method to_s_without_args?(node)
32
- def_node_matcher :to_s_without_args?, '(send _ :to_s)'
32
+ def_node_matcher :to_s_without_args?, '(call _ :to_s)'
33
33
 
34
34
  def on_interpolation(begin_node)
35
35
  final_node = begin_node.children.last
@@ -42,7 +42,7 @@ module RuboCop
42
42
  def on_send(node)
43
43
  return if node.receiver
44
44
 
45
- node.each_child_node(:send) do |child|
45
+ node.each_child_node(:send, :csend) do |child|
46
46
  next if !child.method?(:to_s) || child.arguments.any?
47
47
 
48
48
  register_offense(child, "`#{node.method_name}`")
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for `rescue` blocks targeting the Exception class.
6
+ # Checks for `rescue` blocks targeting the `Exception` class.
7
7
  #
8
8
  # @example
9
9
  #
@@ -97,12 +97,19 @@ module RuboCop
97
97
  end
98
98
 
99
99
  def require_parentheses?(send_node)
100
+ return true if operator_inside_hash?(send_node)
100
101
  return false unless send_node.comparison_method?
101
102
  return false unless (node = send_node.parent)
102
103
 
103
104
  (node.respond_to?(:logical_operator?) && node.logical_operator?) ||
104
105
  (node.respond_to?(:comparison_method?) && node.comparison_method?)
105
106
  end
107
+
108
+ def operator_inside_hash?(send_node)
109
+ # If an operator call (without a dot) is inside a hash, it needs
110
+ # to be parenthesized when converted to safe navigation.
111
+ send_node.parent&.pair_type? && !send_node.loc.dot
112
+ end
106
113
  end
107
114
  end
108
115
  end
@@ -3,11 +3,11 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for Hash creation with a mutable default value.
7
- # Creating a Hash in such a way will share the default value
6
+ # Checks for `Hash` creation with a mutable default value.
7
+ # Creating a `Hash` in such a way will share the default value
8
8
  # across all keys, causing unexpected behavior when modifying it.
9
9
  #
10
- # For example, when the Hash was created with an Array as the argument,
10
+ # For example, when the `Hash` was created with an `Array` as the argument,
11
11
  # calling `hash[:foo] << 'bar'` will also change the value of all
12
12
  # other keys that have not been explicitly assigned to.
13
13
  #
@@ -17,7 +17,7 @@ module RuboCop
17
17
  # rescue, ensure, etc.
18
18
  #
19
19
  # This cop's autocorrection avoids cases like `a ||= 1` because removing assignment from
20
- # operator assignment can cause NameError if this assignment has been used to declare
20
+ # operator assignment can cause `NameError` if this assignment has been used to declare
21
21
  # a local variable. For example, replacing `a ||= 1` with `a || 1` may cause
22
22
  # "undefined local variable or method `a' for main:Object (NameError)".
23
23
  #
@@ -35,7 +35,7 @@ module RuboCop
35
35
  RESTRICT_ON_SEND = %i[+ - * / **].freeze
36
36
 
37
37
  # @!method useless_operation?(node)
38
- def_node_matcher :useless_operation?, '(send (send nil? $_) $_ (int $_))'
38
+ def_node_matcher :useless_operation?, '(call (call nil? $_) $_ (int $_))'
39
39
 
40
40
  # @!method useless_abbreviated_assignment?(node)
41
41
  def_node_matcher :useless_abbreviated_assignment?, '(op-asgn (lvasgn $_) $_ (int $_))'
@@ -50,6 +50,7 @@ module RuboCop
50
50
  corrector.replace(node, variable)
51
51
  end
52
52
  end
53
+ alias on_csend on_send
53
54
 
54
55
  def on_op_asgn(node)
55
56
  return unless useless_abbreviated_assignment?(node)
@@ -52,12 +52,19 @@ module RuboCop
52
52
  'Prefer reading the data from an external source.'
53
53
  RESTRICT_ON_SEND = [:[]].freeze
54
54
 
55
+ # @!method set_const?(node)
56
+ def_node_matcher :set_const?, <<~PATTERN
57
+ (const {cbase nil?} :Set)
58
+ PATTERN
59
+
55
60
  def on_array(node)
56
61
  add_offense(node) if node.children.length >= collection_threshold
57
62
  end
58
63
  alias on_hash on_array
59
64
 
60
65
  def on_index(node)
66
+ return unless set_const?(node.receiver)
67
+
61
68
  add_offense(node) if node.arguments.length >= collection_threshold
62
69
  end
63
70
 
@@ -36,7 +36,7 @@ module RuboCop
36
36
  include MethodComplexity
37
37
  include Utils::IteratingBlock
38
38
 
39
- MSG = 'Cyclomatic complexity for %<method>s is too high. [%<complexity>d/%<max>d]'
39
+ MSG = 'Cyclomatic complexity for `%<method>s` is too high. [%<complexity>d/%<max>d]'
40
40
  COUNTED_NODES = %i[if while until for csend block block_pass
41
41
  rescue when in_pattern and or or_asgn and_asgn].freeze
42
42
 
@@ -27,7 +27,7 @@ module RuboCop
27
27
  # end # ===
28
28
  # end # 7 complexity points
29
29
  class PerceivedComplexity < CyclomaticComplexity
30
- MSG = 'Perceived complexity for %<method>s is too high. [%<complexity>d/%<max>d]'
30
+ MSG = 'Perceived complexity for `%<method>s` is too high. [%<complexity>d/%<max>d]'
31
31
 
32
32
  COUNTED_NODES = (CyclomaticComplexity::COUNTED_NODES - [:when] + [:case]).freeze
33
33
 
@@ -6,7 +6,7 @@ module RuboCop
6
6
  module FrozenStringLiteral
7
7
  module_function
8
8
 
9
- FROZEN_STRING_LITERAL = '# frozen_string_literal:'
9
+ FROZEN_STRING_LITERAL_REGEXP = /#\s*frozen[-_]?string[-_]?literal:/i.freeze
10
10
  FROZEN_STRING_LITERAL_ENABLED = '# frozen_string_literal: true'
11
11
  FROZEN_STRING_LITERAL_TYPES_RUBY27 = %i[str dstr].freeze
12
12
 
@@ -0,0 +1,170 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Common functionality for Style/HashExcept and Style/HashSlice cops.
6
+ # It registers an offense on methods with blocks that are equivalent
7
+ # to Hash#except or Hash#slice.
8
+ module HashSubset
9
+ include RangeHelp
10
+ extend NodePattern::Macros
11
+
12
+ RESTRICT_ON_SEND = %i[reject select filter].freeze
13
+
14
+ SUBSET_METHODS = %i[== != eql? include?].freeze
15
+ ACTIVE_SUPPORT_SUBSET_METHODS = (SUBSET_METHODS + %i[in? exclude?]).freeze
16
+
17
+ MSG = 'Use `%<prefer>s` instead.'
18
+
19
+ # @!method block_with_first_arg_check?(node)
20
+ def_node_matcher :block_with_first_arg_check?, <<~PATTERN
21
+ (block
22
+ (call _ _)
23
+ (args
24
+ $(arg _key)
25
+ (arg _))
26
+ {
27
+ $(send
28
+ {(lvar _key) $_ _ | _ $_ (lvar _key)})
29
+ (send
30
+ $(send
31
+ {(lvar _key) $_ _ | _ $_ (lvar _key)}) :!)
32
+ })
33
+ PATTERN
34
+
35
+ def on_send(node)
36
+ offense_range, key_source = extract_offense(node)
37
+
38
+ return unless offense_range
39
+ return unless semantically_subset_method?(node)
40
+
41
+ preferred_method = "#{preferred_method_name}(#{key_source})"
42
+ add_offense(offense_range, message: format(MSG, prefer: preferred_method)) do |corrector|
43
+ corrector.replace(offense_range, preferred_method)
44
+ end
45
+ end
46
+ alias on_csend on_send
47
+
48
+ private
49
+
50
+ def semantically_subset_method?(node)
51
+ raise NotImplementedError
52
+ end
53
+
54
+ def preferred_method_name
55
+ raise NotImplementedError
56
+ end
57
+
58
+ def extract_offense(node)
59
+ block = node.parent
60
+ return unless extracts_hash_subset?(block)
61
+
62
+ except_key = except_key(block)
63
+ return if except_key.nil? || !safe_to_register_offense?(block, except_key)
64
+
65
+ [offense_range(node), except_key_source(except_key)]
66
+ end
67
+
68
+ def extracts_hash_subset?(block)
69
+ block_with_first_arg_check?(block) do |key_arg, send_node, method|
70
+ return false unless supported_subset_method?(method)
71
+
72
+ case method
73
+ when :include?, :exclude?
74
+ send_node.first_argument.source == key_arg.source
75
+ when :in?
76
+ send_node.receiver.source == key_arg.source
77
+ else
78
+ true
79
+ end
80
+ end
81
+ end
82
+
83
+ def supported_subset_method?(method)
84
+ if active_support_extensions_enabled?
85
+ ACTIVE_SUPPORT_SUBSET_METHODS.include?(method)
86
+ else
87
+ SUBSET_METHODS.include?(method)
88
+ end
89
+ end
90
+
91
+ def semantically_except_method?(node)
92
+ block = node.parent
93
+ body, negated = extract_body_if_negated(block.body)
94
+
95
+ if node.method?('reject')
96
+ body.method?('==') || body.method?('eql?') || included?(body, negated)
97
+ else
98
+ body.method?('!=') || not_included?(body, negated)
99
+ end
100
+ end
101
+
102
+ def semantically_slice_method?(node)
103
+ !semantically_except_method?(node)
104
+ end
105
+
106
+ def included?(body, negated)
107
+ if negated
108
+ body.method?('exclude?')
109
+ else
110
+ body.method?('include?') || body.method?('in?')
111
+ end
112
+ end
113
+
114
+ def not_included?(body, negated)
115
+ included?(body, !negated)
116
+ end
117
+
118
+ def safe_to_register_offense?(block, except_key)
119
+ body = block.body
120
+
121
+ if body.method?('==') || body.method?('!=')
122
+ except_key.sym_type? || except_key.str_type?
123
+ else
124
+ true
125
+ end
126
+ end
127
+
128
+ def extract_body_if_negated(body)
129
+ if body.method?('!')
130
+ [body.receiver, true]
131
+ else
132
+ [body, false]
133
+ end
134
+ end
135
+
136
+ def except_key_source(key)
137
+ if key.array_type?
138
+ key = if key.percent_literal?
139
+ key.each_value.map { |v| decorate_source(v) }
140
+ else
141
+ key.each_value.map(&:source)
142
+ end
143
+ return key.join(', ')
144
+ end
145
+
146
+ key.literal? ? key.source : "*#{key.source}"
147
+ end
148
+
149
+ def decorate_source(value)
150
+ return ":\"#{value.source}\"" if value.dsym_type?
151
+ return "\"#{value.source}\"" if value.dstr_type?
152
+ return ":#{value.source}" if value.sym_type?
153
+
154
+ "'#{value.source}'"
155
+ end
156
+
157
+ def except_key(node)
158
+ key_arg = node.argument_list.first.source
159
+ body, = extract_body_if_negated(node.body)
160
+ lhs, _method_name, rhs = *body
161
+
162
+ lhs.source == key_arg ? rhs : lhs
163
+ end
164
+
165
+ def offense_range(node)
166
+ range_between(node.loc.selector.begin_pos, node.parent.loc.end.end_pos)
167
+ end
168
+ end
169
+ end
170
+ end
@@ -55,14 +55,19 @@ module RuboCop
55
55
  end
56
56
 
57
57
  def if_body_source(if_body)
58
- if if_body.call_type? &&
59
- if_body.last_argument&.hash_type? && if_body.last_argument.pairs.last&.value_omission?
58
+ if if_body.call_type? && !if_body.method?(:[]=) && omitted_value_in_last_hash_arg?(if_body)
60
59
  "#{method_source(if_body)}(#{if_body.arguments.map(&:source).join(', ')})"
61
60
  else
62
61
  if_body.source
63
62
  end
64
63
  end
65
64
 
65
+ def omitted_value_in_last_hash_arg?(if_body)
66
+ return false unless (last_argument = if_body.last_argument)
67
+
68
+ last_argument.hash_type? && last_argument.pairs.last&.value_omission?
69
+ end
70
+
66
71
  def method_source(if_body)
67
72
  end_range = if_body.implicit_call? ? if_body.loc.dot.end : if_body.loc.selector
68
73
 
@@ -2,8 +2,8 @@
2
2
 
3
3
  module RuboCop
4
4
  module Cop
5
- # Common methods shared by Style/TrailingCommaInArguments and
6
- # Style/TrailingCommaInLiteral
5
+ # Common methods shared by Style/TrailingCommaInArguments,
6
+ # Style/TrailingCommaInArrayLiteral and Style/TrailingCommaInHashLiteral
7
7
  module TrailingComma
8
8
  include ConfigurableEnforcedStyle
9
9
  include RangeHelp
@@ -100,6 +100,7 @@ module RuboCop
100
100
  add_offense(node, message: REDUNDANT_HASH_MSG)
101
101
  end
102
102
  end
103
+ alias on_csend on_send
103
104
  alias on_op_asgn on_send
104
105
  end
105
106
  end
@@ -42,14 +42,30 @@ module RuboCop
42
42
  return if node.parent && brace_method?(node.parent)
43
43
 
44
44
  preferred = (value.zero? ? 'first' : 'last')
45
- add_offense(node.loc.selector, message: format(MSG, preferred: preferred)) do |corrector|
46
- corrector.replace(node.loc.selector, ".#{preferred}")
45
+ offense_range = find_offense_range(node)
46
+
47
+ add_offense(offense_range, message: format(MSG, preferred: preferred)) do |corrector|
48
+ corrector.replace(offense_range, preferred_value(node, preferred))
47
49
  end
48
50
  end
49
51
  # rubocop:enable Metrics/AbcSize
52
+ alias on_csend on_send
50
53
 
51
54
  private
52
55
 
56
+ def preferred_value(node, value)
57
+ value = ".#{value}" unless node.loc.dot
58
+ value
59
+ end
60
+
61
+ def find_offense_range(node)
62
+ if node.loc.dot
63
+ node.loc.selector.join(node.source_range.end)
64
+ else
65
+ node.loc.selector
66
+ end
67
+ end
68
+
53
69
  def innermost_braces_node(node)
54
70
  node = node.receiver while node.receiver.send_type? && node.receiver.method?(:[])
55
71
  node
@@ -195,6 +195,7 @@ module RuboCop
195
195
  end
196
196
  end
197
197
  end
198
+ alias on_csend on_send
198
199
 
199
200
  def on_block(node)
200
201
  return if ignored_node?(node)
@@ -348,7 +349,7 @@ module RuboCop
348
349
  case node.type
349
350
  when :block, :numblock
350
351
  yield node
351
- when :send
352
+ when :send, :csend
352
353
  # When a method has an argument which is another method with a block,
353
354
  # that block needs braces, otherwise a syntax error will be introduced
354
355
  # for subsequent arguments.
@@ -369,9 +370,8 @@ module RuboCop
369
370
  end
370
371
  # rubocop:enable Metrics/CyclomaticComplexity
371
372
 
372
- # rubocop:disable Metrics/CyclomaticComplexity
373
373
  def proper_block_style?(node)
374
- return true if require_braces?(node) || require_do_end?(node)
374
+ return true if require_do_end?(node)
375
375
  return special_method_proper_block_style?(node) if special_method?(node.method_name)
376
376
 
377
377
  case style
@@ -381,15 +381,6 @@ module RuboCop
381
381
  when :always_braces then braces_style?(node)
382
382
  end
383
383
  end
384
- # rubocop:enable Metrics/CyclomaticComplexity
385
-
386
- def require_braces?(node)
387
- return false unless node.braces?
388
-
389
- node.each_ancestor(:send).any? do |send|
390
- send.arithmetic_operation? && node.source_range.end_pos < send.loc.selector.begin_pos
391
- end
392
- end
393
384
 
394
385
  def require_do_end?(node)
395
386
  return false if node.braces? || node.multiline?
@@ -483,14 +474,10 @@ module RuboCop
483
474
  end
484
475
 
485
476
  def return_value_of_scope?(node)
486
- return false unless node.parent
487
-
488
- conditional?(node.parent) || array_or_range?(node.parent) ||
489
- node.parent.children.last == node
490
- end
477
+ return false unless (parent = node.parent)
491
478
 
492
- def conditional?(node)
493
- node.if_type? || node.operator_keyword?
479
+ parent.conditional? || parent.operator_keyword? || array_or_range?(parent) ||
480
+ parent.children.last == node
494
481
  end
495
482
 
496
483
  def array_or_range?(node)
@@ -49,7 +49,6 @@ module RuboCop
49
49
  def on_block(node)
50
50
  check_method_node(node.send_node)
51
51
  end
52
-
53
52
  alias on_numblock on_block
54
53
 
55
54
  def on_send(node)
@@ -57,6 +56,7 @@ module RuboCop
57
56
 
58
57
  check_method_node(node)
59
58
  end
59
+ alias on_csend on_send
60
60
 
61
61
  private
62
62
 
@@ -309,7 +309,7 @@ module RuboCop
309
309
  end
310
310
 
311
311
  def allowed_single_line?(branches)
312
- single_line_conditions_only? && branches.any?(&:begin_type?)
312
+ single_line_conditions_only? && branches.compact.any?(&:begin_type?)
313
313
  end
314
314
 
315
315
  def assignment_node(node)
@@ -445,6 +445,8 @@ module RuboCop
445
445
  end
446
446
 
447
447
  [condition.loc.else, condition.loc.end].each do |loc|
448
+ next unless loc
449
+
448
450
  corrector.remove_preceding(loc, loc.column - column)
449
451
  end
450
452
  end
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # Checks for loops which iterate a constant number of times,
7
- # using a Range literal and `#each`. This can be done more readably using
7
+ # using a `Range` literal and `#each`. This can be done more readably using
8
8
  # `Integer#times`.
9
9
  #
10
10
  # This check only applies if the block takes no parameters.
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for exact regexp match inside Regexp literals.
6
+ # Checks for exact regexp match inside `Regexp` literals.
7
7
  #
8
8
  # @example
9
9
  #
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # Suggests `ENV.fetch` for the replacement of `ENV[]`.
7
7
  # `ENV[]` silently fails and returns `nil` when the environment variable is unset,
8
8
  # which may cause unexpected behaviors when the developer forgets to set it.
9
- # On the other hand, `ENV.fetch` raises KeyError or returns the explicitly
9
+ # On the other hand, `ENV.fetch` raises `KeyError` or returns the explicitly
10
10
  # specified default value.
11
11
  #
12
12
  # @example
@@ -151,7 +151,7 @@ module RuboCop
151
151
 
152
152
  def frozen_string_literal_comment(processed_source)
153
153
  processed_source.tokens.find do |token|
154
- token.text.start_with?(FROZEN_STRING_LITERAL)
154
+ token.text.start_with?(FROZEN_STRING_LITERAL_REGEXP)
155
155
  end
156
156
  end
157
157
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for uses of `each_key` and `each_value` Hash methods.
6
+ # Checks for uses of `each_key` and `each_value` `Hash` methods.
7
7
  #
8
8
  # NOTE: If you have an array of two-element arrays, you can put
9
9
  # parentheses around the block arguments to indicate that you're not