aquarium 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data/CHANGES +18 -0
  2. data/README +68 -39
  3. data/RELEASE-PLAN +25 -1
  4. data/UPGRADE +4 -0
  5. data/examples/aspect_design_example.rb +9 -3
  6. data/examples/aspect_design_example_spec.rb +7 -2
  7. data/examples/method_tracing_example.rb +1 -1
  8. data/examples/method_tracing_example_spec.rb +2 -2
  9. data/lib/aquarium/aspects/aspect.rb +53 -60
  10. data/lib/aquarium/aspects/dsl/aspect_dsl.rb +0 -1
  11. data/lib/aquarium/aspects/pointcut.rb +72 -17
  12. data/lib/aquarium/aspects/pointcut_composition.rb +4 -1
  13. data/lib/aquarium/extensions/hash.rb +65 -28
  14. data/lib/aquarium/extensions/set.rb +2 -0
  15. data/lib/aquarium/finders/finder_result.rb +13 -2
  16. data/lib/aquarium/finders/method_finder.rb +54 -28
  17. data/lib/aquarium/finders/type_finder.rb +36 -19
  18. data/lib/aquarium/utils/method_utils.rb +3 -12
  19. data/lib/aquarium/utils/name_utils.rb +27 -1
  20. data/lib/aquarium/version.rb +1 -1
  21. data/spec/aquarium/aspects/aspect_invocation_spec.rb +182 -51
  22. data/spec/aquarium/aspects/aspect_spec.rb +43 -8
  23. data/spec/aquarium/aspects/pointcut_and_composition_spec.rb +32 -3
  24. data/spec/aquarium/aspects/pointcut_or_composition_spec.rb +36 -5
  25. data/spec/aquarium/aspects/pointcut_spec.rb +373 -99
  26. data/spec/aquarium/extensions/hash_spec.rb +129 -38
  27. data/spec/aquarium/finders/finder_result_spec.rb +73 -15
  28. data/spec/aquarium/finders/method_finder_spec.rb +156 -72
  29. data/spec/aquarium/finders/object_finder_spec.rb +1 -0
  30. data/spec/aquarium/finders/type_finder_spec.rb +43 -0
  31. data/spec/aquarium/utils/name_utils_spec.rb +79 -4
  32. metadata +3 -3
@@ -59,7 +59,6 @@ module Aquarium
59
59
  opts
60
60
  end
61
61
  end
62
-
63
62
  end
64
63
  end
65
64
  end
@@ -48,11 +48,11 @@ module Aquarium
48
48
  # <tt>:method => method || [method_list]</tt>::
49
49
  # One or an array of methods, method names and/or method regular expessions to match.
50
50
  # By default, unless :attributes are specified, searches for public instance methods
51
- # with the method option :suppress_ancestor_methods implied, unless explicit method
51
+ # with the method option :exclude_ancestor_methods implied, unless explicit method
52
52
  # options are given.
53
53
  #
54
54
  # <tt>:method_options => [options]</tt>::
55
- # One or more options supported by Aquarium::Finders::MethodFinder. The :suppress_ancestor_methods
55
+ # One or more options supported by Aquarium::Finders::MethodFinder. The :exclude_ancestor_methods
56
56
  # option is most useful.
57
57
  #
58
58
  # <tt>:attributes => attribute || [attribute_list]</tt>::
@@ -88,8 +88,7 @@ module Aquarium
88
88
  join_points_not_matched == other.join_points_not_matched)
89
89
  end
90
90
 
91
- alias :== :eql?
92
- alias :=== :eql?
91
+ alias :== :eql?
93
92
 
94
93
  def empty?
95
94
  return join_points_matched.empty? && join_points_not_matched.empty?
@@ -123,6 +122,10 @@ module Aquarium
123
122
  @specification[:types] = Set.new(make_array(options[:types], options[:type]))
124
123
  @specification[:objects] = Set.new(make_array(options[:objects], options[:object]))
125
124
  @specification[:join_points] = Set.new(make_array(options[:join_points], options[:join_point]))
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]))
126
129
  @specification[:default_object] = Set.new(make_array(options[:default_object]))
127
130
  use_default_object_if_defined unless (types_given? || objects_given?)
128
131
  @specification[:attributes] = Set.new(make_array(options[:attributes], options[:attribute]))
@@ -136,7 +139,10 @@ module Aquarium
136
139
  end
137
140
 
138
141
  def validate_options options
139
- knowns = %w[object objects type types join_point join_points method methods attribute attributes method_options attribute_options default_object].map {|x| x.intern}
142
+ knowns = %w[object objects type types join_point join_points
143
+ exclude_object exclude_objects exclude_type exclude_types exclude_join_point exclude_join_points exclude_method exclude_methods
144
+ method methods attribute attributes
145
+ method_options attribute_options default_object].map {|x| x.intern}
140
146
  unknowns = options.keys - knowns
141
147
  raise Aquarium::Utils::InvalidOptions.new("Unknown options specified: #{unknowns.inspect}") if unknowns.size > 0
142
148
  end
@@ -169,19 +175,38 @@ module Aquarium
169
175
  EOF
170
176
  end
171
177
 
178
+ %w[types objects join_points methods].each do |name|
179
+ class_eval(<<-EOF, __FILE__, __LINE__)
180
+ def exclude_#{name}_given
181
+ @specification[:exclude_#{name}]
182
+ end
183
+
184
+ def exclude_#{name}_given?
185
+ not (exclude_#{name}_given.nil? or exclude_#{name}_given.empty?)
186
+ end
187
+ EOF
188
+ end
189
+
172
190
  private
173
191
 
174
192
  def init_candidate_types
175
193
  explicit_types, type_regexps_or_names = @specification[:types].partition do |type|
176
- is_type? type
194
+ Aquarium::Utils::TypeUtils.is_type? type
195
+ end
196
+ excluded_explicit_types, excluded_type_regexps_or_names = @specification[:exclude_types].partition do |type|
197
+ Aquarium::Utils::TypeUtils.is_type? type
177
198
  end
178
- @candidate_types = Aquarium::Finders::TypeFinder.new.find :types => type_regexps_or_names
179
- @candidate_types.append_matched(make_hash(explicit_types) {|x| Set.new([])}) # Append already-known types
199
+ possible_types = Aquarium::Finders::TypeFinder.new.find :types => type_regexps_or_names, :exclude_types => excluded_type_regexps_or_names
200
+ possible_types.append_matched(make_hash(explicit_types) {|x| Set.new([])})
201
+ @candidate_types = possible_types - Aquarium::Finders::TypeFinder.new.find(:types => excluded_type_regexps_or_names)
202
+ @candidate_types.matched.delete_if {|type, value| excluded_explicit_types.include? type}
180
203
  end
181
204
 
182
205
  def init_candidate_objects
183
206
  object_hash = {}
184
- @specification[:objects].each {|o| object_hash[o] = Set.new([])}
207
+ (@specification[:objects].flatten - @specification[:exclude_objects].flatten).each do |o|
208
+ object_hash[o] = Set.new([])
209
+ end
185
210
  @candidate_objects = Aquarium::Finders::FinderResult.new object_hash
186
211
  end
187
212
 
@@ -204,12 +229,10 @@ module Aquarium
204
229
  add_join_points_for_candidate_join_points
205
230
  end
206
231
 
207
- def is_type? candidate_type
208
- candidate_type.kind_of?(Module) || candidate_type.kind_of?(Class)
209
- end
210
-
211
232
  def add_join_points_for_candidate_join_points
212
- @join_points_matched += @candidate_join_points.matched.keys
233
+ @join_points_matched += @candidate_join_points.matched.keys.find_all do |jp|
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
213
236
  @join_points_not_matched += @candidate_join_points.not_matched.keys
214
237
  end
215
238
 
@@ -221,8 +244,9 @@ module Aquarium
221
244
  def find_methods_for type_or_object_sym, candidates, which_methods
222
245
  return Aquarium::Finders::FinderResult::NIL_OBJECT if candidates.matched.size == 0
223
246
  Aquarium::Finders::MethodFinder.new.find type_or_object_sym => candidates.matched_keys,
224
- :methods => which_methods,
225
- :options => @specification[:method_options].to_a
247
+ :methods => which_methods,
248
+ :exclude_methods => @specification[:exclude_methods],
249
+ :options => @specification[:method_options].to_a
226
250
  end
227
251
 
228
252
  def add_join_points search_results, type_or_object_sym
@@ -243,9 +267,40 @@ module Aquarium
243
267
  end
244
268
 
245
269
  def make_all_method_names
246
- @specification[:methods] + Pointcut.make_attribute_method_names(@specification[:attributes], @specification[:attribute_options])
270
+ @specification[:methods] +
271
+ Pointcut.make_attribute_method_names(@specification[:attributes], @specification[:attribute_options]) -
272
+ @specification[:exclude_methods]
247
273
  end
248
274
 
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
+
249
304
  def self.make_attribute_readers attributes
250
305
  readers = attributes.map do |regexp_or_name|
251
306
  if regexp_or_name.kind_of? Regexp
@@ -19,11 +19,13 @@ class Aquarium::Aspects::Pointcut
19
19
  end
20
20
 
21
21
  alias :union :or
22
+ alias :| :or
22
23
 
23
24
  def and pointcut2
24
25
  result = Aquarium::Aspects::Pointcut.new
25
26
  result.specification = specification.and(pointcut2.specification) do |value1, value2|
26
- value1.intersection_using_eql_comparison value2
27
+ value1 & value2
28
+ # value1.intersection_using_eql_comparison value2
27
29
  end
28
30
  result.join_points_matched = join_points_matched.intersection_using_eql_comparison pointcut2.join_points_matched
29
31
  result.join_points_not_matched = join_points_not_matched.intersection_using_eql_comparison pointcut2.join_points_not_matched
@@ -33,4 +35,5 @@ class Aquarium::Aspects::Pointcut
33
35
  end
34
36
 
35
37
  alias :intersection :and
38
+ alias :& :and
36
39
  end
@@ -4,49 +4,86 @@ module Aquarium
4
4
  module Extensions
5
5
  module HashHelper
6
6
 
7
- # Intersection of self with a second hash, which returns a new hash.
8
- # If the same key is present in both, but the values are
9
- # not "==" or "eql?", then the optional block is invoked to compute the intersection
10
- # of the two values. If no block is given, it is assumed that the two key-value pairs
11
- # should not be considered overlapping.
12
- def intersection other_hash
7
+ def and other_hash
13
8
  return {} if other_hash.nil? or other_hash.empty?
14
9
  keys2 = Set.new(self.keys).intersection(Set.new(other_hash.keys))
15
10
  result = {}
16
11
  keys2.each do |key|
17
- values1 = self[key]
18
- values2 = other_hash[key]
19
- if values1 == values2 or values1.eql?(values2)
20
- result[key] = values1
21
- else block_given?
22
- result[key] = yield values1, values2
12
+ value1 = self[key]
13
+ value2 = other_hash[key]
14
+ if block_given?
15
+ result[key] = yield value1, value2
16
+ elsif value1 == value2 or value1.eql?(value2)
17
+ result[key] = value1
18
+ elsif value1.class == value2.class && value1.respond_to?(:&)
19
+ result[key] = (value1 & value2)
23
20
  end
24
21
  end
25
22
  result
26
23
  end
27
24
 
28
- alias :and :intersection
25
+ alias :intersection :and
26
+ alias :& :and
29
27
 
30
- # Union of self with a second hash, which returns a new hash. If both hashes have
31
- # the same key, the value will be the result of evaluating the given block. If no
32
- # block is given, the result will be same behavior that "merge" provides; the
33
- # value in the second hash "wins".
34
- def union other_hash
28
+ # Union of self with a second hash, which returns a new hash. It's different from
29
+ # Hash#merge in that it attempts to merge non-equivalent values for the same key,
30
+ # using a block, if given, or if they are of the same type and respond to #|, using
31
+ # #| to merge the two values. Otherwise, it behaves like Hash#merge.
32
+ def or other_hash
33
+ return self if other_hash.nil?
35
34
  result = {}
36
- self.each {|key, value| result[key] = value}
37
- return result if other_hash.nil? or other_hash.empty?
38
- other_hash.each do |key, value|
39
- if result[key].nil? or ! block_given?
40
- result[key] = value
41
- else
42
- result[key] = yield result[key], value
35
+ new_keys = self.keys | other_hash.keys
36
+ new_keys.each do |key|
37
+ value1 = self[key]
38
+ value2 = other_hash[key]
39
+ if block_given?
40
+ result[key] = yield value1, value2
41
+ elsif value1.nil? and not value2.nil?
42
+ result[key] = value2
43
+ elsif (not value1.nil?) and value2.nil?
44
+ result[key] = value1
45
+ elsif value1 == value2 or value1.eql?(value2)
46
+ result[key] = value1
47
+ elsif value1.class == value2.class && value1.respond_to?(:|)
48
+ result[key] = (value1 | value2)
49
+ else # Hash#merge behavior
50
+ result[key] = value2
43
51
  end
44
52
  end
45
53
  result
46
54
  end
55
+
56
+ alias :union :or
57
+ alias :| :or
47
58
 
48
- alias :or :union
49
-
59
+ def minus other_hash
60
+ result = self.dup
61
+ return result if other_hash.nil? or other_hash.empty?
62
+ result.each do |key, value|
63
+ if other_hash.include?(key)
64
+ value1 = self[key]
65
+ value2 = other_hash[key]
66
+ if block_given?
67
+ result[key] = yield value1, value2
68
+ elsif value2.nil?
69
+ # do nothing
70
+ elsif value1 == value2 or value1.eql?(value2)
71
+ result.delete key
72
+ elsif value1.class == value2.class && value1.respond_to?(:-)
73
+ result[key] = (value1 - value2)
74
+ else # Hash#merge behavior
75
+ result.delete key
76
+ end
77
+ elsif block_given?
78
+ # Since the block might change the value's type (e.g., [] => Set...)
79
+ result[key] = yield result[key], nil
80
+ end
81
+ end
82
+ result
83
+ end
84
+
85
+ alias :- :minus
86
+
50
87
  # It appears that Hash#== uses Object#== (i.e., self.object_id == other.object_id) when
51
88
  # comparing hash keys. (Array#== uses the overridden #== for the elements.)
52
89
  def eql_when_keys_compared? other
@@ -61,7 +98,7 @@ module Aquarium
61
98
  end
62
99
  true
63
100
  end
64
-
101
+
65
102
  def equivalent_key key
66
103
  i = keys.index(key)
67
104
  i.nil? ? nil : keys[i]
@@ -13,12 +13,14 @@ class Set
13
13
 
14
14
  alias :eql? :==
15
15
 
16
+ # It seems that Set#| should work, but for some reason, it doesn't.
16
17
  def union_using_eql_comparison other
17
18
  first = dup
18
19
  second = other.dup
19
20
  first.size > second.size ? do_union(first, second) : do_union(second, first)
20
21
  end
21
22
 
23
+ # It seems that Set#& should work, but for some reason, it doesn't.
22
24
  def intersection_using_eql_comparison other
23
25
  first = dup
24
26
  second = other.dup
@@ -57,6 +57,7 @@ module Aquarium
57
57
  end
58
58
 
59
59
  alias :union :or
60
+ alias :| :or
60
61
 
61
62
  # "And" two results together
62
63
  def and other_result
@@ -67,7 +68,17 @@ module Aquarium
67
68
  end
68
69
 
69
70
  alias :intersection :and
71
+ alias :& :and
70
72
 
73
+ def minus other_result
74
+ result = FinderResult.new
75
+ result.matched = matched - other_result.matched
76
+ result.not_matched = not_matched - other_result.not_matched
77
+ result
78
+ end
79
+
80
+ alias :- :minus
81
+
71
82
  def append_matched other_hash = {}
72
83
  @matched = convert_hash_values_to_sets hash_union(matched, other_hash)
73
84
  end
@@ -105,7 +116,7 @@ module Aquarium
105
116
  def hash_intersection hash1, hash2
106
117
  return {} if hash1.nil? or hash2.nil?
107
118
  hash1.intersection(hash2) do |value1, value2|
108
- make_set(value1).intersection_using_eql_comparison(make_set(value2))
119
+ make_set(value1) & (make_set(value2))
109
120
  end
110
121
  end
111
122
 
@@ -113,7 +124,7 @@ module Aquarium
113
124
  return hash1 if hash2.nil? or hash2.empty?
114
125
  return hash2 if hash1.nil? or hash1.empty?
115
126
  hash1.union(hash2) do |value1, value2|
116
- make_set(value1).union_using_eql_comparison(make_set(value2))
127
+ make_set(value1) | (make_set(value2))
117
128
  end
118
129
  end
119
130
  end
@@ -1,6 +1,7 @@
1
1
  require 'set'
2
2
  require File.dirname(__FILE__) + '/../utils/array_utils'
3
3
  require File.dirname(__FILE__) + '/../utils/invalid_options'
4
+ require File.dirname(__FILE__) + '/../utils/type_utils'
4
5
  require File.dirname(__FILE__) + '/finder_result'
5
6
 
6
7
  # Find methods and types and objects.
@@ -34,6 +35,11 @@ module Aquarium
34
35
  # One or more method names and regular expressions to match.
35
36
  # Specify one or an array of values.
36
37
  #
38
+ # <tt>:exclude_methods => method_names_and_regexps</tt>::
39
+ # <tt>:exclude_method => method_names_and_regexps</tt>::
40
+ # One or more method names and regular expressions to exclude from the match.
41
+ # Specify one or an array of values.
42
+ #
37
43
  # <tt>:options => method_options</tt>::
38
44
  # By default, searches for public instance methods. Specify one or more
39
45
  # of the following options for alternatives. You can combine any of the
@@ -48,30 +54,38 @@ module Aquarium
48
54
  # <tt>:singleton</tt>:: Search for singleton methods. (Using :class for objects
49
55
  # won't work and :class, :public, :protected, and :private are ignored when
50
56
  # looking for singleton methods.)
51
- # <tt>:suppress_ancestor_methods</tt>:: Suppress "ancestor" methods. This
57
+ # <tt>:exclude_ancestor_methods</tt>:: Suppress "ancestor" methods. This
52
58
  # means that if you search for a override method +foo+ in a
53
59
  # +Derived+ class that is defined in the +Base+ class, you won't find it!
54
60
  #
55
61
  def find options = {}
56
62
  init_specification options
63
+ return Aquarium::Finders::FinderResult.new if nothing_to_find?
57
64
  types_and_objects = input_types + input_objects
58
- return Aquarium::Finders::FinderResult.new if types_and_objects.empty?
59
65
  method_names_or_regexps = input_methods
60
66
  if method_names_or_regexps.empty?
61
67
  not_matched = {}
62
68
  types_and_objects.each {|t| not_matched[t] = []}
63
69
  return Aquarium::Finders::FinderResult.new(:not_matched => not_matched)
64
70
  end
65
- method_options = make_array options[:options]
66
- find_all_by types_and_objects, method_names_or_regexps, method_options
71
+ result = do_find_all_by types_and_objects, method_names_or_regexps
72
+ unless (input_exclude_methods.nil? or input_exclude_methods.empty?)
73
+ result -= do_find_all_by types_and_objects, input_exclude_methods
74
+ end
75
+ result
67
76
  end
68
77
 
69
78
  # finder_result = MethodFinder.new.find_all_by types_and_objects, [methods, [options]]
70
79
  # where if no +methods+ are specified, all are returned, subject to the +options+,
71
80
  # as in #find.
81
+ # Note: Does not support the :exclude_method(s) options.
72
82
  def find_all_by types_and_objects, method_names_or_regexps = :all, *scope_options
73
- return Aquarium::Finders::FinderResult.new if types_and_objects.nil?
74
- @specification = make_options_hash scope_options
83
+ return Aquarium::Finders::FinderResult.new if types_and_objects.nil?
84
+ @specification = { :options => init_method_options(scope_options) }
85
+ do_find_all_by types_and_objects, method_names_or_regexps
86
+ end
87
+
88
+ def do_find_all_by types_and_objects, method_names_or_regexps
75
89
  types_and_objects = make_array types_and_objects
76
90
  names_or_regexps = make_methods_array method_names_or_regexps
77
91
  types_and_objects_to_matched_methods = {}
@@ -84,7 +98,7 @@ module Aquarium
84
98
  reflection_method_names.each do |reflect|
85
99
  method_array += reflect_methods(type_or_object, reflect).grep(make_regexp(name_or_regexp))
86
100
  end
87
- if @specification[:suppress_ancestor_methods]
101
+ if exclude_ancestor_methods?
88
102
  method_array = remove_ancestor_methods type_or_object, reflection_method_names, method_array
89
103
  end
90
104
  found_methods += method_array
@@ -99,20 +113,27 @@ module Aquarium
99
113
  end
100
114
 
101
115
  NIL_OBJECT = MethodFinder.new unless const_defined?(:NIL_OBJECT)
116
+
117
+ RECOGNIZED_METHOD_OPTIONS = %w[public private protected
118
+ instance class exclude_ancestor_methods exclude_ancestor_methods]
102
119
 
103
120
  def self.is_recognized_method_option string_or_symbol
104
- %w[public private protected
105
- instance class suppress_ancestor_methods].include? string_or_symbol.to_s
121
+ RECOGNIZED_METHOD_OPTIONS.include? string_or_symbol.to_s
106
122
  end
107
123
 
108
124
  protected
109
125
 
110
126
  def init_specification options
111
- options[:options] = make_array(options[:options]) unless options[:options].nil?
127
+ options[:options] = init_method_options(options[:options])
112
128
  validate options
113
129
  @specification = options
114
130
  end
115
131
 
132
+ def nothing_to_find?
133
+ types_and_objects = input_types + input_objects
134
+ types_and_objects.nil? or types_and_objects.empty? or input_exclude_methods.include?(:all)
135
+ end
136
+
116
137
  def input_types
117
138
  make_array @specification[:types], @specification[:type]
118
139
  end
@@ -125,6 +146,14 @@ module Aquarium
125
146
  make_array @specification[:methods], @specification[:method]
126
147
  end
127
148
 
149
+ def input_exclude_methods
150
+ make_array @specification[:exclude_methods], @specification[:exclude_method]
151
+ end
152
+
153
+ def exclude_ancestor_methods?
154
+ @specification[:options].include?(:exclude_ancestor_methods) or @specification[:options].include?(:suppress_ancestor_methods)
155
+ end
156
+
128
157
  private
129
158
 
130
159
  def make_methods_array *array_or_single_item
@@ -139,7 +168,7 @@ module Aquarium
139
168
 
140
169
  def remove_ancestor_methods type_or_object, reflection_method_names, method_array
141
170
  type = type_or_object
142
- unless (type_or_object.instance_of?(Class) or type_or_object.instance_of?(Module))
171
+ unless (Aquarium::Utils::TypeUtils.is_type? type_or_object)
143
172
  type = type_or_object.class
144
173
  # Must recalc reflect methods if we've switched to the type of the input object.
145
174
  reflection_method_names = make_methods_reflection_method_names type, "methods"
@@ -156,21 +185,18 @@ module Aquarium
156
185
  method_array
157
186
  end
158
187
 
159
- def make_options_hash *scope_options
160
- return {} if scope_options.nil?
161
- options = {}
162
- scope_options.flatten.each {|o| options[o] = '' unless o.nil?}
163
- unless options[:class] || options[:instance] || options[:singleton]
164
- options[:instance] = ''
165
- end
188
+ def init_method_options *scope_options
189
+ return [] if scope_options.nil?
190
+ options = scope_options.flatten
191
+ options << :instance unless options.include?(:class) or options.include?(:instance) or options.include?(:singleton)
166
192
  options
167
193
  end
168
194
 
169
195
  def make_methods_reflection_method_names type_or_object, root_method_name
170
- is_type = type_or_object.instance_of?(Class) || type_or_object.instance_of?(Module)
196
+ is_type = Aquarium::Utils::TypeUtils.is_type?(type_or_object)
171
197
  scope_prefixes = []
172
198
  class_instance_prefixes = []
173
- @specification.each do |opt, value|
199
+ @specification[:options].each do |opt, value|
174
200
  opt_string = opt.to_s
175
201
  case opt_string
176
202
  when "public", "private", "protected"
@@ -178,7 +204,7 @@ module Aquarium
178
204
  when "instance"
179
205
  class_instance_prefixes += is_type ? [opt_string + "_"] : [""]
180
206
  when "class"
181
- # We want to use the "bare" (public_|private_|)<root_method_name> calls
207
+ # We want to use the "bare" (public|private)_<root_method_name> calls
182
208
  # to get class methods, because we will invoke these methods on class objects!
183
209
  # For instances, class methods aren't supported.
184
210
  class_instance_prefixes += [""] if is_type
@@ -200,18 +226,18 @@ module Aquarium
200
226
  results
201
227
  end
202
228
 
203
- def reflect_methods type_or_object, reflect_method
204
- if type_or_object.kind_of?(String) or type_or_object.kind_of?(Symbol)
205
- eval "#{type_or_object.to_s}.#{reflect_method}"
229
+ def reflect_methods object, reflect_method
230
+ if object.kind_of?(String) or object.kind_of?(Symbol)
231
+ eval "#{object.to_s}.#{reflect_method}"
206
232
  else
207
- return [] unless type_or_object.respond_to? reflect_method
208
- m = type_or_object.method reflect_method
209
- m.call type_or_object
233
+ return [] unless object.respond_to? reflect_method
234
+ method = object.method reflect_method
235
+ method.call object
210
236
  end
211
237
  end
212
238
 
213
239
  def validate options
214
- allowed = %w[type types object objects method methods options class instance public private protected suppress_ancestor_methods].map {|x| x.intern}
240
+ allowed = (%w[type types object objects method methods exclude_method exclude_methods options] + RECOGNIZED_METHOD_OPTIONS).map {|x| x.intern}
215
241
  okay, bad = options.keys.partition {|x| allowed.include?(x)}
216
242
  raise Aquarium::Utils::InvalidOptions.new("Unrecognized option(s): #{bad.inspect}") unless bad.empty?
217
243
  method_options = options[:options]