Class: ADSL::Extract::Rails::InvariantInstrumenter

Inherits:
Instrumenter show all
Defined in:
lib/adsl/extract/rails/invariant_instrumenter.rb

Instance Attribute Summary

Attributes inherited from Instrumenter

#instrumentation_filters, #method_locals_stack, #stack_depth

Instance Method Summary collapse

Methods inherited from Instrumenter

#convert_root_defs_into_defn, #exec_within, #execute_instrumented, get_instance, #instrument, #instrument_sexp, #instrument_string, instrumented, #mark_sexp_instrumented, #method_locals, #previous_locals, #replace, #root_locals, #ruby_parser, #sexp_instrumented?, #with_replace

Constructor Details

#initialize(ar_class_names, *params) ⇒ InvariantInstrumenter

Returns a new instance of InvariantInstrumenter.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/adsl/extract/rails/invariant_instrumenter.rb', line 17

def initialize(ar_class_names, *params)
  super *params

  # if a block is passed to the invariant call, add that block to the last of the parameters instead
  replace :iter do |sexp|
    next sexp unless (
      sexp[1].sexp_type == :call and
      sexp[1][1].nil? and
      sexp[1][2] == :invariant and
      sexp[1].last.sexp_type == :call
    )

    params_for_invariant = sexp[1][3..-1]
    s(:call, nil, :invariant,
      *params_for_invariant[0..-2],
      s(:iter, params_for_invariant.last, *sexp[2..-1])
    )
  end

  # replace and with self.and etc
  [:and, :or].each do |operand|
    replace operand do |sexp|
      s(:if,
        s(:call, nil, :respond_to?, s(:lit, operand)),
        s(:call, s(:self), operand, *sexp.sexp_body),
        s(operand,                  *sexp.sexp_body)
      )
    end
  end

  # replace not with self.not
  replace :call do |sexp|
    next sexp unless sexp[2] == :!
    s(:if,
      s(:call, nil, :respond_to?, s(:lit, :not)),
      s(:call, s(:self), :not, sexp[1].dup),
      sexp
    )
  end
end

Instance Method Details

#instrument_and_execute_source(object, source) ⇒ Object



10
11
12
13
14
15
# File 'lib/adsl/extract/rails/invariant_instrumenter.rb', line 10

def instrument_and_execute_source object, source
  instrumented_source = instrument_string source
  exec_within do
    object.instance_eval instrumented_source
  end
end

#should_instrument?(object, method_name) ⇒ Boolean

Returns:

  • (Boolean)


58
59
60
61
62
63
64
65
# File 'lib/adsl/extract/rails/invariant_instrumenter.rb', line 58

def should_instrument?(object, method_name)
  return false unless super

  klass = object.class != Class ? object.class : object
  method = object.method method_name
  
  klass.name.match(/^ADSL::.*$/).nil? && !(method.source_location[0] =~ /.*lib\/adsl\/.*/)
end