reflexive 0.0.6 → 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.
- data/Gemfile +9 -7
- data/Rakefile +10 -4
- data/config.ru +1 -1
- data/lib/reflexive/application.rb +50 -30
- data/lib/reflexive/coderay_html_encoder.rb +1 -1
- data/lib/reflexive/coderay_ruby_scanner.rb +2 -0
- data/lib/reflexive/core_ext/module/reflexive_instance_methods.rb +44 -0
- data/lib/reflexive/descendants.rb +12 -2
- data/lib/reflexive/helpers.rb +26 -9
- data/lib/reflexive/method_lookup.rb +199 -0
- data/lib/reflexive/methods.rb +3 -2
- data/lib/reflexive/parse_tree_top_down_walker.rb +69 -8
- data/lib/reflexive/reflexive_ripper.rb +5 -2
- data/lib/reflexive/routing_helpers.rb +74 -53
- data/public/stylesheets/reflexive/reflexive.css +5 -0
- data/reflexive.gemspec +9 -6
- data/spec/coderay_html_encoder_spec.rb +8 -2
- data/spec/integration_spec.rb +227 -0
- data/spec/integration_spec_fixture.rb +87 -0
- data/spec/method_lookup_spec.rb +348 -0
- data/spec/methods_spec.rb +246 -28
- data/spec/rails_integration_spec.rb +7 -0
- data/spec/rails_integration_spec_helper.rb +21 -11
- data/spec/reflexive_ripper_spec.rb +57 -19
- data/spec/reflexive_spec.rb +15 -0
- data/views/constants_show.erb +18 -1
- data/views/dashboard.erb +3 -4
- data/views/layout.erb +10 -0
- data/views/methods_apidock.erb +9 -1
- data/views/methods_choose.erb +19 -0
- metadata +76 -40
data/Gemfile
CHANGED
@@ -2,15 +2,17 @@ source "http://rubygems.org"
|
|
2
2
|
|
3
3
|
# keeping this in sync with reflexive.gemspec manually
|
4
4
|
|
5
|
-
gem "rack"
|
6
|
-
gem "sinatra"
|
7
|
-
gem "sinatra_more"
|
8
|
-
gem "coderay"
|
9
|
-
gem "rdiscount"
|
5
|
+
gem "rack", "1.1.0"
|
6
|
+
gem "sinatra", "1.0"
|
7
|
+
gem "sinatra_more", "0.3.40"
|
8
|
+
gem "coderay", "0.9.3"
|
9
|
+
# gem "rdiscount"
|
10
10
|
|
11
11
|
group :development do
|
12
12
|
gem "rails", "3.0.0.beta3"
|
13
13
|
gem "rspec", "2.0.0.beta.8"
|
14
|
-
gem "sinatra-reloader"
|
15
|
-
gem "thin"
|
14
|
+
gem "sinatra-reloader", "0.4.1"
|
15
|
+
gem "thin", "1.2.7"
|
16
|
+
gem "rack-test", "0.5.3"
|
17
|
+
gem "webrat", "0.7.1"
|
16
18
|
end
|
data/Rakefile
CHANGED
@@ -8,14 +8,20 @@ end
|
|
8
8
|
GEM_NAME = "reflexive"
|
9
9
|
|
10
10
|
desc "Relese next version of reflexive gem (do that just after `git commit')"
|
11
|
-
task :release do
|
11
|
+
task :release => :spec do
|
12
12
|
require "rubygems"
|
13
13
|
require "rubygems/version"
|
14
14
|
require "yaml"
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
if ENV["GEM_VERSION"]
|
17
|
+
# release version passed in ENV["GEM_VERSION"]
|
18
|
+
new_version = ENV["GEM_VERSION"]
|
19
|
+
else
|
20
|
+
# by default release next minor version
|
21
|
+
current_version = YAML.load(`gem specification #{ GEM_NAME } -r`)["version"] || Gem::Version.new("0.0.0")
|
22
|
+
new_version = (current_version.segments[0..-2] + [current_version.segments[-1].succ]).join(".")
|
23
|
+
ENV["GEM_VERSION"] = new_version
|
24
|
+
end
|
19
25
|
|
20
26
|
puts "Releasing #{ GEM_NAME } #{ new_version }"
|
21
27
|
|
data/config.ru
CHANGED
@@ -12,10 +12,12 @@ require "reflexive/columnizer"
|
|
12
12
|
require "reflexive/constantize"
|
13
13
|
require "reflexive/descendants"
|
14
14
|
require "reflexive/methods"
|
15
|
+
require "reflexive/method_lookup"
|
15
16
|
|
16
17
|
if ENV["SINATRA_RELOADER"]
|
17
18
|
require "rails/all"
|
18
19
|
require "arel"
|
20
|
+
require File.expand_path("../../../spec/integration_spec_fixture", __FILE__)
|
19
21
|
|
20
22
|
module ::Kernel
|
21
23
|
def r(*args)
|
@@ -60,10 +62,11 @@ module Reflexive
|
|
60
62
|
end
|
61
63
|
|
62
64
|
action "constant_lookup" do
|
63
|
-
if klass = Reflexive.constant_lookup(*params.values_at(:name, :scope))
|
65
|
+
if (klass = Reflexive.constant_lookup(*params.values_at(:name, :scope))) &&
|
66
|
+
(klass.instance_of?(Class) || klass.instance_of?(Module))
|
64
67
|
redirect(constant_path(klass.to_s))
|
65
68
|
else
|
66
|
-
e "failed to lookup
|
69
|
+
e "failed to lookup class/module with name `#{ params[:name] }' in scope #{ params[:scope] }"
|
67
70
|
end
|
68
71
|
end
|
69
72
|
|
@@ -87,54 +90,71 @@ module Reflexive
|
|
87
90
|
end
|
88
91
|
end
|
89
92
|
|
90
|
-
|
93
|
+
def definition_action(klass, level, name)
|
91
94
|
find_klass(klass)
|
92
|
-
@method_name =
|
93
|
-
@path, @line = @klass.method
|
94
|
-
|
95
|
-
|
95
|
+
@method_name = name
|
96
|
+
@path, @line = @klass.send(level == :class ? :method : :instance_method, @method_name).source_location
|
97
|
+
if @path.include?("(eval)")
|
98
|
+
e "#{ name } #{ level } method was generated using `eval' function and can't be browsed"
|
99
|
+
else
|
100
|
+
@source = highlight_file(@path, :highlight_lines => [@line])
|
101
|
+
erb :methods_definition
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
get %r</reflexive/constants/([^/&#]+)/class_methods/([^/&#]+)/definition> do |klass, method|
|
106
|
+
definition_action(klass, :class, method)
|
96
107
|
end
|
97
108
|
|
98
109
|
get %r</reflexive/constants/([^/&#]+)/instance_methods/([^/&#]+)/definition> do |klass, method|
|
110
|
+
definition_action(klass, :instance, method)
|
111
|
+
end
|
112
|
+
|
113
|
+
get %r</reflexive/constants/([^/&#]+)/instance_methods/([^/&#]+)/apidock> do |klass, method|
|
99
114
|
find_klass(klass)
|
100
115
|
@method_name = method
|
101
|
-
@
|
102
|
-
|
103
|
-
erb :methods_definition
|
116
|
+
@level = :instance
|
117
|
+
erb :methods_apidock
|
104
118
|
end
|
105
119
|
|
106
|
-
get %r</reflexive/constants/([^/&#]+)/
|
120
|
+
get %r</reflexive/constants/([^/&#]+)/class_methods/([^/&#]+)/apidock> do |klass, method|
|
107
121
|
find_klass(klass)
|
108
122
|
@method_name = method
|
123
|
+
@level = :class
|
109
124
|
erb :methods_apidock
|
110
125
|
end
|
111
126
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
if
|
116
|
-
redirect(
|
117
|
-
|
127
|
+
def method_lookup_action(klass, level, name)
|
128
|
+
lookup = MethodLookup.new(klass: klass, level: level, name: name)
|
129
|
+
if definitions = lookup.definitions
|
130
|
+
if definitions.size == 1
|
131
|
+
redirect(new_method_definition_path(*definitions[0]) + "#highlighted")
|
132
|
+
else
|
133
|
+
@definitions, @klass, @level, @name, @last_resort_lookup_used =
|
134
|
+
definitions, klass, level, name, lookup.last_resort_lookup_used?
|
135
|
+
erb :methods_choose
|
136
|
+
end
|
137
|
+
elsif documentations = lookup.documentations
|
138
|
+
if documentations.size == 1
|
139
|
+
redirect(method_documentation_path(*documentations[0]))
|
118
140
|
else
|
119
|
-
|
141
|
+
raise ArgumentError, "don't know how to handle multiple documentations"
|
120
142
|
end
|
121
|
-
|
122
|
-
e "failed to find `#{
|
143
|
+
else
|
144
|
+
e "failed to find `#{ name }' #{ level } method for #{ klass }"
|
123
145
|
end
|
146
|
+
#
|
147
|
+
# e "failed to find `#{ method }' instance method for #{ klass }"
|
148
|
+
end
|
149
|
+
|
150
|
+
get %r</reflexive/constants/([^/&#]+)/class_methods/([^/&#]+)> do |klass, method|
|
151
|
+
find_klass(klass)
|
152
|
+
method_lookup_action(@klass, :class, method)
|
124
153
|
end
|
125
154
|
|
126
155
|
get %r</reflexive/constants/([^/&#]+)/instance_methods/([^/&#]+)> do |klass, method|
|
127
156
|
find_klass(klass)
|
128
|
-
|
129
|
-
if @klass.instance_method(method).source_location
|
130
|
-
redirect(instance_method_definition_path(klass, method) +
|
131
|
-
"#highlighted")
|
132
|
-
else
|
133
|
-
redirect(method_documentation_path(klass, method))
|
134
|
-
end
|
135
|
-
rescue NameError
|
136
|
-
e "failed to find `#{ method }' instance method for #{ klass }"
|
137
|
-
end
|
157
|
+
method_lookup_action(@klass, :instance, method)
|
138
158
|
end
|
139
159
|
|
140
160
|
get %r</reflexive/constants/([^/&#]+)> do |klass|
|
@@ -49,6 +49,7 @@ module Reflexive
|
|
49
49
|
in_backtick = false
|
50
50
|
in_symbol = false
|
51
51
|
in_embexpr_nesting = 0
|
52
|
+
|
52
53
|
scanner_events.each do |scanner_event|
|
53
54
|
token_val, event, tags =
|
54
55
|
ReflexiveRipper.destruct_scanner_event(scanner_event)
|
@@ -107,6 +108,7 @@ module Reflexive
|
|
107
108
|
# }
|
108
109
|
# ;
|
109
110
|
@coderay_tokens << [token_val, :content]
|
111
|
+
@coderay_tokens.last << tags if tags
|
110
112
|
@coderay_tokens << [:close, :symbol]
|
111
113
|
in_symbol = false
|
112
114
|
elsif ripper_token == :regexp_beg
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Module
|
2
|
+
if RUBY_VERSION > '1.9.1'
|
3
|
+
alias reflexive_public_instance_methods public_instance_methods
|
4
|
+
alias reflexive_private_instance_methods private_instance_methods
|
5
|
+
alias reflexive_protected_instance_methods protected_instance_methods
|
6
|
+
else
|
7
|
+
# Try to workaround 1.9.1 *_instance_methods issues
|
8
|
+
def reflexive_public_instance_methods(inc_super = true)
|
9
|
+
if inc_super
|
10
|
+
public_instance_methods(true)
|
11
|
+
else
|
12
|
+
methods = public_instance_methods(false)
|
13
|
+
methods -= Module.public_instance_methods(false) unless self === Module
|
14
|
+
methods -= Class.public_instance_methods(false) unless self === Class
|
15
|
+
# ancestors.each do |ancestor|
|
16
|
+
# methods -= ancestor.public_instance_methods(false)
|
17
|
+
# end
|
18
|
+
methods
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def reflexive_protected_instance_methods(inc_super = true)
|
23
|
+
if inc_super
|
24
|
+
protected_instance_methods(true)
|
25
|
+
else
|
26
|
+
methods = protected_instance_methods(false)
|
27
|
+
methods -= Module.protected_instance_methods(false) unless self === Module
|
28
|
+
methods -= Class.protected_instance_methods(false) unless self === Class
|
29
|
+
methods
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def reflexive_private_instance_methods(inc_super = true)
|
34
|
+
if inc_super
|
35
|
+
private_instance_methods(true)
|
36
|
+
else
|
37
|
+
methods = private_instance_methods(false)
|
38
|
+
methods -= Module.private_instance_methods(false) unless self === Module
|
39
|
+
methods -= Class.private_instance_methods(false) unless self === Class
|
40
|
+
methods
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -34,8 +34,18 @@ module Reflexive
|
|
34
34
|
ancestors = c.singleton_class.ancestors[0 .. (generations || -1)]
|
35
35
|
subclass << c if ancestors.include?(klass)
|
36
36
|
end
|
37
|
-
|
38
|
-
|
37
|
+
|
38
|
+
if klass.instance_of?(Module)
|
39
|
+
# descendants of module are also modules which include the module
|
40
|
+
ObjectSpace.each_object(Module) do |c|
|
41
|
+
next if c == klass
|
42
|
+
|
43
|
+
ancestors = c.ancestors[0 .. (generations || -1)]
|
44
|
+
subclass << c if ancestors.include?(klass)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
subclass.uniq
|
39
49
|
end
|
40
50
|
end
|
41
51
|
|
data/lib/reflexive/helpers.rb
CHANGED
@@ -3,15 +3,26 @@ require "reflexive/coderay_ruby_scanner"
|
|
3
3
|
require "reflexive/coderay_html_encoder"
|
4
4
|
|
5
5
|
module Reflexive
|
6
|
+
def self.class_reloading_active?
|
7
|
+
if defined?(Rails)
|
8
|
+
!Rails.configuration.cache_classes rescue false
|
9
|
+
else
|
10
|
+
false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
6
14
|
FILE_EXT = /\.\w+\z/
|
7
15
|
DL_EXT = /\.s?o\z/
|
8
16
|
def self.load_path_lookup(path)
|
9
17
|
path_with_rb_ext = path.sub(FILE_EXT, "") + ".rb"
|
10
|
-
|
11
|
-
$LOAD_PATH.
|
12
|
-
|
18
|
+
|
19
|
+
$LOAD_PATH.each do |load_path|
|
20
|
+
if feature = File.join(load_path, path_with_rb_ext)
|
21
|
+
return feature if File.exists?(feature)
|
22
|
+
end
|
13
23
|
end
|
14
|
-
|
24
|
+
|
25
|
+
nil
|
15
26
|
end
|
16
27
|
|
17
28
|
def self.loaded_features_lookup(path)
|
@@ -48,11 +59,11 @@ module Reflexive
|
|
48
59
|
tokens = CodeRayRubyScanner.new(src).tokenize
|
49
60
|
encoder = CodeRayHtmlEncoder.new(options)
|
50
61
|
encoder.encode_tokens(tokens)
|
51
|
-
elsif path =~ /\.(markdown|md)$/
|
52
|
-
require "rdiscount"
|
53
|
-
src = IO.read(path)
|
54
|
-
markdown = RDiscount.new(src)
|
55
|
-
markdown.to_html
|
62
|
+
# elsif path =~ /\.(markdown|md)$/
|
63
|
+
# require "rdiscount"
|
64
|
+
# src = IO.read(path)
|
65
|
+
# markdown = RDiscount.new(src)
|
66
|
+
# markdown.to_html
|
56
67
|
else
|
57
68
|
CodeRay.scan_file(path).html(options).div
|
58
69
|
end
|
@@ -169,6 +180,12 @@ module Reflexive
|
|
169
180
|
:title => (method_name if link_text.include?("...")))
|
170
181
|
end
|
171
182
|
|
183
|
+
def full_name_link_to_method(constant, level, method_name)
|
184
|
+
link_text = "#{ constant }#{ level == :instance ? "#" : "." }#{ method_name }"
|
185
|
+
link_to(Rack::Utils.escape_html(link_text),
|
186
|
+
new_method_path(constant, level, method_name))
|
187
|
+
end
|
188
|
+
|
172
189
|
##
|
173
190
|
# Truncates a given text after a given :length if text is longer than :length (defaults to 30).
|
174
191
|
# The last characters will be replaced with the :omission (defaults to "в_│") for a total length not exceeding :length.
|
@@ -0,0 +1,199 @@
|
|
1
|
+
require "reflexive/constantize"
|
2
|
+
|
3
|
+
module Reflexive
|
4
|
+
class MethodLookup
|
5
|
+
def initialize(options)
|
6
|
+
unless (@klass, @level, @name = options.values_at(:klass, :level, :name)).all?
|
7
|
+
raise ArgumentError, "must pass :klass, :level, :name as named arguments"
|
8
|
+
end
|
9
|
+
@level, @name = @level.to_sym, @name.to_sym
|
10
|
+
end
|
11
|
+
|
12
|
+
def definitions
|
13
|
+
lookup unless @lookup_done
|
14
|
+
@definitions
|
15
|
+
end
|
16
|
+
|
17
|
+
def documentations
|
18
|
+
lookup unless @lookup_done
|
19
|
+
@documentations
|
20
|
+
end
|
21
|
+
|
22
|
+
def last_resort_lookup_used?
|
23
|
+
@last_resort_lookup_used
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def lookup
|
29
|
+
begin
|
30
|
+
defined_method_lookup
|
31
|
+
rescue NameError => e
|
32
|
+
# don't swallow NameError if it's not related to the method we're looking for
|
33
|
+
raise unless e.message.include?(@name.to_s)
|
34
|
+
heuristic_lookup
|
35
|
+
last_resort_lookup unless lookup_succeed?
|
36
|
+
end
|
37
|
+
@lookup_done = true
|
38
|
+
end
|
39
|
+
|
40
|
+
def lookup_succeed?
|
41
|
+
@definitions && @definitions.size > 0 ||
|
42
|
+
@documentations && @documentations.size > 0
|
43
|
+
end
|
44
|
+
|
45
|
+
def defined_method_lookup
|
46
|
+
unbound_method = @klass.send(method_getter, @name)
|
47
|
+
if unbound_method.source_location
|
48
|
+
@definitions = [[@klass, @level, @name]]
|
49
|
+
elsif @klass.instance_of?(Class) && @level == :class && @name == :new &&
|
50
|
+
(@klass.instance_method(:initialize).source_location rescue false)
|
51
|
+
@definitions = [[@klass, :instance, :initialize]]
|
52
|
+
elsif core_klass = unbound_method.owner
|
53
|
+
if core_klass == Kernel
|
54
|
+
@documentations = [[Kernel, :instance, @name]]
|
55
|
+
elsif core_klass == Module || core_klass.to_s == "#<Class:Module>"
|
56
|
+
if (Module.methods(false) + Module.private_methods(false)).include?(@name)
|
57
|
+
@documentations = [[Module, :class, @name]]
|
58
|
+
else
|
59
|
+
@documentations = [[Module, :instance, @name]]
|
60
|
+
end
|
61
|
+
elsif core_klass == Class
|
62
|
+
if (Class.methods(false) + Class.private_methods(false)).include?(@name)
|
63
|
+
@documentations = [[Class, :class, @name]]
|
64
|
+
else
|
65
|
+
@documentations = [[Class, :instance, @name]]
|
66
|
+
end
|
67
|
+
else
|
68
|
+
if @level == :class
|
69
|
+
if core_klass == @klass
|
70
|
+
@documentations = [[core_klass, :class, @name]]
|
71
|
+
elsif core_klass.to_s =~ /^#<Class:(.+)>$/
|
72
|
+
# get class from singleton class
|
73
|
+
@documentations = [[Reflexive.constantize($1), :class, @name]]
|
74
|
+
end
|
75
|
+
else
|
76
|
+
@documentations = [[core_klass, @level, @name]]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def heuristic_lookup
|
83
|
+
if @klass.instance_of?(Module) && @level == :instance
|
84
|
+
# only instance methods are inherited from modules
|
85
|
+
potential_receivers = included_by_classes.select do |included_by_class|
|
86
|
+
all_instance_methods(included_by_class).include?(@name)
|
87
|
+
end
|
88
|
+
|
89
|
+
potential_receivers += included_by_modules.select do |included_by_module|
|
90
|
+
all_instance_methods(included_by_module).include?(@name)
|
91
|
+
end
|
92
|
+
|
93
|
+
potential_receivers.uniq.each do |receiver|
|
94
|
+
# TODO heuristic lookup shouldn't assume that found method is not core method
|
95
|
+
(@definitions ||= []) << [receiver, :instance, @name]
|
96
|
+
end
|
97
|
+
|
98
|
+
potential_class_receivers = included_by_singleton_classes.select do |included_by_singleton_class|
|
99
|
+
all_class_methods(included_by_singleton_class).include?(@name)
|
100
|
+
end
|
101
|
+
|
102
|
+
potential_class_receivers.uniq.each do |class_receiver|
|
103
|
+
(@definitions ||= []) << [class_receiver, :class, @name]
|
104
|
+
end
|
105
|
+
elsif @klass.instance_of?(Class)
|
106
|
+
# both instance and class methods are inherited by classes
|
107
|
+
|
108
|
+
potential_receivers = inherited_by_classes.select do |inherited_by_class|
|
109
|
+
all_level_methods(inherited_by_class).include?(@name)
|
110
|
+
end
|
111
|
+
|
112
|
+
potential_receivers.uniq.each do |receiver|
|
113
|
+
|
114
|
+
(@definitions ||= []) << [receiver, @level, @name]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def last_resort_lookup
|
120
|
+
@last_resort_lookup_used = true
|
121
|
+
seen = []
|
122
|
+
[Module, Class].each do |module_or_class|
|
123
|
+
ObjectSpace.each_object(module_or_class) do |m|
|
124
|
+
next if seen.include?(m)
|
125
|
+
if all_instance_methods(m).include?(@name)
|
126
|
+
(@definitions ||= []) << [m, :instance, @name]
|
127
|
+
end
|
128
|
+
if all_class_methods(m).include?(@name)
|
129
|
+
(@definitions ||= []) << [m, :class, @name]
|
130
|
+
end
|
131
|
+
seen << m
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def all_instance_methods(klass)
|
137
|
+
klass.instance_methods(false) + klass.private_instance_methods(false)
|
138
|
+
end
|
139
|
+
|
140
|
+
def all_class_methods(klass)
|
141
|
+
klass.methods(false) + klass.private_methods(false)
|
142
|
+
end
|
143
|
+
|
144
|
+
def all_level_methods(klass)
|
145
|
+
@level == :instance ? all_instance_methods(klass) : all_class_methods(klass)
|
146
|
+
end
|
147
|
+
|
148
|
+
def included_by_classes
|
149
|
+
included_by = []
|
150
|
+
ObjectSpace.each_object(Class) do |c|
|
151
|
+
next if c == @klass
|
152
|
+
|
153
|
+
ancestors = c.ancestors
|
154
|
+
included_by << c if ancestors.include?(@klass)
|
155
|
+
end
|
156
|
+
included_by
|
157
|
+
end
|
158
|
+
|
159
|
+
alias inherited_by_classes included_by_classes
|
160
|
+
|
161
|
+
def included_by_modules
|
162
|
+
included_by = []
|
163
|
+
ObjectSpace.each_object(Module) do |m|
|
164
|
+
next if m == @klass
|
165
|
+
|
166
|
+
ancestors = m.ancestors
|
167
|
+
included_by << m if ancestors.include?(@klass)
|
168
|
+
end
|
169
|
+
included_by
|
170
|
+
end
|
171
|
+
|
172
|
+
def included_by_singleton_classes
|
173
|
+
included_by = []
|
174
|
+
ObjectSpace.each_object(Class) do |c|
|
175
|
+
next if c == @klass
|
176
|
+
|
177
|
+
ancestors = c.singleton_class.ancestors
|
178
|
+
included_by << c if ancestors.include?(@klass)
|
179
|
+
end
|
180
|
+
included_by
|
181
|
+
end
|
182
|
+
|
183
|
+
def method_getter
|
184
|
+
@level == :instance ? :instance_method : :method
|
185
|
+
end
|
186
|
+
|
187
|
+
def methods_getter
|
188
|
+
@level == :instance ? :instance_methods : :methods
|
189
|
+
end
|
190
|
+
|
191
|
+
def reverse_methods_getter
|
192
|
+
@level == :instance ? :methods : :instance_methods
|
193
|
+
end
|
194
|
+
|
195
|
+
def reverse_level
|
196
|
+
@level == :instance ? :class : :instance
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|