Class: ADSL::Extract::Instrumenter
- Inherits:
-
Object
- Object
- ADSL::Extract::Instrumenter
show all
- Defined in:
- lib/adsl/extract/instrumenter.rb
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(instrument_domain = Dir.pwd) ⇒ Instrumenter
Returns a new instance of Instrumenter.
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
# File 'lib/adsl/extract/instrumenter.rb', line 84
def initialize(instrument_domain = Dir.pwd)
@instrument_domain = instrument_domain
@replacers = []
@stack_depth = 0
@method_locals_stack = []
replace :defn, :defs do |sexp|
mark_sexp_instrumented sexp
end
replace :call do |sexp|
original_object = sexp.sexp_body[0] || s(:self)
original_method_name = sexp.sexp_body[1]
original_args = sexp.sexp_body[2..-1]
next sexp if [s(:self), nil].include? original_object and Kernel.respond_to? original_method_name
s(:call, nil, :ins_call, original_object, s(:lit, original_method_name), *original_args)
end
end
|
Instance Attribute Details
#instrumentation_filters ⇒ Object
Returns the value of attribute instrumentation_filters.
20
21
22
|
# File 'lib/adsl/extract/instrumenter.rb', line 20
def instrumentation_filters
@instrumentation_filters
end
|
#method_locals_stack ⇒ Object
Returns the value of attribute method_locals_stack.
19
20
21
|
# File 'lib/adsl/extract/instrumenter.rb', line 19
def method_locals_stack
@method_locals_stack
end
|
#stack_depth ⇒ Object
Returns the value of attribute stack_depth.
19
20
21
|
# File 'lib/adsl/extract/instrumenter.rb', line 19
def stack_depth
@stack_depth
end
|
Class Method Details
.get_instance ⇒ Object
25
26
27
|
# File 'lib/adsl/extract/instrumenter.rb', line 25
def self.get_instance()
@instance
end
|
.instrumented ⇒ Object
33
34
35
|
# File 'lib/adsl/extract/instrumenter.rb', line 33
def self.instrumented()
end
|
Instance Method Details
#convert_root_defs_into_defn(sexp) ⇒ Object
152
153
154
|
# File 'lib/adsl/extract/instrumenter.rb', line 152
def convert_root_defs_into_defn(sexp)
sexp.sexp_type == :defs ? s(:defn, *sexp[2..-1]) : sexp
end
|
#exec_within ⇒ Object
49
50
51
52
53
54
55
56
57
58
59
|
# File 'lib/adsl/extract/instrumenter.rb', line 49
def exec_within
Instrumenter.instance_variable_set(:@instance, self) if @stack_depth == 0
@stack_depth += 1
@method_locals_stack << create_locals if respond_to? :create_locals
return yield(self)
ensure
@stack_depth -= 1
@method_locals_stack.pop
Instrumenter.instance_variable_set(:@instance, nil) if @stack_depth == 0
end
|
#execute_instrumented(object, method_name, *args, &block) ⇒ Object
145
146
147
148
149
150
|
# File 'lib/adsl/extract/instrumenter.rb', line 145
def execute_instrumented(object, method_name, *args, &block)
self.exec_within do
instrument object, method_name
return object.send method_name, *args, &block
end
end
|
#instrument(object, method_name) ⇒ Object
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
# File 'lib/adsl/extract/instrumenter.rb', line 166
def instrument(object, method_name)
if should_instrument? object, method_name
begin
method = object.singleton_class.instance_method method_name
source = method.source
sexp = ruby_parser.process source
unless sexp.nil?
sexp = convert_root_defs_into_defn sexp
instrumented_sexp = instrument_sexp sexp
new_code = Ruby2Ruby.new.process instrumented_sexp
object.replace_method method_name, new_code
new_code
else
source
end
rescue MethodSource::SourceNotFoundError
end
end
end
|
#instrument_sexp(sexp) ⇒ Object
196
197
198
199
200
201
202
|
# File 'lib/adsl/extract/instrumenter.rb', line 196
def instrument_sexp(sexp)
return nil if sexp.nil?
@replacers.reverse_each do |types, block, options|
sexp = sexp.block_replace *types, options, &block
end
sexp
end
|
#instrument_string(source) ⇒ Object
156
157
158
159
160
161
162
163
164
|
# File 'lib/adsl/extract/instrumenter.rb', line 156
def instrument_string(source)
sexp = ruby_parser.process source
unless sexp.nil?
instrumented_sexp = instrument_sexp sexp
new_code = Ruby2Ruby.new.process instrumented_sexp
else
source
end
end
|
#mark_sexp_instrumented(sexp) ⇒ Object
61
62
63
64
65
66
67
68
69
70
71
72
73
|
# File 'lib/adsl/extract/instrumenter.rb', line 61
def mark_sexp_instrumented(sexp)
raise 'Already instrumented' if sexp_instrumented? sexp
first_stmt = sexp[3]
if first_stmt[0] != :call or
first_stmt[1] != Instrumenter.to_sexp or
first_stmt[2] != :instrumented
new_stmt = s(:call, Instrumenter.to_sexp, :instrumented)
sexp.insert 3, new_stmt
end
sexp
end
|
#method_locals ⇒ Object
37
38
39
|
# File 'lib/adsl/extract/instrumenter.rb', line 37
def method_locals
@method_locals_stack.last
end
|
#previous_locals ⇒ Object
41
42
43
|
# File 'lib/adsl/extract/instrumenter.rb', line 41
def previous_locals
@method_locals_stack[-2]
end
|
#replace(*types, &block) ⇒ Object
133
134
135
136
|
# File 'lib/adsl/extract/instrumenter.rb', line 133
def replace(*types, &block)
options = types.last.is_a?(Hash) ? types.pop : {}
@replacers << [types, block, options]
end
|
#root_locals ⇒ Object
45
46
47
|
# File 'lib/adsl/extract/instrumenter.rb', line 45
def root_locals
@method_locals_stack.first
end
|
#ruby_parser ⇒ Object
29
30
31
|
# File 'lib/adsl/extract/instrumenter.rb', line 29
def ruby_parser
RUBY_VERSION >= '2' ? Ruby19Parser.new : RubyParser.for_current_ruby
end
|
#sexp_instrumented?(sexp) ⇒ Boolean
75
76
77
78
79
80
81
82
|
# File 'lib/adsl/extract/instrumenter.rb', line 75
def sexp_instrumented?(sexp)
first_stmt = sexp[3]
return (first_stmt[0] == :call and
first_stmt[1] == Instrumenter.to_sexp and
first_stmt[2] == :instrumented)
rescue MethodSource::SourceNotFoundError
return
end
|
#should_instrument?(object, method_name) ⇒ Boolean
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
# File 'lib/adsl/extract/instrumenter.rb', line 109
def should_instrument?(object, method_name)
return false if object.is_a?(Fixnum) or object.is_a?(Symbol)
method = object.singleton_class.instance_method method_name
return false if method.source_location.nil?
return false if method.owner == Kernel
return false if @instrument_domain && !(method.source_location.first =~ /^#{@instrument_domain}.*$/)
(instrumentation_filters || []).each do |filter|
return false unless filter.allow_instrumentation? object, method_name
end
source = method.source
sexp = ruby_parser.process source
!sexp_instrumented? sexp
rescue MethodSource::SourceNotFoundError
return false
rescue NameError => e
return false
end
|
#with_replace(*types, replacer) ⇒ Object
138
139
140
141
142
143
|
# File 'lib/adsl/extract/instrumenter.rb', line 138
def with_replace(*types, replacer)
replace *types, replacer
yield
ensure
@replacers.pop
end
|