object_shadow 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.travis.yml +18 -0
- data/CHANGELOG.md +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/MIT-LICENSE.txt +20 -0
- data/README.md +195 -0
- data/Rakefile +38 -0
- data/lib/object_shadow.rb +17 -0
- data/lib/object_shadow/basic_object.rb +23 -0
- data/lib/object_shadow/info_inspect.rb +69 -0
- data/lib/object_shadow/instance_variables.rb +37 -0
- data/lib/object_shadow/method_introspection.rb +258 -0
- data/lib/object_shadow/object_method.rb +11 -0
- data/lib/object_shadow/version.rb +7 -0
- data/lib/object_shadow/wrap.rb +19 -0
- data/object_shadow.gemspec +21 -0
- data/spec/object_shadow_instance_variables_spec.rb +71 -0
- data/spec/object_shadow_method_introspection_spec.rb +914 -0
- metadata +65 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ObjectShadow
|
4
|
+
module InstanceVariables
|
5
|
+
# Returns the instance variable given
|
6
|
+
# Please note: Does not expect @ prefix
|
7
|
+
def [](ivar_name)
|
8
|
+
object.instance_variable_get(:"@#{ivar_name}")
|
9
|
+
end
|
10
|
+
|
11
|
+
# Sets the instance variable given
|
12
|
+
# Please note: Does not expect @ prefix
|
13
|
+
def []=(ivar_name, value)
|
14
|
+
object.instance_variable_set(:"@#{ivar_name}", value)
|
15
|
+
end
|
16
|
+
|
17
|
+
def remove(ivar_name)
|
18
|
+
object.remove_instance_variable(:"@#{ivar_name}")
|
19
|
+
end
|
20
|
+
|
21
|
+
def variable?(ivar_name)
|
22
|
+
object.instance_variable_defined?(:"@#{ivar_name}")
|
23
|
+
end
|
24
|
+
|
25
|
+
def variables
|
26
|
+
object.instance_variables.map{ |ivar| ivar[1..-1].to_sym }
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_h
|
30
|
+
variables.map{ |ivar| [ivar, self[ivar]] }.to_h
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_a
|
34
|
+
variables.map{ |ivar| self[ivar] }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,258 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ObjectShadow
|
4
|
+
module MethodIntrospection
|
5
|
+
# #shadow#methods returns a sorted list of methods related to the object
|
6
|
+
# in question. It lets you specify the kind of methods you want to retrieve
|
7
|
+
# by the following keyword parameters:
|
8
|
+
#
|
9
|
+
# target: (default :self)
|
10
|
+
#
|
11
|
+
# - :self - This returns the list of methods available to call
|
12
|
+
# on the current object, including singleton methods
|
13
|
+
# If the object is a class/module, this means that it
|
14
|
+
# will return class methods
|
15
|
+
#
|
16
|
+
# - :class - This will refer to the object's class (via the `class`) method
|
17
|
+
# and return its methods, usually to be called from an instance
|
18
|
+
# If called for a class or module, it will return `Class`' methods
|
19
|
+
#
|
20
|
+
# - :instances - This will list all methods which instances of the class (or the class
|
21
|
+
# that includes the module, in case of a module) in question will have
|
22
|
+
# Raises an ArgumentError when called on with a non-`Module`
|
23
|
+
#
|
24
|
+
#
|
25
|
+
# scope: (default :public)
|
26
|
+
#
|
27
|
+
# - :public - Restrict to to methods of public visibility
|
28
|
+
#
|
29
|
+
# - :protected - Restrict to to methods of protected visibility
|
30
|
+
#
|
31
|
+
# - :private - Restrict to to methods of private visibility
|
32
|
+
#
|
33
|
+
# - :all - Restrict to to methods of public visibility
|
34
|
+
#
|
35
|
+
#
|
36
|
+
# inherit: (default :exclude_object)
|
37
|
+
#
|
38
|
+
# - :singleton - Show only methods directly defined in the object's singleton class
|
39
|
+
#
|
40
|
+
# - :self - Show singleton methods and methods directly defined in the object's class,
|
41
|
+
# but do not traverse the inheritance chain
|
42
|
+
#
|
43
|
+
# - :exclude_class - Stop inheritance chain just before Class or Module. For
|
44
|
+
# non-modules it fallbacks to :exclude_object
|
45
|
+
#
|
46
|
+
# - :exclude_object - Stop inheritance chain just before Object
|
47
|
+
#
|
48
|
+
# - :all - Show methods from the whole inheritance chain
|
49
|
+
#
|
50
|
+
def methods(target: :self, scope: :public, inherit: :exclude_class)
|
51
|
+
MethodIntrospection.lookup_chain_for(object, target, inherit, true).flat_map { |lookup_class|
|
52
|
+
full_inheritance_lookup = inherit == :all || inherit == true
|
53
|
+
|
54
|
+
case scope
|
55
|
+
when :public
|
56
|
+
lookup_class.public_instance_methods(full_inheritance_lookup)
|
57
|
+
when :protected
|
58
|
+
lookup_class.protected_instance_methods(full_inheritance_lookup)
|
59
|
+
when :private
|
60
|
+
lookup_class.private_instance_methods(full_inheritance_lookup)
|
61
|
+
when :all
|
62
|
+
lookup_class.instance_methods(full_inheritance_lookup) +
|
63
|
+
lookup_class.private_instance_methods(full_inheritance_lookup)
|
64
|
+
else
|
65
|
+
Kernel.raise ArgumentError, \
|
66
|
+
"(ObjectShadow) Method scope: must be one of [:public, :protected, :private, :all]"
|
67
|
+
end
|
68
|
+
}.uniq.sort
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns true if a method of this name is defined
|
72
|
+
# First parameter is the name of the method in question
|
73
|
+
#
|
74
|
+
# - target: must be one of [:self, :class, :instances]
|
75
|
+
#
|
76
|
+
def method?(method_name, target: :self)
|
77
|
+
MethodIntrospection.simple_lookup_chain_for(object, target).any?{ |lookup_class|
|
78
|
+
if RUBY_VERSION >= "2.6.0"
|
79
|
+
lookup_class.method_defined?(method_name, true) ||
|
80
|
+
lookup_class.private_method_defined?(method_name, true)
|
81
|
+
else
|
82
|
+
lookup_class.method_defined?(method_name) ||
|
83
|
+
lookup_class.private_method_defined?(method_name)
|
84
|
+
end
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns the scope of method name given
|
89
|
+
#
|
90
|
+
# - target: must be one of [:self, :class, :instances]
|
91
|
+
#
|
92
|
+
# Possible return values: [:public, :protected, :private, nil]
|
93
|
+
#
|
94
|
+
def method_scope(method_name, target: :self)
|
95
|
+
MethodIntrospection.simple_lookup_chain_for(object, target).map{ |lookup_class|
|
96
|
+
if RUBY_VERSION >= "2.6.0"
|
97
|
+
case
|
98
|
+
when lookup_class.public_method_defined?(method_name, true)
|
99
|
+
:public
|
100
|
+
when lookup_class.protected_method_defined?(method_name, true)
|
101
|
+
:protected
|
102
|
+
when lookup_class.private_method_defined?(method_name, true)
|
103
|
+
:private
|
104
|
+
else
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
else
|
108
|
+
case
|
109
|
+
when lookup_class.public_method_defined?(method_name)
|
110
|
+
:public
|
111
|
+
when lookup_class.protected_method_defined?(method_name)
|
112
|
+
:protected
|
113
|
+
when lookup_class.private_method_defined?(method_name)
|
114
|
+
:private
|
115
|
+
else
|
116
|
+
nil
|
117
|
+
end
|
118
|
+
end
|
119
|
+
}.compact.first
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns the objectified reference to a method
|
123
|
+
#
|
124
|
+
# - target: must be one of [:self, :class, :instances]
|
125
|
+
#
|
126
|
+
# Pass unbind: true if you always want UnboundMethod objects
|
127
|
+
#
|
128
|
+
# Pass all: true to not only get the method that would be called,
|
129
|
+
# but an Array with every occurrence of this method along the inheritance chain
|
130
|
+
def method(method_name, target: :self, unbind: false, all: false)
|
131
|
+
if all
|
132
|
+
MethodIntrospection.lookup_chain_for(object, target, :all).map{ |lookup_class|
|
133
|
+
if lookup_class.instance_methods(false).include?(method_name) ||
|
134
|
+
lookup_class.private_instance_methods(false).include?(method_name)
|
135
|
+
lookup_class.instance_method(method_name)
|
136
|
+
end
|
137
|
+
}.compact
|
138
|
+
else
|
139
|
+
MethodIntrospection.get_method(object, target, method_name, unbind)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Returns the lookup/ancestor chain for an object
|
144
|
+
#
|
145
|
+
# - target: must be one of [:self, :class, :instances]
|
146
|
+
#
|
147
|
+
# Takes the same inherit options like #methods
|
148
|
+
def method_lookup_chain(target: :self, inherit: :exclude_class)
|
149
|
+
MethodIntrospection.lookup_chain_for(object, target, inherit)
|
150
|
+
end
|
151
|
+
|
152
|
+
class << self
|
153
|
+
def lookup_chain_for(object, target, inherit, optimize = false)
|
154
|
+
validate_arguments! object, target, inherit
|
155
|
+
singleton, klass, chain = get_singleton_klass_and_chain(object, target)
|
156
|
+
|
157
|
+
case inherit
|
158
|
+
when :singleton
|
159
|
+
singleton
|
160
|
+
when :self, false
|
161
|
+
singleton + klass
|
162
|
+
when :exclude_class
|
163
|
+
singleton + chain[0...(chain.index(Class) || chain.index(Module) || chain.index(Object))]
|
164
|
+
when :exclude_object
|
165
|
+
singleton + chain[0...chain.index(Object)]
|
166
|
+
when Module
|
167
|
+
singleton + chain[0..chain.index(inherit)]
|
168
|
+
when :all, true
|
169
|
+
if optimize # full chain build by Ruby using (all=true) param in list
|
170
|
+
singleton + klass
|
171
|
+
else
|
172
|
+
singleton + chain
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def simple_lookup_chain_for(object, target)
|
178
|
+
validate_arguments! object, target
|
179
|
+
singleton, klass, = get_singleton_klass_and_chain(object, target)
|
180
|
+
|
181
|
+
singleton + klass
|
182
|
+
end
|
183
|
+
|
184
|
+
def get_method(object, target, method_name, unbind)
|
185
|
+
case target
|
186
|
+
when :self
|
187
|
+
if unbind
|
188
|
+
object.method(method_name).unbind()
|
189
|
+
else
|
190
|
+
object.method(method_name)
|
191
|
+
end
|
192
|
+
when :class
|
193
|
+
if unbind
|
194
|
+
object.class.method(method_name).unbind()
|
195
|
+
else
|
196
|
+
object.class.method(method_name)
|
197
|
+
end
|
198
|
+
when :instances
|
199
|
+
object.instance_method(method_name)
|
200
|
+
else
|
201
|
+
Kernel.raise ArgumentError, "(ObjectShadow) target: must be one of [:self, :class, :instances]"
|
202
|
+
end
|
203
|
+
rescue NameError
|
204
|
+
nil
|
205
|
+
end
|
206
|
+
|
207
|
+
private
|
208
|
+
|
209
|
+
# Explanation:
|
210
|
+
# - singleton: [singleton_class] or [] if not retrievable
|
211
|
+
# - klass: [first entry of inheritance chain] or [] for modules
|
212
|
+
# - chain: inheritance chain without singleton
|
213
|
+
def get_singleton_klass_and_chain(object, target)
|
214
|
+
target_object = target == :class ? object.class : object
|
215
|
+
|
216
|
+
begin
|
217
|
+
if target == :instances
|
218
|
+
singleton = []
|
219
|
+
klass = target_object.ancestors[0, 1]
|
220
|
+
chain = target_object.ancestors
|
221
|
+
else
|
222
|
+
singleton = [target_object.singleton_class]
|
223
|
+
|
224
|
+
if target_object.is_a? Module
|
225
|
+
klass = []
|
226
|
+
chain = target_object.singleton_class.ancestors[1..-1]
|
227
|
+
else
|
228
|
+
klass = target_object.singleton_class.ancestors[1, 1]
|
229
|
+
chain = target_object.singleton_class.ancestors[1..-1]
|
230
|
+
end
|
231
|
+
end
|
232
|
+
rescue TypeError # e.g. Integer
|
233
|
+
singleton = []
|
234
|
+
klass = target_object.class.ancestors[0, 1]
|
235
|
+
chain = target_object.class.ancestors
|
236
|
+
end
|
237
|
+
|
238
|
+
[singleton, klass, chain]
|
239
|
+
end
|
240
|
+
|
241
|
+
def validate_arguments!(object, target, inherit = nil)
|
242
|
+
unless [:self, :class, :instances].include?(target)
|
243
|
+
Kernel.raise ArgumentError, "(ObjectShadow) target: must be one of [:self, :class, :instances]"
|
244
|
+
end
|
245
|
+
|
246
|
+
if target == :instances
|
247
|
+
if !object.is_a?(Module)
|
248
|
+
Kernel.raise ArgumentError, "(ObjectShadow) target: can only be set to :instances for classes and modules"
|
249
|
+
end
|
250
|
+
|
251
|
+
if inherit == :singleton
|
252
|
+
Kernel.raise ArgumentError, "(ObjectShadow) cannot request :singleton inheritance when target is :instances"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ObjectShadow
|
4
|
+
module Wrap
|
5
|
+
attr_reader :object
|
6
|
+
|
7
|
+
def initialize(object)
|
8
|
+
@object = object
|
9
|
+
end
|
10
|
+
|
11
|
+
# Since shadows are not supposed to be passed around, to_s is left neutral
|
12
|
+
def to_s
|
13
|
+
"#<ObjectShadow of #{object.inspect}>"
|
14
|
+
end
|
15
|
+
|
16
|
+
# The base inspect is boring, too, but it will be improved by InfoInspect
|
17
|
+
alias inspect to_s
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + "/lib/object_shadow/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.name = "object_shadow"
|
7
|
+
gem.version = ObjectShadow::VERSION
|
8
|
+
gem.summary = "Metaprogramming Level 2"
|
9
|
+
gem.description = "provides a simple convenient API for accessing an object's state."
|
10
|
+
gem.authors = ["Jan Lelis"]
|
11
|
+
gem.email = ["mail@janlelis.de"]
|
12
|
+
gem.homepage = "https://github.com/janlelis/object_shadow"
|
13
|
+
gem.license = "MIT"
|
14
|
+
|
15
|
+
gem.files = Dir["{**/}{.*,*}"].select{ |path| File.file?(path) && path !~ /^pkg/ && path !~ /png\z/ }
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.required_ruby_version = "~> 2.0"
|
21
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require_relative "../lib/object_shadow"
|
2
|
+
require "minitest/autorun"
|
3
|
+
|
4
|
+
describe "Object#shadow" do
|
5
|
+
let :c do
|
6
|
+
Class.new do
|
7
|
+
def initialize
|
8
|
+
@ivar = 42
|
9
|
+
@another_variable = 43
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
let :o do
|
15
|
+
c.new
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#variables" do
|
19
|
+
it "shows list of instance variable names" do
|
20
|
+
assert_equal \
|
21
|
+
[:ivar, :another_variable],
|
22
|
+
o.shadow.variables
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#variable?" do
|
27
|
+
it "returns true if variable is defined" do
|
28
|
+
assert \
|
29
|
+
o.shadow.variable?(:ivar)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "returns false if variable is not defined" do
|
33
|
+
refute \
|
34
|
+
o.shadow.variable?(:ovar)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#[]" do
|
39
|
+
it "returns value of given instance variable name" do
|
40
|
+
assert_equal \
|
41
|
+
42,
|
42
|
+
o.shadow[:ivar]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#[]=" do
|
47
|
+
it "sets value of given instance variable name" do
|
48
|
+
o.shadow[:ivar] = 1
|
49
|
+
assert_equal \
|
50
|
+
1,
|
51
|
+
o.instance_variable_get(:@ivar)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "to_h" do
|
56
|
+
it "returns hash of all instance variables" do
|
57
|
+
assert_equal(
|
58
|
+
{ ivar: 42, another_variable: 43 },
|
59
|
+
o.shadow.to_h
|
60
|
+
)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "to_a" do
|
65
|
+
it "returns array of all instance variable values" do
|
66
|
+
assert_equal \
|
67
|
+
[42, 43],
|
68
|
+
o.shadow.to_a
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,914 @@
|
|
1
|
+
require_relative "../lib/object_shadow"
|
2
|
+
require "minitest/autorun"
|
3
|
+
|
4
|
+
describe "Object#shadow" do
|
5
|
+
let :astronomical_body do
|
6
|
+
Class.new do
|
7
|
+
def fly
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
def crash
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def explode
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def make
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def stir
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def idea
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
let :planet do
|
39
|
+
Class.new(astronomical_body) do
|
40
|
+
def rotate
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def bump
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def implode
|
51
|
+
end
|
52
|
+
|
53
|
+
class << self
|
54
|
+
def construct
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
def prepare
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def think
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
let :earth do
|
71
|
+
earth = planet.new
|
72
|
+
|
73
|
+
class << earth
|
74
|
+
def develop
|
75
|
+
end
|
76
|
+
|
77
|
+
protected
|
78
|
+
|
79
|
+
def magnetize
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def repair
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
earth
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
describe "#methods" do
|
93
|
+
describe "[target: :self]" do
|
94
|
+
describe "[scope: :public]" do
|
95
|
+
describe "[inherit: :singleton]" do
|
96
|
+
it "✓" do
|
97
|
+
assert_equal \
|
98
|
+
[:develop],
|
99
|
+
earth.shadow.methods(target: :self, scope: :public, inherit: :singleton)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "[inherit: :self, inherit: false]" do
|
104
|
+
it "✓" do
|
105
|
+
assert_equal \
|
106
|
+
[:develop, :rotate],
|
107
|
+
earth.shadow.methods(target: :self, scope: :public, inherit: :self)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "[inherit: :exclude_object]" do
|
112
|
+
it "✓" do
|
113
|
+
assert_equal \
|
114
|
+
[:develop, :fly, :rotate],
|
115
|
+
earth.shadow.methods(target: :self, scope: :public, inherit: :exclude_object)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "[inherit: Module]" do
|
120
|
+
it "✓" do
|
121
|
+
assert_equal \
|
122
|
+
[:develop, :fly, :rotate],
|
123
|
+
earth.shadow.methods(target: :self, scope: :public, inherit: astronomical_body)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "[inherit: :all, inherit: true]" do
|
128
|
+
it "✓" do
|
129
|
+
assert_equal \
|
130
|
+
(
|
131
|
+
[:develop, :fly, :rotate] +
|
132
|
+
Object.public_instance_methods
|
133
|
+
).sort,
|
134
|
+
earth.shadow.methods(target: :self, scope: :public, inherit: :all)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "[scope: :protected]" do
|
140
|
+
describe "[inherit: :singleton]" do
|
141
|
+
it "✓" do
|
142
|
+
assert_equal \
|
143
|
+
[:magnetize],
|
144
|
+
earth.shadow.methods(target: :self, scope: :protected, inherit: :singleton)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "[inherit: :self, inherit: false]" do
|
149
|
+
it "✓" do
|
150
|
+
assert_equal \
|
151
|
+
[:bump, :magnetize],
|
152
|
+
earth.shadow.methods(target: :self, scope: :protected, inherit: :self)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "[inherit: :exclude_class]" do
|
157
|
+
it "✓" do
|
158
|
+
assert_equal \
|
159
|
+
[:bump, :crash, :magnetize],
|
160
|
+
earth.shadow.methods(target: :self, scope: :protected, inherit: :exclude_class)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "[inherit: :exclude_object]" do
|
165
|
+
it "✓" do
|
166
|
+
assert_equal \
|
167
|
+
[:bump, :crash, :magnetize],
|
168
|
+
earth.shadow.methods(target: :self, scope: :protected, inherit: :exclude_object)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "[inherit: Module]" do
|
173
|
+
it "✓" do
|
174
|
+
assert_equal \
|
175
|
+
[:bump, :crash, :magnetize],
|
176
|
+
earth.shadow.methods(target: :self, scope: :protected, inherit: astronomical_body)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe "[inherit: :all, inherit: true]" do
|
181
|
+
it "✓" do
|
182
|
+
assert_equal \
|
183
|
+
(
|
184
|
+
[:bump, :crash, :magnetize] +
|
185
|
+
Object.protected_instance_methods
|
186
|
+
).sort,
|
187
|
+
earth.shadow.methods(target: :self, scope: :protected, inherit: :all)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe "[scope: :private]" do
|
193
|
+
describe "[inherit: :singleton]" do
|
194
|
+
it "✓" do
|
195
|
+
assert_equal \
|
196
|
+
[:repair],
|
197
|
+
earth.shadow.methods(target: :self, scope: :private, inherit: :singleton)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe "[inherit: :self, inherit: false]" do
|
202
|
+
it "✓" do
|
203
|
+
assert_equal \
|
204
|
+
[:implode, :repair],
|
205
|
+
earth.shadow.methods(target: :self, scope: :private, inherit: :self)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
describe "[inherit: :exclude_class]" do
|
210
|
+
it "✓" do
|
211
|
+
assert_equal \
|
212
|
+
[:explode, :implode, :repair],
|
213
|
+
earth.shadow.methods(target: :self, scope: :private, inherit: :exclude_class)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe "[inherit: :exclude_object]" do
|
218
|
+
it "✓" do
|
219
|
+
assert_equal \
|
220
|
+
[:explode, :implode, :repair],
|
221
|
+
earth.shadow.methods(target: :self, scope: :private, inherit: :exclude_object)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
describe "[inherit: Module]" do
|
226
|
+
it "✓" do
|
227
|
+
assert_equal \
|
228
|
+
[:explode, :implode, :repair],
|
229
|
+
earth.shadow.methods(target: :self, scope: :private, inherit: astronomical_body)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
describe "[inherit: :all, inherit: true]" do
|
234
|
+
it "✓" do
|
235
|
+
assert_equal \
|
236
|
+
(
|
237
|
+
[:explode, :implode, :repair] +
|
238
|
+
Object.private_instance_methods
|
239
|
+
).sort,
|
240
|
+
earth.shadow.methods(target: :self, scope: :private, inherit: :all)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe "[scope: :all]" do
|
246
|
+
describe "[inherit: :singleton]" do
|
247
|
+
it "✓" do
|
248
|
+
assert_equal \
|
249
|
+
[:develop, :magnetize, :repair],
|
250
|
+
earth.shadow.methods(target: :self, scope: :all, inherit: :singleton)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
describe "[inherit: :self, inherit: false]" do
|
255
|
+
it "✓" do
|
256
|
+
assert_equal \
|
257
|
+
[:bump, :develop, :implode, :magnetize, :repair, :rotate],
|
258
|
+
earth.shadow.methods(target: :self, scope: :all, inherit: :self)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
describe "[inherit: :exclude_class]" do
|
263
|
+
it "✓" do
|
264
|
+
assert_equal \
|
265
|
+
[:bump, :crash, :develop, :explode, :fly, :implode, :magnetize, :repair, :rotate],
|
266
|
+
earth.shadow.methods(target: :self, scope: :all, inherit: :exclude_object)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
describe "[inherit: :exclude_object]" do
|
271
|
+
it "✓" do
|
272
|
+
assert_equal \
|
273
|
+
[:bump, :crash, :develop, :explode, :fly, :implode, :magnetize, :repair, :rotate],
|
274
|
+
earth.shadow.methods(target: :self, scope: :all, inherit: :exclude_object)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
describe "[inherit: Module]" do
|
279
|
+
it "✓" do
|
280
|
+
assert_equal \
|
281
|
+
[:bump, :crash, :develop, :explode, :fly, :implode, :magnetize, :repair, :rotate],
|
282
|
+
earth.shadow.methods(target: :self, scope: :all, inherit: astronomical_body)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
describe "[inherit: :all, inherit: true]" do
|
287
|
+
it "✓" do
|
288
|
+
assert_equal \
|
289
|
+
(
|
290
|
+
[:bump, :crash, :develop, :explode, :fly, :implode, :magnetize, :repair, :rotate] +
|
291
|
+
Object.instance_methods +
|
292
|
+
Object.private_instance_methods
|
293
|
+
).sort,
|
294
|
+
earth.shadow.methods(target: :self, scope: :all, inherit: :all)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
|
301
|
+
describe "[target: :class]" do
|
302
|
+
describe "[scope: :public]" do
|
303
|
+
describe "[inherit: :singleton]" do
|
304
|
+
it "✓" do
|
305
|
+
assert_equal \
|
306
|
+
[:construct],
|
307
|
+
earth.shadow.methods(target: :class, scope: :public, inherit: :singleton)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
describe "[inherit: :self, inherit: false]" do
|
312
|
+
it "✓" do
|
313
|
+
assert_equal \
|
314
|
+
[:construct],
|
315
|
+
earth.shadow.methods(target: :class, scope: :public, inherit: :self)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
describe "[inherit: :exclude_class]" do
|
320
|
+
it "✓" do
|
321
|
+
assert_equal \
|
322
|
+
(
|
323
|
+
[:construct, :make] +
|
324
|
+
Object.singleton_class.public_instance_methods(false) +
|
325
|
+
BasicObject.singleton_class.public_instance_methods(false)
|
326
|
+
).sort,
|
327
|
+
earth.shadow.methods(target: :class, scope: :public, inherit: :exclude_class)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
describe "[inherit: :exclude_object]" do
|
332
|
+
it "✓" do
|
333
|
+
assert_equal \
|
334
|
+
(
|
335
|
+
[:construct, :make] +
|
336
|
+
Object.singleton_class.public_instance_methods(false) +
|
337
|
+
BasicObject.singleton_class.public_instance_methods(false) +
|
338
|
+
Class.public_instance_methods(false) +
|
339
|
+
Module.public_instance_methods(false)
|
340
|
+
).sort,
|
341
|
+
earth.shadow.methods(target: :class, scope: :public, inherit: :exclude_object)
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
describe "[inherit: Module]" do
|
346
|
+
it "✓" do
|
347
|
+
assert_equal \
|
348
|
+
(
|
349
|
+
[:construct, :make] +
|
350
|
+
Object.singleton_class.public_instance_methods(false)
|
351
|
+
).sort,
|
352
|
+
earth.shadow.methods(target: :class, scope: :public, inherit: Object.singleton_class)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
describe "[inherit: :all, inherit: true]" do
|
357
|
+
it "✓" do
|
358
|
+
assert_equal \
|
359
|
+
(
|
360
|
+
[:construct, :make] +
|
361
|
+
Object.singleton_class.public_instance_methods(true)
|
362
|
+
).sort,
|
363
|
+
earth.shadow.methods(target: :class, scope: :public, inherit: :all)
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
describe "[scope: :protected]" do
|
369
|
+
describe "[inherit: :singleton]" do
|
370
|
+
it "✓" do
|
371
|
+
assert_equal \
|
372
|
+
[:prepare],
|
373
|
+
earth.shadow.methods(target: :class, scope: :protected, inherit: :singleton)
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
describe "[inherit: :self, inherit: false]" do
|
378
|
+
it "✓" do
|
379
|
+
assert_equal \
|
380
|
+
[:prepare],
|
381
|
+
earth.shadow.methods(target: :class, scope: :protected, inherit: :self)
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
describe "[inherit: :exclude_class]" do
|
386
|
+
it "✓" do
|
387
|
+
assert_equal \
|
388
|
+
(
|
389
|
+
[:prepare, :stir] +
|
390
|
+
Object.singleton_class.protected_instance_methods(false) +
|
391
|
+
BasicObject.singleton_class.protected_instance_methods(false)
|
392
|
+
).sort,
|
393
|
+
earth.shadow.methods(target: :class, scope: :protected, inherit: :exclude_class)
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
describe "[inherit: :exclude_object]" do
|
398
|
+
it "✓" do
|
399
|
+
assert_equal \
|
400
|
+
(
|
401
|
+
[:prepare, :stir] +
|
402
|
+
Object.singleton_class.protected_instance_methods(false) +
|
403
|
+
BasicObject.singleton_class.protected_instance_methods(false) +
|
404
|
+
Class.protected_instance_methods(false) +
|
405
|
+
Module.protected_instance_methods(false)
|
406
|
+
).sort,
|
407
|
+
earth.shadow.methods(target: :class, scope: :protected, inherit: :exclude_object)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
describe "[inherit: Module]" do
|
412
|
+
it "✓" do
|
413
|
+
assert_equal \
|
414
|
+
(
|
415
|
+
[:prepare, :stir] +
|
416
|
+
Object.singleton_class.protected_instance_methods(false)
|
417
|
+
).sort,
|
418
|
+
earth.shadow.methods(target: :class, scope: :protected, inherit: Object.singleton_class)
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
describe "[inherit: :all, inherit: true]" do
|
423
|
+
it "✓" do
|
424
|
+
assert_equal \
|
425
|
+
(
|
426
|
+
[:prepare, :stir] +
|
427
|
+
Object.singleton_class.protected_instance_methods(true)
|
428
|
+
).sort,
|
429
|
+
earth.shadow.methods(target: :class, scope: :protected, inherit: :all)
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
describe "[scope: :private]" do
|
435
|
+
describe "[inherit: :singleton]" do
|
436
|
+
it "✓" do
|
437
|
+
assert_equal \
|
438
|
+
[:think],
|
439
|
+
earth.shadow.methods(target: :class, scope: :private, inherit: :singleton)
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
describe "[inherit: :self, inherit: false]" do
|
444
|
+
it "✓" do
|
445
|
+
assert_equal \
|
446
|
+
[:think],
|
447
|
+
earth.shadow.methods(target: :class, scope: :private, inherit: :self)
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
describe "[inherit: :exclude_class]" do
|
452
|
+
it "✓" do
|
453
|
+
assert_equal \
|
454
|
+
(
|
455
|
+
[:think, :idea] +
|
456
|
+
Object.singleton_class.private_instance_methods(false) +
|
457
|
+
BasicObject.singleton_class.private_instance_methods(false)
|
458
|
+
).sort,
|
459
|
+
earth.shadow.methods(target: :class, scope: :private, inherit: :exclude_class)
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
describe "[inherit: :exclude_object]" do
|
464
|
+
it "✓" do
|
465
|
+
assert_equal \
|
466
|
+
(
|
467
|
+
[:think, :idea] +
|
468
|
+
Object.singleton_class.private_instance_methods(false) +
|
469
|
+
BasicObject.singleton_class.private_instance_methods(false) +
|
470
|
+
Class.private_instance_methods(false) +
|
471
|
+
Module.private_instance_methods(false)
|
472
|
+
).uniq.sort,
|
473
|
+
earth.shadow.methods(target: :class, scope: :private, inherit: :exclude_object)
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
describe "[inherit: Module]" do
|
478
|
+
it "✓" do
|
479
|
+
assert_equal \
|
480
|
+
(
|
481
|
+
[:think, :idea] +
|
482
|
+
Object.singleton_class.private_instance_methods(false)
|
483
|
+
).sort,
|
484
|
+
earth.shadow.methods(target: :class, scope: :private, inherit: Object.singleton_class)
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
describe "[inherit: :all, inherit: true]" do
|
489
|
+
it "✓" do
|
490
|
+
assert_equal \
|
491
|
+
(
|
492
|
+
[:think, :idea] +
|
493
|
+
Object.singleton_class.private_instance_methods(true)
|
494
|
+
).sort,
|
495
|
+
earth.shadow.methods(target: :class, scope: :private, inherit: :all)
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
describe "[scope: :all]" do
|
501
|
+
describe "[inherit: :singleton]" do
|
502
|
+
it "✓" do
|
503
|
+
assert_equal \
|
504
|
+
[:construct, :prepare, :think],
|
505
|
+
earth.shadow.methods(target: :class, scope: :all, inherit: :singleton)
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
describe "[inherit: :self, inherit: false]" do
|
510
|
+
it "✓" do
|
511
|
+
assert_equal \
|
512
|
+
[:construct, :prepare, :think],
|
513
|
+
earth.shadow.methods(target: :class, scope: :all, inherit: :self)
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
describe "[inherit: :exclude_class]" do
|
518
|
+
it "✓" do
|
519
|
+
assert_equal \
|
520
|
+
(
|
521
|
+
[:construct, :idea, :make, :prepare, :stir, :think] +
|
522
|
+
Object.singleton_class.instance_methods(false) +
|
523
|
+
Object.singleton_class.private_instance_methods(false) +
|
524
|
+
BasicObject.singleton_class.instance_methods(false) +
|
525
|
+
BasicObject.singleton_class.private_instance_methods(false)
|
526
|
+
).sort,
|
527
|
+
earth.shadow.methods(target: :class, scope: :all, inherit: :exclude_class)
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
describe "[inherit: :exclude_object]" do
|
532
|
+
it "✓" do
|
533
|
+
assert_equal \
|
534
|
+
(
|
535
|
+
[:construct, :idea, :make, :prepare, :stir, :think] +
|
536
|
+
Object.singleton_class.instance_methods(false) +
|
537
|
+
Object.singleton_class.private_instance_methods(false) +
|
538
|
+
BasicObject.singleton_class.instance_methods(false) +
|
539
|
+
BasicObject.singleton_class.private_instance_methods(false) +
|
540
|
+
Class.instance_methods(false) +
|
541
|
+
Class.private_instance_methods(false) +
|
542
|
+
Module.instance_methods(false) +
|
543
|
+
Module.private_instance_methods(false)
|
544
|
+
).uniq.sort,
|
545
|
+
earth.shadow.methods(target: :class, scope: :all, inherit: :exclude_object)
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
549
|
+
describe "[inherit: Module]" do
|
550
|
+
it "✓" do
|
551
|
+
assert_equal \
|
552
|
+
(
|
553
|
+
[:construct, :idea, :make, :prepare, :stir, :think] +
|
554
|
+
Object.singleton_class.instance_methods(false) +
|
555
|
+
Object.singleton_class.private_instance_methods(false)
|
556
|
+
).sort,
|
557
|
+
earth.shadow.methods(target: :class, scope: :all, inherit: Object.singleton_class)
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
561
|
+
describe "[inherit: :all, inherit: true]" do
|
562
|
+
it "✓" do
|
563
|
+
assert_equal \
|
564
|
+
(
|
565
|
+
[:construct, :idea, :make, :prepare, :stir, :think] +
|
566
|
+
Object.singleton_class.instance_methods(true) +
|
567
|
+
Object.singleton_class.private_instance_methods(true)
|
568
|
+
).sort,
|
569
|
+
earth.shadow.methods(target: :class, scope: :all, inherit: :all)
|
570
|
+
end
|
571
|
+
end
|
572
|
+
end
|
573
|
+
end
|
574
|
+
|
575
|
+
|
576
|
+
describe "[target: :instances]" do
|
577
|
+
describe "context: called for a non-module" do
|
578
|
+
it "✗ will raise an ArgumentError" do
|
579
|
+
assert_raises(ArgumentError) {
|
580
|
+
earth.shadow.methods(target: :instances)
|
581
|
+
}
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
describe "[inherit: :singleton]" do
|
586
|
+
it "✗ will raise an ArgumentError" do
|
587
|
+
assert_raises(ArgumentError) {
|
588
|
+
planet.shadow.methods(target: :instances, inherit: :singleton)
|
589
|
+
}
|
590
|
+
end
|
591
|
+
end
|
592
|
+
|
593
|
+
describe "[scope: :public]" do
|
594
|
+
describe "[inherit: :self, inherit: false]" do
|
595
|
+
it "✓" do
|
596
|
+
assert_equal \
|
597
|
+
[:rotate],
|
598
|
+
planet.shadow.methods(target: :instances, scope: :public, inherit: :self)
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
602
|
+
describe "[inherit: :exclude_object]" do
|
603
|
+
it "✓" do
|
604
|
+
assert_equal \
|
605
|
+
[:fly, :rotate],
|
606
|
+
planet.shadow.methods(target: :instances, scope: :public, inherit: :exclude_object)
|
607
|
+
end
|
608
|
+
end
|
609
|
+
|
610
|
+
describe "[inherit: Module]" do
|
611
|
+
it "✓" do
|
612
|
+
assert_equal \
|
613
|
+
[:fly, :rotate],
|
614
|
+
planet.shadow.methods(target: :instances, scope: :public, inherit: astronomical_body)
|
615
|
+
end
|
616
|
+
end
|
617
|
+
|
618
|
+
describe "[inherit: :all, inherit: true]" do
|
619
|
+
it "✓" do
|
620
|
+
assert_equal \
|
621
|
+
(
|
622
|
+
[:fly, :rotate] +
|
623
|
+
Object.public_instance_methods
|
624
|
+
).sort,
|
625
|
+
planet.shadow.methods(target: :instances, scope: :public, inherit: :all)
|
626
|
+
end
|
627
|
+
end
|
628
|
+
end
|
629
|
+
|
630
|
+
describe "[scope: :protected]" do
|
631
|
+
describe "[inherit: :self, inherit: false]" do
|
632
|
+
it "✓" do
|
633
|
+
assert_equal \
|
634
|
+
[:bump],
|
635
|
+
planet.shadow.methods(target: :instances, scope: :protected, inherit: :self)
|
636
|
+
end
|
637
|
+
end
|
638
|
+
|
639
|
+
describe "[inherit: :exclude_class]" do
|
640
|
+
it "✓" do
|
641
|
+
assert_equal \
|
642
|
+
[:bump, :crash],
|
643
|
+
planet.shadow.methods(target: :instances, scope: :protected, inherit: :exclude_class)
|
644
|
+
end
|
645
|
+
end
|
646
|
+
|
647
|
+
describe "[inherit: :exclude_object]" do
|
648
|
+
it "✓" do
|
649
|
+
assert_equal \
|
650
|
+
[:bump, :crash],
|
651
|
+
planet.shadow.methods(target: :instances, scope: :protected, inherit: :exclude_object)
|
652
|
+
end
|
653
|
+
end
|
654
|
+
|
655
|
+
describe "[inherit: Module]" do
|
656
|
+
it "✓" do
|
657
|
+
assert_equal \
|
658
|
+
[:bump, :crash],
|
659
|
+
planet.shadow.methods(target: :instances, scope: :protected, inherit: astronomical_body)
|
660
|
+
end
|
661
|
+
end
|
662
|
+
|
663
|
+
describe "[inherit: :all, inherit: true]" do
|
664
|
+
it "✓" do
|
665
|
+
assert_equal \
|
666
|
+
(
|
667
|
+
[:bump, :crash] +
|
668
|
+
Object.protected_instance_methods
|
669
|
+
).sort,
|
670
|
+
planet.shadow.methods(target: :instances, scope: :protected, inherit: :all)
|
671
|
+
end
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
describe "[scope: :private]" do
|
676
|
+
describe "[inherit: :self, inherit: false]" do
|
677
|
+
it "✓" do
|
678
|
+
assert_equal \
|
679
|
+
[:implode],
|
680
|
+
planet.shadow.methods(target: :instances, scope: :private, inherit: :self)
|
681
|
+
end
|
682
|
+
end
|
683
|
+
|
684
|
+
describe "[inherit: :exclude_class]" do
|
685
|
+
it "✓" do
|
686
|
+
assert_equal \
|
687
|
+
[:explode, :implode],
|
688
|
+
planet.shadow.methods(target: :instances, scope: :private, inherit: :exclude_class)
|
689
|
+
end
|
690
|
+
end
|
691
|
+
|
692
|
+
describe "[inherit: :exclude_object]" do
|
693
|
+
it "✓" do
|
694
|
+
assert_equal \
|
695
|
+
[:explode, :implode],
|
696
|
+
planet.shadow.methods(target: :instances, scope: :private, inherit: :exclude_object)
|
697
|
+
end
|
698
|
+
end
|
699
|
+
|
700
|
+
describe "[inherit: Module]" do
|
701
|
+
it "✓" do
|
702
|
+
assert_equal \
|
703
|
+
[:explode, :implode],
|
704
|
+
planet.shadow.methods(target: :instances, scope: :private, inherit: astronomical_body)
|
705
|
+
end
|
706
|
+
end
|
707
|
+
|
708
|
+
describe "[inherit: :all, inherit: true]" do
|
709
|
+
it "✓" do
|
710
|
+
assert_equal \
|
711
|
+
(
|
712
|
+
[:explode, :implode] +
|
713
|
+
Object.private_instance_methods
|
714
|
+
).sort,
|
715
|
+
planet.shadow.methods(target: :instances, scope: :private, inherit: :all)
|
716
|
+
end
|
717
|
+
end
|
718
|
+
end
|
719
|
+
|
720
|
+
describe "[scope: :all]" do
|
721
|
+
describe "[inherit: :self, inherit: false]" do
|
722
|
+
it "✓" do
|
723
|
+
assert_equal \
|
724
|
+
[:bump, :implode, :rotate],
|
725
|
+
planet.shadow.methods(target: :instances, scope: :all, inherit: :self)
|
726
|
+
end
|
727
|
+
end
|
728
|
+
|
729
|
+
describe "[inherit: :exclude_class]" do
|
730
|
+
it "✓" do
|
731
|
+
assert_equal \
|
732
|
+
[:bump, :crash, :explode, :fly, :implode, :rotate],
|
733
|
+
planet.shadow.methods(target: :instances, scope: :all, inherit: :exclude_object)
|
734
|
+
end
|
735
|
+
end
|
736
|
+
|
737
|
+
describe "[inherit: :exclude_object]" do
|
738
|
+
it "✓" do
|
739
|
+
assert_equal \
|
740
|
+
[:bump, :crash, :explode, :fly, :implode, :rotate],
|
741
|
+
planet.shadow.methods(target: :instances, scope: :all, inherit: :exclude_object)
|
742
|
+
end
|
743
|
+
end
|
744
|
+
|
745
|
+
describe "[inherit: Module]" do
|
746
|
+
it "✓" do
|
747
|
+
assert_equal \
|
748
|
+
[:bump, :crash, :explode, :fly, :implode, :rotate],
|
749
|
+
planet.shadow.methods(target: :instances, scope: :all, inherit: astronomical_body)
|
750
|
+
end
|
751
|
+
end
|
752
|
+
|
753
|
+
describe "[inherit: :all, inherit: true]" do
|
754
|
+
it "✓" do
|
755
|
+
assert_equal \
|
756
|
+
(
|
757
|
+
[:bump, :crash, :explode, :fly, :implode, :rotate] +
|
758
|
+
Object.instance_methods +
|
759
|
+
Object.private_instance_methods
|
760
|
+
).sort,
|
761
|
+
planet.shadow.methods(target: :instances, scope: :all, inherit: :all)
|
762
|
+
end
|
763
|
+
end
|
764
|
+
end
|
765
|
+
end
|
766
|
+
end
|
767
|
+
|
768
|
+
describe "#method?" do
|
769
|
+
it "will return true if method exists" do
|
770
|
+
assert earth.shadow.method?(:bump)
|
771
|
+
assert earth.shadow.method?(:magnetize)
|
772
|
+
assert earth.shadow.method?(:stir, target: :class)
|
773
|
+
|
774
|
+
assert planet.shadow.method?(:idea)
|
775
|
+
assert planet.shadow.method?(:implode, target: :instances)
|
776
|
+
end
|
777
|
+
|
778
|
+
it "will return false if method does not exist" do
|
779
|
+
refute earth.shadow.method?(:idea)
|
780
|
+
refute earth.shadow.method?(:idiosyncratic)
|
781
|
+
refute earth.shadow.method?(:magnetize, target: :class)
|
782
|
+
|
783
|
+
refute planet.shadow.method?(:rotate)
|
784
|
+
refute planet.shadow.method?(:stir, target: :instances)
|
785
|
+
end
|
786
|
+
end
|
787
|
+
|
788
|
+
describe "#method_scope" do
|
789
|
+
it "will return :public for public methods" do
|
790
|
+
assert_equal :public, earth.shadow.method_scope(:rotate)
|
791
|
+
assert_equal :public, earth.shadow.method_scope(:develop)
|
792
|
+
assert_equal :public, earth.shadow.method_scope(:make, target: :class)
|
793
|
+
|
794
|
+
assert_equal :public, planet.shadow.method_scope(:construct)
|
795
|
+
assert_equal :public, planet.shadow.method_scope(:rotate, target: :instances)
|
796
|
+
end
|
797
|
+
|
798
|
+
it "will return :protected for protected methods" do
|
799
|
+
assert_equal :protected, earth.shadow.method_scope(:bump)
|
800
|
+
assert_equal :protected, earth.shadow.method_scope(:magnetize)
|
801
|
+
assert_equal :protected, earth.shadow.method_scope(:stir, target: :class)
|
802
|
+
|
803
|
+
assert_equal :protected, planet.shadow.method_scope(:prepare)
|
804
|
+
assert_equal :protected, planet.shadow.method_scope(:bump, target: :instances)
|
805
|
+
end
|
806
|
+
|
807
|
+
it "will return :private for private methods" do
|
808
|
+
assert_equal :private, earth.shadow.method_scope(:implode)
|
809
|
+
assert_equal :private, earth.shadow.method_scope(:repair)
|
810
|
+
assert_equal :private, earth.shadow.method_scope(:think, target: :class)
|
811
|
+
|
812
|
+
assert_equal :private, planet.shadow.method_scope(:idea)
|
813
|
+
assert_equal :private, planet.shadow.method_scope(:implode, target: :instances)
|
814
|
+
end
|
815
|
+
|
816
|
+
it "will return nil if method does not exist" do
|
817
|
+
refute earth.shadow.method?(:idea)
|
818
|
+
refute earth.shadow.method?(:magnetize, target: :class)
|
819
|
+
|
820
|
+
refute planet.shadow.method?(:rotate)
|
821
|
+
refute planet.shadow.method?(:stir, target: :instances)
|
822
|
+
end
|
823
|
+
end
|
824
|
+
|
825
|
+
describe "#method" do
|
826
|
+
it "will return Method object" do
|
827
|
+
assert_instance_of Method, earth.shadow.method(:bump)
|
828
|
+
assert_instance_of Method, earth.shadow.method(:magnetize)
|
829
|
+
assert_instance_of Method, earth.shadow.method(:stir, target: :class)
|
830
|
+
|
831
|
+
assert_instance_of Method, planet.shadow.method(:idea)
|
832
|
+
end
|
833
|
+
|
834
|
+
it "will return UnboundMethod object for target: instances "do
|
835
|
+
assert_instance_of UnboundMethod, planet.shadow.method(:implode, target: :instances)
|
836
|
+
end
|
837
|
+
|
838
|
+
it "will return UnboundMethod object when unbind: true is passed" do
|
839
|
+
assert_instance_of UnboundMethod, earth.shadow.method(:bump, unbind: true)
|
840
|
+
end
|
841
|
+
|
842
|
+
it "will return nil if method does not exist" do
|
843
|
+
assert_nil earth.shadow.method(:fun)
|
844
|
+
end
|
845
|
+
|
846
|
+
|
847
|
+
it "returns an array of all (unbound) methods in the lookup chain if all: true is passed" do
|
848
|
+
def earth.bump() end
|
849
|
+
|
850
|
+
res = earth.shadow.method(:bump, all: true)
|
851
|
+
assert_instance_of Array, res
|
852
|
+
assert_instance_of UnboundMethod, res[0]
|
853
|
+
assert_instance_of UnboundMethod, res[1]
|
854
|
+
end
|
855
|
+
end
|
856
|
+
|
857
|
+
describe "#method_lookup_chain" do
|
858
|
+
describe "[inherit: :exclude_class]" do
|
859
|
+
it "shows the lookup chain (including singleton class) for non-classes, stops lookup chain before Class" do
|
860
|
+
assert_equal \
|
861
|
+
[earth.singleton_class, planet, astronomical_body],
|
862
|
+
earth.shadow.method_lookup_chain
|
863
|
+
end
|
864
|
+
|
865
|
+
it "shows the lookup chain for classes, stops lookup chain before Class" do
|
866
|
+
assert_equal \
|
867
|
+
[
|
868
|
+
planet,
|
869
|
+
astronomical_body,
|
870
|
+
Object,
|
871
|
+
BasicObject,
|
872
|
+
].map(&:singleton_class),
|
873
|
+
planet.shadow.method_lookup_chain
|
874
|
+
end
|
875
|
+
end
|
876
|
+
|
877
|
+
describe "[inherit: :all]" do
|
878
|
+
it "shows the lookup chain (including singleton class) for non-classes" do
|
879
|
+
assert_equal \
|
880
|
+
[
|
881
|
+
earth.singleton_class,
|
882
|
+
planet,
|
883
|
+
astronomical_body,
|
884
|
+
Object,
|
885
|
+
Minitest::Expectations,
|
886
|
+
ObjectShadow::ObjectMethod,
|
887
|
+
Kernel,
|
888
|
+
BasicObject,
|
889
|
+
],
|
890
|
+
earth.shadow.method_lookup_chain(inherit: :all)
|
891
|
+
end
|
892
|
+
|
893
|
+
it "shows the lookup chain for classes" do
|
894
|
+
assert_equal \
|
895
|
+
[
|
896
|
+
planet,
|
897
|
+
astronomical_body,
|
898
|
+
Object,
|
899
|
+
BasicObject,
|
900
|
+
].map(&:singleton_class) + [
|
901
|
+
Class,
|
902
|
+
Module,
|
903
|
+
Object,
|
904
|
+
Minitest::Expectations,
|
905
|
+
ObjectShadow::ObjectMethod,
|
906
|
+
Kernel,
|
907
|
+
BasicObject,
|
908
|
+
],
|
909
|
+
planet.shadow.method_lookup_chain(inherit: :all)
|
910
|
+
end
|
911
|
+
end
|
912
|
+
end
|
913
|
+
end
|
914
|
+
|