Rcov::CallSiteAnalyzer

A CallSiteAnalyzer can be used to obtain information about:

Example

example.rb:

 class X
   def f1; f2 end
   def f2; 1 + 1 end
   def f3; f1 end
 end

 analyzer = Rcov::CallSiteAnalyzer.new
 x = X.new
 analyzer.run_hooked do 
   x.f1 
 end
 # ....
 
 analyzer.run_hooked do 
   x.f3
   # the information generated in this run is aggregated
   # to the previously recorded one
 end

 analyzer.analyzed_classes        # => ["X", ... ]
 analyzer.methods_for_class("X")  # => ["f1", "f2", "f3"]
 analyzer.defsite("X#f1")         # => DefSite object
 analyzer.callsites("X#f2")       # => hash with CallSite => count
                                  #    associations
 defsite = analyzer.defsite("X#f1")
 defsite.file                     # => "example.rb"
 defsite.line                     # => 2

You can have several CallSiteAnalyzer objects at a time, and it is possible to nest the # / #/# blocks: each analyzer will manage its data separately. Note however that no special provision is taken to ignore code executed “inside” the CallSiteAnalyzer class.

defsite information is only available for methods that were called under the inspection of the CallSiteAnalyzer, i.o.w. you will only have defsite information for those methods for which callsite information is available.

Public Class Methods

new() click to toggle source
     # File lib/rcov/call_site_analyzer.rb, line 101
101:     def initialize
102:       super(:install_callsite_hook, :remove_callsite_hook,
103:             :reset_callsite)
104:     end

Public Instance Methods

analyzed_classes() click to toggle source

Classes whose methods have been called. Returns an array of strings describing the classes (just klass.to_s for each of them). Singleton classes are rendered as:

  #<Class:MyNamespace::MyClass>
     # File lib/rcov/call_site_analyzer.rb, line 110
110:     def analyzed_classes
111:       raw_data_relative.first.keys.map{|klass, meth| klass}.uniq.sort
112:     end
analyzed_methods(classname) click to toggle source
Alias for: methods_for_class
callsites(classname_or_fullname, methodname = nil) click to toggle source

Returns a hash with CallSite => call count associations or nil Can be called in two ways:

  analyzer.callsites("Foo#f1")         # instance method
  analyzer.callsites("Foo.g1")         # singleton method of the class

or

  analyzer.callsites("Foo", "f1")
  analyzer.callsites("#<class:Foo>", "g1")
     # File lib/rcov/call_site_analyzer.rb, line 130
130:     def callsites(classname_or_fullname, methodname = nil)
131:       rawsites = raw_data_relative.first[expand_name(classname_or_fullname, methodname)]
132:       return nil unless rawsites
133:       ret = {}
134:       # could be a job for inject but it's slow and I don't mind the extra loc
135:       rawsites.each_pair do |backtrace, count|
136:         ret[CallSite.new(backtrace)] = count
137:       end
138:       ret
139:     end
defsite(classname_or_fullname, methodname = nil) click to toggle source

Returns a DefSite object corresponding to the given method Can be called in two ways:

  analyzer.defsite("Foo#f1")         # instance method
  analyzer.defsite("Foo.g1")         # singleton method of the class

or

  analyzer.defsite("Foo", "f1")
  analyzer.defsite("#<class:Foo>", "g1")
     # File lib/rcov/call_site_analyzer.rb, line 148
148:     def defsite(classname_or_fullname, methodname = nil)
149:       file, line = raw_data_relative[1][expand_name(classname_or_fullname, methodname)]
150:       return nil unless file && line
151:       DefSite.new(file, line)
152:     end
methods_for_class(classname) click to toggle source

Methods that were called for the given class. See # for the notation used for singleton classes. Returns an array of strings or nil

     # File lib/rcov/call_site_analyzer.rb, line 117
117:     def methods_for_class(classname)
118:       a = raw_data_relative.first.keys.select{|kl,_| kl == classname}.map{|_,meth| meth}.sort
119:       a.empty? ? nil : a
120:     end
Also aliased as: analyzed_methods

Private Instance Methods

aggregate_data(aggregated_data, delta) click to toggle source
     # File lib/rcov/call_site_analyzer.rb, line 189
189:     def aggregate_data(aggregated_data, delta)
190:       callsites1, defsites1 = aggregated_data
191:       callsites2, defsites2 = delta
192:     
193:       callsites2.each_pair do |(klass, method), hash|
194:         dest_hash = (callsites1[[klass, method]] ||= {})
195:         hash.each_pair do |callsite, count|
196:           dest_hash[callsite] ||= 0
197:           dest_hash[callsite] += count
198:         end
199:       end
200: 
201:       defsites1.update(defsites2)
202:     end
compute_raw_data_difference(first, last) click to toggle source
     # File lib/rcov/call_site_analyzer.rb, line 204
204:     def compute_raw_data_difference(first, last)
205:       difference = {}
206:       default = Hash.new(0)
207: 
208:       callsites1, defsites1 = *first
209:       callsites2, defsites2 = *last
210: 
211:       callsites2.each_pair do |(klass, method), hash|
212:         old_hash = callsites1[[klass, method]] || default
213:         hash.each_pair do |callsite, count|
214:           diff = hash[callsite] - (old_hash[callsite] || 0)
215:           if diff > 0
216:             difference[[klass, method]] ||= {}
217:             difference[[klass, method]][callsite] = diff
218:           end
219:         end
220:       end
221: 
222:       [difference, defsites1.update(defsites2)]
223:     end
data_default() click to toggle source
     # File lib/rcov/call_site_analyzer.rb, line 171
171:     def data_default; [{}, {}] end
expand_name(classname_or_fullname, methodname = nil) click to toggle source
     # File lib/rcov/call_site_analyzer.rb, line 156
156:     def expand_name(classname_or_fullname, methodname = nil)
157:       if methodname.nil?
158:         case classname_or_fullname
159:         when /(.*)#(.*)/ then classname, methodname = $1, $2
160:         when /(.*)\.(.*)/ then classname, methodname = "#<Class:#{$1}>", $2
161:         else
162:           raise ArgumentError, "Incorrect method name"
163:         end
164: 
165:         return [classname, methodname]
166:       end
167: 
168:       [classname_or_fullname, methodname]
169:     end
raw_data_absolute() click to toggle source
     # File lib/rcov/call_site_analyzer.rb, line 173
173:     def raw_data_absolute
174:       raw, method_def_site = RCOV__.generate_callsite_info
175:       ret1 = {}
176:       ret2 = {}
177:       raw.each_pair do |(klass, method), hash|
178:         begin  
179:           key = [klass.to_s, method.to_s]
180:           ret1[key] = hash.clone #Marshal.load(Marshal.dump(hash))
181:           ret2[key] = method_def_site[[klass, method]]
182:         #rescue Exception
183:         end
184:       end
185: 
186:       [ret1, ret2]
187:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.