rubocop-ast
rubocop-ast copied to clipboard
Handle numblock in each cops
Numbered Parameters feature has been introduced since 2.7.
The new node type, numblock, will be supported by rubocop-hq/rubocop#7665, but we still need to modify cops that use on_block or block_type? methods.
For example, Style/BlockDelimiters cop does not work for numblock even if the pull request is merged.
# with TargetRubyVersion: 2.7, and the PR.
# The cop adds an offense to the following code.
items.each do |item| item / 5 end
# The cop does not add an offense but it should.
items.each do _1 / 5 end
In this case, I guess we can add alias on_numblock on_block to the cop. And we can probably add the same code to the similar cops.
And I guess we also need to modify Node#block_type? method call.
I guess we can extend numblock node with BlockNode extension.
Expected behavior
Cops that work for block should work for numblock also.
Actual behavior
It does not work well even with rubocop-hq/rubocop#7665
Steps to reproduce the problem
For Stlye/BlockDelimiters example, we can reproduce the problem with the following commands.
- Install RuboCop with rubocop-hq/rubocop#7665
- Put .rubocop.yml with
TargetRubyVersion: 2.7 - Put the example as a Ruby file
- Execute RuboCop
And we can find the potential target cops with git grep.
$ git grep on_block
lib/rubocop/ast/traversal.rb: def on_block(node)
lib/rubocop/cop/layout/access_modifier_indentation.rb: alias on_block on_class
lib/rubocop/cop/layout/block_alignment.rb: def on_block(node)
lib/rubocop/cop/layout/block_end_newline.rb: def on_block(node)
lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb: def on_block(node)
lib/rubocop/cop/layout/empty_lines_around_block_body.rb: def on_block(node)
lib/rubocop/cop/layout/indentation_width.rb: def on_block(node)
lib/rubocop/cop/layout/multiline_block_layout.rb: def on_block(node)
lib/rubocop/cop/layout/space_around_block_parameters.rb: def on_block(node)
lib/rubocop/cop/layout/space_around_keyword.rb: def on_block(node)
lib/rubocop/cop/layout/space_before_block_braces.rb: def on_block(node)
lib/rubocop/cop/layout/space_inside_block_braces.rb: def on_block(node)
lib/rubocop/cop/lint/next_without_accumulator.rb: def on_block(node)
lib/rubocop/cop/lint/non_deterministic_require_order.rb: def on_block(node)
lib/rubocop/cop/lint/redundant_with_index.rb: def on_block(node)
lib/rubocop/cop/lint/redundant_with_object.rb: def on_block(node)
lib/rubocop/cop/lint/useless_access_modifier.rb: def on_block(node)
lib/rubocop/cop/lint/void.rb: def on_block(node)
lib/rubocop/cop/metrics/block_length.rb: def on_block(node)
lib/rubocop/cop/metrics/method_length.rb: def on_block(node)
lib/rubocop/cop/mixin/method_complexity.rb: def on_block(node)
lib/rubocop/cop/naming/block_parameter_name.rb: def on_block(node)
lib/rubocop/cop/naming/variable_name.rb: alias on_blockarg on_lvasgn
lib/rubocop/cop/style/block_delimiters.rb: def on_block(node)
lib/rubocop/cop/style/collection_methods.rb: def on_block(node)
lib/rubocop/cop/style/each_for_simple_loop.rb: def on_block(node)
lib/rubocop/cop/style/each_with_object.rb: def on_block(node)
lib/rubocop/cop/style/empty_block_parameter.rb: def on_block(node)
lib/rubocop/cop/style/empty_lambda_parameter.rb: def on_block(node)
lib/rubocop/cop/style/for.rb: def on_block(node)
lib/rubocop/cop/style/inverse_methods.rb: def on_block(node)
lib/rubocop/cop/style/lambda.rb: def on_block(node)
lib/rubocop/cop/style/method_called_on_do_end_block.rb: def on_block(node)
lib/rubocop/cop/style/multiline_block_chain.rb: def on_block(node)
lib/rubocop/cop/style/multiline_block_chain.rb: # found by subsequent calls to on_block.
lib/rubocop/cop/style/next.rb: def on_block(node)
lib/rubocop/cop/style/proc.rb: def on_block(node)
lib/rubocop/cop/style/redundant_begin.rb: def on_block(node)
lib/rubocop/cop/style/redundant_self.rb: def on_blockarg(node)
lib/rubocop/cop/style/redundant_self.rb: def on_block(node)
lib/rubocop/cop/style/redundant_sort_by.rb: def on_block(node)
lib/rubocop/cop/style/single_line_block_params.rb: def on_block(node)
lib/rubocop/cop/style/symbol_proc.rb: def on_block(node)
$ git grep -F block_type?
lib/rubocop/ast/node/mixin/method_dispatch_node.rb: parent&.block_type? && eql?(parent.send_node)
lib/rubocop/cop/lint/ambiguous_block_association.rb: send_node.last_argument.block_type? &&
lib/rubocop/cop/lint/assignment_in_condition.rb: return if node.condition.block_type?
lib/rubocop/cop/lint/shadowed_argument.rb: node.conditional? || node.block_type? ||
lib/rubocop/cop/metrics/block_nesting.rb: count_blocks? && node.block_type?
lib/rubocop/cop/mixin/multiline_expression_indentation.rb: break false if a.block_type?
lib/rubocop/cop/mixin/multiline_expression_indentation.rb: ancestor.block_type? && part_of_block_body?(candidate, ancestor)
lib/rubocop/cop/style/auto_resource_cleanup.rb: (parent && (parent.block_type? || !parent.lvasgn_type?))
lib/rubocop/cop/style/inverse_methods.rb: if node.block_type?
lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb: parent = node.parent&.block_type? ? node.parent.parent : node.parent
lib/rubocop/cop/style/method_called_on_do_end_block.rb: return unless receiver&.block_type? &&
lib/rubocop/cop/style/multiline_block_chain.rb: next unless receiver&.block_type? && receiver&.multiline?
lib/rubocop/cop/style/parallel_assignment.rb: node.block_type? || node.send_type?
lib/rubocop/cop/style/redundant_parentheses.rb: !ancestor.begin_type? && !ancestor.def_type? && !ancestor.block_type?
lib/rubocop/cop/style/safe_navigation.rb: receiver = if method_chain.block_type?
lib/rubocop/cop/variable_force/variable.rb: argument? && @scope.node.block_type?
lib/rubocop/cop/variable_force/variable_table.rb: return nil unless scope.node.block_type?
lib/rubocop/cop/variable_force/variable_table.rb: break variables unless scope.node.block_type?
lib/rubocop/cop/variable_force/variable_table.rb: return unless current_scope.node.block_type?
spec/rubocop/ast/send_node_spec.rb: it { expect(send_node.block_node.block_type?).to be(true) }
spec/rubocop/ast/super_node_spec.rb: it { expect(super_node.block_node.block_type?).to be(true) }
RuboCop version
master (with rubocop-hq/rubocop#7665 )
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution and understanding!
I'll see what I can do.
I agree with you that it should work out of the box as much as possible. I would alias on_numblock to on_block; cops that want to do something different can override it but by default it would work. What do you think of Block#arguments returning an array of Nodes like (arg :_1) instead of [] as currently, to make it even more similar?
I'd be tempted for block_type? to be true even for type == :numblock, but maybe it's best to define a common genblock_type?
Transferring to rubocop-ast
I haven't seen any issues with using alias on_numblock on_block, and there's even an InternalAffairs/NumblockHandler cop now.
At least in rubocop-rspec we often disable the cop and skip aliasing, as certain DSL methods don't yield arguments to their blocks, and numblock handling is redundant, like in let(:foo) { "bar" }.
Is there anything actionable left here?
Thanks for the feedback. Let's close then