rubocop 1.6.0 → 1.9.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 (109) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +3 -2
  4. data/config/default.yml +142 -19
  5. data/lib/rubocop.rb +15 -1
  6. data/lib/rubocop/cli/command/auto_genenerate_config.rb +5 -4
  7. data/lib/rubocop/comment_config.rb +6 -6
  8. data/lib/rubocop/config.rb +10 -7
  9. data/lib/rubocop/config_loader.rb +11 -14
  10. data/lib/rubocop/config_loader_resolver.rb +21 -4
  11. data/lib/rubocop/config_obsoletion.rb +5 -3
  12. data/lib/rubocop/config_obsoletion/extracted_cop.rb +6 -6
  13. data/lib/rubocop/config_store.rb +12 -1
  14. data/lib/rubocop/cop/base.rb +1 -1
  15. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +3 -2
  16. data/lib/rubocop/cop/generator.rb +1 -3
  17. data/lib/rubocop/cop/internal_affairs.rb +6 -1
  18. data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +68 -0
  19. data/lib/rubocop/cop/internal_affairs/example_description.rb +89 -0
  20. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +61 -0
  21. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +64 -0
  22. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +145 -0
  23. data/lib/rubocop/cop/layout/class_structure.rb +7 -2
  24. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +19 -3
  25. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +14 -0
  26. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -2
  27. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -10
  28. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +1 -0
  29. data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
  30. data/lib/rubocop/cop/layout/space_before_brackets.rb +62 -0
  31. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +13 -10
  32. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -2
  33. data/lib/rubocop/cop/lint/ambiguous_assignment.rb +59 -0
  34. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +7 -2
  35. data/lib/rubocop/cop/lint/deprecated_constants.rb +75 -0
  36. data/lib/rubocop/cop/lint/duplicate_branch.rb +64 -2
  37. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +44 -0
  38. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +10 -6
  39. data/lib/rubocop/cop/lint/number_conversion.rb +41 -6
  40. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +47 -0
  41. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +39 -0
  42. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +2 -1
  43. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +50 -0
  44. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +50 -17
  45. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -11
  46. data/lib/rubocop/cop/lint/symbol_conversion.rb +102 -0
  47. data/lib/rubocop/cop/lint/triple_quotes.rb +71 -0
  48. data/lib/rubocop/cop/lint/unreachable_loop.rb +17 -0
  49. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  50. data/lib/rubocop/cop/mixin/allowed_identifiers.rb +18 -0
  51. data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -0
  52. data/lib/rubocop/cop/mixin/comments_help.rb +1 -11
  53. data/lib/rubocop/cop/mixin/first_element_line_break.rb +1 -1
  54. data/lib/rubocop/cop/mixin/uncommunicative_name.rb +5 -1
  55. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +59 -5
  56. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +38 -5
  57. data/lib/rubocop/cop/naming/variable_name.rb +2 -0
  58. data/lib/rubocop/cop/naming/variable_number.rb +2 -9
  59. data/lib/rubocop/cop/registry.rb +10 -0
  60. data/lib/rubocop/cop/severity.rb +3 -3
  61. data/lib/rubocop/cop/style/access_modifier_declarations.rb +3 -1
  62. data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
  63. data/lib/rubocop/cop/style/collection_methods.rb +14 -1
  64. data/lib/rubocop/cop/style/commented_keyword.rb +22 -5
  65. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +49 -9
  66. data/lib/rubocop/cop/style/empty_literal.rb +6 -2
  67. data/lib/rubocop/cop/style/endless_method.rb +102 -0
  68. data/lib/rubocop/cop/style/eval_with_location.rb +63 -34
  69. data/lib/rubocop/cop/style/explicit_block_argument.rb +10 -0
  70. data/lib/rubocop/cop/style/float_division.rb +3 -0
  71. data/lib/rubocop/cop/style/for.rb +2 -0
  72. data/lib/rubocop/cop/style/format_string_token.rb +18 -2
  73. data/lib/rubocop/cop/style/hash_except.rb +95 -0
  74. data/lib/rubocop/cop/style/hash_like_case.rb +2 -1
  75. data/lib/rubocop/cop/style/if_inside_else.rb +22 -10
  76. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +96 -0
  77. data/lib/rubocop/cop/style/keyword_parameters_order.rb +12 -2
  78. data/lib/rubocop/cop/style/lambda_call.rb +2 -1
  79. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -0
  80. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +16 -6
  81. data/lib/rubocop/cop/style/method_def_parentheses.rb +7 -0
  82. data/lib/rubocop/cop/style/multiline_method_signature.rb +26 -1
  83. data/lib/rubocop/cop/style/multiline_when_then.rb +3 -1
  84. data/lib/rubocop/cop/style/mutable_constant.rb +13 -3
  85. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +4 -0
  86. data/lib/rubocop/cop/style/nil_comparison.rb +1 -0
  87. data/lib/rubocop/cop/style/non_nil_check.rb +23 -13
  88. data/lib/rubocop/cop/style/raise_args.rb +5 -2
  89. data/lib/rubocop/cop/style/redundant_argument.rb +7 -1
  90. data/lib/rubocop/cop/style/redundant_freeze.rb +8 -4
  91. data/lib/rubocop/cop/style/redundant_return.rb +1 -1
  92. data/lib/rubocop/cop/style/single_line_methods.rb +34 -2
  93. data/lib/rubocop/cop/style/sole_nested_conditional.rb +29 -5
  94. data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
  95. data/lib/rubocop/cop/style/symbol_proc.rb +5 -4
  96. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  97. data/lib/rubocop/cop/style/while_until_modifier.rb +2 -4
  98. data/lib/rubocop/cop/util.rb +3 -1
  99. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -0
  100. data/lib/rubocop/magic_comment.rb +30 -1
  101. data/lib/rubocop/options.rb +10 -10
  102. data/lib/rubocop/rspec/cop_helper.rb +0 -4
  103. data/lib/rubocop/rspec/expect_offense.rb +37 -22
  104. data/lib/rubocop/runner.rb +17 -1
  105. data/lib/rubocop/target_finder.rb +4 -2
  106. data/lib/rubocop/target_ruby.rb +47 -11
  107. data/lib/rubocop/util.rb +16 -0
  108. data/lib/rubocop/version.rb +8 -2
  109. metadata +26 -7
@@ -4,12 +4,15 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # This cop checks for comments put on the same line as some keywords.
7
- # These keywords are: `begin`, `class`, `def`, `end`, `module`.
7
+ # These keywords are: `class`, `module`, `def`, `begin`, `end`.
8
8
  #
9
9
  # Note that some comments
10
10
  # (`:nodoc:`, `:yields:`, `rubocop:disable` and `rubocop:todo`)
11
11
  # are allowed.
12
12
  #
13
+ # Auto-correction removes comments from `end` keyword and keeps comments
14
+ # for `class`, `module`, `def` and `begin` above the keyword.
15
+ #
13
16
  # @example
14
17
  # # bad
15
18
  # if condition
@@ -34,16 +37,17 @@ module RuboCop
34
37
  # y
35
38
  # end
36
39
  class CommentedKeyword < Base
40
+ include RangeHelp
41
+ extend AutoCorrector
42
+
37
43
  MSG = 'Do not place comments on the same line as the ' \
38
44
  '`%<keyword>s` keyword.'
39
45
 
40
46
  def on_new_investigation
41
47
  processed_source.comments.each do |comment|
42
- next unless (match = line(comment).match(/(?<keyword>\S+).*#/))
48
+ next unless (match = line(comment).match(/(?<keyword>\S+).*#/)) && offensive?(comment)
43
49
 
44
- if offensive?(comment)
45
- add_offense(comment, message: format(MSG, keyword: match[:keyword]))
46
- end
50
+ register_offense(comment, match[:keyword])
47
51
  end
48
52
  end
49
53
 
@@ -60,6 +64,19 @@ module RuboCop
60
64
  ].freeze
61
65
  ALLOWED_COMMENT_REGEXES = ALLOWED_COMMENTS.map { |c| /#\s*#{c}/ }.freeze
62
66
 
67
+ def register_offense(comment, matched_keyword)
68
+ add_offense(comment, message: format(MSG, keyword: matched_keyword)) do |corrector|
69
+ range = range_with_surrounding_space(range: comment.loc.expression, newlines: false)
70
+ corrector.remove(range)
71
+
72
+ unless matched_keyword == 'end'
73
+ corrector.insert_before(
74
+ range.source_buffer.line_range(comment.loc.line), "#{comment.text}\n"
75
+ )
76
+ end
77
+ end
78
+ end
79
+
63
80
  def offensive?(comment)
64
81
  line = line(comment)
65
82
  KEYWORD_REGEXES.any? { |r| r.match?(line) } &&
@@ -9,37 +9,77 @@ module RuboCop
9
9
  # This is useful if want to make sure that every RuboCop error gets fixed
10
10
  # and not quickly disabled with a comment.
11
11
  #
12
+ # Specific cops can be allowed with the `AllowedCops` configuration. Note that
13
+ # if this configuration is set, `rubocop:disable all` is still disallowed.
14
+ #
12
15
  # @example
13
16
  # # bad
14
17
  # # rubocop:disable Metrics/AbcSize
15
- # def f
18
+ # def foo
16
19
  # end
17
20
  # # rubocop:enable Metrics/AbcSize
18
21
  #
19
22
  # # good
20
- # def fixed_method_name_and_no_rubocop_comments
23
+ # def foo
24
+ # end
25
+ #
26
+ # @example AllowedCops: [Metrics/AbcSize]
27
+ # # good
28
+ # # rubocop:disable Metrics/AbcSize
29
+ # def foo
21
30
  # end
31
+ # # rubocop:enable Metrics/AbcSize
22
32
  #
23
33
  class DisableCopsWithinSourceCodeDirective < Base
24
34
  extend AutoCorrector
25
35
 
26
36
  # rubocop:enable Lint/RedundantCopDisableDirective
27
- MSG = 'Comment to disable/enable RuboCop.'
37
+ MSG = 'Rubocop disable/enable directives are not permitted.'
38
+ MSG_FOR_COPS = 'Rubocop disable/enable directives for %<cops>s are not permitted.'
28
39
 
29
40
  def on_new_investigation
30
41
  processed_source.comments.each do |comment|
31
- next unless rubocop_directive_comment?(comment)
42
+ directive_cops = directive_cops(comment)
43
+ disallowed_cops = directive_cops - allowed_cops
32
44
 
33
- add_offense(comment) do |corrector|
34
- corrector.replace(comment, '')
35
- end
45
+ next unless disallowed_cops.any?
46
+
47
+ register_offense(comment, directive_cops, disallowed_cops)
36
48
  end
37
49
  end
38
50
 
39
51
  private
40
52
 
41
- def rubocop_directive_comment?(comment)
42
- CommentConfig::COMMENT_DIRECTIVE_REGEXP.match?(comment.text)
53
+ def register_offense(comment, directive_cops, disallowed_cops)
54
+ message = if any_cops_allowed?
55
+ format(MSG_FOR_COPS, cops: "`#{disallowed_cops.join('`, `')}`")
56
+ else
57
+ MSG
58
+ end
59
+
60
+ add_offense(comment, message: message) do |corrector|
61
+ replacement = ''
62
+
63
+ if directive_cops.length != disallowed_cops.length
64
+ replacement = comment.text.sub(/#{Regexp.union(disallowed_cops)},?\s*/, '')
65
+ .sub(/,\s*$/, '')
66
+ end
67
+
68
+ corrector.replace(comment, replacement)
69
+ end
70
+ end
71
+
72
+ def directive_cops(comment)
73
+ match = CommentConfig::COMMENT_DIRECTIVE_REGEXP.match(comment.text)
74
+ match[2] ? match[2].split(',').map(&:strip) : []
75
+ end
76
+
77
+ def allowed_cops
78
+ Array(cop_config['AllowedCops'])
79
+ end
80
+
81
+ def any_cops_allowed?
82
+ allowed_cops.any?
43
83
  end
44
84
  end
45
85
  end
@@ -32,8 +32,12 @@ module RuboCop
32
32
  def_node_matcher :str_node, '(send (const {nil? cbase} :String) :new)'
33
33
  def_node_matcher :array_with_block,
34
34
  '(block (send (const {nil? cbase} :Array) :new) args _)'
35
- def_node_matcher :hash_with_block,
36
- '(block (send (const {nil? cbase} :Hash) :new) args _)'
35
+ def_node_matcher :hash_with_block, <<~PATTERN
36
+ {
37
+ (block (send (const {nil? cbase} :Hash) :new) args _)
38
+ (numblock (send (const {nil? cbase} :Hash) :new) ...)
39
+ }
40
+ PATTERN
37
41
 
38
42
  def on_send(node)
39
43
  return unless (message = offense_message(node))
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for endless methods.
7
+ #
8
+ # It can enforce either the use of endless methods definitions
9
+ # for single-lined method bodies, or disallow endless methods.
10
+ #
11
+ # Other method definition types are not considered by this cop.
12
+ #
13
+ # The supported styles are:
14
+ # * allow_single_line (default) - only single line endless method definitions are allowed.
15
+ # * allow_always - all endless method definitions are allowed.
16
+ # * disallow - all endless method definitions are disallowed.
17
+ #
18
+ # NOTE: Incorrect endless method definitions will always be
19
+ # corrected to a multi-line definition.
20
+ #
21
+ # @example EnforcedStyle: allow_single_line (default)
22
+ # # good
23
+ # def my_method() = x
24
+ #
25
+ # # bad, multi-line endless method
26
+ # def my_method() = x.foo
27
+ # .bar
28
+ # .baz
29
+ #
30
+ # @example EnforcedStyle: allow_always
31
+ # # good
32
+ # def my_method() = x
33
+ #
34
+ # # good
35
+ # def my_method() = x.foo
36
+ # .bar
37
+ # .baz
38
+ #
39
+ # @example EnforcedStyle: disallow
40
+ # # bad
41
+ # def my_method; x end
42
+ #
43
+ # # bad
44
+ # def my_method() = x.foo
45
+ # .bar
46
+ # .baz
47
+ #
48
+ class EndlessMethod < Base
49
+ include ConfigurableEnforcedStyle
50
+ extend TargetRubyVersion
51
+ extend AutoCorrector
52
+
53
+ minimum_target_ruby_version 3.0
54
+
55
+ CORRECTION_STYLES = %w[multiline single_line].freeze
56
+ MSG = 'Avoid endless method definitions.'
57
+ MSG_MULTI_LINE = 'Avoid endless method definitions with multiple lines.'
58
+
59
+ def on_def(node)
60
+ if style == :disallow
61
+ handle_disallow_style(node)
62
+ else
63
+ handle_allow_style(node)
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def handle_allow_style(node)
70
+ return unless node.endless?
71
+ return if node.single_line? || style == :allow_always
72
+
73
+ add_offense(node, message: MSG_MULTI_LINE) do |corrector|
74
+ correct_to_multiline(corrector, node)
75
+ end
76
+ end
77
+
78
+ def handle_disallow_style(node)
79
+ return unless node.endless?
80
+
81
+ add_offense(node) do |corrector|
82
+ correct_to_multiline(corrector, node)
83
+ end
84
+ end
85
+
86
+ def correct_to_multiline(corrector, node)
87
+ replacement = <<~RUBY.strip
88
+ def #{node.method_name}#{arguments(node)}
89
+ #{node.body.source}
90
+ end
91
+ RUBY
92
+
93
+ corrector.replace(node, replacement)
94
+ end
95
+
96
+ def arguments(node, missing = '')
97
+ node.arguments.any? ? node.arguments.source : missing
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -3,9 +3,14 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # This cop checks `eval` method usage. `eval` can receive source location
7
- # metadata, that are filename and line number. The metadata is used by
8
- # backtraces. This cop recommends to pass the metadata to `eval` method.
6
+ # This cop ensures that eval methods (`eval`, `instance_eval`, `class_eval`
7
+ # and `module_eval`) are given filename and line number values (`__FILE__`
8
+ # and `__LINE__`). This data is used to ensure that any errors raised
9
+ # within the evaluated code will be given the correct identification
10
+ # in a backtrace.
11
+ #
12
+ # The cop also checks that the line number given relative to `__LINE__` is
13
+ # correct.
9
14
  #
10
15
  # @example
11
16
  # # bad
@@ -32,27 +37,17 @@ module RuboCop
32
37
  # end
33
38
  # RUBY
34
39
  class EvalWithLocation < Base
35
- MSG = 'Pass `__FILE__` and `__LINE__` to `eval` method, ' \
36
- 'as they are used by backtraces.'
37
- MSG_INCORRECT_LINE = 'Use `%<expected>s` instead of `%<actual>s`, ' \
38
- 'as they are used by backtraces.'
40
+ MSG = 'Pass `__FILE__` and `__LINE__` to `%<method_name>s`.'
41
+ MSG_EVAL = 'Pass a binding, `__FILE__` and `__LINE__` to `eval`.'
42
+ MSG_INCORRECT_FILE = 'Incorrect file for `%<method_name>s`; ' \
43
+ 'use `%<expected>s` instead of `%<actual>s`.'
44
+ MSG_INCORRECT_LINE = 'Incorrect line number for `%<method_name>s`; ' \
45
+ 'use `%<expected>s` instead of `%<actual>s`.'
39
46
 
40
47
  RESTRICT_ON_SEND = %i[eval class_eval module_eval instance_eval].freeze
41
48
 
42
- def_node_matcher :eval_without_location?, <<~PATTERN
43
- {
44
- (send nil? :eval ${str dstr})
45
- (send nil? :eval ${str dstr} _)
46
- (send nil? :eval ${str dstr} _ #special_file_keyword?)
47
- (send nil? :eval ${str dstr} _ #special_file_keyword? _)
48
-
49
- (send _ {:class_eval :module_eval :instance_eval}
50
- ${str dstr})
51
- (send _ {:class_eval :module_eval :instance_eval}
52
- ${str dstr} #special_file_keyword?)
53
- (send _ {:class_eval :module_eval :instance_eval}
54
- ${str dstr} #special_file_keyword? _)
55
- }
49
+ def_node_matcher :valid_eval_receiver?, <<~PATTERN
50
+ { nil? (const {nil? cbase} :Kernel) }
56
51
  PATTERN
57
52
 
58
53
  def_node_matcher :line_with_offset?, <<~PATTERN
@@ -63,17 +58,31 @@ module RuboCop
63
58
  PATTERN
64
59
 
65
60
  def on_send(node)
66
- eval_without_location?(node) do |code|
67
- if with_lineno?(node)
68
- on_with_lineno(node, code)
69
- else
70
- add_offense(node)
71
- end
61
+ # Classes should not redefine eval, but in case one does, it shouldn't
62
+ # register an offense. Only `eval` without a receiver and `Kernel.eval`
63
+ # are considered.
64
+ return if node.method?(:eval) && !valid_eval_receiver?(node.receiver)
65
+
66
+ code = node.arguments.first
67
+ return unless code.str_type? || code.dstr_type?
68
+
69
+ file, line = file_and_line(node)
70
+
71
+ if line
72
+ check_file(node, file)
73
+ check_line(node, code)
74
+ else
75
+ register_offense(node)
72
76
  end
73
77
  end
74
78
 
75
79
  private
76
80
 
81
+ def register_offense(node)
82
+ msg = node.method?(:eval) ? MSG_EVAL : format(MSG, method_name: node.method_name)
83
+ add_offense(node, message: msg)
84
+ end
85
+
77
86
  def special_file_keyword?(node)
78
87
  node.str_type? &&
79
88
  node.source == '__FILE__'
@@ -84,6 +93,11 @@ module RuboCop
84
93
  node.source == '__LINE__'
85
94
  end
86
95
 
96
+ def file_and_line(node)
97
+ base = node.method?(:eval) ? 2 : 1
98
+ [node.arguments[base], node.arguments[base + 1]]
99
+ end
100
+
87
101
  # FIXME: It's a Style/ConditionalAssignment's false positive.
88
102
  # rubocop:disable Style/ConditionalAssignment
89
103
  def with_lineno?(node)
@@ -95,17 +109,32 @@ module RuboCop
95
109
  end
96
110
  # rubocop:enable Style/ConditionalAssignment
97
111
 
98
- def message_incorrect_line(actual, sign, line_diff)
112
+ def message_incorrect_line(method_name, actual, sign, line_diff)
99
113
  expected =
100
114
  if line_diff.zero?
101
115
  '__LINE__'
102
116
  else
103
117
  "__LINE__ #{sign} #{line_diff}"
104
118
  end
105
- format(MSG_INCORRECT_LINE, actual: actual.source, expected: expected)
119
+
120
+ format(MSG_INCORRECT_LINE,
121
+ method_name: method_name,
122
+ actual: actual.source,
123
+ expected: expected)
124
+ end
125
+
126
+ def check_file(node, file_node)
127
+ return true if special_file_keyword?(file_node)
128
+
129
+ message = format(MSG_INCORRECT_FILE,
130
+ method_name: node.method_name,
131
+ expected: '__FILE__',
132
+ actual: file_node.source)
133
+
134
+ add_offense(file_node, message: message)
106
135
  end
107
136
 
108
- def on_with_lineno(node, code)
137
+ def check_line(node, code)
109
138
  line_node = node.arguments.last
110
139
  lineno_range = line_node.loc.expression
111
140
  line_diff = string_first_line(code) - lineno_range.first_line
@@ -124,22 +153,22 @@ module RuboCop
124
153
  end
125
154
  end
126
155
 
127
- def add_offense_for_same_line(_node, line_node)
156
+ def add_offense_for_same_line(node, line_node)
128
157
  return if special_line_keyword?(line_node)
129
158
 
130
159
  add_offense(
131
160
  line_node.loc.expression,
132
- message: message_incorrect_line(line_node, nil, 0)
161
+ message: message_incorrect_line(node.method_name, line_node, nil, 0)
133
162
  )
134
163
  end
135
164
 
136
- def add_offense_for_different_line(_node, line_node, line_diff)
165
+ def add_offense_for_different_line(node, line_node, line_diff)
137
166
  sign = line_diff.positive? ? :+ : :-
138
167
  return if line_with_offset?(line_node, sign, line_diff.abs)
139
168
 
140
169
  add_offense(
141
170
  line_node.loc.expression,
142
- message: message_incorrect_line(line_node, sign, line_diff.abs)
171
+ message: message_incorrect_line(node.method_name, line_node, sign, line_diff.abs)
143
172
  )
144
173
  end
145
174
  end
@@ -6,6 +6,9 @@ module RuboCop
6
6
  # This cop enforces the use of explicit block argument to avoid writing
7
7
  # block literal that just passes its arguments to another block.
8
8
  #
9
+ # NOTE: This cop only registers an offense if the block args match the
10
+ # yield args exactly.
11
+ #
9
12
  # @example
10
13
  # # bad
11
14
  # def with_tmp_dir
@@ -75,7 +78,14 @@ module RuboCop
75
78
  private
76
79
 
77
80
  def yielding_arguments?(block_args, yield_args)
81
+ yield_args = yield_args.dup.fill(
82
+ nil,
83
+ yield_args.length, block_args.length - yield_args.length
84
+ )
85
+
78
86
  yield_args.zip(block_args).all? do |yield_arg, block_arg|
87
+ next false unless yield_arg && block_arg
88
+
79
89
  block_arg && yield_arg.children.first == block_arg.children.first
80
90
  end
81
91
  end