rubocop 1.30.0 → 1.31.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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -2
  3. data/config/default.yml +41 -8
  4. data/config/obsoletion.yml +2 -0
  5. data/exe/rubocop +15 -7
  6. data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
  7. data/lib/rubocop/cli/command/suggest_extensions.rb +3 -3
  8. data/lib/rubocop/config.rb +4 -0
  9. data/lib/rubocop/config_loader.rb +1 -0
  10. data/lib/rubocop/config_validator.rb +9 -5
  11. data/lib/rubocop/cop/base.rb +4 -0
  12. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  13. data/lib/rubocop/cop/bundler/gem_filename.rb +4 -4
  14. data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -2
  15. data/lib/rubocop/cop/corrector.rb +2 -2
  16. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +3 -3
  17. data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +1 -1
  18. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +31 -16
  19. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -1
  20. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  21. data/lib/rubocop/cop/gemspec/require_mfa.rb +20 -20
  22. data/lib/rubocop/cop/generator.rb +1 -1
  23. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -5
  24. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  25. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
  26. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  27. data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
  28. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +25 -4
  29. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +4 -4
  30. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +9 -9
  31. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +9 -9
  32. data/lib/rubocop/cop/layout/first_argument_indentation.rb +27 -27
  33. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +17 -11
  34. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +49 -10
  35. data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
  36. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +68 -0
  37. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +120 -0
  38. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
  39. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
  40. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -2
  41. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  42. data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
  43. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -1
  44. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
  45. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +10 -10
  46. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -3
  47. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +7 -7
  48. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  49. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +51 -0
  50. data/lib/rubocop/cop/lint/interpolation_check.rb +1 -1
  51. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +121 -0
  52. data/lib/rubocop/cop/lint/number_conversion.rb +3 -3
  53. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  54. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +5 -5
  55. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  56. data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -1
  57. data/lib/rubocop/cop/lint/regexp_as_condition.rb +2 -2
  58. data/lib/rubocop/cop/lint/struct_new_override.rb +2 -2
  59. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
  60. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +44 -0
  61. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  62. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +36 -12
  63. data/lib/rubocop/cop/mixin/range_help.rb +7 -3
  64. data/lib/rubocop/cop/naming/accessor_method_name.rb +3 -1
  65. data/lib/rubocop/cop/naming/variable_number.rb +17 -17
  66. data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
  67. data/lib/rubocop/cop/style/and_or.rb +8 -8
  68. data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -1
  69. data/lib/rubocop/cop/style/block_delimiters.rb +4 -2
  70. data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
  71. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -0
  72. data/lib/rubocop/cop/style/empty_else.rb +10 -10
  73. data/lib/rubocop/cop/style/empty_method.rb +16 -1
  74. data/lib/rubocop/cop/style/encoding.rb +1 -1
  75. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  76. data/lib/rubocop/cop/style/fetch_env_var.rb +9 -2
  77. data/lib/rubocop/cop/style/format_string_token.rb +48 -17
  78. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  79. data/lib/rubocop/cop/style/guard_clause.rb +8 -6
  80. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -1
  81. data/lib/rubocop/cop/style/hash_except.rb +88 -8
  82. data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
  83. data/lib/rubocop/cop/style/implicit_runtime_error.rb +2 -2
  84. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  85. data/lib/rubocop/cop/style/line_end_concatenation.rb +1 -1
  86. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  87. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
  88. data/lib/rubocop/cop/style/missing_else.rb +24 -24
  89. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -2
  90. data/lib/rubocop/cop/style/multiline_if_then.rb +1 -1
  91. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -3
  92. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
  93. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
  94. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -3
  95. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  96. data/lib/rubocop/cop/style/nested_ternary_operator.rb +19 -7
  97. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  98. data/lib/rubocop/cop/style/not.rb +1 -1
  99. data/lib/rubocop/cop/style/redundant_argument.rb +1 -1
  100. data/lib/rubocop/cop/style/redundant_return.rb +1 -1
  101. data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
  102. data/lib/rubocop/cop/style/rescue_standard_error.rb +10 -10
  103. data/lib/rubocop/cop/style/safe_navigation.rb +3 -0
  104. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
  105. data/lib/rubocop/cop/style/string_concatenation.rb +5 -6
  106. data/lib/rubocop/cop/style/struct_inheritance.rb +2 -2
  107. data/lib/rubocop/cop/style/swap_values.rb +1 -1
  108. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  109. data/lib/rubocop/cop/style/unpack_first.rb +1 -1
  110. data/lib/rubocop/cop/util.rb +1 -1
  111. data/lib/rubocop/cops_documentation_generator.rb +18 -1
  112. data/lib/rubocop/formatter/disabled_config_formatter.rb +8 -5
  113. data/lib/rubocop/formatter/formatter_set.rb +20 -19
  114. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +15 -2
  115. data/lib/rubocop/formatter/html_formatter.rb +0 -1
  116. data/lib/rubocop/formatter/offense_count_formatter.rb +2 -0
  117. data/lib/rubocop/formatter/simple_text_formatter.rb +6 -9
  118. data/lib/rubocop/formatter.rb +31 -0
  119. data/lib/rubocop/options.rb +25 -2
  120. data/lib/rubocop/rake_task.rb +30 -9
  121. data/lib/rubocop/runner.rb +2 -2
  122. data/lib/rubocop/server/cache.rb +109 -0
  123. data/lib/rubocop/server/cli.rb +104 -0
  124. data/lib/rubocop/server/client_command/base.rb +44 -0
  125. data/lib/rubocop/server/client_command/exec.rb +59 -0
  126. data/lib/rubocop/server/client_command/restart.rb +25 -0
  127. data/lib/rubocop/server/client_command/start.rb +43 -0
  128. data/lib/rubocop/server/client_command/status.rb +28 -0
  129. data/lib/rubocop/server/client_command/stop.rb +31 -0
  130. data/lib/rubocop/server/client_command.rb +26 -0
  131. data/lib/rubocop/server/core.rb +79 -0
  132. data/lib/rubocop/server/errors.rb +23 -0
  133. data/lib/rubocop/server/helper.rb +34 -0
  134. data/lib/rubocop/server/server_command/base.rb +50 -0
  135. data/lib/rubocop/server/server_command/exec.rb +34 -0
  136. data/lib/rubocop/server/server_command/stop.rb +24 -0
  137. data/lib/rubocop/server/server_command.rb +21 -0
  138. data/lib/rubocop/server/socket_reader.rb +65 -0
  139. data/lib/rubocop/server.rb +53 -0
  140. data/lib/rubocop/version.rb +15 -8
  141. data/lib/rubocop.rb +7 -26
  142. metadata +27 -4
  143. data/lib/rubocop/cop/gemspec/date_assignment.rb +0 -49
@@ -98,6 +98,8 @@ module RuboCop
98
98
  check_inside(node, left_brace, right_brace)
99
99
  end
100
100
 
101
+ alias on_numblock on_block
102
+
101
103
  private
102
104
 
103
105
  def check_inside(node, left_brace, right_brace)
@@ -126,7 +128,7 @@ module RuboCop
126
128
  end
127
129
 
128
130
  def braces_with_contents_inside(node, inner)
129
- args_delimiter = node.arguments.loc.begin # Can be ( | or nil.
131
+ args_delimiter = node.arguments.loc.begin if node.block_type? # Can be ( | or nil.
130
132
 
131
133
  check_left_brace(inner, node.loc.begin, args_delimiter)
132
134
  check_right_brace(inner, node.loc.begin, node.loc.end, node.single_line?)
@@ -185,7 +187,7 @@ module RuboCop
185
187
  'Space between { and | detected.')
186
188
  end
187
189
  else
188
- brace_with_space = range_with_surrounding_space(range: left_brace, side: :right)
190
+ brace_with_space = range_with_surrounding_space(left_brace, side: :right)
189
191
  space(brace_with_space.begin_pos + 1, brace_with_space.end_pos,
190
192
  'Space inside { detected.')
191
193
  end
@@ -196,7 +198,7 @@ module RuboCop
196
198
  end
197
199
 
198
200
  def space_inside_right_brace(right_brace)
199
- brace_with_space = range_with_surrounding_space(range: right_brace, side: :left)
201
+ brace_with_space = range_with_surrounding_space(right_brace, side: :left)
200
202
  space(brace_with_space.begin_pos, brace_with_space.end_pos - 1,
201
203
  'Space inside } detected.')
202
204
  end
@@ -6,12 +6,12 @@ module RuboCop
6
6
  # Looks for trailing blank lines and a final newline in the
7
7
  # source code.
8
8
  #
9
- # @example EnforcedStyle: final_blank_line
10
- # # `final_blank_line` looks for one blank line followed by a new line
11
- # # at the end of files.
9
+ # @example EnforcedStyle: final_newline (default)
10
+ # # `final_newline` looks for one newline at the end of files.
12
11
  #
13
12
  # # bad
14
13
  # class Foo; end
14
+ #
15
15
  # # EOF
16
16
  #
17
17
  # # bad
@@ -19,15 +19,14 @@ module RuboCop
19
19
  #
20
20
  # # good
21
21
  # class Foo; end
22
- #
23
22
  # # EOF
24
23
  #
25
- # @example EnforcedStyle: final_newline (default)
26
- # # `final_newline` looks for one newline at the end of files.
24
+ # @example EnforcedStyle: final_blank_line
25
+ # # `final_blank_line` looks for one blank line followed by a new line
26
+ # # at the end of files.
27
27
  #
28
28
  # # bad
29
29
  # class Foo; end
30
- #
31
30
  # # EOF
32
31
  #
33
32
  # # bad
@@ -35,6 +34,7 @@ module RuboCop
35
34
  #
36
35
  # # good
37
36
  # class Foo; end
37
+ #
38
38
  # # EOF
39
39
  #
40
40
  class TrailingEmptyLines < Base
@@ -89,7 +89,7 @@ module RuboCop
89
89
  end
90
90
 
91
91
  def whitespace_only?(range)
92
- source = range_with_surrounding_space(range: range).source
92
+ source = range_with_surrounding_space(range).source
93
93
  source.start_with?("\n") && source.end_with?("\n")
94
94
  end
95
95
 
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for overwriting an exception with an exception result by use `rescue =>`.
7
+ #
8
+ # You intended to write as `rescue StandardError`.
9
+ # However, you have written `rescue => StandardError`.
10
+ # In that case, the result of `rescue` will overwrite `StandardError`.
11
+ #
12
+ # @example
13
+ #
14
+ # # bad
15
+ # begin
16
+ # something
17
+ # rescue => StandardError
18
+ # end
19
+ #
20
+ # # good
21
+ # begin
22
+ # something
23
+ # rescue StandardError
24
+ # end
25
+ #
26
+ class ConstantOverwrittenInRescue < Base
27
+ extend AutoCorrector
28
+ include RangeHelp
29
+
30
+ MSG = '`%<constant>s` is overwritten by `rescue =>`.'
31
+
32
+ # @!method overwritten_constant(node)
33
+ def_node_matcher :overwritten_constant, <<~PATTERN
34
+ (resbody nil? (casgn nil? $_) nil?)
35
+ PATTERN
36
+
37
+ def self.autocorrect_incompatible_with
38
+ [Naming::RescuedExceptionsVariableName, Style::RescueStandardError]
39
+ end
40
+
41
+ def on_resbody(node)
42
+ return unless (constant = overwritten_constant(node))
43
+
44
+ add_offense(node.loc.assoc, message: format(MSG, constant: constant)) do |corrector|
45
+ corrector.remove(range_between(node.loc.keyword.end_pos, node.loc.assoc.end_pos))
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -24,7 +24,7 @@ module RuboCop
24
24
  class InterpolationCheck < Base
25
25
  extend AutoCorrector
26
26
 
27
- MSG = 'Interpolation in single quoted string detected. '\
27
+ MSG = 'Interpolation in single quoted string detected. ' \
28
28
  'Use double quoted strings if you need interpolation.'
29
29
 
30
30
  def on_str(node)
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for non-atomic file operation.
7
+ # And then replace it with a nearly equivalent and atomic method.
8
+ #
9
+ # These can cause problems that are difficult to reproduce,
10
+ # especially in cases of frequent file operations in parallel,
11
+ # such as test runs with parallel_rspec.
12
+ #
13
+ # For examples: creating a directory if there is none, has the following problems
14
+ #
15
+ # An exception occurs when the directory didn't exist at the time of `exist?`,
16
+ # but someone else created it before `mkdir` was executed.
17
+ #
18
+ # Subsequent processes are executed without the directory that should be there
19
+ # when the directory existed at the time of `exist?`,
20
+ # but someone else deleted it shortly afterwards.
21
+ #
22
+ # @safety
23
+ # This cop is unsafe, because autocorrection change to atomic processing.
24
+ # The atomic processing of the replacement destination is not guaranteed
25
+ # to be strictly equivalent to that before the replacement.
26
+ #
27
+ # @example
28
+ # # bad
29
+ # unless FileTest.exist?(path)
30
+ # FileUtils.makedirs(path)
31
+ # end
32
+ #
33
+ # if FileTest.exist?(path)
34
+ # FileUtils.remove(path)
35
+ # end
36
+ #
37
+ # # good
38
+ # FileUtils.mkdir_p(path)
39
+ #
40
+ # FileUtils.rm_rf(path)
41
+ #
42
+ class NonAtomicFileOperation < Base
43
+ extend AutoCorrector
44
+ include Alignment
45
+ include RangeHelp
46
+
47
+ MSG = 'Remove unnecessary existence checks `%<receiver>s.%<method_name>s`.'
48
+ MAKE_METHODS = %i[makedirs mkdir mkdir_p mkpath].freeze
49
+ REMOVE_METHODS = %i[remove remove_dir remove_entry remove_entry_secure delete unlink
50
+ remove_file rm rm_f rm_r rm_rf rmdir rmtree safe_unlink].freeze
51
+ RESTRICT_ON_SEND = (MAKE_METHODS + REMOVE_METHODS).freeze
52
+
53
+ # @!method send_exist_node(node)
54
+ def_node_search :send_exist_node, <<-PATTERN
55
+ $(send (const nil? {:FileTest :File :Dir :Shell}) {:exist? :exists?} ...)
56
+ PATTERN
57
+
58
+ # @!method receiver_and_method_name(node)
59
+ def_node_matcher :receiver_and_method_name, <<-PATTERN
60
+ (send (const nil? $_) $_ ...)
61
+ PATTERN
62
+
63
+ # @!method force?(node)
64
+ def_node_search :force?, <<~PATTERN
65
+ (pair (sym :force) (:true))
66
+ PATTERN
67
+
68
+ # @!method explicit_not_force?(node)
69
+ def_node_search :explicit_not_force?, <<~PATTERN
70
+ (pair (sym :force) (:false))
71
+ PATTERN
72
+
73
+ def on_send(node)
74
+ return unless node.parent&.if_type?
75
+ return if explicit_not_force?(node)
76
+ return unless (exist_node = send_exist_node(node.parent).first)
77
+ return unless exist_node.first_argument == node.first_argument
78
+
79
+ offense(node, exist_node)
80
+ end
81
+
82
+ private
83
+
84
+ def offense(node, exist_node)
85
+ range = range_between(node.parent.loc.keyword.begin_pos,
86
+ exist_node.loc.expression.end_pos)
87
+
88
+ add_offense(range, message: message(exist_node)) do |corrector|
89
+ autocorrect(corrector, node, range)
90
+ end
91
+ end
92
+
93
+ def message(node)
94
+ receiver, method_name = receiver_and_method_name(node)
95
+ format(MSG, receiver: receiver, method_name: method_name)
96
+ end
97
+
98
+ def autocorrect(corrector, node, range)
99
+ corrector.remove(range)
100
+ corrector.replace(node.child_nodes.first.loc.name, 'FileUtils')
101
+ corrector.replace(node.loc.selector, replacement_method(node))
102
+ corrector.remove(node.parent.loc.end) if node.parent.multiline?
103
+ end
104
+
105
+ def replacement_method(node)
106
+ return node.method_name if force_option?(node)
107
+
108
+ if MAKE_METHODS.include?(node.method_name)
109
+ 'mkdir_p'
110
+ elsif REMOVE_METHODS.include?(node.method_name)
111
+ 'rm_rf'
112
+ end
113
+ end
114
+
115
+ def force_option?(node)
116
+ node.arguments.any? { |arg| force?(arg) }
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -64,9 +64,9 @@ module RuboCop
64
64
  to_c: "#{Complex.name}(%<number_object>s)",
65
65
  to_r: "#{Rational.name}(%<number_object>s)"
66
66
  }.freeze
67
- MSG = 'Replace unsafe number conversion with number '\
68
- 'class parsing, instead of using '\
69
- '`%<current>s`, use stricter '\
67
+ MSG = 'Replace unsafe number conversion with number ' \
68
+ 'class parsing, instead of using ' \
69
+ '`%<current>s`, use stricter ' \
70
70
  '`%<corrected_method>s`.'
71
71
  CONVERSION_METHODS = %i[Integer Float Complex Rational to_i to_f to_c to_r].freeze
72
72
  METHODS = CONVERSION_METHOD_CLASS_MAPPING.keys.map(&:inspect).join(' ')
@@ -55,7 +55,7 @@ module RuboCop
55
55
 
56
56
  def chained_calls?(node)
57
57
  first_argument = node.first_argument
58
- first_argument.send_type? && (node.children.last&.children&.count || 0) > 1
58
+ first_argument.call_type? && (node.children.last&.children&.count || 0) > 1
59
59
  end
60
60
 
61
61
  def ternary_expression?(node)
@@ -71,16 +71,16 @@ module RuboCop
71
71
  processed_source.comment_config.comment_only_line?(directive_comment_range.line) &&
72
72
  directive_comment_range.begin_pos == line_comment_range.begin_pos
73
73
  # When the previous line is blank, it should be retained
74
- range_with_surrounding_space(range: directive_comment_range, side: :right)
74
+ range_with_surrounding_space(directive_comment_range, side: :right)
75
75
  else
76
76
  # Eat the entire comment, the preceding space, and the preceding
77
77
  # newline if there is one.
78
78
  original_begin = directive_comment_range.begin_pos
79
79
  range = range_with_surrounding_space(
80
- range: directive_comment_range, side: :left, newlines: true
80
+ directive_comment_range, side: :left, newlines: true
81
81
  )
82
82
 
83
- range_with_surrounding_space(range: range,
83
+ range_with_surrounding_space(range,
84
84
  side: :right,
85
85
  # Special for a comment that
86
86
  # begins the file: remove
@@ -94,13 +94,13 @@ module RuboCop
94
94
  # is NOT being removed?
95
95
  if ends_its_line?(ranges.last) && trailing_range?(ranges, range)
96
96
  # Eat the comma on the left.
97
- range = range_with_surrounding_space(range: range, side: :left)
97
+ range = range_with_surrounding_space(range, side: :left)
98
98
  range = range_with_surrounding_comma(range, :left)
99
99
  end
100
100
 
101
101
  range = range_with_surrounding_comma(range, :right)
102
102
  # Eat following spaces up to EOL, but not the newline itself.
103
- range_with_surrounding_space(range: range, side: :right, newlines: false)
103
+ range_with_surrounding_space(range, side: :right, newlines: false)
104
104
  end
105
105
 
106
106
  def each_redundant_disable(&block)
@@ -60,7 +60,7 @@ module RuboCop
60
60
  message: format(MSG, cop: all_or_name(name))
61
61
  ) do |corrector|
62
62
  if directive.match?(cop_names)
63
- corrector.remove(range_with_surrounding_space(range: directive.range, side: :right))
63
+ corrector.remove(range_with_surrounding_space(directive.range, side: :right))
64
64
  else
65
65
  corrector.remove(range_with_comma(comment, name))
66
66
  end
@@ -41,7 +41,7 @@ module RuboCop
41
41
  return unless unnecessary_require_statement?(node)
42
42
 
43
43
  add_offense(node) do |corrector|
44
- range = range_with_surrounding_space(range: node.loc.expression, side: :right)
44
+ range = range_with_surrounding_space(node.loc.expression, side: :right)
45
45
 
46
46
  corrector.remove(range)
47
47
  end
@@ -19,8 +19,8 @@ module RuboCop
19
19
  class RegexpAsCondition < Base
20
20
  extend AutoCorrector
21
21
 
22
- MSG = 'Do not use regexp literal as a condition.' \
23
- ' The regexp literal matches `$_` implicitly.'
22
+ MSG = 'Do not use regexp literal as a condition. ' \
23
+ 'The regexp literal matches `$_` implicitly.'
24
24
 
25
25
  def on_match_current_line(node)
26
26
  add_offense(node) { |corrector| corrector.replace(node, "#{node.source} =~ $_") }
@@ -22,8 +22,8 @@ module RuboCop
22
22
  # g.count #=> 2
23
23
  #
24
24
  class StructNewOverride < Base
25
- MSG = '`%<member_name>s` member overrides `Struct#%<method_name>s`' \
26
- ' and it may be unexpected.'
25
+ MSG = '`%<member_name>s` member overrides `Struct#%<method_name>s` ' \
26
+ 'and it may be unexpected.'
27
27
  RESTRICT_ON_SEND = %i[new].freeze
28
28
 
29
29
  STRUCT_METHOD_NAMES = Struct.instance_methods
@@ -45,7 +45,7 @@ module RuboCop
45
45
 
46
46
  def trailing_comma_range(node)
47
47
  range_with_surrounding_space(
48
- range: node.arguments[-2].source_range,
48
+ node.arguments[-2].source_range,
49
49
  side: :right
50
50
  ).end.resize(1)
51
51
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for useless `else` in `begin..end` without `rescue`.
7
+ #
8
+ # NOTE: This syntax is no longer valid on Ruby 2.6 or higher.
9
+ #
10
+ # @example
11
+ #
12
+ # # bad
13
+ #
14
+ # begin
15
+ # do_something
16
+ # else
17
+ # do_something_else # This will never be run.
18
+ # end
19
+ #
20
+ # @example
21
+ #
22
+ # # good
23
+ #
24
+ # begin
25
+ # do_something
26
+ # rescue
27
+ # handle_errors
28
+ # else
29
+ # do_something_else
30
+ # end
31
+ class UselessElseWithoutRescue < Base
32
+ MSG = '`else` without `rescue` is useless.'
33
+
34
+ def on_new_investigation
35
+ processed_source.diagnostics.each do |diagnostic|
36
+ next unless diagnostic.reason == :useless_else
37
+
38
+ add_offense(diagnostic.location, severity: diagnostic.level)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -49,7 +49,7 @@ module RuboCop
49
49
  when :heredoc
50
50
  ->(node) { heredoc_node?(node) }
51
51
  else
52
- raise ArgumentError, "Unknown foldable type: #{type.inspect}. "\
52
+ raise ArgumentError, "Unknown foldable type: #{type.inspect}. " \
53
53
  "Valid foldable types are: #{FOLDABLE_TYPES.join(', ')}."
54
54
  end
55
55
  end
@@ -25,15 +25,17 @@ module RuboCop
25
25
 
26
26
  def check_first(first, left_brace, left_parenthesis, offset)
27
27
  actual_column = first.source_range.column
28
- expected_column = base_column(left_brace, left_parenthesis) +
29
- configured_indentation_width + offset
28
+
29
+ indent_base_column, indent_base_type = indent_base(left_brace, left_parenthesis)
30
+ expected_column = indent_base_column + configured_indentation_width + offset
31
+
30
32
  @column_delta = expected_column - actual_column
31
33
  styles = detected_styles(actual_column, offset, left_parenthesis, left_brace)
32
34
 
33
35
  if @column_delta.zero?
34
36
  check_expected_style(styles)
35
37
  else
36
- incorrect_style_detected(styles, first, left_parenthesis)
38
+ incorrect_style_detected(styles, first, indent_base_type)
37
39
  end
38
40
  end
39
41
 
@@ -45,14 +47,36 @@ module RuboCop
45
47
  end
46
48
  end
47
49
 
48
- def base_column(left_brace, left_parenthesis)
49
- if style == brace_alignment_style
50
- left_brace.column
51
- elsif left_parenthesis && style == :special_inside_parentheses
52
- left_parenthesis.column + 1
53
- else
54
- left_brace.source_line =~ /\S/
50
+ def indent_base(left_brace, left_parenthesis)
51
+ return [left_brace.column, :left_brace_or_bracket] if style == brace_alignment_style
52
+
53
+ pair = hash_pair_where_value_beginning_with(left_brace)
54
+ if pair && key_and_value_begin_on_same_line?(pair) && pair.right_sibling
55
+ return [pair.loc.column, :parent_hash_key]
55
56
  end
57
+
58
+ if left_parenthesis && style == :special_inside_parentheses
59
+ return [left_parenthesis.column + 1, :first_colmn_after_left_parenthesis]
60
+ end
61
+
62
+ [left_brace.source_line =~ /\S/, :start_of_line]
63
+ end
64
+
65
+ def hash_pair_where_value_beginning_with(left_brace)
66
+ node = node_beginning_with(left_brace)
67
+ node.parent&.pair_type? ? node.parent : nil
68
+ end
69
+
70
+ def node_beginning_with(left_brace)
71
+ processed_source.ast.each_descendant do |node|
72
+ if node.loc.is_a?(Parser::Source::Map::Collection) && (node.loc.begin == left_brace)
73
+ break node
74
+ end
75
+ end
76
+ end
77
+
78
+ def key_and_value_begin_on_same_line?(pair)
79
+ same_line?(pair.key, pair.value)
56
80
  end
57
81
 
58
82
  def detected_styles(actual_column, offset, left_parenthesis, left_brace)
@@ -73,8 +97,8 @@ module RuboCop
73
97
  styles
74
98
  end
75
99
 
76
- def incorrect_style_detected(styles, first, left_parenthesis)
77
- msg = message(base_description(left_parenthesis))
100
+ def incorrect_style_detected(styles, first, base_column_type)
101
+ msg = message(base_description(base_column_type))
78
102
 
79
103
  add_offense(first, message: msg) do |corrector|
80
104
  autocorrect(corrector, first)
@@ -51,9 +51,13 @@ module RuboCop
51
51
  Parser::Source::Range.new(buffer, begin_pos, end_pos)
52
52
  end
53
53
 
54
- def range_with_surrounding_space(range:, side: :both,
55
- newlines: true, whitespace: false,
56
- continuations: false)
54
+ NOT_GIVEN = Module.new
55
+ def range_with_surrounding_space(range_positional = NOT_GIVEN, # rubocop:disable Metrics/ParameterLists
56
+ range: NOT_GIVEN, side: :both, newlines: true,
57
+ whitespace: false, continuations: false)
58
+
59
+ range = range_positional unless range_positional == NOT_GIVEN
60
+
57
61
  buffer = @processed_source.buffer
58
62
  src = buffer.source
59
63
 
@@ -63,7 +63,9 @@ module RuboCop
63
63
  end
64
64
 
65
65
  def bad_writer_name?(node)
66
- node.method_name.to_s.start_with?('set_') && node.arguments.one?
66
+ node.method_name.to_s.start_with?('set_') &&
67
+ node.arguments.one? &&
68
+ node.first_argument.arg_type?
67
69
  end
68
70
  end
69
71
  end
@@ -11,23 +11,6 @@ module RuboCop
11
11
  # can be used to specify whether method names and symbols should be checked.
12
12
  # Both are enabled by default.
13
13
  #
14
- # @example EnforcedStyle: snake_case
15
- # # bad
16
- # :some_sym1
17
- # variable1 = 1
18
- #
19
- # def some_method1; end
20
- #
21
- # def some_method_1(arg1); end
22
- #
23
- # # good
24
- # :some_sym_1
25
- # variable_1 = 1
26
- #
27
- # def some_method_1; end
28
- #
29
- # def some_method_1(arg_1); end
30
- #
31
14
  # @example EnforcedStyle: normalcase (default)
32
15
  # # bad
33
16
  # :some_sym_1
@@ -45,6 +28,23 @@ module RuboCop
45
28
  #
46
29
  # def some_method1(arg1); end
47
30
  #
31
+ # @example EnforcedStyle: snake_case
32
+ # # bad
33
+ # :some_sym1
34
+ # variable1 = 1
35
+ #
36
+ # def some_method1; end
37
+ #
38
+ # def some_method_1(arg1); end
39
+ #
40
+ # # good
41
+ # :some_sym_1
42
+ # variable_1 = 1
43
+ #
44
+ # def some_method_1; end
45
+ #
46
+ # def some_method_1(arg_1); end
47
+ #
48
48
  # @example EnforcedStyle: non_integer
49
49
  # # bad
50
50
  # :some_sym1
@@ -72,7 +72,7 @@ module RuboCop
72
72
  if (preferred_accessors = preferred_accessors(node))
73
73
  corrector.replace(node, preferred_accessors)
74
74
  else
75
- range = range_with_surrounding_space(range: node.loc.expression, side: :left)
75
+ range = range_with_surrounding_space(node.loc.expression, side: :left)
76
76
  corrector.remove(range)
77
77
  end
78
78
  end
@@ -12,10 +12,7 @@ module RuboCop
12
12
  # between logical operators (`&&` and `||`) and semantic operators (`and` and `or`),
13
13
  # and that might change the behavior.
14
14
  #
15
- # @example EnforcedStyle: always
16
- # # bad
17
- # foo.save and return
18
- #
15
+ # @example EnforcedStyle: conditionals (default)
19
16
  # # bad
20
17
  # if foo and bar
21
18
  # end
@@ -24,10 +21,16 @@ module RuboCop
24
21
  # foo.save && return
25
22
  #
26
23
  # # good
24
+ # foo.save and return
25
+ #
26
+ # # good
27
27
  # if foo && bar
28
28
  # end
29
29
  #
30
- # @example EnforcedStyle: conditionals (default)
30
+ # @example EnforcedStyle: always
31
+ # # bad
32
+ # foo.save and return
33
+ #
31
34
  # # bad
32
35
  # if foo and bar
33
36
  # end
@@ -36,9 +39,6 @@ module RuboCop
36
39
  # foo.save && return
37
40
  #
38
41
  # # good
39
- # foo.save and return
40
- #
41
- # # good
42
42
  # if foo && bar
43
43
  # end
44
44
  class AndOr < Base
@@ -133,7 +133,7 @@ module RuboCop
133
133
  def register_offense_to_method_definition_arguments(method_definition)
134
134
  add_offense(arguments_range(method_definition)) do |corrector|
135
135
  arguments_range = range_with_surrounding_space(
136
- range: method_definition.arguments.source_range, side: :left
136
+ method_definition.arguments.source_range, side: :left
137
137
  )
138
138
  corrector.replace(arguments_range, '(...)')
139
139
  end