Skip to content

Commit

Permalink
Change to methods on scope that do not depend on context
Browse files Browse the repository at this point in the history
  • Loading branch information
mbj committed Mar 8, 2024
1 parent 1d6287f commit 70cd945
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 78 deletions.
60 changes: 12 additions & 48 deletions lib/mutant/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,8 @@ class Context
include Adamantium, Anima.new(:scope, :source_path)
extend AST::Sexp

NAMESPACE_DELIMITER = '::'

# Return root node for mutation
#
# @return [Parser::AST::Node]
def root(node)
nesting.reverse.reduce(node) do |current, raw_scope|
self.class.wrap(raw_scope, current)
end
def match_expressions
scope.match_expressions
end

# Identification string
Expand All @@ -24,53 +17,24 @@ def identification
scope.raw.name
end

# Return root node for mutation
#
# @return [Parser::AST::Node]
def root(node)
scope.nesting.reverse.reduce(node) do |current, raw_scope|
self.class.wrap(raw_scope, current)
end
end

# Wrap node into ast node
def self.wrap(raw_scope, node)
name = s(:const, nil, raw_scope.name.split(NAMESPACE_DELIMITER).last.to_sym)
name = s(:const, nil, raw_scope.name.split(Scope::NAMESPACE_DELIMITER).last.to_sym)
case raw_scope
when Class
s(:class, name, nil, node)
when Module
s(:module, name, node)
end
end

# Nesting of scope
#
# @return [Enumerable<Class,Module>]
def nesting
const = Object
name_nesting.map do |name|
const = const.const_get(name)
end
end
memoize :nesting

# Unqualified name of scope
#
# @return [String]
def unqualified_name
name_nesting.last
end

# Match expressions for scope
#
# @return [Enumerable<Expression>]
def match_expressions
name_nesting.each_index.reverse_each.map do |index|
Expression::Namespace::Recursive.new(
scope_name: name_nesting.take(index.succ).join(NAMESPACE_DELIMITER)
)
end
end
memoize :match_expressions

private

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

end # Context
end # Mutant
2 changes: 1 addition & 1 deletion lib/mutant/matcher/method/metaclass.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def metaclass_target?(node)

def sclass_const_name?(node)
name = node.children.fetch(CONST_NAME_INDEX)
name.to_s.eql?(context.unqualified_name)
name.to_s.eql?(scope.unqualified_name)
end

end # Evaluator
Expand Down
2 changes: 1 addition & 1 deletion lib/mutant/matcher/method/singleton.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def receiver?(node)

def receiver_name?(node)
name = node.children.fetch(NAME_INDEX)
name.to_s.eql?(context.unqualified_name)
name.to_s.eql?(scope.unqualified_name)
end

end # Evaluator
Expand Down
42 changes: 41 additions & 1 deletion lib/mutant/scope.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,46 @@
module Mutant
# Class or Module bound to an exact expression
class Scope
include Anima.new(:raw, :expression)
include Adamantium, Anima.new(:raw, :expression)

NAMESPACE_DELIMITER = '::'

# Nesting of scope
#
# @return [Enumerable<Class,Module>]
def nesting
const = Object
name_nesting.map do |name|
const = const.const_get(name)
end
end
memoize :nesting

# Unqualified name of scope
#
# @return [String]
def unqualified_name
name_nesting.last
end

# Match expressions for scope
#
# @return [Enumerable<Expression>]
def match_expressions
name_nesting.each_index.reverse_each.map do |index|
Expression::Namespace::Recursive.new(
scope_name: name_nesting.take(index.succ).join(NAMESPACE_DELIMITER)
)
end
end
memoize :match_expressions

private

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

end # Scope
end # Mutant
27 changes: 0 additions & 27 deletions spec/unit/mutant/context_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,33 +72,6 @@ class Literal
end
end

describe '#unqualified_name' do
subject { object.unqualified_name }

context 'with top level constant name' do
let(:scope) do
Mutant::Scope.new(
expression: instance_double(Mutant::Expression),
raw: TestApp
)
end

it 'should return the unqualified name' do
should eql('TestApp')
end

it_should_behave_like 'an idempotent method'
end

context 'with scoped constant name' do
it 'should return the unqualified name' do
should eql('Literal')
end

it_should_behave_like 'an idempotent method'
end
end

describe '#match_expressions' do
subject { object.match_expressions }

Expand Down
34 changes: 34 additions & 0 deletions spec/unit/mutant/scope_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

RSpec.describe Mutant::Scope do
describe '#unqualified_name' do
subject { object.unqualified_name }

let(:object) do
Mutant::Scope.new(
expression: instance_double(Mutant::Expression),
raw: raw_scope
)
end

context 'with top level constant name' do
let(:raw_scope) { TestApp }

it 'should return the unqualified name' do
should eql('TestApp')
end

it_should_behave_like 'an idempotent method'
end

context 'with scoped constant name' do
let(:raw_scope) { TestApp::Literal }

it 'should return the unqualified name' do
should eql('Literal')
end

it_should_behave_like 'an idempotent method'
end
end
end

0 comments on commit 70cd945

Please sign in to comment.