private_please 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +3 -5
  4. data/CHANGELOG +4 -0
  5. data/Gemfile +2 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +58 -98
  8. data/Rakefile +6 -2
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/lib/private_please/config.rb +15 -0
  12. data/lib/private_please/methods_calls_tracker.rb +44 -0
  13. data/lib/private_please/reporting/simple_text.rb +43 -0
  14. data/lib/private_please/reporting/templates/simple.txt.erb +11 -0
  15. data/lib/private_please/storage/called_methods_memory_store.rb +20 -0
  16. data/lib/private_please/tracking/debug/trace_point_data_logger.rb +81 -0
  17. data/lib/private_please/tracking/method_details.rb +27 -0
  18. data/lib/private_please/tracking/result.rb +25 -0
  19. data/lib/private_please/tracking/trace_point_details.rb +41 -0
  20. data/lib/private_please/tracking/trace_point_processor.rb +71 -0
  21. data/lib/private_please/utils/ruby_utils.rb +44 -0
  22. data/lib/private_please/utils/source_file_utils.rb +20 -0
  23. data/lib/private_please/utils/two_level_stack.rb +13 -0
  24. data/lib/private_please/version.rb +2 -1
  25. data/lib/private_please.rb +27 -34
  26. data/private_please.gemspec +32 -25
  27. metadata +106 -185
  28. data/Guardfile +0 -8
  29. data/LICENSE +0 -22
  30. data/TODO +0 -20
  31. data/bin/pp_ruby +0 -62
  32. data/bin/ruby_pp +0 -62
  33. data/doc/dev_notes.txt +0 -32
  34. data/doc/fixtures/complex.rb +0 -103
  35. data/doc/fixtures/empty_class.rb +0 -7
  36. data/doc/fixtures/fixture_helper.rb +0 -8
  37. data/doc/fixtures/sample.rb +0 -57
  38. data/lib/private_please/candidate.rb +0 -49
  39. data/lib/private_please/report/table.rb +0 -44
  40. data/lib/private_please/report.rb +0 -6
  41. data/lib/private_please/reporter/base.rb +0 -14
  42. data/lib/private_please/reporter/data_compiler.rb +0 -82
  43. data/lib/private_please/reporter/helpers/options_helpers.rb +0 -37
  44. data/lib/private_please/reporter/helpers/text_table_helpers.rb +0 -9
  45. data/lib/private_please/reporter/simple_text.rb +0 -18
  46. data/lib/private_please/reporter/templates/simple.txt.erb +0 -80
  47. data/lib/private_please/reporter.rb +0 -8
  48. data/lib/private_please/ruby_backports.rb +0 -22
  49. data/lib/private_please/storage/calls_store.rb +0 -41
  50. data/lib/private_please/storage/candidates_store.rb +0 -52
  51. data/lib/private_please/storage/methods_names.rb +0 -10
  52. data/lib/private_please/storage/methods_names_bucket.rb +0 -69
  53. data/lib/private_please/storage.rb +0 -8
  54. data/lib/private_please/tracking/extension.rb +0 -12
  55. data/lib/private_please/tracking/instrumentor.rb +0 -49
  56. data/lib/private_please/tracking/instruments_all_methods_below.rb +0 -28
  57. data/lib/private_please/tracking/instruments_automatically_all_methods_in_all_classes.rb +0 -68
  58. data/lib/private_please/tracking/line_change_tracker.rb +0 -26
  59. data/lib/private_please/tracking/load_utils/gem_utils.rb +0 -49
  60. data/lib/private_please/tracking/load_utils/standard_lib_utils.rb +0 -38
  61. data/lib/private_please/tracking/load_utils.rb +0 -32
  62. data/lib/private_please/tracking/utils.rb +0 -34
  63. data/lib/private_please/tracking.rb +0 -49
  64. data/sample.rb +0 -68
  65. data/spec/01_tracking_candidate_methods/excluding_gems_and_standard_libraries_spec.rb +0 -31
  66. data/spec/01_tracking_candidate_methods/explicitely_with_the_private_please_command_spec.rb +0 -118
  67. data/spec/01_tracking_candidate_methods/load_utils_spec.rb +0 -40
  68. data/spec/01_tracking_candidate_methods/systematically_in_auto_mode_spec.rb +0 -185
  69. data/spec/03_logging_calls_on_candidate_methods_spec.rb +0 -37
  70. data/spec/04_instrumented_program_activity_observation_result_spec.rb +0 -86
  71. data/spec/05_reporting/report_table_spec.rb +0 -51
  72. data/spec/06_at_exit_spec.rb +0 -18
  73. data/spec/_helpers/assert_helpers.rb +0 -76
  74. data/spec/fixtures/bug_22.rb +0 -17
  75. data/spec/fixtures/bug_30.rb +0 -6
  76. data/spec/fixtures/issue_25.rb +0 -12
  77. data/spec/fixtures/sample_class_for_report.rb +0 -56
  78. data/spec/fixtures/sample_class_with_all_calls_combinations.rb +0 -69
  79. data/spec/sandbox/Gemfile +0 -4
  80. data/spec/sandbox/Gemfile.lock +0 -14
  81. data/spec/sandbox/README.txt +0 -26
  82. data/spec/sandbox/normal.rb +0 -7
  83. data/spec/sandbox/normal_prepended_with_require.rb +0 -8
  84. data/spec/spec_helper.rb +0 -38
  85. data/spec/units/calls_store_spec.rb +0 -15
  86. data/spec/units/candidates_store_spec.rb +0 -55
  87. data/spec/units/reporter/data_compiler_spec.rb +0 -12
  88. data/spec/units/reporter/fixtures/simple_case_1.rb +0 -30
  89. data/spec/units/reporter/fixtures/simple_case_2.rb +0 -55
@@ -1,69 +0,0 @@
1
- # Associates and indexes classes (name) and some of their methods (names).
2
- # Ex:
3
- # +-------------+---------------------------------------+
4
- # | class name => 1+ methods names |
5
- # +-------------+---------------------------------------+
6
- # | 'Foo' | MethodsNames.new('foo to_baz to_bar') |
7
- # | 'Bar' | MethodsNames.new('qux') |
8
- # +-------------+---------------------------------------+
9
-
10
- module PrivatePlease
11
- module Storage
12
-
13
- class MethodsNamesBucket < Hash
14
-
15
- def initialize
16
- super{|hash, class_name|
17
- #hash[class_name] = PrivatePlease::Storage::MethodsNames.new
18
- hash.set_methods_names(class_name, MethodsNames.new)
19
- }
20
- end
21
-
22
- def clone
23
- (self.class).new.tap do |klone|
24
- classes_names.each do |class_name|
25
- klone.set_methods_names(class_name, (self).get_methods_names(class_name))
26
- end
27
- end
28
- end
29
-
30
- #--------------------------------------------------------------------------
31
- # QUERIES:
32
- #--------------------------------------------------------------------------
33
-
34
- alias_method :classes_names, :keys
35
- alias_method :get_methods_names, :[]
36
- # undef :[], :keys # should be undef-ed, but that complexifies the test #TODO : undef :[], :keys
37
- # ( => must define ==(other) and cast type of 'other')
38
-
39
- #--------------------------------------------------------------------------
40
- # COMMANDS:
41
- #--------------------------------------------------------------------------
42
-
43
- alias_method :set_methods_names, :[]=
44
- undef :[]=
45
-
46
- def add_method_name(class_name, method_name)
47
- self.get_methods_names(class_name).add(method_name)
48
- end
49
-
50
- def remove(other)
51
- other.classes_names.each do |cn|
52
- next if (methods_to_remove = other.get_methods_names(cn)).empty?
53
- next if (methods_before = self .get_methods_names(cn)).empty?
54
- difference = methods_before - methods_to_remove
55
- self.set_methods_names(cn, difference)
56
- end
57
- prune!
58
- self
59
- end
60
-
61
- private
62
-
63
- def prune!
64
- self.reject!{|_, v|v.empty?}
65
- end
66
- end
67
-
68
- end
69
- end
@@ -1,8 +0,0 @@
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'
@@ -1,12 +0,0 @@
1
- module PrivatePlease ; module Tracking
2
-
3
- module Extension
4
-
5
- def private_please
6
- include PrivatePlease::Tracking::InstrumentsAllMethodsBelow
7
- set_trace_func PrivatePlease::Tracking::LineChangeTracker::MY_TRACE_FUN
8
- end
9
-
10
- end
11
-
12
- end end
@@ -1,49 +0,0 @@
1
- module PrivatePlease ; module Tracking
2
-
3
- module Instrumentor
4
- class << self
5
-
6
- def add_call_tracking_code_to(candidate)
7
- return if candidate.already_instrumented?
8
- candidate.mark_as_instrumented
9
-
10
- klass, method_name = candidate.klass, candidate.method_name
11
- candidate.instance_method? ?
12
- add_call_tracking_code_to_instance_method(klass, method_name) :
13
- add_call_tracking_code_to_class_method( klass, method_name)
14
- end
15
-
16
-
17
- private
18
-
19
- def add_call_tracking_code_to_class_method(klass, method_name)
20
- orig_method = klass.singleton_class.instance_method(method_name)
21
- klass.class_eval <<RUBY
22
- define_singleton_method(method_name) do |*args, &blk| # def self.observed_method_i(..)
23
- set_trace_func(nil) #don't track activity while here #
24
- PrivatePlease::Tracking.after_singleton_method_call(method_name, self_class=self)
25
- set_trace_func(LineChangeTracker::MY_TRACE_FUN) #
26
- # make the original call : #
27
- orig_method.bind(self).call(*args, &blk) # <call original method>
28
- end # end
29
- RUBY
30
- end
31
-
32
-
33
- def add_call_tracking_code_to_instance_method(klass, method_name)
34
- orig_method = klass.instance_method(method_name)
35
- klass.class_eval <<RUBY
36
- define_method(method_name) do |*args, &blk| # def observed_method_i(..)
37
- set_trace_func(nil) #don't track activity while here #
38
- PrivatePlease::Tracking.after_instance_method_call(method_name, self.class)
39
- set_trace_func(LineChangeTracker::MY_TRACE_FUN) #
40
- # make the original call : #
41
- orig_method.bind(self).call(*args, &blk) # <call original method>
42
- end # end
43
- RUBY
44
- end
45
-
46
- end
47
- end
48
-
49
- end end
@@ -1,28 +0,0 @@
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
@@ -1,68 +0,0 @@
1
- module Kernel
2
-
3
- alias_method :_orig_require, :require
4
-
5
- def require string
6
- prev_val = PrivatePlease.pp_automatic_mode_enabled?
7
- if PrivatePlease::Tracking::LoadUtils.standard_lib_or_gem?(string)
8
- PrivatePlease.pp_automatic_mode_disable
9
- end
10
-
11
- send :_orig_require, string
12
-
13
- PrivatePlease.pp_automatic_mode_enable(prev_val)
14
- end
15
-
16
- end
17
-
18
- class Class
19
-
20
- def singleton_method_added(method_name)
21
- return unless PrivatePlease.pp_automatic_mode_enabled?
22
-
23
- return if PrivatePlease::Tracking::Utils.private_singleton_method?(self, method_name) \
24
- || PrivatePlease::Tracking::Utils.singleton_method_defined_by_ancestor?(self, method_name)
25
-
26
- candidate = PrivatePlease::Candidate.for_class_method(klass = self, method_name)
27
- PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
28
- end
29
-
30
-
31
- def method_added(method_name)
32
- return unless PrivatePlease.pp_automatic_mode_enabled?
33
-
34
- return if [:method_added].include?(method_name)
35
- return if PrivatePlease::Tracking::Utils.private_instance_method?(self, method_name) \
36
- || PrivatePlease::Tracking::Utils.instance_method_defined_by_ancestor?(self, method_name)
37
-
38
- candidate = PrivatePlease::Candidate.for_instance_method(klass = self, method_name)
39
- PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
40
- end
41
-
42
- end
43
-
44
-
45
- class Module
46
-
47
- def singleton_method_added(method_name)
48
- return unless PrivatePlease.pp_automatic_mode_enabled?
49
-
50
- return if [:included].include?(method_name) #&& !self.is_a?(Class)
51
- return if PrivatePlease::Tracking::Utils.private_singleton_method?(self, method_name)
52
-
53
- candidate = PrivatePlease::Candidate.for_class_method(klass = self, method_name)
54
- PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
55
- end
56
-
57
-
58
- def method_added(method_name)
59
- return unless PrivatePlease.pp_automatic_mode_enabled?
60
-
61
- return if [:method_added, :singleton_method_added].include?(method_name)
62
- return if PrivatePlease::Tracking::Utils.private_instance_method?(self, method_name)
63
-
64
- candidate = PrivatePlease::Candidate.for_instance_method(klass = self, method_name)
65
- PrivatePlease::Tracking::Instrumentor.add_call_tracking_code_to(candidate)
66
- end
67
- end
68
-
@@ -1,26 +0,0 @@
1
- module PrivatePlease ; module Tracking
2
-
3
- class LineChangeTracker
4
- class << self
5
-
6
- attr_accessor :prev_prev_self, :prev_self, :curr_self
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
14
- end
15
-
16
- MY_TRACE_FUN = lambda do |event, file, line, id, binding, klass|
17
- return unless 'line'==event
18
- LineChangeTracker.prev_prev_self = LineChangeTracker.prev_self
19
- LineChangeTracker.prev_self = LineChangeTracker.curr_self
20
- LineChangeTracker.curr_self = (eval 'self', binding)
21
- #puts "my : #{event} in #{file}/#{line} id:#{id} klass:#{klass} - self = #{(eval'self', binding).inspect}"
22
- end
23
-
24
- end
25
-
26
- end end
@@ -1,49 +0,0 @@
1
- # OPTIMISATION :
2
- # Calls to `$ gem ..` are slow (esp. on jruby!)
3
- # => we 1/ pre-perform them asynchronously (Threads) when this file is loaded,
4
- # 2/ cache the obtained value in a variable,
5
- # 3/ rewrite the slow method as a noop version that simply returns the cached value.
6
-
7
- module PrivatePlease::Tracking::LoadUtils
8
-
9
- module GemUtils
10
-
11
- class << self
12
-
13
- # performs `$ gem env`
14
- #
15
- def gem_env
16
- GEM_ENV_PRELOADER.join
17
- gem_env # call the fast/just rewritten version
18
- end
19
-
20
- # performs `$ gem list` + extracts the names
21
- #
22
- def gems_names
23
- GEMS_NAMES_PRELOADER.join
24
- gems_names
25
- end
26
-
27
- #-------------------------------------------------------------------------------------------------------------------
28
- private
29
-
30
- GEM_ENV_PRELOADER = Thread.new do
31
- @@_cached_gem_env = `gem env`
32
- def GemUtils.gem_env
33
- @@_cached_gem_env
34
- end
35
- end
36
-
37
- GEMS_NAMES_PRELOADER = Thread.new do
38
- @@_cached_gems_names = `gem list`. # very slow on jruby
39
- split("\n").
40
- map { |l| l.match(/(\S+)\s+.*/)[1]} # ["bundle", "bundler", "rspec", ..]
41
- def GemUtils.gems_names
42
- @@_cached_gems_names
43
- end
44
- end
45
-
46
- end
47
- end
48
-
49
- end
@@ -1,38 +0,0 @@
1
- module PrivatePlease::Tracking::LoadUtils
2
-
3
- module StandardLibUtils
4
-
5
- class << self
6
-
7
- def standard_lib?(requiree)
8
- path_base = "#{std_lib_home}/#{requiree}"
9
- if File.exists?(path_base)
10
- path_base
11
- elsif File.exists?("#{path_base}.rb")
12
- "#{path_base}.rb"
13
- end
14
- end
15
-
16
- #-------------------------------------------------------------------------------------------------------------------
17
- private
18
-
19
- # Ex: "/Users/ara/.rbenv/versions/jruby-1.7.3/bin/jruby"
20
- def ruby_executable
21
- @@_ruby_executable ||= GemUtils.gem_env.match(/RUBY EXECUTABLE:\s*(.*)/)[1]
22
- end
23
-
24
- # Ex: "/Users/ara/.rbenv/versions/jruby-1.7.3/lib/ruby/1.9"
25
- def std_lib_home
26
- @@_std_lib_home ||= begin
27
- basedir = ruby_executable.gsub(/bin\/[j]?ruby/, 'lib/ruby') # => "/Users/ara/.rbenv/versions/jruby-1.7.3/lib/ruby"
28
- # jruby has 2+ directories of std. libs under the basedir : 1.8 and 1.9
29
- $:.detect {|path| # We choose the one that is also in the load path.
30
- path =~ /#{basedir}\/[12][^\/]+$/ #
31
- } # => "/Users/ara/.rbenv/versions/jruby-1.7.3/lib/ruby/1.9"
32
- end # ^^^ == the mode
33
- end
34
-
35
- end
36
- end
37
-
38
- end
@@ -1,32 +0,0 @@
1
- module PrivatePlease::Tracking
2
-
3
- module LoadUtils
4
- require File.dirname(__FILE__) + '/load_utils/gem_utils'
5
- require File.dirname(__FILE__) + '/load_utils/standard_lib_utils'
6
-
7
- class << self
8
-
9
- def standard_lib_or_gem?(requiree)
10
- (@@_standard_lib_or_gem ||= {})[requiree] ||= begin
11
- standard_lib?(requiree) || gem?(requiree)
12
- end
13
- end
14
-
15
- def standard_lib?(requiree)
16
- (@@_standard_lib ||= {})[requiree] ||= StandardLibUtils.standard_lib?(requiree)
17
- end
18
-
19
- def gem?(requiree)
20
- (@@_gems ||= {})[requiree] ||= begin
21
- base_name = requiree.include?('/') ?
22
- requiree.split('/').first : # ex: require 'rspec/autorun'
23
- requiree # ex: require 'rspec'
24
- GemUtils.gems_names.include?(base_name)
25
- end
26
-
27
- end
28
-
29
- end
30
- end
31
-
32
- end
@@ -1,34 +0,0 @@
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
@@ -1,49 +0,0 @@
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/load_utils'
46
- require 'private_please/tracking/instrumentor'
47
- require 'private_please/tracking/extension'
48
- require 'private_please/tracking/instruments_all_methods_below'
49
- require 'private_please/tracking/instruments_automatically_all_methods_in_all_classes'