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

Fix to reset visibility after insertion #1314

Merged
merged 3 commits into from
Apr 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# v0.11.5 unreleased

* [#1314](https://github.com/mbj/mutant/pull/1314)

Fix visibility of mutated methods to retain original value.

Fix: [#1242]

* [#1311](https://github.com/mbj/mutant/pull/1311)

Change to fully enforced license.
Expand Down
46 changes: 23 additions & 23 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
mutant (0.11.4)
mutant (0.11.5)
diff-lcs (~> 1.3)
parser (~> 3.1.0)
regexp_parser (~> 2.0, >= 2.0.3)
Expand All @@ -18,41 +18,41 @@ GEM
specs:
ast (2.4.2)
diff-lcs (1.5.0)
parallel (1.21.0)
parser (3.1.0.0)
parallel (1.22.1)
parser (3.1.1.0)
ast (~> 2.4.1)
rainbow (3.0.0)
regexp_parser (2.1.1)
rainbow (3.1.1)
regexp_parser (2.2.1)
rexml (3.2.5)
rspec (3.10.0)
rspec-core (~> 3.10.0)
rspec-expectations (~> 3.10.0)
rspec-mocks (~> 3.10.0)
rspec-core (3.10.1)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
rspec (3.11.0)
rspec-core (~> 3.11.0)
rspec-expectations (~> 3.11.0)
rspec-mocks (~> 3.11.0)
rspec-core (3.11.0)
rspec-support (~> 3.11.0)
rspec-expectations (3.11.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-support (~> 3.11.0)
rspec-its (1.3.0)
rspec-core (>= 3.0.0)
rspec-expectations (>= 3.0.0)
rspec-mocks (3.10.2)
rspec-mocks (3.11.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-support (3.10.3)
rubocop (1.22.3)
rspec-support (~> 3.11.0)
rspec-support (3.11.0)
rubocop (1.26.1)
parallel (~> 1.10)
parser (>= 3.0.0.0)
parser (>= 3.1.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml
rubocop-ast (>= 1.12.0, < 2.0)
rubocop-ast (>= 1.16.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.13.0)
parser (>= 3.0.1.1)
rubocop-ast (1.16.0)
parser (>= 3.1.1.0)
ruby-progressbar (1.11.0)
sorbet-runtime (0.5.9636)
sorbet-runtime (0.5.9837)
unicode-display_width (2.1.0)
unparser (0.6.4)
diff-lcs (~> 1.3)
Expand All @@ -71,4 +71,4 @@ DEPENDENCIES
rubocop (~> 1.7)

BUNDLED WITH
2.2.32
2.3.6
4 changes: 2 additions & 2 deletions lib/mutant/ast/regexp/transformer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ class Table
#
# @return [Table]
def self.create(*rows)
table = rows.map do |ast_type, token, klass|
table = rows.to_h do |ast_type, token, klass|
[ast_type, Mapping.new(::Regexp::Token.new(*token), klass)]
end.to_h
end

new(table)
end
Expand Down
4 changes: 2 additions & 2 deletions lib/mutant/cli/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,9 @@ def parse_subcommand(arguments)
end

def format_subcommands
commands = subcommands.map do |subcommand|
commands = subcommands.to_h do |subcommand|
[subcommand.command_name, subcommand.short_description]
end.to_h
end

width = commands.each_key.map(&:length).max

Expand Down
4 changes: 2 additions & 2 deletions lib/mutant/env.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ def cover_index(mutation_index)
#
# @return Hash{Mutation => Enumerable<Test>}
def selections
subjects.map do |subject|
subjects.to_h do |subject|
[subject, selector.call(subject)]
end.to_h
end
end
memoize :selections

Expand Down
5 changes: 2 additions & 3 deletions lib/mutant/matcher/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class Config

private_constant(*constants(false))

DEFAULT = new(anima.attribute_names.map { |name| [name, []] }.to_h)
DEFAULT = new(anima.attribute_names.to_h { |name| [name, []] })

expression = Transform::Block.capture(:expression) do |input|
Mutant::Config::DEFAULT.expression_parser.call(input)
Expand Down Expand Up @@ -74,8 +74,7 @@ def add(attribute, value)
def merge(other)
self.class.new(
to_h
.map { |name, value| [name, value + other.public_send(name)] }
.to_h
.to_h { |name, value| [name, value + other.public_send(name)] }
)
end

Expand Down
30 changes: 27 additions & 3 deletions lib/mutant/matcher/method.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,40 @@ def subject
node = matched_node_path.last || return

self.class::SUBJECT_CLASS.new(
context: context,
node: node
context: context,
node: node,
visibility: visibility
)
end
memoize :subject

def matched_node_path
AST.find_last_path(ast, &method(:match?))
end
memoize :matched_node_path

def visibility
# This can be cleaned up once we are on >ruby-3.0
# Method#{public,private,protected}? exists there.
#
# On Ruby 3.1 this can just be:
#
# if target_method.private?
# :private
# elsif target_method.protected?
# :protected
# else
# :public
# end
#
# Change to this once 3.0 is EOL.
if scope.private_methods.include?(method_name)
:private
elsif scope.protected_methods.include?(method_name)
:protected
else
:public
end
end
end # Evaluator

private_constant(*constants(false))
Expand Down
10 changes: 10 additions & 0 deletions lib/mutant/matcher/method/instance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ def match?(node)
node.children.fetch(NAME_INDEX).equal?(method_name)
end

def visibility
if scope.private_instance_methods.include?(method_name)
:private
elsif scope.protected_instance_methods.include?(method_name)
:protected
else
:public
end
end

# Evaluator specialized for memoized instance methods
class Memoized < self
SUBJECT_CLASS = Subject::Method::Instance::Memoized
Expand Down
5 changes: 4 additions & 1 deletion lib/mutant/mutation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ def insert(kernel)
kernel: kernel,
source: monkeypatch,
subject: subject
)
).fmap do
subject.post_insert
nil
end
end

# Rendered mutation diff
Expand Down
2 changes: 1 addition & 1 deletion lib/mutant/repository/diff.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def diff_index(root)
Mutant
.traverse(->(line) { parse_line(root, line) }, lines)
.fmap do |paths|
paths.map { |path| [path.path, path] }.to_h
paths.to_h { |path| [path.path, path] }
end
end
end
Expand Down
7 changes: 7 additions & 0 deletions lib/mutant/subject.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ def prepare
self
end

# Perform post insert cleanup
#
# @return [self]
def post_insert
self
end

# Source line range
#
# @return [Range<Integer>]
Expand Down
1 change: 1 addition & 0 deletions lib/mutant/subject/method.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module Mutant
class Subject
# Abstract base class for method subjects
class Method < self
include anima.add(:visibility)

# Method name
#
Expand Down
5 changes: 5 additions & 0 deletions lib/mutant/subject/method/instance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ def prepare
self
end

def post_insert
scope.__send__(visibility, name)
self
end

# Mutator for memoizable memoized instance methods
class Memoized < self
include AST::Sexp
Expand Down
5 changes: 5 additions & 0 deletions lib/mutant/subject/method/singleton.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ def prepare
self
end

def post_insert
scope.singleton_class.__send__(visibility, name)
self
end

end # Singleton
end # Method
end # Subject
Expand Down
3 changes: 1 addition & 2 deletions lib/mutant/transform.rb
Original file line number Diff line number Diff line change
Expand Up @@ -351,15 +351,14 @@ def transform_optional(input)
def transform_keys(keys, input)
success(
keys
.map do |key|
.to_h do |key|
[
key.value,
coerce_key(key, input).from_right do |error|
return failure(error)
end
]
end
.to_h
)
end
# rubocop:enable Metrics/MethodLength
Expand Down
2 changes: 1 addition & 1 deletion lib/mutant/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

module Mutant
# Current mutant version
VERSION = '0.11.4'
VERSION = '0.11.5'
end # Mutant
3 changes: 0 additions & 3 deletions lib/mutant/zombifier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ class Zombifier

include AST::Sexp

# rubocop:disable Lint/InheritException
LoadError = Class.new(::LoadError)
# rubocop:enable Lint/InheritException

# Initialize object
#
# @param [Symbol] namespace
Expand Down
2 changes: 2 additions & 0 deletions mutant-minitest.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Gem::Specification.new do |gem|

gem.required_ruby_version = '>= 2.7'

gem.metadata['rubygems_mfa_required'] = 'true'

gem.add_runtime_dependency('minitest', '~> 5.11')
gem.add_runtime_dependency('mutant', "= #{gem.version}")
end
2 changes: 2 additions & 0 deletions mutant-rspec.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Gem::Specification.new do |gem|
gem.files = %w[lib/mutant/integration/rspec.rb]
gem.extra_rdoc_files = %w[LICENSE]

gem.metadata['rubygems_mfa_required'] = 'true'

gem.required_ruby_version = '>= 2.7'

gem.add_runtime_dependency('mutant', "= #{gem.version}")
Expand Down
2 changes: 2 additions & 0 deletions mutant.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Gem::Specification.new do |gem|
gem.extra_rdoc_files = %w[LICENSE]
gem.executables = %w[mutant]

gem.metadata['rubygems_mfa_required'] = 'true'

gem.required_ruby_version = '>= 2.7'

gem.add_runtime_dependency('diff-lcs', '~> 1.3')
Expand Down
5 changes: 3 additions & 2 deletions spec/unit/mutant/cli_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -496,11 +496,12 @@ def self.main_body

let(:subject_a) do
Mutant::Subject::Method::Instance.new(
context: Mutant::Context.new(
context: Mutant::Context.new(
Object,
'subject.rb'
),
node: s(:def, :send, s(:args), nil)
node: s(:def, :send, s(:args), nil),
visibility: :public
)
end

Expand Down
5 changes: 3 additions & 2 deletions spec/unit/mutant/matcher/descendants_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ def apply
let(:expected_subjects) do
[
Mutant::Subject::Method::Instance.new(
context: Mutant::Context.new(
context: Mutant::Context.new(
TestApp::Foo::Bar::Baz,
TestApp::ROOT.join('lib/test_app.rb')
),
node: s(:def, :foo, s(:args), nil)
node: s(:def, :foo, s(:args), nil),
visibility: :public
)
]
end
Expand Down
Loading