Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enforce numblock verification for ALL the cops that check block nodes #10915

Merged
merged 47 commits into from Aug 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
1971dfa
Depend on rubocop-ast 1.20.1 for numblocks support in #macro?
gsamokovarov Aug 8, 2022
b214a06
Introduce InternalAffairs/NumblockHandler
gsamokovarov Aug 12, 2022
ec1739d
Disable InternalAffairs/NumbockHandler for block cops
gsamokovarov Aug 12, 2022
1cf4f08
Disable InternalAffairs/NumblockHandler for Layout/SpaceAroundBlockPa…
gsamokovarov Aug 12, 2022
462955c
Disable InternalAffairs/NumblockHandler for Lint/EmptyBlock
gsamokovarov Aug 12, 2022
fef71ab
Disable InternalAffairs/NumblockHandler for Naming/BlockParameterName
gsamokovarov Aug 12, 2022
5425fd8
Disable InternalAffairs/NumblockHandler for Style/TrailingCommaInBloc…
gsamokovarov Aug 12, 2022
e8afc00
Disable InternalAffairs/NumblockHandler for Style/SingleLineBlockParams
gsamokovarov Aug 12, 2022
37ef3de
Disable InternalAffairs/NumblockHandler for Style/EmptyBlockParameter
gsamokovarov Aug 12, 2022
71776fc
Disable InternalAffairs/NumblockHandler for Style/EmptyLambdaParameter
gsamokovarov Aug 12, 2022
45dc712
Disable InternalAffairs/NumblockHandler for Style/NilLambda
gsamokovarov Aug 12, 2022
9a3f41f
Disable InternalAffairs/NumblockHandler for Style/EachForSimpleLoop
gsamokovarov Aug 12, 2022
b5d452c
Disable InternalAffairs/NumblockHandler for Style/RedundantFetchBlock
gsamokovarov Aug 12, 2022
3b8b65d
Disable InternalAffairs/NumblockHandler for HashTransformMethod
gsamokovarov Aug 12, 2022
fff6f47
Disable InternalAffairs/NumblockHandler for Layout/SpaceAroundKeyword
gsamokovarov Aug 12, 2022
3fea156
Fix Layout/BlockAlignment with numblocks
gsamokovarov Aug 12, 2022
9297084
Fix Layout/BlockEndNewline with numblocks
gsamokovarov Aug 12, 2022
413cc86
Fix Layout/EmptyLinesAroundAccessModifier with numblocks
gsamokovarov Aug 12, 2022
8010fb4
Fix Layout/EmptyLinesAroundBlockBody with numblocks
gsamokovarov Aug 12, 2022
69b6400
Fix Layout/IndentationWidth with numblocks
gsamokovarov Aug 12, 2022
d4ad9bc
Fix Layout/LineLength with numblocks
gsamokovarov Aug 12, 2022
39d2ffc
Fix Layout/MultilineBlockLayout with numblocks
gsamokovarov Aug 12, 2022
9d90591
Fix Layout/SpaceBeforeBlockBraces with numblocks
gsamokovarov Aug 12, 2022
e707f3b
Fix Lint/NextWithoutAccumulator with numblocks
gsamokovarov Aug 12, 2022
911de36
Fix Lint/NonDeterministicRequireOrder with numblocks
gsamokovarov Aug 12, 2022
58a6577
Fix Lint/RedundantWithIndex with numblocks
gsamokovarov Aug 12, 2022
198047b
Fix Lint/RedundantWithObject with numblocks
gsamokovarov Aug 12, 2022
bff739a
Fix Lint/UnreachableLoop for numblocks
gsamokovarov Aug 12, 2022
8cb4af9
Fix Lint/UselessAccessModifier with numblocks
gsamokovarov Aug 12, 2022
92cbae5
Fix Lint/Void with numblocks
gsamokovarov Aug 12, 2022
494424c
Fix Metrics{AbcSize,CyclomaticComplexity} with numblocks
gsamokovarov Aug 12, 2022
d5dd796
Fix Style/MethodCalledOnDoEndBlock with numblocks
gsamokovarov Aug 12, 2022
6e67b89
Fix Style/Proc with numblocks
gsamokovarov Aug 12, 2022
b9555f6
Fix Style/For with numblocks
gsamokovarov Aug 12, 2022
a136188
Fix Style/TopLevelMethodDefinition with numblocks
gsamokovarov Aug 12, 2022
a049d32
Fix Style/CombinableLoops with numblocks
gsamokovarov Aug 12, 2022
33d5d21
Fix Style/MultilineBlockChain with numblocks
gsamokovarov Aug 12, 2022
254564b
Fix Style/ObjectThen with numblocks
gsamokovarov Aug 12, 2022
be532af
Fix Style/Next for numblocks
gsamokovarov Aug 12, 2022
88c78bd
Fix Style/RedundantSelf with numblocks
gsamokovarov Aug 12, 2022
bdb1db9
Fix Style/RedundantBegin with numblocks
gsamokovarov Aug 12, 2022
381c2b8
Fix Style/RedundantSortBy with numblocks
gsamokovarov Aug 12, 2022
c55de18
Fix Style/InverseMethods with numblocks
gsamokovarov Aug 12, 2022
ba93975
Fix Style/CollectionMethods with numblocks
gsamokovarov Aug 12, 2022
78532ed
Fix Style/EachWithObject with numblocks
gsamokovarov Aug 12, 2022
abb950d
Fix Style/HashEachMethods with numblock
gsamokovarov Aug 12, 2022
e63c32f
Single changelog entry for the block cops without numblock fixes
gsamokovarov Aug 12, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions .rubocop.yml
Expand Up @@ -163,5 +163,9 @@ InternalAffairs/StyleDetectedApiUse:
Exclude:
- 'lib/rubocop/cop/mixin/percent_array.rb'

InternalAffairs/NumblockHandler:
gsamokovarov marked this conversation as resolved.
Show resolved Hide resolved
Exclude:
- 'lib/rubocop/cop/internal_affairs/*.rb'

Gemspec/DependencyVersion:
Enabled: true
1 change: 1 addition & 0 deletions changelog/change_rubocop_ast_version.md
@@ -0,0 +1 @@
* [#10915](https://github.com/rubocop/rubocop/pull/10915): Depend on rubocop-ast 1.20.1 for numblocks support in #macro?. ([@gsamokovarov][])
1 change: 1 addition & 0 deletions changelog/fix_block_cops_without_numblock_support.md
@@ -0,0 +1 @@
* [#10915](https://github.com/rubocop/rubocop/pull/10915): Fix numblock support to `Layout/BlockAlignment`, `Layout/BlockEndNewline`, `Layout/EmptyLinesAroundAccessModifier`, `Layout/EmptyLinesAroundBlockBody`, `Layout/IndentationWidth`, `Layout/LineLength`, `Layout/MultilineBlockLayout`, `Layout/SpaceBeforeBlockBraces`, `Lint/NextWithoutAccumulator`, `Lint/NonDeterministicRequireOrder`, `Lint/RedundantWithIndex`, `Lint/RedundantWithObject`, `Lint/UnreachableLoop`, `Lint/UselessAccessModifier`, `Lint/Void`, `Metrics/AbcSize`, `Metrics/CyclomaticComplexity`, `Style/CollectionMethods`, `Style/CombinableLoops`, `Style/EachWithObject`, `Style/For`, `Style/HashEachMethods`, `Style/InverseMethods`, `Style/MethodCalledOnDoEndBlock`, `Style/MultilineBlockChain`, `Style/Next`, `Style/ObjectThen`, `Style/Proc`, `Style/RedundantBegin`, `Style/RedundantSelf`, `Style/RedundantSortBy` and `Style/TopLevelMethodDefinition`. ([@gsamokovarov][])
2 changes: 1 addition & 1 deletion lib/rubocop/cop/gemspec/require_mfa.rb
Expand Up @@ -84,7 +84,7 @@ class RequireMFA < Base
(str "true")
PATTERN

def on_block(node) # rubocop:disable Metrics/MethodLength
def on_block(node) # rubocop:disable Metrics/MethodLength, InternalAffairs/NumblockHandler
gem_specification(node) do |block_var|
metadata_value = metadata(node)
mfa_value = mfa_value(metadata_value)
Expand Down
1 change: 1 addition & 0 deletions lib/rubocop/cop/internal_affairs.rb
Expand Up @@ -10,6 +10,7 @@
require_relative 'internal_affairs/node_destructuring'
require_relative 'internal_affairs/node_matcher_directive'
require_relative 'internal_affairs/node_type_predicate'
require_relative 'internal_affairs/numblock_handler'
require_relative 'internal_affairs/offense_location_keyword'
require_relative 'internal_affairs/redundant_context_config_parameter'
require_relative 'internal_affairs/redundant_described_class_as_subject'
Expand Down
69 changes: 69 additions & 0 deletions lib/rubocop/cop/internal_affairs/numblock_handler.rb
@@ -0,0 +1,69 @@
# frozen_string_literal: true

module RuboCop
module Cop
module InternalAffairs
# Checks for missing `numblock handlers. The blocks with numbered
# arguments introduced in Ruby 2.7 are parsed with a node type of
# `numblock` instead of block. Cops that define `block` handlers
# need to define `numblock` handlers or disable this cope for them.
#
# @example
#
# # bad
# class BlockRelatedCop < Base
# def on_block(node)
# end
# end
#
# # good
# class BlockRelatedCop < Base
# def on_block(node)
# end
#
# alias on_numblock on_block
# end
#
# class BlockRelatedCop < Base
# def on_block(node)
# end
#
# alias_method :on_numblock, :on_block
# end
#
# class BlockRelatedCop < Base
# def on_block(node)
# end
#
# def on_numblock(node)
# end
# end
class NumblockHandler < Base
MSG = 'Define on_numblock to handle blocks with numbered arguments.'

def on_def(node)
return unless block_handler?(node)
return unless node.parent

add_offense(node) unless numblock_handler?(node.parent)
end

private

# @!method block_handler?(node)
def_node_matcher :block_handler?, <<~PATTERN
(def :on_block (args (arg :node)) ...)
PATTERN

# @!method numblock_handler?(node)
def_node_matcher :numblock_handler?, <<~PATTERN
{
`(def :on_numblock (args (arg :node)) ...)
`(alias (sym :on_numblock) (sym :on_block))
`(send nil? :alias_method (sym :on_numblock) (sym :on_block))
}
PATTERN
end
end
end
end
2 changes: 2 additions & 0 deletions lib/rubocop/cop/layout/block_alignment.rb
Expand Up @@ -82,6 +82,8 @@ def on_block(node)
check_block_alignment(start_for_block_node(node), node)
end

alias on_numblock on_block

def style_parameter_name
'EnforcedStyleAlignWith'
end
Expand Down
2 changes: 2 additions & 0 deletions lib/rubocop/cop/layout/block_end_newline.rb
Expand Up @@ -39,6 +39,8 @@ def on_block(node)
register_offense(node)
end

alias on_numblock on_block

private

def register_offense(node)
Expand Down
7 changes: 5 additions & 2 deletions lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb
Expand Up @@ -80,8 +80,11 @@ def on_block(node)
@block_line = node.source_range.first_line
end

def on_send(node)
return unless node.bare_access_modifier? && !node.parent&.block_type?
alias on_numblock on_block

def on_send(node) # rubocop:disable Metrics/CyclomaticComplexity
return unless node.bare_access_modifier? &&
!(node.parent&.block_type? || node.parent&.numblock_type?)
return if expected_empty_lines?(node)

message = message(node)
Expand Down
2 changes: 2 additions & 0 deletions lib/rubocop/cop/layout/empty_lines_around_block_body.rb
Expand Up @@ -32,6 +32,8 @@ def on_block(node)

check(node, node.body, adjusted_first_line: first_line)
end

alias on_numblock on_block
end
end
end
Expand Down
2 changes: 2 additions & 0 deletions lib/rubocop/cop/layout/indentation_width.rb
Expand Up @@ -90,6 +90,8 @@ def on_block(node)
check_members(end_loc, [node.body])
end

alias on_numblock on_block

def on_class(node)
base = node.loc.keyword
return if same_line?(base, node.body)
Expand Down
4 changes: 3 additions & 1 deletion lib/rubocop/cop/layout/line_length.rb
Expand Up @@ -74,6 +74,8 @@ def on_block(node)
check_for_breakable_block(node)
end

alias on_numblock on_block

def on_potential_breakable_node(node)
check_for_breakable_node(node)
end
Expand Down Expand Up @@ -131,7 +133,7 @@ def breakable_block_range(block_node)
if block_node.arguments? && !block_node.lambda?
block_node.arguments.loc.end
else
block_node.loc.begin
block_node.braces? ? block_node.loc.begin : block_node.loc.begin.adjust(begin_pos: 1)
end
end

Expand Down
2 changes: 2 additions & 0 deletions lib/rubocop/cop/layout/multiline_block_layout.rb
Expand Up @@ -68,6 +68,8 @@ def on_block(node)
add_offense_for_expression(node, node.body, MSG)
end

alias on_numblock on_block

private

def args_on_beginning_line?(node)
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/layout/space_around_block_parameters.rb
Expand Up @@ -29,7 +29,7 @@ class SpaceAroundBlockParameters < Base
include RangeHelp
extend AutoCorrector

def on_block(node)
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
arguments = node.arguments

return unless node.arguments? && pipes?(arguments)
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/layout/space_around_keyword.rb
Expand Up @@ -41,7 +41,7 @@ def on_and(node)
check(node, [:operator].freeze) if node.keyword?
end

def on_block(node)
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
check(node, %i[begin end].freeze)
end

Expand Down
2 changes: 2 additions & 0 deletions lib/rubocop/cop/layout/space_before_block_braces.rb
Expand Up @@ -76,6 +76,8 @@ def on_block(node)
end
end

alias on_numblock on_block

private

def check_empty(left_brace, space_plus_brace, used_style)
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/lint/empty_block.rb
Expand Up @@ -63,7 +63,7 @@ module Lint
class EmptyBlock < Base
MSG = 'Empty block detected.'

def on_block(node)
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
return if node.body
return if allow_empty_lambdas? && lambda_or_proc?(node)
return if cop_config['AllowComments'] && allow_comment?(node)
Expand Down
31 changes: 25 additions & 6 deletions lib/rubocop/cop/lint/next_without_accumulator.rb
Expand Up @@ -25,13 +25,8 @@ module Lint
class NextWithoutAccumulator < Base
MSG = 'Use `next` with an accumulator argument in a `reduce`.'

# @!method on_body_of_reduce(node)
def_node_matcher :on_body_of_reduce, <<~PATTERN
(block (send _recv {:reduce :inject} !sym) _blockargs $(begin ...))
PATTERN

def on_block(node)
on_body_of_reduce(node) do |body|
on_block_body_of_reduce(node) do |body|
void_next = body.each_node(:next).find do |n|
n.children.empty? && parent_block_node(n) == node
end
Expand All @@ -40,11 +35,35 @@ def on_block(node)
end
end

def on_numblock(node)
on_numblock_body_of_reduce(node) do |body|
void_next = body.each_node(:next).find do |n|
n.children.empty? && parent_numblock_node(n) == node
end

add_offense(void_next) if void_next
end
end

private

# @!method on_block_body_of_reduce(node)
def_node_matcher :on_block_body_of_reduce, <<~PATTERN
(block (send _recv {:reduce :inject} !sym) _blockargs $(begin ...))
PATTERN

# @!method on_numblock_body_of_reduce(node)
def_node_matcher :on_numblock_body_of_reduce, <<~PATTERN
(numblock (send _recv {:reduce :inject} !sym) _argscount $(begin ...))
PATTERN

def parent_block_node(node)
node.each_ancestor(:block).first
end

def parent_numblock_node(node)
node.each_ancestor(:numblock).first
end
end
end
end
Expand Down
12 changes: 12 additions & 0 deletions lib/rubocop/cop/lint/non_deterministic_require_order.rb
Expand Up @@ -74,6 +74,18 @@ def on_block(node)
end
end

def on_numblock(node)
return if target_ruby_version >= 3.0
return unless node.body
return unless unsorted_dir_loop?(node.send_node)

node.argument_list
.filter { |argument| var_is_required?(node.body, argument.name) }
.each do
add_offense(node.send_node) { |corrector| correct_block(corrector, node.send_node) }
end
end

def on_block_pass(node)
return if target_ruby_version >= 3.0
return unless method_require?(node)
Expand Down
23 changes: 13 additions & 10 deletions lib/rubocop/cop/lint/redundant_with_index.rb
Expand Up @@ -33,16 +33,6 @@ class RedundantWithIndex < Base
MSG_EACH_WITH_INDEX = 'Use `each` instead of `each_with_index`.'
MSG_WITH_INDEX = 'Remove redundant `with_index`.'

# @!method redundant_with_index?(node)
def_node_matcher :redundant_with_index?, <<~PATTERN
(block
$(send
_ {:each_with_index :with_index} ...)
(args
(arg _))
...)
PATTERN

def on_block(node)
return unless (send = redundant_with_index?(node))

Expand All @@ -58,8 +48,21 @@ def on_block(node)
end
end

alias on_numblock on_block

private

# @!method redundant_with_index?(node)
def_node_matcher :redundant_with_index?, <<~PATTERN
{
(block
$(send _ {:each_with_index :with_index} ...)
(args (arg _)) ...)
(numblock
$(send _ {:each_with_index :with_index} ...) 1 ...)
}
PATTERN

def message(node)
if node.method?(:each_with_index)
MSG_EACH_WITH_INDEX
Expand Down
23 changes: 12 additions & 11 deletions lib/rubocop/cop/lint/redundant_with_object.rb
Expand Up @@ -31,19 +31,8 @@ class RedundantWithObject < Base
extend AutoCorrector

MSG_EACH_WITH_OBJECT = 'Use `each` instead of `each_with_object`.'

MSG_WITH_OBJECT = 'Remove redundant `with_object`.'

# @!method redundant_with_object?(node)
def_node_matcher :redundant_with_object?, <<~PATTERN
(block
$(send _ {:each_with_object :with_object}
_)
(args
(arg _))
...)
PATTERN

def on_block(node)
return unless (send = redundant_with_object?(node))

Expand All @@ -59,8 +48,20 @@ def on_block(node)
end
end

alias on_numblock on_block

private

# @!method redundant_with_object?(node)
def_node_matcher :redundant_with_object?, <<~PATTERN
{
(block
$(send _ {:each_with_object :with_object} _) (args (arg _)) ...)
(numblock
$(send _ {:each_with_object :with_object} _) 1 ...)
}
PATTERN

def message(node)
if node.method?(:each_with_object)
MSG_EACH_WITH_OBJECT
Expand Down
8 changes: 7 additions & 1 deletion lib/rubocop/cop/lint/unreachable_loop.rb
Expand Up @@ -101,10 +101,14 @@ def on_block(node)
check(node) if loop_method?(node)
end

def on_numblock(node)
check(node) if loop_method?(node)
end

private

def loop_method?(node)
return false unless node.block_type?
return false unless node.block_type? || node.numblock_type?

send_node = node.send_node
return false if matches_allowed_pattern?(send_node.source)
Expand Down Expand Up @@ -179,6 +183,8 @@ def check_case(node)

def preceded_by_continue_statement?(break_statement)
break_statement.left_siblings.any? do |sibling|
# Numblocks have the arguments count as a number in the AST.
next if sibling.is_a?(Integer)
next if sibling.loop_keyword? || loop_method?(sibling)

sibling.each_descendant(*CONTINUE_KEYWORDS).any?
Expand Down