diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3b85970a6..1568c311b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: name: Base steps runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Check Whitespace run: git diff --check -- HEAD~1 ruby-spec: @@ -23,7 +23,7 @@ jobs: ruby: [ruby-2.7, ruby-3.0, ruby-3.1] os: [macos-latest, ubuntu-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} @@ -39,7 +39,7 @@ jobs: ruby: [ruby-2.7, ruby-3.0, ruby-3.1] os: [macos-latest, ubuntu-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 - uses: ruby/setup-ruby@v1 @@ -57,7 +57,7 @@ jobs: ruby: [ruby-2.7, ruby-3.0, ruby-3.1] os: [macos-latest, ubuntu-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} @@ -77,7 +77,7 @@ jobs: ruby: [ruby-2.7, ruby-3.0, ruby-3.1] os: [macos-latest, ubuntu-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} @@ -93,7 +93,7 @@ jobs: ruby: [ruby-2.7, ruby-3.0, ruby-3.1] os: [macos-latest, ubuntu-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} @@ -109,7 +109,7 @@ jobs: ruby: [ruby-2.7, ruby-3.0, ruby-3.1] os: [macos-latest, ubuntu-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} @@ -125,7 +125,7 @@ jobs: ruby: [ruby-2.7, ruby-3.0, ruby-3.1] os: [macos-latest, ubuntu-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} diff --git a/Changelog.md b/Changelog.md index a164246a7..9290058ed 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,9 @@ +# v0.11.6 2022-04-10 + +* [#1317](https://github.com/mbj/mutant/pull/1317) + + Fix forward arg mutations. + # v0.11.5 2022-04-03 * [#1314](https://github.com/mbj/mutant/pull/1314) diff --git a/Gemfile.lock b/Gemfile.lock index ee49a8a33..59e1ff269 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - mutant (0.11.5) + mutant (0.11.6) diff-lcs (~> 1.3) parser (~> 3.1.0) regexp_parser (~> 2.0, >= 2.0.3) diff --git a/foo.rb b/foo.rb deleted file mode 100644 index fcad1d9a1..000000000 --- a/foo.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -def verses(first_verse, last_verse) - first_verse.downto(last_verse).map { verse(_1) }.join("\n") -end diff --git a/lib/mutant/mutation.rb b/lib/mutant/mutation.rb index 608c25385..34971e33c 100644 --- a/lib/mutant/mutation.rb +++ b/lib/mutant/mutation.rb @@ -7,7 +7,7 @@ class Mutation include Concord::Public.new(:subject, :node) CODE_DELIMITER = "\0" - CODE_RANGE = (0..4).freeze + CODE_RANGE = (..4).freeze # Mutation identification code # diff --git a/lib/mutant/mutator/node/arguments.rb b/lib/mutant/mutator/node/arguments.rb index 3eb689384..b7ed60357 100644 --- a/lib/mutant/mutator/node/arguments.rb +++ b/lib/mutant/mutator/node/arguments.rb @@ -19,17 +19,27 @@ def dispatch end def emit_argument_presence - emit_type unless removed_block_arg?(EMPTY_ARRAY) + emit_type unless removed_block_arg?(EMPTY_ARRAY) || forward_arg? - Util::Array::Presence.call(children).each do |children| - unless removed_block_arg?(children) || (children.one? && n_mlhs?(children.first)) - emit_type(*children) + children.each_with_index do |removed, index| + new_arguments = children.dup + new_arguments.delete_at(index) + unless n_forward_arg?(removed) || removed_block_arg?(new_arguments) || only_mlhs?(new_arguments) + emit_type(*new_arguments) end end end - def removed_block_arg?(children) - anonymous_block_arg? && children.none?(&ANONYMOUS_BLOCKARG_PRED) + def only_mlhs?(new_arguments) + new_arguments.one? && n_mlhs?(new_arguments.first) + end + + def forward_arg? + children.last && n_forward_arg?(children.last) + end + + def removed_block_arg?(new_arguments) + anonymous_block_arg? && new_arguments.none?(&ANONYMOUS_BLOCKARG_PRED) end def anonymous_block_arg? @@ -47,7 +57,7 @@ def emit_argument_mutations end def invalid_argument_replacement?(mutant, index) - n_arg?(mutant) && children[0...index].any?(&method(:n_optarg?)) + n_arg?(mutant) && children[...index].any?(&method(:n_optarg?)) end def emit_mlhs_expansion diff --git a/lib/mutant/mutator/node/send.rb b/lib/mutant/mutator/node/send.rb index 4632d9a64..ea75e818d 100644 --- a/lib/mutant/mutator/node/send.rb +++ b/lib/mutant/mutator/node/send.rb @@ -241,7 +241,9 @@ def emit_argument_propagation argument = Mutant::Util.one(arguments) - emit_propagation(argument) unless n_kwargs?(argument) + return if n_kwargs?(argument) || n_forwarded_args?(argument) + + emit_propagation(argument) end def mutate_receiver diff --git a/lib/mutant/mutator/node/send/attribute_assignment.rb b/lib/mutant/mutator/node/send/attribute_assignment.rb index adff72a98..081622e9b 100644 --- a/lib/mutant/mutator/node/send/attribute_assignment.rb +++ b/lib/mutant/mutator/node/send/attribute_assignment.rb @@ -7,7 +7,7 @@ class Send # Mutator for attribute assignments class AttributeAssignment < self - ATTRIBUTE_RANGE = (0..-2).freeze + ATTRIBUTE_RANGE = (..-2).freeze private_constant(*constants(false)) diff --git a/lib/mutant/mutator/node/when.rb b/lib/mutant/mutator/node/when.rb index bb3ebf625..979a9fc7d 100644 --- a/lib/mutant/mutator/node/when.rb +++ b/lib/mutant/mutator/node/when.rb @@ -22,7 +22,7 @@ def dispatch def mutate_conditions conditions = children.length - 1 - children[0..-2].each_index do |index| + children[..-2].each_index do |index| delete_child(index) if conditions > 1 mutate_child(index) end diff --git a/lib/mutant/version.rb b/lib/mutant/version.rb index 340d97db8..6a930fa2d 100644 --- a/lib/mutant/version.rb +++ b/lib/mutant/version.rb @@ -2,5 +2,5 @@ module Mutant # Current mutant version - VERSION = '0.11.5' + VERSION = '0.11.6' end # Mutant diff --git a/meta/def.rb b/meta/def.rb index 6ca649e5f..d2ed58844 100644 --- a/meta/def.rb +++ b/meta/def.rb @@ -170,7 +170,6 @@ end Mutant::Meta::Example.add :def do - source 'def self.foo(a, b); end' # Deletion of each argument @@ -188,3 +187,29 @@ mutation 'def self.foo(a, b); raise; end' mutation 'def self.foo(a, b); super; end' end + +Mutant::Meta::Example.add :def do + source 'def foo(...); end' + + mutation 'def foo(...); raise; end' + mutation 'def foo(...); super; end' +end + +Mutant::Meta::Example.add :def do + source 'def foo(a, ...); end' + + mutation 'def foo(_a, ...); end' + mutation 'def foo(a, ...); raise; end' + mutation 'def foo(a, ...); super; end' + mutation 'def foo(...); end' +end + +Mutant::Meta::Example.add :def, :send do + source 'def foo(...); bar(...) end' + + mutation 'def foo(...); bar; end' + mutation 'def foo(...); raise; end' + mutation 'def foo(...); super; end' + mutation 'def foo(...); nil; end' + mutation 'def foo(...); end' +end diff --git a/spec/support/xspec.rb b/spec/support/xspec.rb index e2015a5f4..e933bee97 100644 --- a/spec/support/xspec.rb +++ b/spec/support/xspec.rb @@ -90,7 +90,7 @@ def self.assert_not_empty(event_list) private_class_method :assert_not_empty def self.assert_total(event_list) - return unless event_list[0..-2].map(&:first).any?(&TERMINATE_EVENTS.public_method(:include?)) + return unless event_list[..-2].map(&:first).any?(&TERMINATE_EVENTS.public_method(:include?)) fail "Reaction not total: #{event_list}" end diff --git a/spec/unit/mutant/cli_spec.rb b/spec/unit/mutant/cli_spec.rb index 7f0aec22a..6e11e1933 100644 --- a/spec/unit/mutant/cli_spec.rb +++ b/spec/unit/mutant/cli_spec.rb @@ -806,7 +806,7 @@ def self.main_body let(:expected_events) do [ - *super()[0..-2], + *super()[..-2], [ :stderr, :puts, diff --git a/spec/unit/mutant/expression/namespace/recursive_spec.rb b/spec/unit/mutant/expression/namespace/recursive_spec.rb index f342ecc0a..1015c17d0 100644 --- a/spec/unit/mutant/expression/namespace/recursive_spec.rb +++ b/spec/unit/mutant/expression/namespace/recursive_spec.rb @@ -49,19 +49,19 @@ context 'on constants' do let(:other) { parse_expression('TestApp::Literal::Deep') } - it { should be(input[0..-2].length) } + it { should be(input[..-2].length) } end context 'on singleton method' do let(:other) { parse_expression('TestApp::Literal.foo') } - it { should be(input[0..-2].length) } + it { should be(input[..-2].length) } end context 'on instance method' do let(:other) { parse_expression('TestApp::Literal#foo') } - it { should be(input[0..-2].length) } + it { should be(input[..-2].length) } end end end