ruby-prof 0.16.2 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +15 -0
  3. data/README.rdoc +36 -5
  4. data/bin/ruby-prof +7 -2
  5. data/doc/LICENSE.html +2 -1
  6. data/doc/README_rdoc.html +42 -8
  7. data/doc/Rack.html +2 -1
  8. data/doc/Rack/RubyProf.html +25 -18
  9. data/doc/Rack/RubyProf/RackProfiler.html +343 -0
  10. data/doc/RubyProf.html +14 -2
  11. data/doc/RubyProf/AbstractPrinter.html +91 -12
  12. data/doc/RubyProf/AggregateCallInfo.html +2 -1
  13. data/doc/RubyProf/CallInfo.html +18 -78
  14. data/doc/RubyProf/CallInfoPrinter.html +2 -1
  15. data/doc/RubyProf/CallInfoVisitor.html +2 -1
  16. data/doc/RubyProf/CallStackPrinter.html +35 -29
  17. data/doc/RubyProf/CallTreePrinter.html +98 -14
  18. data/doc/RubyProf/Cmd.html +11 -5
  19. data/doc/RubyProf/DeprecationWarnings.html +148 -0
  20. data/doc/RubyProf/DotPrinter.html +2 -1
  21. data/doc/RubyProf/FlatPrinter.html +2 -1
  22. data/doc/RubyProf/FlatPrinterWithLineNumbers.html +7 -5
  23. data/doc/RubyProf/GraphHtmlPrinter.html +18 -12
  24. data/doc/RubyProf/GraphPrinter.html +2 -1
  25. data/doc/RubyProf/MethodInfo.html +19 -88
  26. data/doc/RubyProf/MultiPrinter.html +231 -17
  27. data/doc/RubyProf/Profile.html +184 -39
  28. data/doc/RubyProf/Profile/ExcludeCommonMethods.html +411 -0
  29. data/doc/RubyProf/Profile/LegacyMethodElimination.html +158 -0
  30. data/doc/RubyProf/ProfileTask.html +2 -1
  31. data/doc/RubyProf/Thread.html +4 -39
  32. data/doc/created.rid +21 -19
  33. data/doc/css/fonts.css +6 -6
  34. data/doc/examples/flat_txt.html +2 -1
  35. data/doc/examples/graph_html.html +2 -1
  36. data/doc/examples/graph_txt.html +2 -1
  37. data/doc/index.html +47 -7
  38. data/doc/js/darkfish.js +7 -7
  39. data/doc/js/search_index.js +1 -1
  40. data/doc/js/search_index.js.gz +0 -0
  41. data/doc/js/searcher.js +1 -0
  42. data/doc/js/searcher.js.gz +0 -0
  43. data/doc/table_of_contents.html +190 -80
  44. data/ext/ruby_prof/extconf.rb +4 -0
  45. data/ext/ruby_prof/rp_call_info.c +19 -1
  46. data/ext/ruby_prof/rp_call_info.h +8 -3
  47. data/ext/ruby_prof/rp_method.c +282 -57
  48. data/ext/ruby_prof/rp_method.h +28 -5
  49. data/ext/ruby_prof/rp_stack.c +69 -24
  50. data/ext/ruby_prof/rp_stack.h +21 -9
  51. data/ext/ruby_prof/rp_thread.c +4 -1
  52. data/ext/ruby_prof/ruby_prof.c +142 -39
  53. data/ext/ruby_prof/ruby_prof.h +3 -0
  54. data/lib/ruby-prof.rb +10 -0
  55. data/lib/ruby-prof/call_info.rb +0 -11
  56. data/lib/ruby-prof/method_info.rb +4 -12
  57. data/lib/ruby-prof/printers/abstract_printer.rb +19 -1
  58. data/lib/ruby-prof/printers/call_info_printer.rb +1 -1
  59. data/lib/ruby-prof/printers/call_stack_printer.rb +9 -4
  60. data/lib/ruby-prof/printers/call_tree_printer.rb +15 -2
  61. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +23 -4
  62. data/lib/ruby-prof/printers/graph_html_printer.rb +10 -5
  63. data/lib/ruby-prof/printers/graph_printer.rb +2 -2
  64. data/lib/ruby-prof/printers/multi_printer.rb +44 -18
  65. data/lib/ruby-prof/profile.rb +13 -42
  66. data/lib/ruby-prof/profile/exclude_common_methods.rb +201 -0
  67. data/lib/ruby-prof/profile/legacy_method_elimination.rb +49 -0
  68. data/lib/ruby-prof/rack.rb +130 -51
  69. data/lib/ruby-prof/thread.rb +0 -6
  70. data/lib/ruby-prof/version.rb +1 -1
  71. data/ruby-prof.gemspec +4 -3
  72. data/test/aggregate_test.rb +1 -1
  73. data/test/exclude_methods_test.rb +146 -0
  74. data/test/line_number_test.rb +12 -3
  75. data/test/multi_printer_test.rb +23 -2
  76. data/test/no_method_class_test.rb +1 -1
  77. data/test/printers_test.rb +21 -1
  78. data/test/rack_test.rb +64 -0
  79. data/test/recursive_test.rb +15 -15
  80. data/test/test_helper.rb +11 -0
  81. metadata +20 -13
@@ -42,11 +42,14 @@ typedef struct
42
42
  {
43
43
  VALUE running;
44
44
  VALUE paused;
45
+
45
46
  prof_measurer_t* measurer;
46
47
  VALUE threads;
48
+
47
49
  st_table* threads_tbl;
48
50
  st_table* exclude_threads_tbl;
49
51
  st_table* include_threads_tbl;
52
+ st_table* exclude_methods_tbl;
50
53
  thread_data_t* last_thread_data;
51
54
  double measurement_at_pause_resume;
52
55
  int merge_fibers;
@@ -8,6 +8,16 @@ rescue LoadError
8
8
  require "ruby_prof.so"
9
9
  end
10
10
 
11
+ module RubyProf
12
+ module DeprecationWarnings
13
+ def deprecation_warning(feature, recommendation = nil)
14
+ $stderr.puts "DEPRECATION WARNING: #{feature}"
15
+ $stderr.puts recommendation unless recommendation.nil?
16
+ end
17
+ end
18
+ extend DeprecationWarnings
19
+ end
20
+
11
21
  require 'ruby-prof/version'
12
22
  require 'ruby-prof/call_info'
13
23
  require 'ruby-prof/compatibility'
@@ -9,17 +9,6 @@ module RubyProf
9
9
  # children: array of call info children (can be empty)
10
10
  # target: method info (containing an array of call infos)
11
11
 
12
- attr_reader :recursive
13
-
14
- def detect_recursion(visited_methods = Hash.new(0))
15
- @recursive = (visited_methods[target] += 1) > 1
16
- children.each do |child|
17
- child.detect_recursion(visited_methods)
18
- end
19
- visited_methods.delete(target) if (visited_methods[target] -= 1) == 0
20
- return @recursive
21
- end
22
-
23
12
  def children_time
24
13
  children.inject(0) do |sum, call_info|
25
14
  sum += call_info.total_time
@@ -18,10 +18,6 @@ module RubyProf
18
18
  end
19
19
  end
20
20
 
21
- def detect_recursion
22
- call_infos.each(&:detect_recursion)
23
- end
24
-
25
21
  def called
26
22
  @called ||= begin
27
23
  call_infos.inject(0) do |sum, call_info|
@@ -33,7 +29,7 @@ module RubyProf
33
29
  def total_time
34
30
  @total_time ||= begin
35
31
  call_infos.inject(0) do |sum, call_info|
36
- sum += call_info.total_time unless call_info.recursive
32
+ sum += call_info.total_time if !call_info.recursive?
37
33
  sum
38
34
  end
39
35
  end
@@ -42,7 +38,7 @@ module RubyProf
42
38
  def self_time
43
39
  @self_time ||= begin
44
40
  call_infos.inject(0) do |sum, call_info|
45
- sum += call_info.self_time unless call_info.recursive
41
+ sum += call_info.self_time if !call_info.recursive?
46
42
  sum
47
43
  end
48
44
  end
@@ -51,7 +47,7 @@ module RubyProf
51
47
  def wait_time
52
48
  @wait_time ||= begin
53
49
  call_infos.inject(0) do |sum, call_info|
54
- sum += call_info.wait_time unless call_info.recursive
50
+ sum += call_info.wait_time if !call_info.recursive?
55
51
  sum
56
52
  end
57
53
  end
@@ -60,7 +56,7 @@ module RubyProf
60
56
  def children_time
61
57
  @children_time ||= begin
62
58
  call_infos.inject(0) do |sum, call_info|
63
- sum += call_info.children_time unless call_info.recursive
59
+ sum += call_info.children_time if !call_info.recursive?
64
60
  sum
65
61
  end
66
62
  end
@@ -78,10 +74,6 @@ module RubyProf
78
74
  end
79
75
  end
80
76
 
81
- def recursive?
82
- (@recursive ||= call_infos.detect(&:recursive) ? :true : :false) == :true
83
- end
84
-
85
77
  def children
86
78
  @children ||= call_infos.map(&:children).flatten
87
79
  end
@@ -26,6 +26,9 @@ module RubyProf
26
26
  # Available values are :total_time, :self_time,
27
27
  # :wait_time, :children_time
28
28
  # Default value is :total_time
29
+ # :editor_uri - Specifies editor uri scheme used for opening files
30
+ # e.g. :atm or :mvim. For OS X default is :txmt.
31
+ # Use RUBY_PROF_EDITOR_URI environment variable to overide.
29
32
  def setup_options(options = {})
30
33
  @options = options
31
34
  end
@@ -42,6 +45,16 @@ module RubyProf
42
45
  @options[:sort_method] || :total_time
43
46
  end
44
47
 
48
+ def editor_uri
49
+ default_uri = if RUBY_PLATFORM =~ /darwin/ \
50
+ && !ENV['RUBY_PROF_EDITOR_URI']
51
+ 'txmt'
52
+ else
53
+ false
54
+ end
55
+ ENV['RUBY_PROF_EDITOR_URI'] || @options[:editor_uri] || default_uri
56
+ end
57
+
45
58
  def method_name(method)
46
59
  name = method.full_name
47
60
  if print_file
@@ -81,5 +94,10 @@ module RubyProf
81
94
 
82
95
  def print_footer(thread)
83
96
  end
97
+
98
+ # whether this printer need a :path option pointing to a directory
99
+ def self.needs_dir?
100
+ false
101
+ end
84
102
  end
85
- end
103
+ end
@@ -31,7 +31,7 @@ module RubyProf
31
31
  @output << "wt:#{sprintf("%#{TIME_WIDTH}.2f", call_info.wait_time)}, "
32
32
  @output << "ct:#{sprintf("%#{TIME_WIDTH}.2f", call_info.children_time)}, "
33
33
  @output << "call:#{call_info.called}, "
34
- @output << "rec:#{call_info.recursive}"
34
+ @output << "rec:#{call_info.recursive?}"
35
35
  @output << ")"
36
36
  @output << "\n"
37
37
  end
@@ -36,9 +36,13 @@ module RubyProf
36
36
  # :application - a String to overide the name of the application,
37
37
  # as it appears on the report.
38
38
  #
39
+ # :editor_uri - Specifies editor uri scheme used for opening files
40
+ # e.g. :atm or :mvim. For OS X default is :txmt.
41
+ # Use RUBY_PROF_EDITOR_URI environment variable to overide.
39
42
  def print(output = STDOUT, options = {})
40
43
  @output = output
41
44
  setup_options(options)
45
+ @editor = editor_uri
42
46
  if @graph_html = options.delete(:graph)
43
47
  @graph_html = "file://" + @graph_html if @graph_html[0]=="/"
44
48
  end
@@ -52,7 +56,7 @@ module RubyProf
52
56
  @result.threads.each do |thread|
53
57
  @current_thread_id = thread.fiber_id
54
58
  @overall_time = thread.total_time
55
- thread_info = "Thread: #{thread.id}"
59
+ thread_info = String.new("Thread: #{thread.id}")
56
60
  thread_info << ", Fiber: #{thread.fiber_id}" unless thread.id == thread.fiber_id
57
61
  thread_info << " (#{"%4.2f%%" % ((@overall_time/@overall_threads_time)*100)} ~ #{@overall_time})"
58
62
  @output.print "<div class=\"thread\">#{thread_info}</div>"
@@ -116,8 +120,10 @@ module RubyProf
116
120
  if file =~ /\/ruby_runtime$/
117
121
  h(name(call_info))
118
122
  else
119
- if RUBY_PLATFORM =~ /darwin/
120
- "<a href=\"txmt://open?url=file://#{file}&line=#{method.line}\">#{h(name(call_info))}</a>"
123
+ if @editor
124
+ "<a href=\"#{@editor}://" \
125
+ "open?url=file://#{file}&line=#{method.line}\">" \
126
+ "#{h(name(call_info))}</a>"
121
127
  else
122
128
  "<a href=\"file://#{file}##{method.line}\">#{h(name(call_info))}</a>"
123
129
  end
@@ -257,4 +263,3 @@ end_help
257
263
  end
258
264
  end
259
265
  end
260
-
@@ -44,11 +44,20 @@ module RubyProf
44
44
  end
45
45
 
46
46
  def print(options = {})
47
+ validate_print_params(options)
47
48
  setup_options(options)
48
49
  determine_event_specification_and_value_scale
49
50
  print_threads
50
51
  end
51
52
 
53
+ def validate_print_params(options)
54
+ if options.is_a?(IO)
55
+ raise ArgumentError, "#{self.class.name}#print cannot print to IO objects"
56
+ elsif !options.is_a?(Hash)
57
+ raise ArgumentError, "#{self.class.name}#print requires an options hash"
58
+ end
59
+ end
60
+
52
61
  def print_threads
53
62
  remove_subsidiary_files_from_previous_profile_runs
54
63
  # TODO: merge fibers of a given thread here, instead of relying
@@ -79,6 +88,10 @@ module RubyProf
79
88
  @options[:path] || "."
80
89
  end
81
90
 
91
+ def self.needs_dir?
92
+ true
93
+ end
94
+
82
95
  def base_name
83
96
  @options[:profile] || "profile"
84
97
  end
@@ -110,7 +123,7 @@ module RubyProf
110
123
  def print_method(output, method)
111
124
  # Print out the file and method name
112
125
  output << "fl=#{file(method)}\n"
113
- output << "fn=#{method_name(method)}\n"
126
+ output << "fn=#{method.calltree_name}\n"
114
127
 
115
128
  # Now print out the function line number and its self time
116
129
  output << "#{method.line} #{convert(method.self_time)}\n"
@@ -118,7 +131,7 @@ module RubyProf
118
131
  # Now print out all the children methods
119
132
  method.children.each do |callee|
120
133
  output << "cfl=#{file(callee.target)}\n"
121
- output << "cfn=#{method_name(callee.target)}\n"
134
+ output << "cfn=#{callee.target.calltree_name}\n"
122
135
  output << "calls=#{callee.called} #{callee.line}\n"
123
136
 
124
137
  # Print out total times here!
@@ -13,6 +13,7 @@ module RubyProf
13
13
  #
14
14
  class FlatPrinterWithLineNumbers < FlatPrinter
15
15
  def print_methods(thread)
16
+ @editor = editor_uri
16
17
  total_time = thread.total_time
17
18
 
18
19
  methods = thread.methods.sort_by(&sort_method).reverse
@@ -38,8 +39,8 @@ module RubyProf
38
39
  if method.source_file == 'ruby_runtime'
39
40
  @output << "\n"
40
41
  else
41
- @output << "\n defined at:\n"
42
- @output << " %s:%s\n" % [File.expand_path(method.source_file), method.line]
42
+ @output << "\n defined at:\n"
43
+ @output << defined_at_format % [File.expand_path(method.source_file), method.line]
43
44
  end
44
45
 
45
46
  callers = []
@@ -52,13 +53,31 @@ module RubyProf
52
53
  callers.uniq!
53
54
 
54
55
  unless callers.empty?
55
- @output << " called from:\n"
56
+ @output << " called from:\n"
56
57
  callers.each do |args|
57
- @output << " %s (%s:%s)\n" % args
58
+ @output << called_from_format % args
58
59
  end
59
60
  end
60
61
  @output << "\n"
61
62
  end
62
63
  end
64
+
65
+ private
66
+
67
+ def defined_at_format
68
+ if @editor
69
+ " #{@editor}://open?url=file://%s&line=%s\n"
70
+ else
71
+ " %s:%s\n"
72
+ end
73
+ end
74
+
75
+ def called_from_format
76
+ if @editor
77
+ " %s (#{@editor}://open?url=file://%s&line=%s)\n"
78
+ else
79
+ " %s (%s:%s)\n"
80
+ end
81
+ end
63
82
  end
64
83
  end
@@ -20,6 +20,9 @@ module RubyProf
20
20
  # :template - specify an ERB template to use, instead of the
21
21
  # built-in self.template
22
22
  #
23
+ # :editor_uri - Specifies editor uri scheme used for opening files
24
+ # e.g. :atm or :mvim. For OS X default is :txmt.
25
+ # Use RUBY_PROF_EDITOR_URI environment variable to overide.
23
26
 
24
27
  class GraphHtmlPrinter < AbstractPrinter
25
28
  include ERB::Util
@@ -36,6 +39,7 @@ module RubyProf
36
39
  def print(output = STDOUT, options = {})
37
40
  @output = output
38
41
  setup_options(options)
42
+ @editor = editor_uri
39
43
  @output << @erb.result(binding).split("\n").map(&:rstrip).join("\n") << "\n"
40
44
  end
41
45
 
@@ -63,8 +67,10 @@ module RubyProf
63
67
  if srcfile =~ /\/ruby_runtime$/
64
68
  ""
65
69
  else
66
- if RUBY_PLATFORM =~ /darwin/
67
- "<a href=\"txmt://open?url=file://#{h srcfile}&line=#{linenum}\" title=\"#{h srcfile}:#{linenum}\">#{linenum}</a>"
70
+ if @editor
71
+ "<a href=\"#{@editor}://" \
72
+ "open?url=file://#{h srcfile}&line=#{linenum}\"" \
73
+ "title=\"#{h srcfile}:#{linenum}\">#{linenum}</a>"
68
74
  else
69
75
  "<a href=\"file://#{h srcfile}##{linenum}\" title=\"#{h srcfile}:#{linenum}\">#{linenum}</a>"
70
76
  end
@@ -194,8 +200,8 @@ module RubyProf
194
200
  </tr>
195
201
  <% end %>
196
202
  <tr class="method">
197
- <td><%= sprintf("%.2f\%", total_percentage) %></td>
198
- <td><%= sprintf("%.2f\%", self_percentage) %></td>
203
+ <td><%= sprintf("%.2f%%", total_percentage) %></td>
204
+ <td><%= sprintf("%.2f%%", self_percentage) %></td>
199
205
  <td><%= sprintf("%.2f", method.total_time) %></td>
200
206
  <td><%= sprintf("%.2f", method.self_time) %></td>
201
207
  <td><%= sprintf("%.2f", method.wait_time) %></td>
@@ -241,4 +247,3 @@ module RubyProf
241
247
  end
242
248
  end
243
249
  end
244
-
@@ -56,8 +56,8 @@ module RubyProf
56
56
  print_parents(thread, method)
57
57
 
58
58
  # 1 is for % sign
59
- @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", total_percentage)
60
- @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", self_percentage)
59
+ @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f%%", total_percentage)
60
+ @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f%%", self_percentage)
61
61
  @output << sprintf("%#{TIME_WIDTH}.3f", method.total_time)
62
62
  @output << sprintf("%#{TIME_WIDTH}.3f", method.self_time)
63
63
  @output << sprintf("%#{TIME_WIDTH}.3f", method.wait_time)
@@ -5,33 +5,30 @@ module RubyProf
5
5
  # one profiling run. Currently prints a flat profile, a callgrind
6
6
  # profile, a call stack profile and a graph profile.
7
7
  class MultiPrinter
8
- def initialize(result)
9
- @stack_printer = CallStackPrinter.new(result)
10
- @graph_printer = GraphHtmlPrinter.new(result)
11
- @tree_printer = CallTreePrinter.new(result)
12
- @flat_printer = FlatPrinter.new(result)
8
+ def initialize(result, printers = [:stack, :graph, :tree, :flat])
9
+ @stack_printer = CallStackPrinter.new(result) if printers.include?(:stack)
10
+ @graph_printer = GraphHtmlPrinter.new(result) if printers.include?(:graph)
11
+ @tree_printer = CallTreePrinter.new(result) if printers.include?(:tree)
12
+ @flat_printer = FlatPrinter.new(result) if printers.include?(:flat)
13
+ end
14
+
15
+ def self.needs_dir?
16
+ true
13
17
  end
14
18
 
15
19
  # create profile files under options[:path] or the current
16
20
  # directory. options[:profile] is used as the base name for the
17
21
  # pofile file, defaults to "profile".
18
22
  def print(options)
23
+ validate_print_params(options)
24
+
19
25
  @profile = options.delete(:profile) || "profile"
20
26
  @directory = options.delete(:path) || File.expand_path(".")
21
27
 
22
- File.open(stack_profile, "w") do |f|
23
- @stack_printer.print(f, options.merge(:graph => "#{@profile}.graph.html"))
24
- end
25
-
26
- File.open(graph_profile, "w") do |f|
27
- @graph_printer.print(f, options)
28
- end
29
-
30
- @tree_printer.print(options.merge(:path => @directory, :profile => @profile))
31
-
32
- File.open(flat_profile, "w") do |f|
33
- @flat_printer.print(f, options)
34
- end
28
+ print_to_stack(options) if @stack_printer
29
+ print_to_graph(options) if @graph_printer
30
+ print_to_tree(options) if @tree_printer
31
+ print_to_flat(options) if @flat_printer
35
32
  end
36
33
 
37
34
  # the name of the call stack profile file
@@ -54,5 +51,34 @@ module RubyProf
54
51
  "#{@directory}/#{@profile}.flat.txt"
55
52
  end
56
53
 
54
+ def print_to_stack(options)
55
+ File.open(stack_profile, "w") do |f|
56
+ @stack_printer.print(f, options.merge(:graph => "#{@profile}.graph.html"))
57
+ end
58
+ end
59
+
60
+ def print_to_graph(options)
61
+ File.open(graph_profile, "w") do |f|
62
+ @graph_printer.print(f, options)
63
+ end
64
+ end
65
+
66
+ def print_to_tree(options)
67
+ @tree_printer.print(options.merge(:path => @directory, :profile => @profile))
68
+ end
69
+
70
+ def print_to_flat(options)
71
+ File.open(flat_profile, "w") do |f|
72
+ @flat_printer.print(f, options)
73
+ end
74
+ end
75
+
76
+ def validate_print_params(options)
77
+ if options.is_a?(IO)
78
+ raise ArgumentError, "#{self.class.name}#print cannot print to IO objects"
79
+ elsif !options.is_a?(Hash)
80
+ raise ArgumentError, "#{self.class.name}#print requires an options hash"
81
+ end
82
+ end
57
83
  end
58
84
  end
@@ -1,55 +1,26 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require 'ruby-prof/profile/exclude_common_methods'
4
+ require 'ruby-prof/profile/legacy_method_elimination'
5
+
3
6
  module RubyProf
4
7
  class Profile
5
- # This method gets called once profiling has been completed
6
- # but before results are returned to the user. Thus it provides
7
- # a hook to do any necessary post-processing on the call graph.
8
- def post_process
9
- self.threads.each do |thread|
10
- thread.detect_recursion
11
- end
12
- end
8
+ include LegacyMethodElimination
13
9
 
14
- # eliminate some calls from the graph by merging the information into callers.
15
- # matchers can be a list of strings or regular expressions or the name of a file containing regexps.
16
- def eliminate_methods!(matchers)
17
- matchers = read_regexps_from_file(matchers) if matchers.is_a?(String)
18
- eliminated = []
19
- threads.each do |thread|
20
- matchers.each{ |matcher| eliminated.concat(eliminate_methods(thread.methods, matcher)) }
21
- end
22
- eliminated
10
+ # Hides methods that, when represented as a call graph, have
11
+ # extremely large in and out degrees and make navigation impossible.
12
+ def exclude_common_methods!
13
+ ExcludeCommonMethods.apply!(self)
23
14
  end
24
15
 
25
- private
26
-
27
- # read regexps from file
28
- def read_regexps_from_file(file_name)
29
- matchers = []
30
- File.open(file_name).each_line do |l|
31
- next if (l =~ /^(#.*|\s*)$/) # emtpy lines and lines starting with #
32
- matchers << Regexp.new(l.strip)
16
+ def exclude_methods!(mod, *method_or_methods)
17
+ [method_or_methods].flatten.each do |name|
18
+ exclude_method!(mod, name)
33
19
  end
34
20
  end
35
21
 
36
- # eliminate methods matching matcher
37
- def eliminate_methods(methods, matcher)
38
- eliminated = []
39
- i = 0
40
- while i < methods.size
41
- method_info = methods[i]
42
- method_name = method_info.full_name
43
- if matcher === method_name
44
- raise "can't eliminate root method" if method_info.root?
45
- eliminated << methods.delete_at(i)
46
- method_info.eliminate!
47
- else
48
- i += 1
49
- end
50
- end
51
- eliminated
22
+ def exclude_singleton_methods!(mod, *method_or_methods)
23
+ exclude_methods!(mod.singleton_class, *method_or_methods)
52
24
  end
53
-
54
25
  end
55
26
  end