rubocop 1.39.0 → 1.41.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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +65 -9
  4. data/exe/rubocop +1 -1
  5. data/lib/rubocop/comment_config.rb +5 -0
  6. data/lib/rubocop/config.rb +33 -9
  7. data/lib/rubocop/config_loader.rb +14 -5
  8. data/lib/rubocop/config_loader_resolver.rb +1 -1
  9. data/lib/rubocop/config_validator.rb +1 -1
  10. data/lib/rubocop/cop/badge.rb +9 -4
  11. data/lib/rubocop/cop/base.rb +26 -17
  12. data/lib/rubocop/cop/commissioner.rb +8 -3
  13. data/lib/rubocop/cop/cop.rb +1 -1
  14. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +22 -6
  15. data/lib/rubocop/cop/internal_affairs/cop_description.rb +3 -1
  16. data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
  17. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  18. data/lib/rubocop/cop/layout/empty_lines.rb +2 -0
  19. data/lib/rubocop/cop/layout/extra_spacing.rb +10 -6
  20. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +38 -2
  21. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +49 -2
  22. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +61 -2
  23. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +52 -2
  24. data/lib/rubocop/cop/layout/indentation_style.rb +3 -1
  25. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +5 -0
  26. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  27. data/lib/rubocop/cop/layout/line_length.rb +2 -0
  28. data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +51 -2
  29. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +49 -2
  30. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +53 -2
  31. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +58 -2
  32. data/lib/rubocop/cop/layout/redundant_line_break.rb +2 -2
  33. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +1 -1
  34. data/lib/rubocop/cop/layout/trailing_whitespace.rb +6 -2
  35. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  36. data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
  37. data/lib/rubocop/cop/lint/constant_resolution.rb +4 -0
  38. data/lib/rubocop/cop/lint/debugger.rb +3 -1
  39. data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
  40. data/lib/rubocop/cop/lint/duplicate_branch.rb +0 -2
  41. data/lib/rubocop/cop/lint/duplicate_methods.rb +19 -8
  42. data/lib/rubocop/cop/lint/empty_block.rb +1 -5
  43. data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
  44. data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
  45. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -5
  46. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
  47. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +13 -3
  48. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  49. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +10 -12
  50. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -4
  51. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +4 -3
  52. data/lib/rubocop/cop/lint/void.rb +6 -6
  53. data/lib/rubocop/cop/metrics/block_length.rb +9 -4
  54. data/lib/rubocop/cop/metrics/class_length.rb +10 -5
  55. data/lib/rubocop/cop/metrics/method_length.rb +9 -4
  56. data/lib/rubocop/cop/metrics/module_length.rb +10 -5
  57. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +6 -3
  58. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  59. data/lib/rubocop/cop/mixin/allowed_identifiers.rb +2 -2
  60. data/lib/rubocop/cop/mixin/annotation_comment.rb +13 -6
  61. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +21 -9
  62. data/lib/rubocop/cop/mixin/first_element_line_break.rb +11 -7
  63. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +28 -5
  64. data/lib/rubocop/cop/mixin/line_length_help.rb +8 -1
  65. data/lib/rubocop/cop/mixin/method_complexity.rb +5 -3
  66. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +5 -3
  67. data/lib/rubocop/cop/mixin/percent_array.rb +3 -5
  68. data/lib/rubocop/cop/mixin/require_library.rb +2 -0
  69. data/lib/rubocop/cop/mixin/rescue_node.rb +3 -3
  70. data/lib/rubocop/cop/mixin/statement_modifier.rb +15 -1
  71. data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +2 -0
  72. data/lib/rubocop/cop/naming/inclusive_language.rb +4 -1
  73. data/lib/rubocop/cop/registry.rb +29 -14
  74. data/lib/rubocop/cop/style/array_intersect.rb +111 -0
  75. data/lib/rubocop/cop/style/concat_array_literals.rb +66 -0
  76. data/lib/rubocop/cop/style/documentation.rb +1 -1
  77. data/lib/rubocop/cop/style/guard_clause.rb +36 -5
  78. data/lib/rubocop/cop/style/if_with_semicolon.rb +4 -4
  79. data/lib/rubocop/cop/style/inverse_methods.rb +2 -0
  80. data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -1
  81. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  82. data/lib/rubocop/cop/style/redundant_argument.rb +3 -0
  83. data/lib/rubocop/cop/style/redundant_constant_base.rb +85 -0
  84. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +39 -0
  85. data/lib/rubocop/cop/style/redundant_return.rb +7 -0
  86. data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
  87. data/lib/rubocop/cop/style/require_order.rb +140 -0
  88. data/lib/rubocop/cop/style/safe_navigation.rb +35 -6
  89. data/lib/rubocop/cop/style/select_by_regexp.rb +8 -4
  90. data/lib/rubocop/cop/style/semicolon.rb +2 -1
  91. data/lib/rubocop/cop/style/string_literals.rb +1 -5
  92. data/lib/rubocop/cop/style/symbol_proc.rb +2 -4
  93. data/lib/rubocop/cop/team.rb +1 -1
  94. data/lib/rubocop/cop/util.rb +32 -5
  95. data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
  96. data/lib/rubocop/cop/variable_force.rb +20 -29
  97. data/lib/rubocop/cops_documentation_generator.rb +22 -3
  98. data/lib/rubocop/directive_comment.rb +1 -1
  99. data/lib/rubocop/file_patterns.rb +43 -0
  100. data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
  101. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  102. data/lib/rubocop/formatter.rb +3 -1
  103. data/lib/rubocop/options.rb +8 -0
  104. data/lib/rubocop/path_util.rb +34 -16
  105. data/lib/rubocop/result_cache.rb +1 -1
  106. data/lib/rubocop/rspec/cop_helper.rb +4 -1
  107. data/lib/rubocop/rspec/support.rb +2 -2
  108. data/lib/rubocop/server/core.rb +1 -1
  109. data/lib/rubocop/target_finder.rb +1 -1
  110. data/lib/rubocop/target_ruby.rb +1 -1
  111. data/lib/rubocop/version.rb +1 -1
  112. data/lib/rubocop.rb +16 -6
  113. metadata +10 -3
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # Ensures that each key in a multi-line hash
7
7
  # starts on a separate line.
8
8
  #
9
- # @example
9
+ # @example AllowMultilineFinalElement: false (default)
10
10
  #
11
11
  # # bad
12
12
  # {
@@ -14,12 +14,54 @@ module RuboCop
14
14
  # c: 3
15
15
  # }
16
16
  #
17
+ # # bad
18
+ # { a: 1, b: {
19
+ # c: 3,
20
+ # }}
21
+ #
17
22
  # # good
18
23
  # {
19
24
  # a: 1,
20
25
  # b: 2,
21
26
  # c: 3
22
27
  # }
28
+ #
29
+ # # good
30
+ # {
31
+ # a: 1,
32
+ # b: {
33
+ # c: 3,
34
+ # }
35
+ # }
36
+ #
37
+ # @example AllowMultilineFinalElement: true
38
+ #
39
+ # # bad
40
+ # {
41
+ # a: 1, b: 2,
42
+ # c: 3
43
+ # }
44
+ #
45
+ # # good
46
+ # { a: 1, b: {
47
+ # c: 3,
48
+ # }}
49
+ #
50
+ # # good
51
+ # {
52
+ # a: 1,
53
+ # b: 2,
54
+ # c: 3
55
+ # }
56
+ #
57
+ #
58
+ # # good
59
+ # {
60
+ # a: 1,
61
+ # b: {
62
+ # c: 3,
63
+ # }
64
+ # }
23
65
  class MultilineHashKeyLineBreaks < Base
24
66
  include MultilineElementLineBreaks
25
67
  extend AutoCorrector
@@ -31,8 +73,9 @@ module RuboCop
31
73
  # braces like {foo: 1}. That is, not a kwargs hashes.
32
74
  # Style/MultilineMethodArgumentLineBreaks handles those.
33
75
  return unless starts_with_curly_brace?(node)
76
+ return unless node.loc.begin
34
77
 
35
- check_line_breaks(node, node.children) if node.loc.begin
78
+ check_line_breaks(node, node.children, ignore_last: ignore_last_element?)
36
79
  end
37
80
 
38
81
  private
@@ -40,6 +83,10 @@ module RuboCop
40
83
  def starts_with_curly_brace?(node)
41
84
  node.loc.begin
42
85
  end
86
+
87
+ def ignore_last_element?
88
+ !!cop_config['AllowMultilineFinalElement']
89
+ end
43
90
  end
44
91
  end
45
92
  end
@@ -9,13 +9,18 @@ module RuboCop
9
9
  # NOTE: This cop does not move the first argument, if you want that to
10
10
  # be on a separate line, see `Layout/FirstMethodArgumentLineBreak`.
11
11
  #
12
- # @example
12
+ # @example AllowMultilineFinalElement: false (default)
13
13
  #
14
14
  # # bad
15
15
  # foo(a, b,
16
16
  # c
17
17
  # )
18
18
  #
19
+ # # bad
20
+ # foo(a, b, {
21
+ # foo: "bar",
22
+ # })
23
+ #
19
24
  # # good
20
25
  # foo(
21
26
  # a,
@@ -25,6 +30,46 @@ module RuboCop
25
30
  #
26
31
  # # good
27
32
  # foo(a, b, c)
33
+ #
34
+ # # good
35
+ # foo(
36
+ # a,
37
+ # b,
38
+ # {
39
+ # foo: "bar",
40
+ # }
41
+ # )
42
+ #
43
+ # @example AllowMultilineFinalElement: true
44
+ #
45
+ # # bad
46
+ # foo(a, b,
47
+ # c
48
+ # )
49
+ #
50
+ # # good
51
+ # foo(a, b, {
52
+ # foo: "bar",
53
+ # })
54
+ #
55
+ # # good
56
+ # foo(
57
+ # a,
58
+ # b,
59
+ # c
60
+ # )
61
+ #
62
+ # # good
63
+ # foo(a, b, c)
64
+ #
65
+ # # good
66
+ # foo(
67
+ # a,
68
+ # b,
69
+ # {
70
+ # foo: "bar",
71
+ # }
72
+ # )
28
73
  class MultilineMethodArgumentLineBreaks < Base
29
74
  include MultilineElementLineBreaks
30
75
  extend AutoCorrector
@@ -45,7 +90,13 @@ module RuboCop
45
90
  last_arg = args.last
46
91
  args = args[0...-1] + last_arg.children if last_arg&.hash_type? && !last_arg&.braces?
47
92
 
48
- check_line_breaks(node, args)
93
+ check_line_breaks(node, args, ignore_last: ignore_last_element?)
94
+ end
95
+
96
+ private
97
+
98
+ def ignore_last_element?
99
+ !!cop_config['AllowMultilineFinalElement']
49
100
  end
50
101
  end
51
102
  end
@@ -9,7 +9,7 @@ module RuboCop
9
9
  # NOTE: This cop does not move the first argument, if you want that to
10
10
  # be on a separate line, see `Layout/FirstMethodParameterLineBreak`.
11
11
  #
12
- # @example
12
+ # @example AllowMultilineFinalElement: false (default)
13
13
  #
14
14
  # # bad
15
15
  # def foo(a, b,
@@ -17,6 +17,47 @@ module RuboCop
17
17
  # )
18
18
  # end
19
19
  #
20
+ # # bad
21
+ # def foo(a, b = {
22
+ # foo: "bar",
23
+ # })
24
+ # end
25
+ #
26
+ # # good
27
+ # def foo(
28
+ # a,
29
+ # b,
30
+ # c
31
+ # )
32
+ # end
33
+ #
34
+ # # good
35
+ # def foo(
36
+ # a,
37
+ # b = {
38
+ # foo: "bar",
39
+ # }
40
+ # )
41
+ # end
42
+ #
43
+ # # good
44
+ # def foo(a, b, c)
45
+ # end
46
+ #
47
+ # @example AllowMultilineFinalElement: true
48
+ #
49
+ # # bad
50
+ # def foo(a, b,
51
+ # c
52
+ # )
53
+ # end
54
+ #
55
+ # # good
56
+ # def foo(a, b = {
57
+ # foo: "bar",
58
+ # })
59
+ # end
60
+ #
20
61
  # # good
21
62
  # def foo(
22
63
  # a,
@@ -26,6 +67,15 @@ module RuboCop
26
67
  # end
27
68
  #
28
69
  # # good
70
+ # def foo(
71
+ # a,
72
+ # b = {
73
+ # foo: "bar",
74
+ # }
75
+ # )
76
+ # end
77
+ #
78
+ # # good
29
79
  # def foo(a, b, c)
30
80
  # end
31
81
  class MultilineMethodParameterLineBreaks < Base
@@ -37,7 +87,13 @@ module RuboCop
37
87
  def on_def(node)
38
88
  return if node.arguments.empty?
39
89
 
40
- check_line_breaks(node, node.arguments)
90
+ check_line_breaks(node, node.arguments, ignore_last: ignore_last_element?)
91
+ end
92
+
93
+ private
94
+
95
+ def ignore_last_element?
96
+ !!cop_config['AllowMultilineFinalElement']
41
97
  end
42
98
  end
43
99
  end
@@ -84,11 +84,11 @@ module RuboCop
84
84
  return true if other_cop_takes_precedence?(node)
85
85
 
86
86
  !cop_config['InspectBlocks'] && (node.block_type? ||
87
- node.each_descendant(:block).any?(&:multiline?))
87
+ any_descendant?(node, :block, &:multiline?))
88
88
  end
89
89
 
90
90
  def other_cop_takes_precedence?(node)
91
- single_line_block_chain_enabled? && node.each_descendant(:block).any? do |block_node|
91
+ single_line_block_chain_enabled? && any_descendant?(node, :block) do |block_node|
92
92
  block_node.parent.send_type? && block_node.parent.loc.dot && !block_node.multiline?
93
93
  end
94
94
  end
@@ -79,7 +79,7 @@ module RuboCop
79
79
  def ends_in_end?(processed_source)
80
80
  buffer = processed_source.buffer
81
81
 
82
- return true if buffer.source.strip.start_with?('__END__')
82
+ return true if buffer.source.match?(/\s*__END__/)
83
83
  return false if processed_source.tokens.empty?
84
84
 
85
85
  extra = buffer.source[processed_source.tokens.last.end_pos..]
@@ -109,10 +109,14 @@ module RuboCop
109
109
  def extract_heredocs(ast)
110
110
  return [] unless ast
111
111
 
112
- ast.each_node(:str, :dstr, :xstr).select(&:heredoc?).map do |node|
112
+ heredocs = []
113
+ ast.each_node(:str, :dstr, :xstr) do |node|
114
+ next unless node.heredoc?
115
+
113
116
  body = node.location.heredoc_body
114
- [node, body.first_line...body.last_line]
117
+ heredocs << [node, body.first_line...body.last_line]
115
118
  end
119
+ heredocs
116
120
  end
117
121
 
118
122
  def offense_range(lineno, line)
@@ -63,7 +63,7 @@ module RuboCop
63
63
  return unless node.arguments?
64
64
 
65
65
  return unless ambiguous_block_association?(node)
66
- return if node.parenthesized? || node.last_argument.lambda? || node.last_argument.proc? ||
66
+ return if node.parenthesized? || node.last_argument.lambda_or_proc? ||
67
67
  allowed_method_pattern?(node)
68
68
 
69
69
  message = message(node)
@@ -11,6 +11,10 @@ module RuboCop
11
11
  # an assignment to indicate "I know I'm using an assignment
12
12
  # as a condition. It's not a mistake."
13
13
  #
14
+ # @safety
15
+ # This cop's autocorrection is unsafe because it assumes that
16
+ # the author meant to use an assignment result as a condition.
17
+ #
14
18
  # @example
15
19
  # # bad
16
20
  # if some_var = true
@@ -35,6 +39,8 @@ module RuboCop
35
39
  # end
36
40
  #
37
41
  class AssignmentInCondition < Base
42
+ extend AutoCorrector
43
+
38
44
  include SafeAssignment
39
45
 
40
46
  MSG_WITH_SAFE_ASSIGNMENT_ALLOWED =
@@ -53,7 +59,11 @@ module RuboCop
53
59
  next :skip_children if skip_children?(asgn_node)
54
60
  next if allowed_construct?(asgn_node)
55
61
 
56
- add_offense(asgn_node.loc.operator)
62
+ add_offense(asgn_node.loc.operator) do |corrector|
63
+ next unless safe_assignment_allowed?
64
+
65
+ corrector.wrap(asgn_node, '(', ')')
66
+ end
57
67
  end
58
68
  end
59
69
  alias on_while on_if
@@ -16,6 +16,10 @@ module RuboCop
16
16
  # using the same name a namespace and a class. To avoid too many unnecessary
17
17
  # offenses, Enable this cop with `Only: [The, Constant, Names, Causing, Issues]`
18
18
  #
19
+ # NOTE: `Style/RedundantConstantBase` cop is disabled if this cop is enabled to prevent
20
+ # conflicting rules. Because it respects user configurations that want to enable
21
+ # this cop which is disabled by default.
22
+ #
19
23
  # @example
20
24
  # # By default checks every constant
21
25
  #
@@ -96,8 +96,10 @@ module RuboCop
96
96
  end
97
97
 
98
98
  def debugger_method?(send_node)
99
+ method_name = send_node.method_name
100
+
99
101
  debugger_methods.any? do |method|
100
- next unless method[:method_name] == send_node.method_name
102
+ next unless method[:method_name] == method_name
101
103
 
102
104
  if method[:receiver].nil?
103
105
  send_node.receiver.nil?
@@ -14,7 +14,8 @@ module RuboCop
14
14
  # Alternative: 'alternative_value'
15
15
  # DeprecatedVersion: 'deprecated_version'
16
16
  #
17
- # By default, `NIL`, `TRUE`, `FALSE` and `Random::DEFAULT` are configured.
17
+ # By default, `NIL`, `TRUE`, `FALSE`, `Net::HTTPServerException, `Random::DEFAULT`,
18
+ # `Struct::Group`, and `Struct::Passwd` are configured.
18
19
  #
19
20
  # @example
20
21
  #
@@ -22,13 +23,19 @@ module RuboCop
22
23
  # NIL
23
24
  # TRUE
24
25
  # FALSE
26
+ # Net::HTTPServerException
25
27
  # Random::DEFAULT # Return value of Ruby 2 is `Random` instance, Ruby 3.0 is `Random` class.
28
+ # Struct::Group
29
+ # Struct::Passwd
26
30
  #
27
31
  # # good
28
32
  # nil
29
33
  # true
30
34
  # false
35
+ # Net::HTTPClientException
31
36
  # Random.new # `::DEFAULT` has been deprecated in Ruby 3, `.new` is compatible with Ruby 2.
37
+ # Etc::Group
38
+ # Etc::Passwd
32
39
  #
33
40
  class DeprecatedConstants < Base
34
41
  extend AutoCorrector
@@ -84,8 +84,6 @@ module RuboCop
84
84
  # end
85
85
  #
86
86
  class DuplicateBranch < Base
87
- include RescueNode
88
-
89
87
  MSG = 'Duplicate branch body detected.'
90
88
 
91
89
  def on_branching_statement(node)
@@ -57,19 +57,20 @@ module RuboCop
57
57
  def initialize(config = nil, options = nil)
58
58
  super
59
59
  @definitions = {}
60
+ @scopes = Hash.new { |hash, key| hash[key] = [] }
60
61
  end
61
62
 
62
63
  def on_def(node)
63
64
  # if a method definition is inside an if, it is very likely
64
65
  # that a different definition is used depending on platform, etc.
65
- return if node.ancestors.any?(&:if_type?)
66
+ return if node.each_ancestor.any?(&:if_type?)
66
67
  return if possible_dsl?(node)
67
68
 
68
69
  found_instance_method(node, node.method_name)
69
70
  end
70
71
 
71
72
  def on_defs(node)
72
- return if node.ancestors.any?(&:if_type?)
73
+ return if node.each_ancestor.any?(&:if_type?)
73
74
  return if possible_dsl?(node)
74
75
 
75
76
  if node.receiver.const_type?
@@ -157,16 +158,18 @@ module RuboCop
157
158
 
158
159
  def found_method(node, method_name)
159
160
  key = method_key(node, method_name)
161
+ scope = node.each_ancestor(:rescue, :ensure).first&.type
160
162
 
161
163
  if @definitions.key?(key)
162
- loc = if DEF_TYPES.include?(node.type)
163
- node.loc.keyword.join(node.loc.name)
164
- else
165
- node.loc.expression
166
- end
164
+ if scope && !@scopes[scope].include?(key)
165
+ @definitions[key] = node
166
+ @scopes[scope] << key
167
+ return
168
+ end
169
+
167
170
  message = message_for_dup(node, method_name, key)
168
171
 
169
- add_offense(loc, message: message)
172
+ add_offense(location(node), message: message)
170
173
  else
171
174
  @definitions[key] = node
172
175
  end
@@ -180,6 +183,14 @@ module RuboCop
180
183
  end
181
184
  end
182
185
 
186
+ def location(node)
187
+ if DEF_TYPES.include?(node.type)
188
+ node.loc.keyword.join(node.loc.name)
189
+ else
190
+ node.loc.expression
191
+ end
192
+ end
193
+
183
194
  def on_attr(node, attr_name, args)
184
195
  case attr_name
185
196
  when :attr
@@ -65,7 +65,7 @@ module RuboCop
65
65
 
66
66
  def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
67
67
  return if node.body
68
- return if allow_empty_lambdas? && lambda_or_proc?(node)
68
+ return if allow_empty_lambdas? && node.lambda_or_proc?
69
69
  return if cop_config['AllowComments'] && allow_comment?(node)
70
70
 
71
71
  add_offense(node)
@@ -88,10 +88,6 @@ module RuboCop
88
88
  regexp_pattern = "# rubocop : (disable|todo) ([^,],)* (all|#{cop_name})"
89
89
  Regexp.new(regexp_pattern.gsub(' ', '\s*')).match?(comment)
90
90
  end
91
-
92
- def lambda_or_proc?(node)
93
- node.lambda? || node.proc?
94
- end
95
91
  end
96
92
  end
97
93
  end
@@ -68,7 +68,7 @@ module RuboCop
68
68
  MSG = 'Avoid `%<keyword>s` branches without a body.'
69
69
 
70
70
  def on_if(node)
71
- return if node.body
71
+ return if node.body || same_line?(node.loc.begin, node.loc.end)
72
72
  return if cop_config['AllowComments'] && contains_comments?(node)
73
73
 
74
74
  add_offense(node, message: format(MSG, keyword: node.keyword)) do |corrector|
@@ -6,9 +6,10 @@ module RuboCop
6
6
  # Checks for interpolation in a single quoted string.
7
7
  #
8
8
  # @safety
9
- # This cop is generally safe, but is marked as unsafe because
10
- # it is possible to actually intentionally have text inside
11
- # `#{...}` in a single quoted string.
9
+ # This cop's autocorrection is unsafe because although it always replaces single quotes as
10
+ # if it were miswritten double quotes, it is not always the case. For example,
11
+ # `'#{foo} bar'` would be replaced by `"#{foo} bar"`, so the replaced code would evaluate
12
+ # the expression `foo`.
12
13
  #
13
14
  # @example
14
15
  #
@@ -44,7 +44,6 @@ module RuboCop
44
44
  class NonAtomicFileOperation < Base
45
45
  extend AutoCorrector
46
46
  include Alignment
47
- include RangeHelp
48
47
 
49
48
  MSG_REMOVE_FILE_EXIST_CHECK = 'Remove unnecessary existence check ' \
50
49
  '`%<receiver>s.%<method_name>s`.'
@@ -101,10 +100,11 @@ module RuboCop
101
100
  def register_offense(node, exist_node)
102
101
  add_offense(node, message: message_change_force_method(node)) unless force_method?(node)
103
102
 
104
- range = range_between(node.parent.loc.keyword.begin_pos,
105
- exist_node.loc.expression.end_pos)
103
+ parent = node.parent
104
+ range = parent.loc.keyword.begin.join(parent.condition.source_range.end)
105
+
106
106
  add_offense(range, message: message_remove_file_exist_check(exist_node)) do |corrector|
107
- autocorrect(corrector, node, range) unless node.parent.elsif?
107
+ autocorrect(corrector, node, range) unless parent.elsif?
108
108
  end
109
109
  end
110
110
 
@@ -120,7 +120,12 @@ module RuboCop
120
120
  def autocorrect(corrector, node, range)
121
121
  corrector.remove(range)
122
122
  autocorrect_replace_method(corrector, node)
123
- corrector.remove(node.parent.loc.end) if node.parent.multiline?
123
+
124
+ if node.parent.modifier_form?
125
+ corrector.remove(node.source_range.end.join(node.parent.loc.keyword.begin))
126
+ else
127
+ corrector.remove(node.parent.loc.end)
128
+ end
124
129
  end
125
130
 
126
131
  def autocorrect_replace_method(corrector, node)
@@ -40,11 +40,16 @@ module RuboCop
40
40
  unless node.arguments.one? && first_argument_starts_with_left_parenthesis?(node)
41
41
  return true
42
42
  end
43
+ return true if first_argument_block_type?(node.first_argument)
43
44
 
44
45
  node.operator_method? || node.setter_method? || chained_calls?(node) ||
45
46
  valid_first_argument?(node.first_argument)
46
47
  end
47
48
 
49
+ def first_argument_block_type?(first_arg)
50
+ first_arg.block_type? || first_arg.numblock_type?
51
+ end
52
+
48
53
  def valid_first_argument?(first_arg)
49
54
  first_arg.operator_keyword? || first_arg.hash_type? || ternary_expression?(first_arg)
50
55
  end
@@ -131,18 +131,28 @@ module RuboCop
131
131
  def each_already_disabled(cop, line_ranges)
132
132
  line_ranges.each_cons(2) do |previous_range, range|
133
133
  next if ignore_offense?(range)
134
- next unless followed_ranges?(previous_range, range)
135
-
136
134
  # If a cop is disabled in a range that begins on the same line as
137
135
  # the end of the previous range, it means that the cop was
138
136
  # already disabled by an earlier comment. So it's redundant
139
137
  # whether there are offenses or not.
138
+ next unless followed_ranges?(previous_range, range)
139
+
140
140
  comment = processed_source.comment_at_line(range.begin)
141
141
 
142
+ next unless comment
142
143
  # Comments disabling all cops don't count since it's reasonable
143
144
  # to disable a few select cops first and then all cops further
144
145
  # down in the code.
145
- yield comment, cop if comment && !all_disabled?(comment)
146
+ next if all_disabled?(comment)
147
+
148
+ redundant =
149
+ if department_disabled?(cop, comment)
150
+ find_redundant_department(cop, range)
151
+ else
152
+ cop
153
+ end
154
+
155
+ yield comment, redundant
146
156
  end
147
157
  end
148
158
 
@@ -42,7 +42,7 @@ module RuboCop
42
42
  MSG = 'Unnecessary enabling of %<cop>s.'
43
43
 
44
44
  def on_new_investigation
45
- return if processed_source.blank?
45
+ return if processed_source.blank? || !processed_source.raw_source.include?('enable')
46
46
 
47
47
  offenses = processed_source.comment_config.extra_enabled_comments
48
48
  offenses.each { |comment, cop_names| register_offense(comment, cop_names) }
@@ -45,13 +45,12 @@ module RuboCop
45
45
  bad_method?(node) do |safe_nav, method|
46
46
  return if nil_methods.include?(method) || PLUS_MINUS_METHODS.include?(node.method_name)
47
47
 
48
- method_chain = method_chain(node)
49
48
  location =
50
49
  Parser::Source::Range.new(node.source_range.source_buffer,
51
50
  safe_nav.source_range.end_pos,
52
- method_chain.source_range.end_pos)
51
+ node.source_range.end_pos)
53
52
  add_offense(location) do |corrector|
54
- autocorrect(corrector, offense_range: location, send_node: method_chain)
53
+ autocorrect(corrector, offense_range: location, send_node: node)
55
54
  end
56
55
  end
57
56
  end
@@ -62,15 +61,16 @@ module RuboCop
62
61
  # @param [RuboCop::AST::SendNode] send_node
63
62
  # @return [String]
64
63
  def add_safe_navigation_operator(offense_range:, send_node:)
65
- source = \
66
- if send_node.method?(:[]) || send_node.method?(:[]=)
64
+ source =
65
+ if brackets?(send_node)
67
66
  format(
68
- '%<method_name>s(%<arguments>s)',
67
+ '%<method_name>s(%<arguments>s)%<method_chain>s',
69
68
  arguments: send_node.arguments.map(&:source).join(', '),
70
- method_name: send_node.method_name
69
+ method_name: send_node.method_name,
70
+ method_chain: send_node.source_range.end.join(send_node.source_range.end).source
71
71
  )
72
72
  else
73
- offense_range.source.dup
73
+ offense_range.source
74
74
  end
75
75
  source.prepend('.') unless source.start_with?('.')
76
76
  source.prepend('&')
@@ -89,10 +89,8 @@ module RuboCop
89
89
  )
90
90
  end
91
91
 
92
- def method_chain(node)
93
- chain = node
94
- chain = chain.parent if chain.send_type? && chain.parent&.call_type?
95
- chain
92
+ def brackets?(send_node)
93
+ send_node.method?(:[]) || send_node.method?(:[]=)
96
94
  end
97
95
  end
98
96
  end