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.
- checksums.yaml +7 -0
- data/.ruby-version +1 -1
- data/.travis.yml +3 -5
- data/CHANGELOG +4 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +21 -0
- data/README.md +58 -98
- data/Rakefile +6 -2
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/private_please/config.rb +15 -0
- data/lib/private_please/methods_calls_tracker.rb +44 -0
- data/lib/private_please/reporting/simple_text.rb +43 -0
- data/lib/private_please/reporting/templates/simple.txt.erb +11 -0
- data/lib/private_please/storage/called_methods_memory_store.rb +20 -0
- data/lib/private_please/tracking/debug/trace_point_data_logger.rb +81 -0
- data/lib/private_please/tracking/method_details.rb +27 -0
- data/lib/private_please/tracking/result.rb +25 -0
- data/lib/private_please/tracking/trace_point_details.rb +41 -0
- data/lib/private_please/tracking/trace_point_processor.rb +71 -0
- data/lib/private_please/utils/ruby_utils.rb +44 -0
- data/lib/private_please/utils/source_file_utils.rb +20 -0
- data/lib/private_please/utils/two_level_stack.rb +13 -0
- data/lib/private_please/version.rb +2 -1
- data/lib/private_please.rb +27 -34
- data/private_please.gemspec +32 -25
- metadata +106 -185
- data/Guardfile +0 -8
- data/LICENSE +0 -22
- data/TODO +0 -20
- data/bin/pp_ruby +0 -62
- data/bin/ruby_pp +0 -62
- data/doc/dev_notes.txt +0 -32
- data/doc/fixtures/complex.rb +0 -103
- data/doc/fixtures/empty_class.rb +0 -7
- data/doc/fixtures/fixture_helper.rb +0 -8
- data/doc/fixtures/sample.rb +0 -57
- data/lib/private_please/candidate.rb +0 -49
- data/lib/private_please/report/table.rb +0 -44
- data/lib/private_please/report.rb +0 -6
- data/lib/private_please/reporter/base.rb +0 -14
- data/lib/private_please/reporter/data_compiler.rb +0 -82
- data/lib/private_please/reporter/helpers/options_helpers.rb +0 -37
- data/lib/private_please/reporter/helpers/text_table_helpers.rb +0 -9
- data/lib/private_please/reporter/simple_text.rb +0 -18
- data/lib/private_please/reporter/templates/simple.txt.erb +0 -80
- data/lib/private_please/reporter.rb +0 -8
- data/lib/private_please/ruby_backports.rb +0 -22
- data/lib/private_please/storage/calls_store.rb +0 -41
- data/lib/private_please/storage/candidates_store.rb +0 -52
- data/lib/private_please/storage/methods_names.rb +0 -10
- data/lib/private_please/storage/methods_names_bucket.rb +0 -69
- data/lib/private_please/storage.rb +0 -8
- data/lib/private_please/tracking/extension.rb +0 -12
- data/lib/private_please/tracking/instrumentor.rb +0 -49
- data/lib/private_please/tracking/instruments_all_methods_below.rb +0 -28
- data/lib/private_please/tracking/instruments_automatically_all_methods_in_all_classes.rb +0 -68
- data/lib/private_please/tracking/line_change_tracker.rb +0 -26
- data/lib/private_please/tracking/load_utils/gem_utils.rb +0 -49
- data/lib/private_please/tracking/load_utils/standard_lib_utils.rb +0 -38
- data/lib/private_please/tracking/load_utils.rb +0 -32
- data/lib/private_please/tracking/utils.rb +0 -34
- data/lib/private_please/tracking.rb +0 -49
- data/sample.rb +0 -68
- data/spec/01_tracking_candidate_methods/excluding_gems_and_standard_libraries_spec.rb +0 -31
- data/spec/01_tracking_candidate_methods/explicitely_with_the_private_please_command_spec.rb +0 -118
- data/spec/01_tracking_candidate_methods/load_utils_spec.rb +0 -40
- data/spec/01_tracking_candidate_methods/systematically_in_auto_mode_spec.rb +0 -185
- data/spec/03_logging_calls_on_candidate_methods_spec.rb +0 -37
- data/spec/04_instrumented_program_activity_observation_result_spec.rb +0 -86
- data/spec/05_reporting/report_table_spec.rb +0 -51
- data/spec/06_at_exit_spec.rb +0 -18
- data/spec/_helpers/assert_helpers.rb +0 -76
- data/spec/fixtures/bug_22.rb +0 -17
- data/spec/fixtures/bug_30.rb +0 -6
- data/spec/fixtures/issue_25.rb +0 -12
- data/spec/fixtures/sample_class_for_report.rb +0 -56
- data/spec/fixtures/sample_class_with_all_calls_combinations.rb +0 -69
- data/spec/sandbox/Gemfile +0 -4
- data/spec/sandbox/Gemfile.lock +0 -14
- data/spec/sandbox/README.txt +0 -26
- data/spec/sandbox/normal.rb +0 -7
- data/spec/sandbox/normal_prepended_with_require.rb +0 -8
- data/spec/spec_helper.rb +0 -38
- data/spec/units/calls_store_spec.rb +0 -15
- data/spec/units/candidates_store_spec.rb +0 -55
- data/spec/units/reporter/data_compiler_spec.rb +0 -12
- data/spec/units/reporter/fixtures/simple_case_1.rb +0 -30
- 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,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,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,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
|