private_please 0.0.5 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,44 +0,0 @@
1
- module PrivatePlease::Report
2
-
3
- class Table
4
-
5
- def initialize(col_1, col_2)
6
- @col_1, @col_2 = col_1, col_2
7
-
8
- prepare_data
9
- end
10
-
11
- #----------------------------------------------------------------------------
12
- # QUERIES:
13
- #----------------------------------------------------------------------------
14
-
15
- attr_reader :col_1,
16
- :col_2,
17
- :rows,
18
- :longest_value_length
19
-
20
- def empty?
21
- col_1.empty? && col_2.empty?
22
- end
23
-
24
- #----------------------------------------------------------------------------
25
- # COMMANDS:
26
- #----------------------------------------------------------------------------
27
-
28
- # none (immutable)
29
-
30
- #----------------------------------------------------------------------------
31
- private
32
-
33
- def prepare_data
34
- @longest_value_length = [col_1 + col_2].flatten.map(&:length).max || 0
35
-
36
- # pad whichever column is shorter
37
- @col_1[@col_2.length-1] ||= nil unless @col_2.empty?
38
- @col_2[@col_1.length-1] ||= nil unless @col_1.empty?
39
-
40
- @rows = @col_1.zip(@col_2)
41
- end
42
-
43
- end
44
- end
@@ -1,6 +0,0 @@
1
- module PrivatePlease
2
- module Report
3
- end
4
- end
5
-
6
- require File.dirname(__FILE__) + '/report/table'
@@ -1,14 +0,0 @@
1
- require File.dirname(__FILE__) + '/data_compiler'
2
- module PrivatePlease ; module Reporter
3
-
4
- class Base
5
-
6
- attr_reader :data
7
-
8
- def initialize(candidates_store, calls_store)
9
- @data = DataCompiler.new(candidates_store, calls_store).compile_data
10
- end
11
-
12
- end
13
-
14
- end end
@@ -1,82 +0,0 @@
1
- module PrivatePlease ; module Reporter
2
-
3
- class Data < Struct.new(
4
- :candidates_classes_names,
5
- :good_candidates, :bad_candidates, :never_called_candidates,
6
- :good_candidates_c, :bad_candidates_c, :never_called_candidates_c,
7
- :building_time
8
- )
9
- end
10
-
11
- class DataCompiler
12
-
13
- def initialize(candidates_store, calls_store)
14
- @candidates_store = candidates_store
15
- @calls_store = calls_store
16
- end
17
-
18
- # TODO : optimize (with Hamster?)
19
- def compile_data
20
- start_time = Time.now
21
-
22
- bad_candidates,
23
- bad_candidates_c = read_bad_candidates
24
- candidates_classes_names = read_candidates_classes_names
25
-
26
- good_candidates,
27
- good_candidates_c = compute_good_candidates(bad_candidates, bad_candidates_c)
28
-
29
- never_called_candidates,
30
- never_called_candidates_c = compute_never_called_candidates(good_candidates, bad_candidates,
31
- good_candidates_c, bad_candidates_c)
32
-
33
- remove_candidates_with_no_methods!(bad_candidates, good_candidates, never_called_candidates,
34
- bad_candidates_c, good_candidates_c, never_called_candidates_c)
35
- building_time = Time.now - start_time
36
-
37
- Data.new(
38
- candidates_classes_names,
39
- good_candidates, bad_candidates, never_called_candidates,
40
- good_candidates_c, bad_candidates_c, never_called_candidates_c,
41
- building_time
42
- )
43
- end
44
-
45
- private
46
-
47
- def read_candidates_classes_names
48
- @candidates_store.classes_names.sort
49
- end
50
-
51
- def read_bad_candidates
52
- [ bad_candidates = @calls_store.external_calls,
53
- bad_candidates_c = @calls_store.class_external_calls
54
- ]
55
- end
56
-
57
- def compute_good_candidates(bad_candidates, bad_candidates_c)
58
- [ good_candidates = @calls_store.internal_calls .clone.remove(bad_candidates),
59
- good_candidates_c = @calls_store.class_internal_calls.clone.remove(bad_candidates_c)
60
- ]
61
- end
62
-
63
- def compute_never_called_candidates(good_candidates, bad_candidates, good_candidates_c, bad_candidates_c)
64
- never_called_candidates = @candidates_store.instance_methods.clone.
65
- remove(good_candidates).
66
- remove(bad_candidates)
67
-
68
- never_called_candidates_c = @candidates_store.class_methods.clone.
69
- remove(good_candidates_c).
70
- remove(bad_candidates_c)
71
- [never_called_candidates, never_called_candidates_c]
72
- end
73
-
74
- def remove_candidates_with_no_methods!(bad_candidates, good_candidates, never_called_candidates, bad_candidates_c, good_candidates_c, never_called_candidates_c)
75
- [
76
- bad_candidates, bad_candidates_c, good_candidates, good_candidates_c, never_called_candidates, never_called_candidates_c
77
- ].each { |arr| arr.reject! { |k, v| v.empty? } }
78
- end
79
-
80
- end
81
-
82
- end end
@@ -1,37 +0,0 @@
1
-
2
- DEFAULT_REPORT_OPTIONS = {
3
- :show_never_called_candidates_section? => false,
4
- :show_bad_candidates_section? => false,
5
- :show_empty_classes? => false
6
- }
7
-
8
- def options
9
- Object.new.tap do |o|
10
- def o.show_never_called_candidates_section?
11
- (ENV['PP_OPTIONS'] =~ /--show-never-called/) || DEFAULT_REPORT_OPTIONS[:show_never_called_candidates_section?]
12
- end
13
-
14
- def o.show_bad_candidates_section?
15
- (ENV['PP_OPTIONS'] =~ /--show-bad-candidates/) || DEFAULT_REPORT_OPTIONS[:show_bad_candidates_section?]
16
- end
17
-
18
- def o.show_empty_classes?
19
- (ENV['PP_OPTIONS'] =~ /--show-empty-classes/) || DEFAULT_REPORT_OPTIONS[:show_empty_classes?]
20
- end
21
- end
22
- end
23
-
24
- def options_footer_parts
25
- parts = []
26
- DEFAULT_REPORT_OPTIONS.keys.each do |key|
27
- display = "--#{key}".gsub('_', '-')
28
- current_value = options.send(key)
29
- is_default = DEFAULT_REPORT_OPTIONS[key] == current_value
30
- parts << [display, (is_default ? '*' : ' '), current_value]
31
- end
32
- longest_value_length = parts.map(&:first).map(&:length).max || 0
33
- parts.each do |p|
34
- p[0] = p[0].ljust(longest_value_length)
35
- end
36
- parts
37
- end
@@ -1,9 +0,0 @@
1
-
2
- def table_for(col_1, col_2)
3
- PrivatePlease::Report::Table.new(col_1, col_2)
4
- end
5
-
6
- def names_from(class_name, candidates, prefix)
7
- candidates.get_methods_names(class_name).collect{|n|"#{prefix}#{n}"}
8
- end
9
-
@@ -1,18 +0,0 @@
1
- require File.dirname(__FILE__) + '/base'
2
- require 'erb'
3
- require File.dirname(__FILE__) + '/helpers/options_helpers'
4
- require File.dirname(__FILE__) + '/helpers/text_table_helpers'
5
- module PrivatePlease ; module Reporter
6
-
7
- class SimpleText < Base
8
-
9
- TEMPLATE_PATH = File.expand_path(File.dirname(__FILE__) + '/templates/simple.txt.erb')
10
-
11
- def text
12
- erb = ERB.new(File.read(TEMPLATE_PATH), 0, "%<>")
13
- erb.result(binding)
14
- end
15
-
16
- end
17
-
18
- end end
@@ -1,80 +0,0 @@
1
- ====================================================================================
2
- = PrivatePlease report : =
3
- ====================================================================================
4
- % data.candidates_classes_names .sort.each do |class_name|
5
- %
6
- % show_good_candidates_section = true
7
- % show_bad_candidates_section = options.show_bad_candidates_section?
8
- % show_never_candidates_section = options.show_never_called_candidates_section?
9
- %
10
- % if show_good_candidates_section
11
- % good_candidates_table = table_for(
12
- % names_from(class_name, data.good_candidates , prefix = "#"),
13
- % names_from(class_name, data.good_candidates_c, prefix = "."))
14
- % end
15
- % if show_bad_candidates_section
16
- % bad_candidates_table = table_for(
17
- % names_from(class_name, data.bad_candidates , prefix = "#"),
18
- % names_from(class_name, data.bad_candidates_c, prefix = "."))
19
- % end
20
- % if show_never_candidates_section
21
- % never_called_candidates_table = table_for(
22
- % names_from(class_name, data.never_called_candidates , prefix = "#"),
23
- % names_from(class_name, data.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 && !options.show_empty_classes?
34
- %
35
-
36
- <%= class_name
37
- %>
38
- %
39
- % if show_good_candidates_section
40
- % t = good_candidates_table
41
-
42
- * Good candidates : can be made private :
43
- ------------------------------------------
44
- % cell_width = 3 + [38, t.longest_value_length].max
45
- % t.rows.each do |inst_m, class_m|
46
- <%= inst_m && inst_m.ljust(cell_width) %><%= class_m && class_m.ljust(cell_width) %>
47
- % end
48
- % end
49
- %
50
- % if show_bad_candidates_section
51
- % t = bad_candidates_table
52
-
53
- * Bad candidates : must stay public/protected:
54
- . . . . . . . . . . . . . . . . . . . . .
55
- % cell_width = 3 + [38, t.longest_value_length].max
56
- % t.rows.each do |inst_m, class_m|
57
- <%= inst_m && inst_m.ljust(cell_width) %><%= class_m && class_m.ljust(cell_width) %>
58
- % end
59
- % end
60
- %
61
- % if show_never_candidates_section
62
- % t = never_called_candidates_table
63
-
64
- * Methods that were never called :
65
- . . . . . . . . . . . . . . . . . . . . .
66
- % cell_width = 3 + [38, t.longest_value_length].max
67
- % t.rows.each do |inst_m, class_m|
68
- <%= inst_m && inst_m.ljust(cell_width) %><%= class_m && class_m.ljust(cell_width) %>
69
- % end
70
- % end
71
- %
72
- % end
73
-
74
- ====================================================================================
75
-
76
- Report options :
77
- % options_footer_parts.each do |o|
78
- <%= (value = o[2]) ? "V" : 'x' %> <%= is_default = o[1] %> <%= display = o[0] %>
79
- % end
80
- (PP_OPTIONS = <%= ENV['PP_OPTIONS'] %>)
@@ -1,8 +0,0 @@
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,22 +0,0 @@
1
- # Unify the Ruby APIs across versions
2
- #
3
-
4
- # src : https://github.com/marcandre/backports/blob/master/lib/backports/1.9.1/kernel/define_singleton_method.rb
5
- unless Kernel.method_defined? :define_singleton_method
6
- module Kernel
7
- def define_singleton_method(*args, &block)
8
- class << self
9
- self
10
- end.send(:define_method, *args, &block)
11
- end
12
- end
13
- end
14
-
15
- # src: https://github.com/marcandre/backports/blob/master/lib/backports/1.9.2/kernel/singleton_class.rb
16
- unless Kernel.method_defined? :singleton_class
17
- module Kernel
18
- def singleton_class
19
- class << self; self; end
20
- end
21
- end
22
- end
@@ -1,41 +0,0 @@
1
- # As the main program runs, the various method calls are logged here
2
- # (only for the methods marked with `private_please`)
3
-
4
- module PrivatePlease
5
- module Storage
6
-
7
- class CallsStore
8
-
9
- def initialize
10
- @internal_calls = MethodsNamesBucket.new
11
- @external_calls = MethodsNamesBucket.new
12
- @class_internal_calls = MethodsNamesBucket.new
13
- @class_external_calls = MethodsNamesBucket.new
14
- end
15
-
16
- #--------------------------------------------------------------------------
17
- # QUERIES:
18
- #--------------------------------------------------------------------------
19
-
20
- attr_reader :internal_calls,
21
- :external_calls,
22
- :class_internal_calls,
23
- :class_external_calls
24
-
25
- #--------------------------------------------------------------------------
26
- # COMMANDS:
27
- #--------------------------------------------------------------------------
28
-
29
- def store_outside_call(candidate)
30
- bucket = candidate.instance_method? ? external_calls : class_external_calls
31
- bucket.add_method_name(candidate.klass_name, candidate.method_name)
32
- end
33
-
34
- def store_inside_call(candidate)
35
- bucket = candidate.instance_method? ? internal_calls : class_internal_calls
36
- bucket.add_method_name(candidate.klass_name, candidate.method_name)
37
- end
38
- end
39
-
40
- end
41
- end
@@ -1,52 +0,0 @@
1
- # Holds in 2 "buckets" the details (class name + methods names) of the
2
- # methods that are candidate for privatization.
3
- # Those methods were marked via `private_please` in the code.
4
- # Instance methods and class methods are kept separate.
5
-
6
- module PrivatePlease
7
- module Storage
8
-
9
- class CandidatesStore
10
-
11
- def initialize
12
- @instance_methods = MethodsNamesBucket.new
13
- @class_methods = MethodsNamesBucket.new
14
- end
15
-
16
- #--------------------------------------------------------------------------
17
- # QUERIES:
18
- #--------------------------------------------------------------------------
19
-
20
- attr_reader :instance_methods,
21
- :class_methods
22
-
23
- def empty?
24
- instance_methods.empty? && class_methods.empty?
25
- end
26
-
27
- def stored?(candidate)
28
- bucket_for(candidate).get_methods_names(candidate.klass_name).include?(candidate.method_name)
29
- end
30
-
31
- def classes_names
32
- (instance_methods.classes_names + class_methods .classes_names).uniq
33
- end
34
-
35
- #--------------------------------------------------------------------------
36
- # COMMANDS:
37
- #--------------------------------------------------------------------------
38
-
39
- def store(candidate)
40
- bucket_for(candidate).add_method_name(candidate.klass_name, candidate.method_name)
41
- end
42
-
43
- #--------------------------------------------------------------------------
44
- private
45
-
46
- def bucket_for(candidate)
47
- candidate.instance_method? ? @instance_methods : @class_methods
48
- end
49
-
50
- end
51
- end
52
- end
@@ -1,10 +0,0 @@
1
- require 'set'
2
- module PrivatePlease
3
- module Storage
4
-
5
- class MethodsNames < Set
6
- # based on Set => no risk of duplicates when using #add
7
- end
8
-
9
- end
10
- end