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,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