Skip to content

Commit

Permalink
Change to consistently use scope object
Browse files Browse the repository at this point in the history
  • Loading branch information
mbj committed Mar 8, 2024
1 parent 33885c8 commit 1d6287f
Show file tree
Hide file tree
Showing 35 changed files with 491 additions and 187 deletions.
24 changes: 12 additions & 12 deletions lib/mutant/bootstrap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ module Bootstrap
'%<scope_class>s#name from: %<scope>s raised an error: %<exception>s'

CLASS_NAME_TYPE_MISMATCH_FORMAT =
'%<scope_class>s#name from: %<scope>s returned %<name>s'
'%<scope_class>s#name from: %<raw_scope>s returned %<name>s'

private_constant(*constants(false))

Expand Down Expand Up @@ -139,41 +139,41 @@ def self.matchable_scopes(env)
env.record(__method__) do
config = env.config

scopes = env.world.object_space.each_object(Module).with_object([]) do |scope, aggregate|
expression = expression(config.reporter, config.expression_parser, scope) || next
aggregate << Scope.new(raw: scope, expression: expression)
scopes = env.world.object_space.each_object(Module).with_object([]) do |raw_scope, aggregate|
expression = expression(config.reporter, config.expression_parser, raw_scope) || next
aggregate << Scope.new(raw: raw_scope, expression: expression)
end

scopes.sort_by { |scope| scope.expression.syntax }
end
end
private_class_method :matchable_scopes

def self.scope_name(reporter, scope)
scope.name
def self.scope_name(reporter, raw_scope)
raw_scope.name
rescue => exception
semantics_warning(
reporter,
CLASS_NAME_RAISED_EXCEPTION,
exception: exception.inspect,
scope: scope,
scope_class: scope.class
scope: raw_scope,
scope_class: raw_scope.class
)
nil
end
private_class_method :scope_name

# rubocop:disable Metrics/MethodLength
def self.expression(reporter, expression_parser, scope)
name = scope_name(reporter, scope) or return
def self.expression(reporter, expression_parser, raw_scope)
name = scope_name(reporter, raw_scope) or return

unless name.instance_of?(String)
semantics_warning(
reporter,
CLASS_NAME_TYPE_MISMATCH_FORMAT,
name: name,
scope_class: scope.class,
scope: scope
scope_class: raw_scope.class,
raw_scope: raw_scope
)
return
end
Expand Down
23 changes: 7 additions & 16 deletions lib/mutant/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,22 @@ class Context
#
# @return [Parser::AST::Node]
def root(node)
nesting.reverse.reduce(node) do |current, scope|
self.class.wrap(scope, current)
nesting.reverse.reduce(node) do |current, raw_scope|
self.class.wrap(raw_scope, current)
end
end

# Identification string
#
# @return [String]
def identification
scope.name
scope.raw.name
end

# Wrap node into ast node
#
# @param [Class, Module] scope
# @param [Parser::AST::Node] node
#
# @return [Parser::AST::Class]
# if scope is of kind Class
#
# @return [Parser::AST::Module]
# if scope is of kind module
def self.wrap(scope, node)
name = s(:const, nil, scope.name.split(NAMESPACE_DELIMITER).last.to_sym)
case scope
def self.wrap(raw_scope, node)
name = s(:const, nil, raw_scope.name.split(NAMESPACE_DELIMITER).last.to_sym)
case raw_scope
when Class
s(:class, name, nil, node)
when Module
Expand Down Expand Up @@ -77,7 +68,7 @@ def match_expressions
private

def name_nesting
scope.name.split(NAMESPACE_DELIMITER)
scope.raw.name.split(NAMESPACE_DELIMITER)
end
memoize :name_nesting

Expand Down
5 changes: 4 additions & 1 deletion lib/mutant/expression/method.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ def self.valid_method_name?(name)
private

def scope
Object.const_get(scope_name)
Scope.new(
raw: Object.const_get(scope_name),
expression: Namespace::Exact.new(scope_name: scope_name)
)
end

end # Method
Expand Down
5 changes: 4 additions & 1 deletion lib/mutant/expression/methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ def match_length(expression)
private

def scope
Object.const_get(scope_name)
Scope.new(
expression: Namespace::Exact.new(scope_name: scope_name),
raw: Object.const_get(scope_name)
)
end

end # Methods
Expand Down
8 changes: 4 additions & 4 deletions lib/mutant/expression/namespace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ class Exact < self
#
# @return [Matcher]
def matcher
scope = find_scope
raw_scope = find_raw_scope

if scope
Matcher::Scope.new(scope: scope)
if raw_scope
Matcher::Scope.new(scope: Scope.new(expression: self, raw: raw_scope))
else
Matcher::Null.new
end
Expand All @@ -83,7 +83,7 @@ def matcher

private

def find_scope
def find_raw_scope
Object.const_get(scope_name)
rescue NameError # rubocop:disable Lint/SuppressedException
end
Expand Down
2 changes: 1 addition & 1 deletion lib/mutant/matcher/descendants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def call(env)
const = env.world.try_const_get(const_name) or return EMPTY_ARRAY

Chain.new(
matchers: matched_scopes(env, const).map { |scope| Scope.new(scope: scope.raw) }
matchers: matched_scopes(env, const).map { |scope| Scope.new(scope: scope) }
).call(env)
end

Expand Down
4 changes: 2 additions & 2 deletions lib/mutant/matcher/method.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ def visibility
# end
#
# Change to this once 3.0 is EOL.
if scope.private_methods.include?(method_name)
if scope.raw.private_methods.include?(method_name)
:private
elsif scope.protected_methods.include?(method_name)
elsif scope.raw.protected_methods.include?(method_name)
:protected
else
:public
Expand Down
9 changes: 5 additions & 4 deletions lib/mutant/matcher/method/instance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Instance < self

# Dispatching builder, detects memoizable case
#
# @param [Class, Module] scope
# @param [Scope] scope
# @param [UnboundMethod] method
#
# @return [Matcher::Method::Instance]
Expand All @@ -31,7 +31,7 @@ def self.new(scope:, target_method:)
# rubocop:enable Metrics/MethodLength

def self.memoized_method?(scope, method_name)
scope < Adamantium && scope.memoized?(method_name)
scope.raw < Adamantium && scope.raw.memoized?(method_name)
end
private_class_method :memoized_method?

Expand All @@ -48,9 +48,9 @@ def match?(node)
end

def visibility
if scope.private_instance_methods.include?(method_name)
if scope.raw.private_instance_methods.include?(method_name)
:private
elsif scope.protected_instance_methods.include?(method_name)
elsif scope.raw.protected_instance_methods.include?(method_name)
:protected
else
:public
Expand All @@ -65,6 +65,7 @@ class Memoized < self

def source_location
scope
.raw
.unmemoized_instance_method(method_name)
.source_location
end
Expand Down
15 changes: 8 additions & 7 deletions lib/mutant/matcher/methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ class Singleton < self
private

def access(_env, method_name)
scope.method(method_name)
scope.raw.method(method_name)
end

def candidate_scope
scope.singleton_class
scope.raw.singleton_class
end

end # Singleton
Expand All @@ -73,11 +73,11 @@ class Metaclass < self
private

def access(_env, method_name)
scope.method(method_name)
scope.raw.method(method_name)
end

def candidate_scope
scope.singleton_class
scope.raw.singleton_class
end
end # Metaclass

Expand Down Expand Up @@ -105,18 +105,19 @@ class Instance < self
private

# rubocop:disable Lint/RescueException
# mutant:disable - unstable source locations under < ruby-3.2
def access(env, method_name)
scope.instance_method(method_name)
candidate_scope.instance_method(method_name)
rescue Exception => exception
env.warn(
MESSAGE % { scope: scope, method_name: method_name, exception: exception }
MESSAGE % { scope: scope, method_name: method_name, exception: exception.inspect }
)
nil
end
# rubocop:enable Lint/RescueException

def candidate_scope
scope
scope.raw
end

end # Instance
Expand Down
2 changes: 1 addition & 1 deletion lib/mutant/matcher/namespace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Namespace < self
# @return [Enumerable<Subject>]
def call(env)
Chain.new(
matchers: matched_scopes(env).map { |scope| Scope.new(scope: scope.raw) }
matchers: matched_scopes(env).map { |scope| Scope.new(scope: scope) }
).call(env)
end

Expand Down
11 changes: 10 additions & 1 deletion lib/mutant/meta/example.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def identification
# @return [Context]
def context
Context.new(
scope: Object,
scope: scope,
source_path: location.path
)
end
Expand All @@ -65,6 +65,15 @@ def generated
end
memoize :generated

private

def scope
Scope.new(
expression: Expression::Namespace::Exact.new(scope_name: 'Object'),
raw: Object
)
end

end # Example
end # Meta
end # Mutant
2 changes: 1 addition & 1 deletion lib/mutant/subject/method.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def expression
Expression::Method.new(
method_name: name.to_s,
scope_symbol: self.class::SYMBOL,
scope_name: scope.name
scope_name: scope.raw.name
)
end
memoize :expression
Expand Down
5 changes: 3 additions & 2 deletions lib/mutant/subject/method/instance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ class Instance < self
#
# @return [self]
def prepare
scope.undef_method(name)
scope.raw.undef_method(name)
self
end

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

Expand All @@ -31,6 +31,7 @@ class Memoized < self
# @return [self]
def prepare
scope
.raw
.instance_variable_get(:@memoized_methods)
.delete(name)

Expand Down
2 changes: 1 addition & 1 deletion lib/mutant/subject/method/metaclass.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Metaclass < self
#
# @return [self]
def prepare
scope.singleton_class.public_send(:undef_method, name)
scope.raw.singleton_class.undef_method(name)
self
end

Expand Down
4 changes: 2 additions & 2 deletions lib/mutant/subject/method/singleton.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ class Singleton < self
#
# @return [self]
def prepare
scope.singleton_class.__send__(:undef_method, name)
scope.raw.singleton_class.undef_method(name)
self
end

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

Expand Down
9 changes: 8 additions & 1 deletion spec/support/shared_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,16 @@ def setup_shared_context
)
end

let(:scope) do
Mutant::Scope.new(
expression: Mutant::Expression::Namespace::Exact.new(scope_name: 'Object'),
raw: Object
)
end

let(:subject_a_context) do
Mutant::Context.new(
scope: Object,
scope: scope,
source_path: 'suvject-a.rb'
)
end
Expand Down
11 changes: 9 additions & 2 deletions spec/unit/mutant/bootstrap_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,15 @@ def object.name
)
end

let(:scope) do
Mutant::Scope.new(
expression: parse_expression('TestApp::Literal'),
raw: TestApp::Literal
)
end

let(:expected_subjects) do
Mutant::Matcher::Scope.new(scope: TestApp::Literal).call(env_initial)
Mutant::Matcher::Scope.new(scope: scope).call(env_initial)
end

let(:expected_env) do
Expand Down Expand Up @@ -330,7 +337,7 @@ def object.name
)

Mutant::Matcher::Scope
.new(scope: TestApp::Literal)
.new(scope: scope)
.call(Mutant::Env.empty(world, config)).last
end

Expand Down
Loading

0 comments on commit 1d6287f

Please sign in to comment.