aquarium 0.1.7 → 0.1.8
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/CHANGES +20 -0
- data/README +17 -0
- data/UPGRADE +5 -0
- data/lib/aquarium/aspects/advice.rb +10 -9
- data/lib/aquarium/aspects/aspect.rb +274 -199
- data/lib/aquarium/aspects/default_object_handler.rb +22 -10
- data/lib/aquarium/aspects/exclusion_handler.rb +61 -0
- data/lib/aquarium/aspects/join_point.rb +18 -17
- data/lib/aquarium/aspects/pointcut.rb +44 -49
- data/lib/aquarium/finders/method_finder.rb +1 -1
- data/lib/aquarium/finders/object_finder.rb +1 -0
- data/lib/aquarium/utils/method_utils.rb +49 -8
- data/lib/aquarium/version.rb +1 -1
- data/spec/aquarium/aspects/advice_chain_node_spec.rb +5 -3
- data/spec/aquarium/aspects/aspect_invocation_spec.rb +1334 -31
- data/spec/aquarium/aspects/aspect_spec.rb +164 -426
- data/spec/aquarium/aspects/concurrent_aspects_with_objects_and_types_spec.rb +18 -2
- data/spec/aquarium/aspects/join_point_spec.rb +46 -4
- data/spec/aquarium/aspects/pointcut_spec.rb +80 -39
- data/spec/aquarium/finders/method_finder_spec.rb +25 -2
- data/spec/aquarium/finders/type_finder_spec.rb +1 -1
- data/spec/aquarium/spec_example_classes.rb +17 -0
- data/spec/aquarium/utils/method_utils_spec.rb +270 -46
- metadata +4 -3
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'aquarium/utils/array_utils'
|
2
|
+
|
1
3
|
module Aquarium
|
2
4
|
module Aspects
|
3
5
|
# Some classes and modules support a :default_object flag and use it if no type or
|
@@ -5,21 +7,31 @@ module Aquarium
|
|
5
7
|
# this module have a hash @specification defined with keys :default_object, :types,
|
6
8
|
# and :objects.
|
7
9
|
module DefaultObjectHandler
|
8
|
-
|
9
|
-
|
10
|
+
include Aquarium::Utils::ArrayUtils
|
11
|
+
|
12
|
+
def default_objects_given
|
13
|
+
if @default_objects.nil?
|
14
|
+
ary1 = make_array(@specification[:default_objects])
|
15
|
+
ary2 = make_array(@specification[:default_object])
|
16
|
+
@default_objects = ary1 + ary2
|
17
|
+
end
|
18
|
+
@default_objects
|
10
19
|
end
|
11
20
|
|
12
|
-
def
|
13
|
-
not
|
21
|
+
def default_objects_given?
|
22
|
+
not default_objects_given.empty?
|
14
23
|
end
|
15
24
|
|
16
25
|
def use_default_object_if_defined
|
17
|
-
return unless
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
26
|
+
return unless default_objects_given?
|
27
|
+
default_objects_given.each do |object|
|
28
|
+
if (object.kind_of?(Class) || object.kind_of?(Module))
|
29
|
+
@specification[:types] ||= []
|
30
|
+
@specification[:types] << default_objects_given
|
31
|
+
else
|
32
|
+
@specification[:objects] ||= []
|
33
|
+
@specification[:objects] << default_objects_given
|
34
|
+
end
|
23
35
|
end
|
24
36
|
end
|
25
37
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
|
2
|
+
module Aquarium
|
3
|
+
module Aspects
|
4
|
+
|
5
|
+
# Defines methods shared by several classes that take :exclude_* arguments.
|
6
|
+
module ExclusionHandler
|
7
|
+
|
8
|
+
def join_point_excluded? jp
|
9
|
+
is_excluded_pointcut?(jp) or is_excluded_join_point?(jp) or is_excluded_type_or_object?(jp.type_or_object) or is_excluded_method?(jp.method_name)
|
10
|
+
end
|
11
|
+
|
12
|
+
def is_excluded_pointcut? jp
|
13
|
+
return false if @specification[:exclude_pointcuts].nil?
|
14
|
+
@specification[:exclude_pointcuts].find do |pc|
|
15
|
+
pc.join_points_matched.find do |jp2|
|
16
|
+
jp2 == jp || jp2.eql?(jp)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Using @specification[:exclude_join_points].include?(jp) doesn't always work correctly (it probably uses equal())!
|
22
|
+
def is_excluded_join_point? jp
|
23
|
+
return false if @specification[:exclude_join_points].nil?
|
24
|
+
@specification[:exclude_join_points].find {|jp2| jp2 == jp || jp2.eql?(jp)}
|
25
|
+
end
|
26
|
+
|
27
|
+
def is_excluded_type_or_object? type_or_object
|
28
|
+
unless @specification[:exclude_objects].nil?
|
29
|
+
return true if @specification[:exclude_objects].include?(type_or_object)
|
30
|
+
end
|
31
|
+
unless @specification[:exclude_types].nil?
|
32
|
+
return true if @specification[:exclude_types].find do |t|
|
33
|
+
case t
|
34
|
+
when String: type_or_object.name.eql?(t)
|
35
|
+
when Symbol: type_or_object.name.eql?(t.to_s)
|
36
|
+
when Regexp: type_or_object.name =~ t
|
37
|
+
else type_or_object == t
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
def is_excluded_method? method
|
45
|
+
is_explicitly_excluded_method?(method) or matches_excluded_method_regex?(method)
|
46
|
+
end
|
47
|
+
|
48
|
+
def is_explicitly_excluded_method? method
|
49
|
+
return false if @specification[:exclude_methods].nil?
|
50
|
+
@specification[:exclude_methods].include? method
|
51
|
+
end
|
52
|
+
|
53
|
+
def matches_excluded_method_regex? method
|
54
|
+
return false if @specification[:exclude_methods].nil?
|
55
|
+
regexs = @specification[:exclude_methods].find_all {|s| s.kind_of? Regexp}
|
56
|
+
return false if regexs.empty?
|
57
|
+
regexs.find {|re| method.to_s =~ re}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -38,17 +38,18 @@ module Aquarium
|
|
38
38
|
# We require the same object id, not just equal objects.
|
39
39
|
def <=> other
|
40
40
|
return 0 if object_id == other.object_id
|
41
|
+
return 1 if other.nil?
|
41
42
|
result = self.class <=> other.class
|
42
43
|
return result unless result == 0
|
43
|
-
result = (self.advice_kind.nil?
|
44
|
+
result = (self.advice_kind.nil? and other.advice_kind.nil?) ? 0 : self.advice_kind <=> other.advice_kind
|
44
45
|
return result unless result == 0
|
45
|
-
result = (self.advised_object.object_id.nil?
|
46
|
+
result = (self.advised_object.object_id.nil? and other.advised_object.object_id.nil?) ? 0 : self.advised_object.object_id <=> other.advised_object.object_id
|
46
47
|
return result unless result == 0
|
47
|
-
result = (self.parameters.nil?
|
48
|
+
result = (self.parameters.nil? and other.parameters.nil?) ? 0 : self.parameters <=> other.parameters
|
48
49
|
return result unless result == 0
|
49
|
-
result = (self.returned_value.nil?
|
50
|
+
result = (self.returned_value.nil? and other.returned_value.nil?) ? 0 : self.returned_value <=> other.returned_value
|
50
51
|
return result unless result == 0
|
51
|
-
(self.raised_exception.nil?
|
52
|
+
(self.raised_exception.nil? and other.raised_exception.nil?) ? 0 : self.raised_exception <=> other.raised_exception
|
52
53
|
end
|
53
54
|
|
54
55
|
def eql? other
|
@@ -68,7 +69,7 @@ module Aquarium
|
|
68
69
|
end
|
69
70
|
|
70
71
|
%w[type object].each do |attr|
|
71
|
-
class_eval
|
72
|
+
class_eval(<<-EOF, __FILE__, __LINE__)
|
72
73
|
# Deprecated, as JoinPoint#type overrides Module#type in a non-substitutable way!
|
73
74
|
# JoinPoint#target_#{attr} will be removed in the next release.
|
74
75
|
# Use JoinPoint#target_#{attr} instead
|
@@ -105,16 +106,15 @@ module Aquarium
|
|
105
106
|
@target_type = options[:type]
|
106
107
|
@target_object = options[:object]
|
107
108
|
@method_name = options[:method_name] || options[:method]
|
108
|
-
@instance_method = options[:instance_method]
|
109
109
|
class_method = options[:class_method].nil? ? false : options[:class_method]
|
110
|
-
@instance_method = (!class_method)
|
110
|
+
@instance_method = options[:instance_method].nil? ? (!class_method) : options[:instance_method]
|
111
111
|
@instance_or_class_method = @instance_method ? :instance : :class
|
112
112
|
@visibility = Aquarium::Utils::MethodUtils.visibility(type_or_object, @method_name, class_or_instance_method_flag)
|
113
113
|
assert_valid options
|
114
114
|
end
|
115
115
|
|
116
116
|
def type_or_object
|
117
|
-
|
117
|
+
target_type || target_object
|
118
118
|
end
|
119
119
|
|
120
120
|
alias_method :target_type_or_object, :type_or_object
|
@@ -128,7 +128,6 @@ module Aquarium
|
|
128
128
|
return results.matched.size == 1 ? true : false
|
129
129
|
end
|
130
130
|
|
131
|
-
# TODO while convenient, it couples advice-type information where it doesn't belong!
|
132
131
|
def proceed *args, &block
|
133
132
|
context.method(:proceed).call self, *args, &block
|
134
133
|
end
|
@@ -146,20 +145,22 @@ module Aquarium
|
|
146
145
|
|
147
146
|
# We require the same object id, not just equal objects.
|
148
147
|
def <=> other
|
149
|
-
return 0
|
148
|
+
return 0 if object_id == other.object_id
|
149
|
+
return 1 if other.nil?
|
150
150
|
result = self.class <=> other.class
|
151
151
|
return result unless result == 0
|
152
|
-
result = (self.target_type.nil?
|
152
|
+
result = (self.target_type.nil? and other.target_type.nil?) ? 0 : self.target_type.to_s <=> other.target_type.to_s
|
153
153
|
return result unless result == 0
|
154
|
-
result = (self.target_object.
|
155
|
-
result = self.target_object.object_id <=> other.target_object.object_id
|
154
|
+
result = (self.target_object.nil? and other.target_object.nil?) ? 0 : self.target_object.object_id <=> other.target_object.object_id
|
156
155
|
return result unless result == 0
|
157
|
-
result = (self.method_name.nil?
|
156
|
+
result = (self.method_name.nil? and other.method_name.nil?) ? 0 : self.method_name.to_s <=> other.method_name.to_s
|
158
157
|
return result unless result == 0
|
159
158
|
result = self.instance_method? == other.instance_method?
|
160
159
|
return 1 unless result == true
|
161
|
-
|
162
|
-
return
|
160
|
+
return 0 if self.context.nil? and other.context.nil?
|
161
|
+
return -1 if self.context.nil? and !other.context.nil?
|
162
|
+
return 1 if !self.context.nil? and other.context.nil?
|
163
|
+
return self.context <=> other.context
|
163
164
|
end
|
164
165
|
|
165
166
|
def eql? other
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'set'
|
2
2
|
require 'aquarium/aspects/join_point'
|
3
|
+
require 'aquarium/aspects/exclusion_handler'
|
3
4
|
require 'aquarium/utils'
|
4
5
|
require 'aquarium/extensions'
|
5
6
|
require 'aquarium/finders/finder_result'
|
@@ -18,8 +19,9 @@ module Aquarium
|
|
18
19
|
include Aquarium::Utils::ArrayUtils
|
19
20
|
include Aquarium::Utils::HashUtils
|
20
21
|
include Aquarium::Utils::SetUtils
|
22
|
+
include ExclusionHandler
|
21
23
|
include DefaultObjectHandler
|
22
|
-
|
24
|
+
|
23
25
|
attr_reader :specification
|
24
26
|
|
25
27
|
# Construct a Pointcut for methods in types or objects.
|
@@ -66,6 +68,24 @@ module Aquarium
|
|
66
68
|
# One or more of <tt>:readers</tt>, <tt>:reader</tt> (synonymous),
|
67
69
|
# <tt>:writers</tt>, and/or <tt>:writer</tt> (synonymous). By default, both
|
68
70
|
# readers and writers are matched.
|
71
|
+
#
|
72
|
+
# <tt>:exclude_pointcuts => pc || [pc_list]</tt>::
|
73
|
+
# <tt>:exclude_pointcut => pc || [pc_list]</tt>::
|
74
|
+
# <tt>:exclude_join_points => jp || [jp_list]</tt>::
|
75
|
+
# <tt>:exclude_join_point => jp || [jp_list]</tt>::
|
76
|
+
# <tt>:exclude_types => type || [type_list]</tt>::
|
77
|
+
# <tt>:exclude_types => type || [type_list]</tt>::
|
78
|
+
# <tt>:exclude_type => type || [type_list]</tt>::
|
79
|
+
# <tt>:exclude_objects => object || [object_list]</tt>::
|
80
|
+
# <tt>:exclude_object => object || [object_list]</tt>::
|
81
|
+
# <tt>:exclude_methods => method || [method_list]</tt>::
|
82
|
+
# <tt>:exclude_method => method || [method_list]</tt>::
|
83
|
+
# <tt>:exclude_attributes => attribute || [attribute_list]</tt>::
|
84
|
+
# <tt>:exclude_attribute => attribute || [attribute_list]</tt>::
|
85
|
+
# Exclude the specified "things" from the matched join points. If pointcuts are
|
86
|
+
# excluded, they should be subsets of the matched pointcuts. Otherwise, the
|
87
|
+
# resulting pointcut will be empty!
|
88
|
+
#
|
69
89
|
def initialize options = {}
|
70
90
|
init_specification options
|
71
91
|
init_candidate_types
|
@@ -113,22 +133,20 @@ module Aquarium
|
|
113
133
|
|
114
134
|
attr_writer :join_points_matched, :join_points_not_matched, :specification, :candidate_types, :candidate_objects, :candidate_join_points
|
115
135
|
|
136
|
+
ALLOWED_OPTIONS_SINGULAR = %w[type object join_point method exclude_type exclude_object exclude_join_point exclude_pointcut exclude_method
|
137
|
+
default_object attribute method_option attribute_option]
|
138
|
+
|
116
139
|
def init_specification options
|
117
140
|
@specification = {}
|
118
141
|
options ||= {}
|
119
142
|
validate_options options
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
@specification[:exclude_types] = Set.new(make_array(options[:exclude_type], options[:exclude_types]))
|
126
|
-
@specification[:exclude_objects] = Set.new(make_array(options[:exclude_object], options[:exclude_objects]))
|
127
|
-
@specification[:exclude_join_points] = Set.new(make_array(options[:exclude_join_point], options[:exclude_join_points]))
|
128
|
-
@specification[:exclude_methods] = Set.new(make_array(options[:exclude_method], options[:exclude_methods]))
|
129
|
-
@specification[:default_object] = Set.new(make_array(options[:default_object]))
|
143
|
+
ALLOWED_OPTIONS_SINGULAR.each do |option|
|
144
|
+
self.instance_eval(<<-EOF, __FILE__, __LINE__)
|
145
|
+
@specification[:#{option}s]= Set.new(make_array(options[:#{option}], options[:#{option}s]))
|
146
|
+
EOF
|
147
|
+
end
|
130
148
|
use_default_object_if_defined unless (types_given? || objects_given?)
|
131
|
-
|
149
|
+
|
132
150
|
raise Aquarium::Utils::InvalidOptions.new(":all is not yet supported for :attributes.") if @specification[:attributes] == Set.new([:all])
|
133
151
|
init_methods_specification options
|
134
152
|
end
|
@@ -139,10 +157,11 @@ module Aquarium
|
|
139
157
|
end
|
140
158
|
|
141
159
|
def validate_options options
|
142
|
-
knowns =
|
143
|
-
|
144
|
-
|
145
|
-
|
160
|
+
knowns = []
|
161
|
+
ALLOWED_OPTIONS_SINGULAR.each do |x|
|
162
|
+
knowns << x.intern
|
163
|
+
knowns << "#{x}s".intern
|
164
|
+
end
|
146
165
|
unknowns = options.keys - knowns
|
147
166
|
raise Aquarium::Utils::InvalidOptions.new("Unknown options specified: #{unknowns.inspect}") if unknowns.size > 0
|
148
167
|
end
|
@@ -175,7 +194,7 @@ module Aquarium
|
|
175
194
|
EOF
|
176
195
|
end
|
177
196
|
|
178
|
-
%w[types objects join_points methods].each do |name|
|
197
|
+
%w[types objects join_points pointcuts methods].each do |name|
|
179
198
|
class_eval(<<-EOF, __FILE__, __LINE__)
|
180
199
|
def exclude_#{name}_given
|
181
200
|
@specification[:exclude_#{name}]
|
@@ -227,15 +246,20 @@ module Aquarium
|
|
227
246
|
find_join_points_for :type, candidate_types, make_all_method_names
|
228
247
|
find_join_points_for :object, candidate_objects, make_all_method_names
|
229
248
|
add_join_points_for_candidate_join_points
|
249
|
+
remove_excluded_join_points
|
230
250
|
end
|
231
251
|
|
232
252
|
def add_join_points_for_candidate_join_points
|
233
|
-
@join_points_matched += @candidate_join_points.matched.keys
|
234
|
-
not (is_excluded_join_point?(jp) or is_excluded_type_or_object?(jp.type_or_object) or is_excluded_method?(jp.method_name))
|
235
|
-
end
|
253
|
+
@join_points_matched += @candidate_join_points.matched.keys
|
236
254
|
@join_points_not_matched += @candidate_join_points.not_matched.keys
|
237
255
|
end
|
238
256
|
|
257
|
+
def remove_excluded_join_points
|
258
|
+
@join_points_matched.delete_if do |jp|
|
259
|
+
join_point_excluded? jp
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
239
263
|
def find_join_points_for type_or_object_sym, candidates, method_names
|
240
264
|
results = find_methods_for type_or_object_sym, candidates, method_names
|
241
265
|
add_join_points results, type_or_object_sym
|
@@ -272,35 +296,6 @@ module Aquarium
|
|
272
296
|
@specification[:exclude_methods]
|
273
297
|
end
|
274
298
|
|
275
|
-
def is_excluded_join_point? jp
|
276
|
-
@specification[:exclude_join_points].include? jp
|
277
|
-
end
|
278
|
-
|
279
|
-
def is_excluded_type_or_object? type_or_object
|
280
|
-
return true if @specification[:exclude_objects].include?(type_or_object)
|
281
|
-
@specification[:exclude_types].find do |t|
|
282
|
-
case t
|
283
|
-
when String: type_or_object.name.eql?(t)
|
284
|
-
when Symbol: type_or_object.name.eql?(t.to_s)
|
285
|
-
when Regexp: type_or_object.name =~ t
|
286
|
-
end
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
def is_excluded_method? method
|
291
|
-
is_explicitly_excluded_method?(method) or matches_excluded_method_regex?(method)
|
292
|
-
end
|
293
|
-
|
294
|
-
def is_explicitly_excluded_method? method
|
295
|
-
@specification[:exclude_methods].include? method
|
296
|
-
end
|
297
|
-
|
298
|
-
def matches_excluded_method_regex? method
|
299
|
-
regexs = @specification[:exclude_methods].find_all {|s| s.kind_of? Regexp}
|
300
|
-
return false if regexs.empty?
|
301
|
-
regexs.find {|re| method.to_s =~ re}
|
302
|
-
end
|
303
|
-
|
304
299
|
def self.make_attribute_readers attributes
|
305
300
|
readers = attributes.map do |regexp_or_name|
|
306
301
|
if regexp_or_name.kind_of? Regexp
|
@@ -173,7 +173,7 @@ module Aquarium
|
|
173
173
|
# Must recalc reflect methods if we've switched to the type of the input object.
|
174
174
|
reflection_method_names = make_methods_reflection_method_names type, "methods"
|
175
175
|
end
|
176
|
-
ancestors =
|
176
|
+
ancestors = type.ancestors + type.included_modules
|
177
177
|
return method_array if ancestors.nil? || ancestors.size <= 1 # 1 for type_or_object itself!
|
178
178
|
ancestors.each do |ancestor|
|
179
179
|
unless ancestor.name == type.to_s
|
@@ -16,27 +16,72 @@ module Aquarium
|
|
16
16
|
end
|
17
17
|
hash
|
18
18
|
end
|
19
|
+
|
20
|
+
def self.visibility type_or_instance, method_sym, class_or_instance_only = nil, include_ancestors = true
|
21
|
+
find_method(type_or_instance, method_sym, class_or_instance_only, include_ancestors) do |type_or_instance, method_sym, protection|
|
22
|
+
return protection
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.has_method type_or_instance, method_sym, class_or_instance_only = nil, include_ancestors = true
|
27
|
+
found = find_method(type_or_instance, method_sym, class_or_instance_only, include_ancestors) do |type_or_instance, method_sym, protection|
|
28
|
+
return true
|
29
|
+
end
|
30
|
+
found ? true : false # found could be nil; return false, if so
|
31
|
+
end
|
19
32
|
|
20
|
-
def self.
|
33
|
+
def self.find_method type_or_instance, method_sym, class_or_instance_only = nil, include_ancestors = true
|
21
34
|
meta_method_suffixes = determine_meta_method_suffixes type_or_instance, class_or_instance_only
|
22
35
|
meta_method_suffixes.each do |suffix|
|
23
36
|
%w[public protected private].each do |protection|
|
24
37
|
meta_method = "#{protection}_#{suffix}"
|
25
|
-
|
26
|
-
|
38
|
+
methods = type_or_instance.send(meta_method, include_ancestors)
|
39
|
+
if methods.include?(method_sym.to_s)
|
40
|
+
return yield(type_or_instance, method_sym, protection.intern)
|
27
41
|
end
|
28
42
|
end
|
29
43
|
end
|
30
44
|
nil
|
31
45
|
end
|
32
46
|
|
47
|
+
# Which type in a hierarchy actually defines a method?
|
48
|
+
def self.definer type_or_instance, method_sym, class_or_instance_only = nil
|
49
|
+
return nil if type_or_instance.nil? or method_sym.nil?
|
50
|
+
return nil unless has_method(type_or_instance, method_sym, class_or_instance_only)
|
51
|
+
ancestors = ancestors_for type_or_instance
|
52
|
+
determine_definer ancestors, type_or_instance, method_sym, class_or_instance_only
|
53
|
+
end
|
54
|
+
|
33
55
|
private
|
34
56
|
|
57
|
+
# For objects, include the singleton/eigenclass in case a method of interest was actually defined just for the object.
|
58
|
+
def self.ancestors_for object
|
59
|
+
if Aquarium::Utils::TypeUtils.is_type? object
|
60
|
+
object.ancestors
|
61
|
+
else
|
62
|
+
eigen = (class << object; self; end)
|
63
|
+
[eigen] + eigen.ancestors
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.determine_definer ancestors, type_or_instance, method_sym, class_or_instance_only
|
68
|
+
candidates = ancestors.find_all {|a| has_method(a, method_sym, class_or_instance_only, false) { true }}
|
69
|
+
if candidates.size == 2 and Aquarium::Utils::TypeUtils.is_type?(type_or_instance) == false
|
70
|
+
return determine_actual_parent(type_or_instance, candidates)
|
71
|
+
end
|
72
|
+
candidates.size == 1 ? candidates.first : raise("Bug: Got multiple types #{candidates.inspect} that implement method #{method_sym}")
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.determine_actual_parent object, candidates
|
76
|
+
return nil unless (object.is_a?(candidates[0]) and object.is_a?(candidates[1]))
|
77
|
+
candidates[0].name == "" ? candidates[1] : candidates[0]
|
78
|
+
end
|
79
|
+
|
35
80
|
def self.determine_meta_method_suffixes type_or_instance, class_or_instance_only
|
36
81
|
limits = class_or_instance_only.nil? ? [:instance_method_only, :class_method_only] : [class_or_instance_only]
|
37
82
|
meta_method_suffixes = []
|
38
83
|
limits.each do |limit|
|
39
|
-
if
|
84
|
+
if Aquarium::Utils::TypeUtils.is_type? type_or_instance
|
40
85
|
meta_method_suffixes << "instance_methods" if limit == :instance_method_only
|
41
86
|
meta_method_suffixes << "methods" if limit == :class_method_only
|
42
87
|
else
|
@@ -45,10 +90,6 @@ module Aquarium
|
|
45
90
|
end
|
46
91
|
meta_method_suffixes
|
47
92
|
end
|
48
|
-
|
49
|
-
def self.find_method type_or_instance, method_sym, meta_method
|
50
|
-
type_or_instance.send(meta_method).include?(method_sym.to_s)
|
51
|
-
end
|
52
93
|
end
|
53
94
|
end
|
54
95
|
end
|