reflexive 0.0.6 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|