private_please 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.gitignore +0 -1
  2. data/.travis.yml +10 -0
  3. data/CHANGELOG +8 -0
  4. data/README.md +92 -42
  5. data/bin/pp_ruby +62 -0
  6. data/bin/ruby_pp +62 -0
  7. data/doc/dev_notes.txt +32 -0
  8. data/doc/fixtures/complex.rb +103 -0
  9. data/doc/fixtures/empty_class.rb +7 -0
  10. data/doc/fixtures/fixture_helper.rb +8 -0
  11. data/doc/fixtures/sample.rb +57 -0
  12. data/lib/private_please/candidate.rb +10 -2
  13. data/lib/private_please/report/table.rb +44 -0
  14. data/lib/private_please/report.rb +6 -0
  15. data/lib/private_please/reporter/base.rb +28 -0
  16. data/lib/private_please/reporter/helpers/options_helpers.rb +12 -0
  17. data/lib/private_please/reporter/helpers/text_table_helpers.rb +9 -0
  18. data/lib/private_please/{report/reporter.rb → reporter/simple_text.rb} +12 -18
  19. data/lib/private_please/reporter/templates/simple.txt.erb +77 -0
  20. data/lib/private_please/reporter.rb +8 -0
  21. data/lib/private_please/storage/methods_names.rb +1 -0
  22. data/lib/private_please/storage.rb +8 -0
  23. data/lib/private_please/tracking/extension.rb +3 -10
  24. data/lib/private_please/tracking/instrumentor.rb +13 -35
  25. data/lib/private_please/tracking/instruments_all_methods_below.rb +28 -0
  26. data/lib/private_please/tracking/instruments_automatically_all_methods_in_all_classes.rb +52 -0
  27. data/lib/private_please/tracking/line_change_tracker.rb +8 -18
  28. data/lib/private_please/tracking/utils.rb +34 -0
  29. data/lib/private_please/tracking.rb +48 -0
  30. data/lib/private_please/version.rb +1 -1
  31. data/lib/private_please.rb +27 -44
  32. data/private_please.gemspec +7 -1
  33. data/spec/{01_marking_candidate_methods_to_observe_spec.rb → 01_tracking_candidate_methods/explicitely_with_the_private_please_command_spec.rb} +35 -70
  34. data/spec/01_tracking_candidate_methods/systematically_in_auto_mode_spec.rb +187 -0
  35. data/spec/{02_logging_calls_on_candidate_methods_spec.rb → 03_logging_calls_on_candidate_methods_spec.rb} +2 -4
  36. data/spec/04_instrumented_program_activity_observation_result_spec.rb +2 -5
  37. data/spec/05_reporting/report_table_spec.rb +51 -0
  38. data/spec/06_at_exit_spec.rb +18 -0
  39. data/spec/fixtures/bug_22.rb +17 -0
  40. data/spec/fixtures/sample_class_for_report.rb +2 -0
  41. data/spec/sandbox/Gemfile +4 -0
  42. data/spec/sandbox/Gemfile.lock +14 -0
  43. data/spec/sandbox/README.txt +26 -0
  44. data/spec/sandbox/normal.rb +7 -0
  45. data/spec/sandbox/normal_prepended_with_require.rb +8 -0
  46. data/spec/spec_helper.rb +6 -2
  47. metadata +50 -13
  48. data/lib/private_please/report/templates/simple.txt.erb +0 -61
  49. data/lib/private_please/tracking/instruments_all_below.rb +0 -41
@@ -1,24 +1,14 @@
1
+ require File.dirname(__FILE__) + '/base'
1
2
  require 'erb'
2
- module PrivatePlease ; module Report
3
- class Reporter
3
+ require File.dirname(__FILE__) + '/helpers/options_helpers'
4
+ require File.dirname(__FILE__) + '/helpers/text_table_helpers'
5
+ module PrivatePlease ; module Reporter
4
6
 
5
- TEMPLATE_PATH = File.expand_path(File.dirname(__FILE__) + '/templates/simple.txt.erb')
6
-
7
- attr_reader :candidates_store, :calls_store,
8
- :good_candidates, :bad_candidates,
9
- :good_candidates_c, :bad_candidates_c,
10
- :never_called_candidates, :never_called_candidates_c,
11
- :building_time
12
-
13
-
14
- def initialize(candidates_store, calls_store)
15
- @candidates_store = candidates_store
16
- @calls_store = calls_store
7
+ class SimpleText < Base
17
8
 
18
- prepare_report_data
19
- end
9
+ TEMPLATE_PATH = File.expand_path(File.dirname(__FILE__) + '/templates/simple.txt.erb')
20
10
 
21
- def to_s
11
+ def text
22
12
  erb = ERB.new(File.read(TEMPLATE_PATH), 0, "%<>")
23
13
  erb.result(binding)
24
14
  end
@@ -29,7 +19,7 @@ module PrivatePlease ; module Report
29
19
  start_time = Time.now
30
20
  @bad_candidates = calls_store.external_calls .clone
31
21
  @bad_candidates_c = calls_store.class_external_calls.clone
32
- # TODO : optimize
22
+ # TODO : optimize (with Hamster?)
33
23
  @good_candidates = calls_store.internal_calls .clone.remove(@bad_candidates)
34
24
  @good_candidates_c= calls_store.class_internal_calls.clone.remove(@bad_candidates_c)
35
25
 
@@ -40,6 +30,9 @@ module PrivatePlease ; module Report
40
30
  @never_called_candidates_c = candidates_store.class_methods.clone.
41
31
  remove(@good_candidates_c).
42
32
  remove(@bad_candidates_c )
33
+ [
34
+ @bad_candidates, @bad_candidates_c, @good_candidates, @good_candidates_c, @never_called_candidates, @never_called_candidates_c
35
+ ].each {|arr| arr.reject!{|k, v| v.empty?}}
43
36
  @building_time = Time.now - start_time
44
37
 
45
38
  @candidates_classes_names = (candidates_store.instance_methods.classes_names +
@@ -49,4 +42,5 @@ module PrivatePlease ; module Report
49
42
  @never_called_candidates_classes_names = (@never_called_candidates_c .classes_names + @never_called_candidates.classes_names).uniq.sort
50
43
  end
51
44
  end
45
+
52
46
  end end
@@ -0,0 +1,77 @@
1
+ ====================================================================================
2
+ = PrivatePlease report : =
3
+ ====================================================================================
4
+ % @candidates_classes_names .sort.each do |class_name|
5
+ %
6
+ % show_good_candidates_section = true
7
+ % show_bad_candidates_section = show_bad_candidates_section?
8
+ % show_never_candidates_section = show_never_called_candidates_section?
9
+ %
10
+ % if show_good_candidates_section
11
+ % good_candidates_table = table_for(
12
+ % names_from(class_name, good_candidates , prefix = "#"),
13
+ % names_from(class_name, good_candidates_c, prefix = "."))
14
+ % end
15
+ % if show_bad_candidates_section
16
+ % bad_candidates_table = table_for(
17
+ % names_from(class_name, bad_candidates , prefix = "#"),
18
+ % names_from(class_name, bad_candidates_c, prefix = "."))
19
+ % end
20
+ % if show_never_candidates_section
21
+ % never_called_candidates_table = table_for(
22
+ % names_from(class_name, never_called_candidates , prefix = "#"),
23
+ % names_from(class_name, never_called_candidates_c, prefix = "."))
24
+ % end
25
+ %
26
+ % # Always hide empty tables :
27
+ % ###########################
28
+ % show_good_candidates_section &&= !good_candidates_table.empty?
29
+ % show_bad_candidates_section &&= !bad_candidates_table.empty?
30
+ % show_never_candidates_section &&= !never_called_candidates_table.empty?
31
+ %
32
+ % nothing_to_show = !(show_good_candidates_section || show_bad_candidates_section || show_never_candidates_section)
33
+ % next if nothing_to_show && !show_empty_classes?
34
+ %
35
+ <%= class_name
36
+ %>
37
+ %
38
+ % if show_good_candidates_section
39
+ % t = good_candidates_table
40
+
41
+ * Good candidates : can be made private :
42
+ ------------------------------------------
43
+ % cell_width = 3 + [38, t.longest_value_length].max
44
+ % t.rows.each do |inst_m, class_m|
45
+ <%= inst_m && inst_m.ljust(cell_width) %><%= class_m && class_m.ljust(cell_width) %>
46
+ % end
47
+ % end
48
+ %
49
+ % if show_bad_candidates_section
50
+ % t = bad_candidates_table
51
+
52
+ * Bad candidates : must stay public/protected:
53
+ . . . . . . . . . . . . . . . . . . . . .
54
+ % cell_width = 3 + [38, t.longest_value_length].max
55
+ % t.rows.each do |inst_m, class_m|
56
+ <%= inst_m && inst_m.ljust(cell_width) %><%= class_m && class_m.ljust(cell_width) %>
57
+ % end
58
+ % end
59
+ %
60
+ % if show_never_candidates_section
61
+ % t = never_called_candidates_table
62
+
63
+ * Methods that were never called :
64
+ . . . . . . . . . . . . . . . . . . . . .
65
+ % cell_width = 3 + [38, t.longest_value_length].max
66
+ % t.rows.each do |inst_m, class_m|
67
+ <%= inst_m && inst_m.ljust(cell_width) %><%= class_m && class_m.ljust(cell_width) %>
68
+ % end
69
+ % end
70
+ %
71
+ % end
72
+
73
+ ====================================================================================
74
+ % if ENV['PP_OPTIONS']
75
+ Default display overriden :
76
+ $PP_OPTIONS = <%= ENV['PP_OPTIONS'].inspect %>
77
+ % end
@@ -0,0 +1,8 @@
1
+ module PrivatePlease
2
+ module Reporter
3
+
4
+ end
5
+ end
6
+
7
+ require File.dirname(__FILE__) + '/reporter/base'
8
+ require File.dirname(__FILE__) + '/reporter/simple_text'
@@ -1,3 +1,4 @@
1
+ require 'set'
1
2
  module PrivatePlease
2
3
  module Storage
3
4
 
@@ -0,0 +1,8 @@
1
+ module PrivatePlease
2
+ module Storage
3
+ end
4
+ end
5
+ require File.dirname(__FILE__) + '/storage/calls_store'
6
+ require File.dirname(__FILE__) + '/storage/candidates_store'
7
+ require File.dirname(__FILE__) + '/storage/methods_names'
8
+ require File.dirname(__FILE__) + '/storage/methods_names_bucket'
@@ -2,16 +2,9 @@ module PrivatePlease ; module Tracking
2
2
 
3
3
  module Extension
4
4
 
5
- def private_please(*methods_to_observe)
6
- parameterless_call = methods_to_observe.empty?
7
- klass = self
8
-
9
- if parameterless_call
10
- klass.send :include, PrivatePlease::Tracking::InstrumentsAllBelow
11
-
12
- else
13
- Instrumentor.instrument_instance_methods_for_pp_observation(klass, methods_to_observe)
14
- end
5
+ def private_please
6
+ include PrivatePlease::Tracking::InstrumentsAllMethodsBelow
7
+ set_trace_func PrivatePlease::Tracking::LineChangeTracker::MY_TRACE_FUN
15
8
  end
16
9
 
17
10
  end
@@ -1,71 +1,49 @@
1
1
  module PrivatePlease ; module Tracking
2
2
 
3
3
  module Instrumentor
4
+ class << self
4
5
 
5
- def self.instrument_instance_methods_for_pp_observation(klass, methods_to_observe)
6
- class_instance_methods = klass.instance_methods.collect(&:to_sym)
7
- methods_to_observe = methods_to_observe.collect(&:to_sym)
8
- # reject invalid methods names
9
- methods_to_observe.reject! do |m|
10
- already_defined_instance_method = class_instance_methods.include?(m)
11
- invalid = !already_defined_instance_method
12
- end
13
-
14
- methods_to_observe.each do |method_name|
15
- candidate = Candidate.for_instance_method(klass, method_name)
16
- instrument_candidate_for_pp_observation(candidate) # end
17
- end
18
- end
19
-
20
-
21
- def self.instrument_candidate_for_pp_observation(candidate)
6
+ def add_call_tracking_code_to(candidate)
22
7
  return if candidate.already_instrumented?
23
- PrivatePlease.remember_candidate(candidate)
8
+ candidate.mark_as_instrumented
24
9
 
25
10
  klass, method_name = candidate.klass, candidate.method_name
26
11
  candidate.instance_method? ?
27
- instrument_instance_method_with_pp_observation(klass, method_name) :
28
- instrument_class_method_with_pp_observation( klass, method_name)
12
+ add_call_tracking_code_to_instance_method(klass, method_name) :
13
+ add_call_tracking_code_to_class_method( klass, method_name)
29
14
  end
30
15
 
31
16
 
17
+ private
32
18
 
33
- def self.instrument_class_method_with_pp_observation(klass, method_name)
19
+ def add_call_tracking_code_to_class_method(klass, method_name)
34
20
  orig_method = klass.singleton_class.instance_method(method_name)
35
21
  klass.class_eval <<RUBY
36
22
  define_singleton_method(method_name) do |*args, &blk| # def self.observed_method_i(..)
37
23
  set_trace_func(nil) #don't track activity while here #
38
- #
39
- zelf_class=self #
40
- candidate = PrivatePlease::Candidate.for_class_method(zelf_class, method_name)
41
- PrivatePlease.after_method_call(candidate, LineChangeTracker.outside_class_method_call_detected?(zelf_class))
42
- #
24
+ PrivatePlease::Tracking.after_singleton_method_call(method_name, self_class=self)
43
25
  set_trace_func(LineChangeTracker::MY_TRACE_FUN) #
44
- # make the call : #
26
+ # make the original call : #
45
27
  orig_method.bind(self).call(*args, &blk) # <call original method>
46
28
  end # end
47
29
  RUBY
48
30
  end
49
- private_class_method :instrument_class_method_with_pp_observation
50
31
 
51
32
 
52
- def self.instrument_instance_method_with_pp_observation(klass, method_name)
33
+ def add_call_tracking_code_to_instance_method(klass, method_name)
53
34
  orig_method = klass.instance_method(method_name)
54
35
  klass.class_eval <<RUBY
55
36
  define_method(method_name) do |*args, &blk| # def observed_method_i(..)
56
37
  set_trace_func(nil) #don't track activity while here #
57
- #
58
- candidate = PrivatePlease::Candidate.for_instance_method(self.class, method_name)
59
- PrivatePlease.after_method_call(candidate, LineChangeTracker.outside_instance_method_call_detected?(self)) #
60
- #
38
+ PrivatePlease::Tracking.after_instance_method_call(method_name, self.class)
61
39
  set_trace_func(LineChangeTracker::MY_TRACE_FUN) #
62
- # make the call : #
40
+ # make the original call : #
63
41
  orig_method.bind(self).call(*args, &blk) # <call original method>
64
42
  end # end
65
43
  RUBY
66
44
  end
67
- private_class_method :instrument_instance_method_with_pp_observation
68
45
 
69
46
  end
47
+ end
70
48
 
71
49
  end end
@@ -0,0 +1,28 @@
1
+ module PrivatePlease ; module Tracking
2
+
3
+ module InstrumentsAllMethodsBelow
4
+ include PrivatePlease::Tracking::Extension
5
+
6
+ def self.included(base)
7
+
8
+ def base.singleton_method_added(method_name)
9
+ return if Utils.private_singleton_method?(self, method_name) \
10
+ || Utils.singleton_method_defined_by_ancestor?(self, method_name)
11
+
12
+ candidate = Candidate.for_class_method(klass = self, method_name)
13
+ Instrumentor.add_call_tracking_code_to(candidate)
14
+ end
15
+
16
+
17
+ def base.method_added(method_name)
18
+ return if Utils.private_instance_method?(self, method_name) \
19
+ || Utils.instance_method_defined_by_ancestor?(self, method_name)
20
+
21
+ candidate = Candidate.for_instance_method(klass = self, method_name)
22
+ Instrumentor.add_call_tracking_code_to(candidate)
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ end end
@@ -0,0 +1,52 @@
1
+
2
+ class Class
3
+
4
+ def singleton_method_added(method_name)
5
+ return unless PrivatePlease.pp_automatic_mode_enabled?
6
+
7
+ return if PrivatePlease::Tracking::Utils.private_singleton_method?(self, method_name) \
8
+ || PrivatePlease::Tracking::Utils.singleton_method_defined_by_ancestor?(self, method_name)
9
+
10
+ candidate = PrivatePlease::Candidate.for_class_method(klass = self, method_name)
11
+ PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
12
+ end
13
+
14
+
15
+ def method_added(method_name)
16
+ return unless PrivatePlease.pp_automatic_mode_enabled?
17
+
18
+ return if [:method_added].include?(method_name)
19
+ return if PrivatePlease::Tracking::Utils.private_instance_method?(self, method_name) \
20
+ || PrivatePlease::Tracking::Utils.instance_method_defined_by_ancestor?(self, method_name)
21
+
22
+ candidate = PrivatePlease::Candidate.for_instance_method(klass = self, method_name)
23
+ PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
24
+ end
25
+
26
+ end
27
+
28
+
29
+ class Module
30
+
31
+ def singleton_method_added(method_name)
32
+ return unless PrivatePlease.pp_automatic_mode_enabled?
33
+
34
+ return if [:included].include?(method_name) #&& !self.is_a?(Class)
35
+ return if PrivatePlease::Tracking::Utils.private_singleton_method?(self, method_name)
36
+
37
+ candidate = PrivatePlease::Candidate.for_class_method(klass = self, method_name)
38
+ PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
39
+ end
40
+
41
+
42
+ def method_added(method_name)
43
+ return unless PrivatePlease.pp_automatic_mode_enabled?
44
+
45
+ return if [:method_added, :singleton_method_added].include?(method_name)
46
+ return if PrivatePlease::Tracking::Utils.private_instance_method?(self, method_name)
47
+
48
+ candidate = PrivatePlease::Candidate.for_instance_method(klass = self, method_name)
49
+ PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
50
+ end
51
+ end
52
+
@@ -2,8 +2,15 @@ module PrivatePlease ; module Tracking
2
2
 
3
3
  class LineChangeTracker
4
4
  class << self
5
+
5
6
  attr_accessor :prev_prev_self, :prev_self, :curr_self
6
7
  @@prev_self = @@curr_self = nil
8
+
9
+ alias :call_initiator :prev_self
10
+
11
+ def reset
12
+ prev_prev_self = prev_self = curr_self = nil
13
+ end
7
14
  end
8
15
 
9
16
  MY_TRACE_FUN = lambda do |event, file, line, id, binding, klass|
@@ -14,23 +21,6 @@ module PrivatePlease ; module Tracking
14
21
  #puts "my : #{event} in #{file}/#{line} id:#{id} klass:#{klass} - self = #{(eval'self', binding).inspect}"
15
22
  end
16
23
 
17
- def self.outside_instance_method_call_detected?(zelf)
18
- caller_class != zelf.class
19
- end
20
-
21
- def self.outside_class_method_call_detected?(zelf_class)
22
- caller_class != zelf_class
23
- end
24
-
25
- private
26
-
27
- def self.caller_class
28
- call_initiator = LineChangeTracker.prev_self
29
- (caller_is_class_method = call_initiator.is_a?(Class)) ?
30
- call_initiator :
31
- call_initiator.class
32
- end
33
24
  end
34
- end end
35
25
 
36
- set_trace_func(PrivatePlease::Tracking::LineChangeTracker::MY_TRACE_FUN) #
26
+ end end
@@ -0,0 +1,34 @@
1
+ module PrivatePlease::Tracking
2
+
3
+ module Utils
4
+ class << self
5
+
6
+ def private_instance_method?(klass, method_name)
7
+ klass.private_method_defined?(method_name)
8
+ end
9
+
10
+ def private_singleton_method?(klass, method_name)
11
+ klass.singleton_class.private_method_defined?(method_name)
12
+ end
13
+
14
+ def instance_method_defined_by_ancestor?(klass, method_name)
15
+ ancestor_of(klass).any? do |a|
16
+ a.method_defined?(method_name) || a.private_method_defined?(method_name)
17
+ end
18
+ end
19
+
20
+ def singleton_method_defined_by_ancestor?(klass, method_name)
21
+ ancestor_of(klass).any? do |a|
22
+ a.singleton_class.method_defined?(method_name) || a.singleton_class.private_method_defined?(method_name)
23
+ end
24
+ end
25
+
26
+ private
27
+ def ancestor_of(klass)
28
+ klass.ancestors - [klass]
29
+ end
30
+
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,48 @@
1
+ require 'private_please/tracking/line_change_tracker'
2
+ module PrivatePlease
3
+ module Tracking
4
+
5
+ class << self
6
+
7
+ def after_instance_method_call(method_name, zelf_class)
8
+ store_call_to_tracked_method(
9
+ candidate = PrivatePlease::Candidate.for_instance_method(zelf_class, method_name),
10
+ is_outside_call = (caller_class != zelf_class)
11
+ )
12
+ end
13
+
14
+ def after_singleton_method_call(method_name, zelf_class)
15
+ store_call_to_tracked_method(
16
+ candidate = PrivatePlease::Candidate.for_class_method(zelf_class, method_name),
17
+ is_outside_call = (caller_class != zelf_class)
18
+ )
19
+ end
20
+
21
+ private
22
+
23
+ def caller_class
24
+ call_initiator = LineChangeTracker.call_initiator
25
+ if call_initiator.nil?
26
+ #TODO : investigate why and how this happens
27
+ end
28
+ (caller_is_class_method = call_initiator.is_a?(Class)) ?
29
+ call_initiator :
30
+ call_initiator.class
31
+ end
32
+
33
+ def store_call_to_tracked_method(candidate, is_outside_call)
34
+ is_outside_call ?
35
+ PrivatePlease.calls_store.store_outside_call(candidate) :
36
+ PrivatePlease.calls_store.store_inside_call( candidate)
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
43
+
44
+ require 'private_please/tracking/utils'
45
+ require 'private_please/tracking/instrumentor'
46
+ require 'private_please/tracking/extension'
47
+ require 'private_please/tracking/instruments_all_methods_below'
48
+ require 'private_please/tracking/instruments_automatically_all_methods_in_all_classes'
@@ -1,3 +1,3 @@
1
1
  module PrivatePlease
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -1,66 +1,49 @@
1
1
  require 'private_please/version'
2
2
  require 'private_please/ruby_backports'
3
3
  require 'private_please/candidate'
4
- require 'private_please/storage/calls_store'
5
- require 'private_please/storage/candidates_store'
6
- require 'private_please/storage/methods_names'
7
- require 'private_please/storage/methods_names_bucket'
8
- require 'private_please/report/reporter'
9
- require 'private_please/tracking/line_change_tracker'
10
- require 'private_please/tracking/extension'
11
- require 'private_please/tracking/instrumentor'
12
- require 'private_please/tracking/instruments_all_below'
4
+ require 'private_please/storage'
5
+ require 'private_please/report'
6
+ require 'private_please/reporter'
7
+
8
+ at_exit do
9
+ PrivatePlease.at_exit
10
+ end
13
11
 
14
12
  module PrivatePlease
15
13
 
16
14
  def self.install
17
15
  Module.send :include, PrivatePlease::Tracking::Extension
16
+ PrivatePlease.pp_automatic_mode_enable
17
+ set_trace_func PrivatePlease::Tracking::LineChangeTracker::MY_TRACE_FUN
18
18
  end
19
19
 
20
- #--------------
21
- # config
22
- #--------------
23
-
24
- def self.after_method_call(candidate, outside_call)
25
- outside_call ?
26
- calls_store.store_outside_call(candidate) :
27
- calls_store.store_inside_call(candidate)
28
- end
29
-
30
- def self.remember_candidate(candidate)
31
- candidates_store.store(candidate)
32
- end
33
-
34
-
35
- #--------------
36
- # data & config containers :
37
- #--------------
20
+ def self.pp_automatic_mode_enabled? ; !!$pp_automatic_mode_enabled end
21
+ def self.pp_automatic_mode_enable ; $pp_automatic_mode_enabled = true end
22
+ def self.pp_automatic_mode_disable ; $pp_automatic_mode_enabled = false end
38
23
 
39
- def self.reset_before_new_test
40
- @@_calls_store = @@_candidates_store = nil
24
+ # TODO : replace class methods by PP instance + instance methods
25
+ def self.calls_store
26
+ @@_calls_store ||= Storage::CallsStore.new
41
27
  end
42
28
 
43
- #--------------
44
- # report
45
- #--------------
46
-
47
- def self.report
48
- Report::Reporter.new(candidates_store, calls_store)
29
+ def self.candidates_store
30
+ @@_candidates_store ||= Storage::CandidatesStore.new
49
31
  end
50
32
 
51
- private
52
-
53
- def self.calls_store
54
- @@_calls_store ||= Storage::CallsStore.new
33
+ def self.reset
34
+ @@_candidates_store = @@_calls_store = nil
35
+ Tracking::LineChangeTracker.reset
36
+ set_trace_func nil
55
37
  end
56
38
 
57
- def self.candidates_store
58
- @@_candidates_store ||= Storage::CandidatesStore.new
39
+ def self.at_exit
40
+ report = PrivatePlease::Reporter::SimpleText.new(PrivatePlease.candidates_store, PrivatePlease.calls_store)
41
+ unless $private_please_tests_are_running
42
+ $stdout.puts report.text
43
+ end
59
44
  end
60
45
  end
61
46
 
47
+ require 'private_please/tracking'
62
48
 
63
49
  PrivatePlease.install
64
- at_exit {
65
- puts PrivatePlease.report.to_s
66
- }
@@ -1,5 +1,11 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/private_please/version', __FILE__)
2
+ if RUBY_VERSION == '1.8.7'
3
+ # avoid double-require of version.rb - see http://bit.ly/18lspBV
4
+ $:.unshift File.expand_path("../lib", __FILE__)
5
+ require "private_please/version"
6
+ else
7
+ require File.expand_path('../lib/private_please/version', __FILE__)
8
+ end
3
9
 
4
10
  Gem::Specification.new do |gem|
5
11
  gem.authors = ["Alain Ravet"]