Class: MutationTester::Mutator

Inherits:
Object
  • Object
show all
Defined in:
lib/mutation_tester/mutator.rb

Constant Summary collapse

MUTATIONS =
{
  arithmetic: {
    :+ => %i[- * /],
    :- => %i[+ * /],
    :* => %i[+ - /],
    :/ => %i[+ - *],
    :% => %i[+ - *],
    :** => %i[* +]
  },
  comparison: {
    :> => %i[< >= <= ==],
    :< => %i[> >= <= ==],
    :>= => %i[< > <= ==],
    :<= => %i[> >= < ==],
    :== => %i[!= > <],
    :!= => %i[== > <],
    :<=> => [:==]
  },
  bitwise: {
    :| => %i[&],
    :& => %i[|],
    :^ => %i[| &]
  },
  strict_equality: {
    :== => %i[eql? equal?]
  }
}.freeze
REQUIRE_METHODS =
%i[require require_relative load autoload].freeze
PURE_TRANSFORMATIONS =
%i[
  uniq compact sort flatten strip chomp downcase upcase capitalize
  reverse round floor ceil abs to_a
].freeze
BLOCK_NODE_TYPES =
%i[block numblock itblock].freeze
PLAIN_METHOD_NAME =
/\A[A-Za-z_][A-Za-z0-9_]*[?!]?\z/.freeze
NON_MUTABLE_ARGUMENT_TYPES =
%i[block_pass splat kwsplat].freeze
DISABLE_ANNOTATION =
/mutation_tester:disable\b/.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source_file, config = MutationTester.configuration) ⇒ Mutator

Returns a new instance of Mutator.



58
59
60
61
62
63
64
65
66
# File 'lib/mutation_tester/mutator.rb', line 58

def initialize(source_file, config = MutationTester.configuration)
  @source_file = source_file
  @config = config
  @original_content = File.read(source_file)
  @mutation_id = 0
  @skipped_count = 0
  @excluded_count = 0
  @disabled_lines = []
end

Instance Attribute Details

#excluded_countObject (readonly)

Returns the value of attribute excluded_count.



56
57
58
# File 'lib/mutation_tester/mutator.rb', line 56

def excluded_count
  @excluded_count
end

#skipped_countObject (readonly)

Returns the value of attribute skipped_count.



56
57
58
# File 'lib/mutation_tester/mutator.rb', line 56

def skipped_count
  @skipped_count
end

Class Method Details

.disabled_lines(content) ⇒ Object



46
47
48
49
50
51
52
53
54
# File 'lib/mutation_tester/mutator.rb', line 46

def self.disabled_lines(content)
  _ast, comments = Parser::CurrentRuby.parse_with_comments(content)
  comments
    .select { |comment| comment.text.match?(DISABLE_ANNOTATION) }
    .map { |comment| comment.location.line }
    .uniq
rescue Parser::SyntaxError
  []
end

Instance Method Details

#generate_mutations(ast) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
# File 'lib/mutation_tester/mutator.rb', line 68

def generate_mutations(ast)
  @skipped_count = 0
  @excluded_count = 0
  @disabled_lines = self.class.disabled_lines(@original_content)
  @in_memory_safe_context = false
  @class_body_block_depth = 0
  mutations = collect_mutations(ast)
  mutations = filter_mutations(mutations)
  report_skipped(mutations.size) if @skipped_count.positive?
  mutations
end