diff --git a/changelog/change_enable_blocknodeargument_list_for.md b/changelog/change_enable_blocknodeargument_list_for.md new file mode 100644 index 000000000..57b773d31 --- /dev/null +++ b/changelog/change_enable_blocknodeargument_list_for.md @@ -0,0 +1 @@ +* [#155](https://github.com/rubocop-hq/rubocop-ast/pull/155): Enable `BlockNode#argument_list` for `numblock`s. ([@dvandersluis][]) diff --git a/lib/rubocop/ast/node/block_node.rb b/lib/rubocop/ast/node/block_node.rb index a17ed7b54..523690586 100644 --- a/lib/rubocop/ast/node/block_node.rb +++ b/lib/rubocop/ast/node/block_node.rb @@ -40,9 +40,11 @@ def arguments # # @return [Array] def argument_list - return [].freeze unless arguments? - - arguments.argument_list + if numblock_type? + numbered_arguments + else + arguments.argument_list + end end # The body of this block. @@ -130,6 +132,18 @@ def lambda? def void_context? VOID_CONTEXT_METHODS.include?(method_name) end + + private + + # Numbered arguments of this `numblock`. + def numbered_arguments + return [].freeze unless numblock_type? + + max_param = children[1] + 1.upto(max_param).map do |i| + ArgNode.new(:arg, [:"_#{i}"]) + end.freeze + end end end end diff --git a/spec/rubocop/ast/block_node_spec.rb b/spec/rubocop/ast/block_node_spec.rb index 66ce0ef69..147e5649e 100644 --- a/spec/rubocop/ast/block_node_spec.rb +++ b/spec/rubocop/ast/block_node_spec.rb @@ -52,6 +52,8 @@ describe '#argument_list' do subject(:argument_list) { block_node.argument_list } + let(:names) { argument_list.map(&:name) } + context 'with no arguments' do let(:source) { 'foo { bar }' } @@ -59,18 +61,28 @@ end context 'all argument types' do - let(:source) { 'foo { |a, b = 42, (c, *d), e:, f: 42, **g, &h| nil }' } + let(:source) { 'foo { |a, b = 42, (c, *d), e:, f: 42, **g, &h; i| nil }' } - it { expect(argument_list.size).to eq(8) } + it { expect(names).to eq(%i[a b c d e f g h i]) } end + # rubocop:disable Naming/VariableNumber context '>= Ruby 2.7', :ruby27 do context 'using numbered parameters' do - let(:source) { 'foo { _1 }' } + context 'with skipped params' do + let(:source) { 'foo { _7 }' } + + it { expect(names).to eq(%i[_1 _2 _3 _4 _5 _6 _7]) } + end + + context 'with sequential params' do + let(:source) { 'foo { _1 + _2 }' } - it { is_expected.to be_empty } + it { expect(names).to eq(%i[_1 _2]) } + end end end + # rubocop:enable Naming/VariableNumber end describe '#arguments?' do