rubocop 1.30.0 → 1.31.0

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