aquarium 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/CHANGES +35 -0
  2. data/MIT-LICENSE +1 -1
  3. data/README +66 -20
  4. data/Rakefile +1 -1
  5. data/UPGRADE +5 -0
  6. data/examples/aspect_design_example.rb +5 -4
  7. data/examples/aspect_design_example_spec.rb +6 -5
  8. data/examples/design_by_contract_example.rb +3 -3
  9. data/examples/design_by_contract_example_spec.rb +4 -4
  10. data/examples/method_missing_example.rb +1 -1
  11. data/examples/method_missing_example_spec.rb +2 -2
  12. data/examples/method_tracing_example.rb +3 -3
  13. data/examples/method_tracing_example_spec.rb +6 -6
  14. data/lib/aquarium/aspects/advice.rb +2 -3
  15. data/lib/aquarium/aspects/aspect.rb +100 -246
  16. data/lib/aquarium/aspects/{default_object_handler.rb → default_objects_handler.rb} +7 -6
  17. data/lib/aquarium/aspects/dsl/aspect_dsl.rb +2 -2
  18. data/lib/aquarium/aspects/pointcut.rb +190 -107
  19. data/lib/aquarium/finders/method_finder.rb +120 -34
  20. data/lib/aquarium/finders/type_finder.rb +2 -5
  21. data/lib/aquarium/utils.rb +1 -0
  22. data/lib/aquarium/utils/array_utils.rb +11 -3
  23. data/lib/aquarium/utils/options_utils.rb +74 -0
  24. data/lib/aquarium/utils/type_utils.rb +25 -11
  25. data/lib/aquarium/version.rb +1 -1
  26. data/spec/aquarium/aspects/advice_chain_node_spec.rb +1 -1
  27. data/spec/aquarium/aspects/advice_spec.rb +1 -1
  28. data/spec/aquarium/aspects/aspect_invocation_spec.rb +179 -145
  29. data/spec/aquarium/aspects/aspect_spec.rb +1 -1
  30. data/spec/aquarium/aspects/aspect_with_nested_types_spec.rb +1 -1
  31. data/spec/aquarium/aspects/aspect_with_subtypes_spec.rb +1 -1
  32. data/spec/aquarium/aspects/concurrent_aspects_spec.rb +1 -1
  33. data/spec/aquarium/aspects/concurrent_aspects_with_objects_and_types_spec.rb +1 -1
  34. data/spec/aquarium/aspects/default_objects_handler_spec.rb +147 -0
  35. data/spec/aquarium/aspects/dsl/aspect_dsl_spec.rb +72 -121
  36. data/spec/aquarium/aspects/join_point_spec.rb +1 -1
  37. data/spec/aquarium/aspects/pointcut_and_composition_spec.rb +1 -1
  38. data/spec/aquarium/aspects/pointcut_or_composition_spec.rb +48 -47
  39. data/spec/aquarium/aspects/pointcut_spec.rb +727 -410
  40. data/spec/aquarium/extensions/hash_spec.rb +1 -1
  41. data/spec/aquarium/extensions/regex_spec.rb +1 -1
  42. data/spec/aquarium/extensions/set_spec.rb +1 -1
  43. data/spec/aquarium/extensions/string_spec.rb +1 -1
  44. data/spec/aquarium/extensions/symbol_spec.rb +1 -1
  45. data/spec/aquarium/extras/design_by_contract_spec.rb +1 -1
  46. data/spec/aquarium/finders/finder_result_spec.rb +1 -1
  47. data/spec/aquarium/finders/method_finder_spec.rb +49 -16
  48. data/spec/aquarium/finders/type_finder_spec.rb +1 -1
  49. data/spec/aquarium/finders/type_finder_with_descendents_and_ancestors_spec.rb +16 -1
  50. data/spec/aquarium/utils/array_utils_spec.rb +31 -6
  51. data/spec/aquarium/utils/hash_utils_spec.rb +1 -1
  52. data/spec/aquarium/utils/html_escaper_spec.rb +1 -1
  53. data/spec/aquarium/utils/logic_error_spec.rb +1 -1
  54. data/spec/aquarium/utils/method_utils_spec.rb +1 -1
  55. data/spec/aquarium/utils/name_utils_spec.rb +1 -1
  56. data/spec/aquarium/utils/nil_object_spec.rb +1 -1
  57. data/spec/aquarium/utils/set_utils_spec.rb +1 -1
  58. data/spec/aquarium/utils/type_utils_spec.rb +1 -1
  59. metadata +9 -7
@@ -72,8 +72,7 @@ module Aquarium
72
72
 
73
73
  def last
74
74
  last_node = nil
75
- each { |node| last_node = node unless node.nil? } #; p "<br/>last_node: #{last_node.inspect .gsub(/\</,"&lt;").gsub(/\>/,"&gt;")}"}
76
- # p "<br/><br/>returning last_node: #{last_node.inspect .gsub(/\</,"&lt;").gsub(/\>/,"&gt;")}"
75
+ each { |node| last_node = node unless node.nil? }
77
76
  last_node
78
77
  end
79
78
 
@@ -166,7 +165,7 @@ module Aquarium
166
165
  end
167
166
 
168
167
  def after_raising_exceptions_list
169
- list = make_array(@after_raising)
168
+ list = @after_raising.kind_of?(Set) ? @after_raising.to_a : @after_raising
170
169
  (list.nil? || list.empty? || (list.size == 1 && list[0] == "")) ? [Object] : list
171
170
  end
172
171
  end
@@ -6,7 +6,7 @@ require 'aquarium/aspects/exclusion_handler'
6
6
  require 'aquarium/aspects/join_point'
7
7
  require 'aquarium/aspects/pointcut'
8
8
  require 'aquarium/aspects/pointcut_composition'
9
- require 'aquarium/aspects/default_object_handler'
9
+ require 'aquarium/aspects/default_objects_handler'
10
10
 
11
11
  module Aquarium
12
12
  module Aspects
@@ -23,55 +23,37 @@ module Aquarium
23
23
  class Aspect
24
24
  include Advice
25
25
  include ExclusionHandler
26
- include DefaultObjectHandler
26
+ include DefaultObjectsHandler
27
+ include Aquarium::Aspects
27
28
  include Aquarium::Utils::ArrayUtils
28
29
  include Aquarium::Utils::HashUtils
29
30
  include Aquarium::Utils::HtmlEscaper
31
+ include Aquarium::Utils::OptionsUtils
30
32
 
31
- attr_accessor :verbose, :log
32
33
  attr_reader :specification, :pointcuts, :advice
33
34
 
34
- OTHER_ALLOWED_OPTIONS_SINGULAR = %w[type_and_descendents type_and_ancestors exclude_type_and_descendents exclude_type_and_ancestors].map {|o| o.intern}
35
- OTHER_ALLOWED_OPTIONS_PLURAL = %w[types_and_descendents types_and_ancestors exclude_types_and_descendents exclude_types_and_ancestors].map {|o| o.intern}
35
+ CANONICAL_OPTIONS = Pointcut::CANONICAL_OPTIONS.merge({
36
+ "advice" => %w[action do_action use_advice advise_with invoke call],
37
+ "pointcuts" => %w[pointcut within_pointcuts within_pointcut on_pointcuts on_pointcut],
38
+ "exclude_pointcuts" => %w[exclude_pointcut exclude_on_pointcut exclude_on_pointcuts exclude_within_pointcut exclude_within_pointcuts]
39
+ })
40
+
41
+ ALL_ALLOWED_OPTIONS = CANONICAL_OPTIONS.keys.inject([]) {|ary,i| ary << i << CANONICAL_OPTIONS[i]}.flatten +
42
+ Pointcut::ATTRIBUTE_OPTIONS
36
43
 
37
- ALLOWED_OPTIONS_SINGULAR = %w[advice type object method attribute method_option attribute_option pointcut default_object
38
- exclude_type exclude_object exclude_pointcut exclude_join_point exclude_method exclude_attribute noop].map {|o| o.intern}
39
-
40
- ALLOWED_OPTIONS_PLURAL = OTHER_ALLOWED_OPTIONS_PLURAL + ALLOWED_OPTIONS_SINGULAR.map {|o| "#{o.to_s}s".intern}
41
-
42
- ALLOWED_OPTIONS = ALLOWED_OPTIONS_PLURAL + ALLOWED_OPTIONS_SINGULAR + OTHER_ALLOWED_OPTIONS_SINGULAR
44
+ ALL_ALLOWED_OPTION_SYMBOLS = ALL_ALLOWED_OPTIONS.map {|o| o.intern} + Advice::kinds
43
45
 
44
- ADVICE_OPTIONS_SYNONYMS_MAP = {
45
- :call => :advice,
46
- :invoke => :advice,
47
- :advise_with => :advice
48
- }
49
-
50
- ALLOWED_OPTIONS_SYNONYMS_MAP = {
51
- :type => :types,
52
- :type_and_descendents => :types_and_descendents,
53
- :type_and_ancestors => :types_and_ancestors,
54
- :within_type => :types,
55
- :within_types => :types,
56
- :object => :objects,
57
- :within_object => :objects,
58
- :within_objects => :objects,
59
- :method => :methods,
60
- :within_method => :methods,
61
- :within_methods => :methods,
62
- :attribute => :attributes,
63
- :pointcut => :pointcuts,
64
- :within_pointcut => :pointcuts,
65
- :within_pointcuts => :pointcuts,
66
- :exclude_type => :exclude_types,
67
- :exclude_type_and_descendents => :exclude_types_and_descendents,
68
- :exclude_type_and_ancestors => :exclude_types_and_ancestors,
69
- :exclude_object => :exclude_objects,
70
- :exclude_pointcut => :exclude_pointcuts,
71
- :exclude_join_point => :exclude_join_points,
72
- :exclude_method => :exclude_methods,
73
- :exclude_attribute => :exclude_attributes,
74
- }
46
+ CANONICAL_OPTIONS.keys.each do |name|
47
+ module_eval(<<-EOF, __FILE__, __LINE__)
48
+ def #{name}_given
49
+ @specification[:#{name}]
50
+ end
51
+
52
+ def #{name}_given?
53
+ not (#{name}_given.nil? or #{name}_given.empty?)
54
+ end
55
+ EOF
56
+ end
75
57
 
76
58
  # Aspect.new (:around | :before | :after | :after_returning | :after_raising ) \
77
59
  # (:pointcuts => [...]), | \
@@ -87,21 +69,32 @@ module Aquarium
87
69
  # <tt>:around</tt>::
88
70
  # Invoke the specified advice "around" the join points. It is up to the advice
89
71
  # itself to call <tt>join_point.proceed</tt> (where <tt>join_point</tt> is the
90
- # first argument passed to the advice) if it wants the advised method to actually
72
+ # first option passed to the advice) if it wants the advised method to actually
91
73
  # execute.
92
74
  #
93
75
  # <tt>:before</tt>::
94
- # Invoke the specified advice as before the join point.
76
+ # Invoke the specified advice before the join point.
95
77
  #
96
78
  # <tt>:after</tt>::
97
- # Invoke the specified advice as after the join point either returns successfully
79
+ # Invoke the specified advice after the join point either returns successfully
98
80
  # or raises an exception.
99
81
  #
100
82
  # <tt>:after_returning</tt>::
101
- # Invoke the specified advice as after the join point returns successfully.
83
+ # Invoke the specified advice after the join point returns successfully.
102
84
  #
103
- # <tt>:after_raising</tt>::
104
- # Invoke the specified advice as after the join point raises an exception.
85
+ # <tt>:after_raising [=> exception || [exception_list]]</tt>::
86
+ # Invoke the specified advice after the join point raises one of the specified exceptions.
87
+ # If no exceptions are specified, the advice is invoked after any exception is raised.
88
+ #
89
+ # <tt>:advice => proc</tt>::
90
+ # <tt>:action => proc</tt>::
91
+ # <tt>:do_action => proc</tt>::
92
+ # <tt>:use_advice => proc</tt>::
93
+ # <tt>:advise_with => proc</tt>::
94
+ # <tt>:invoke => proc</tt>::
95
+ # <tt>:call => proc</tt>::
96
+ # The specified advice to be invoked. Only one advice may be specified. If a block is
97
+ # specified, it is used instead.
105
98
  #
106
99
  # <tt>:pointcuts => pointcut || [pointcut_list]</tt>::
107
100
  # <tt>:pointcut => pointcut || [pointcut_list]</tt>::
@@ -110,90 +103,18 @@ module Aquarium
110
103
  # One or an array of Pointcut or JoinPoint objects. Mutually-exclusive with the :types, :objects,
111
104
  # :methods, :attributes, :method_options, and :attribute_options parameters.
112
105
  #
113
- # <tt>:types => type || [type_list]</tt>::
114
- # <tt>:type => type || [type_list]</tt>::
115
- # <tt>:within_type => type || [type_list]</tt>::
116
- # <tt>:within_types => type || [type_list]</tt>::
117
- # One or an array of types, type names and/or type regular expessions to advise.
118
- # All the :types, :objects, :methods, :attributes, :method_options, and :attribute_options
119
- # are used to construct Pointcuts internally.
120
- #
121
- # <tt>:types_and_descendents => type || [type_list]</tt>::
122
- # <tt>:type_and_descendents => type || [type_list]</tt>::
123
- # <tt>:types_and_ancestors => type || [type_list]</tt>::
124
- # <tt>:type_and_ancestors => type || [type_list]</tt>::
125
- # One or an array of types and either their descendents or ancestors.
126
- # If you want both the descendents _and_ ancestors, use both options.
127
- #
128
- # <tt>:objects => object || [object_list]</tt>::
129
- # <tt>:object => object || [object_list]</tt>::
130
- # <tt>:within_object => object || [object_list]</tt>::
131
- # <tt>:within_objects => object || [object_list]</tt>::
132
- # One or an array of objects to advise.
133
- #
134
- # <tt>:default_objects => object || [object_list]</tt>::
135
- # <tt>:default_object => object || [object_list]</tt>::
136
- # An "internal" flag used by the methods that AspectDSL adds to Object. When no object
137
- # or type is specified, the value of :default_objects will be used, if defined. The
138
- # AspectDSL methods set the value to self, so that the user doesn't have to in the
139
- # appropriate contexts, for convenience. This flag is subject to change, so don't
140
- # use it explicitly!
141
- #
142
- # <tt>:methods => method || [method_list]</tt>::
143
- # <tt>:method => method || [method_list]</tt>::
144
- # <tt>:within_method => method || [method_list]</tt>::
145
- # <tt>:within_methods => method || [method_list]</tt>::
146
- # One or an array of methods, method names and/or method regular expessions to match.
147
- # Unless :attributes are specified, defaults to :all, which searches for all public
148
- # instance methods with an implied :method_options => :exclude_ancestor_methods, unless
149
- # :method_options provided explicitly.
150
- #
151
- # <tt>:method_options => [options]</tt>::
152
- # One or more options supported by Aquarium::Finders::MethodFinder. Defaults to :exclude_ancestor_methods
106
+ # <tt>:noop</tt>::
107
+ # Does not actually advise any join points. Useful for testing.
153
108
  #
154
- # <tt>:attributes => attribute || [attribute_list]</tt>::
155
- # <tt>:attribute => attribute || [attribute_list]</tt>::
156
- # <tt>:within_attribute => attribute || [attribute_list]</tt>::
157
- # <tt>:within_attributes => attribute || [attribute_list]</tt>::
158
- # One or an array of attribute names and/or regular expessions to match.
159
- # This is syntactic sugar for the corresponding attribute readers and/or writers
160
- # methods, as specified using the <tt>:attrbute_options. Any matches will be
161
- # joined with the matched :methods.</tt>.
162
- #
163
- # <tt>:attribute_options => [options]</tt>::
164
- # One or more of <tt>:readers</tt>, <tt>:reader</tt> (synonymous),
165
- # <tt>:writers</tt>, and/or <tt>:writer</tt> (synonymous). By default, both
166
- # readers and writers are matched.
167
- #
168
- # <tt>:exclude_pointcuts => pc || [pc_list]</tt>::
169
- # <tt>:exclude_pointcut => pc || [pc_list]</tt>::
170
- # <tt>:exclude_join_points => jp || [jp_list]</tt>::
171
- # <tt>:exclude_join_point => jp || [jp_list]</tt>::
172
- # <tt>:exclude_types => type || [type_list]</tt>::
173
- # <tt>:exclude_types => type || [type_list]</tt>::
174
- # <tt>:exclude_type => type || [type_list]</tt>::
175
- # <tt>:exclude_objects => object || [object_list]</tt>::
176
- # <tt>:exclude_object => object || [object_list]</tt>::
177
- # <tt>:exclude_methods => method || [method_list]</tt>::
178
- # <tt>:exclude_method => method || [method_list]</tt>::
179
- # <tt>:exclude_attributes => attribute || [attribute_list]</tt>::
180
- # <tt>:exclude_attribute => attribute || [attribute_list]</tt>::
181
- # Exclude the specified "things" from the matched join points.
182
- #
183
- # <tt>:exclude_types_and_descendents => type || [type_list]</tt>::
184
- # <tt>:exclude_type_and_descendents => type || [type_list]</tt>::
185
- # <tt>:exclude_types_and_ancestors => type || [type_list]</tt>::
186
- # <tt>:exclude_type_and_ancestors => type || [type_list]</tt>::
187
- # Exclude the specified types and their descendents, ancestors.
188
- # If you want to exclude both the descendents _and_ ancestors, use both options.
189
- #
190
- # The actual advice to execute is the block or you can pass a Proc using :advice => proc.
191
- # Note that the advice takes a join_point argument, which will include a non-nil
192
- # JoinPoint#Context object, the object being executed, and the argument list to the method.
109
+ # It also accepts all the same options that Pointcut accepts, including the synonyms for :types,
110
+ # :methods, etc.
193
111
  def initialize *options, &block
194
- process_input options, &block
112
+ @first_option_that_was_method = []
113
+ opts = rationalize options
114
+ init_specification opts, canonical_options, &block
195
115
  init_pointcuts
196
- return if specification[:noop]
116
+ validate_specification
117
+ return if noop
197
118
  advise_join_points
198
119
  end
199
120
 
@@ -205,8 +126,15 @@ module Aquarium
205
126
  get_jps :join_points_not_matched
206
127
  end
207
128
 
129
+ def canonical_options
130
+ CANONICAL_OPTIONS
131
+ end
132
+ def all_allowed_option_symbols
133
+ ALL_ALLOWED_OPTION_SYMBOLS + @first_option_that_was_method
134
+ end
135
+
208
136
  def unadvise
209
- return if @specification[:noop]
137
+ return if noop
210
138
  @pointcuts.each do |pointcut|
211
139
  interesting_join_points(pointcut).each do |join_point|
212
140
  remove_advice_for_aspect_at join_point
@@ -233,24 +161,24 @@ module Aquarium
233
161
 
234
162
  protected
235
163
 
236
- def process_input options, &block
237
- @original_options = options.flatten
238
- make_specification options, &block
239
- @verbose = @specification[:verbose] || false
240
- @log = @specification[:log] || ""
241
- end
242
-
243
- def make_specification options, &block
244
- opts = rationalize_parameters options.flatten.dup
245
- # For non-hash inputs, use an empty string for the value
246
- @specification = Aquarium::Utils::MethodUtils.method_args_to_hash(*opts) {|option| ""}
247
- use_default_object_if_defined unless some_type_or_pc_option_given?
248
- use_first_nonadvice_symbol_as_method(opts) unless methods_given?
164
+ def rationalize options
165
+ return {} if options.nil? or options.empty?
166
+ return options if options.size > 1
167
+ # remove [] wrapping if we're wrapping a single hash element
168
+ return (options.first.kind_of?(Hash) or options.first.kind_of?(Array)) ? options.first : options
169
+ end
170
+
171
+ def init_type_specific_specification original_options, options_hash, &block
172
+ Advice.kinds.each do |kind|
173
+ @specification[kind] = Set.new(make_array(options_hash[kind])) if options_hash[kind]
174
+ end
175
+ @specification.merge! Pointcut.make_attribute_reading_writing_options(options_hash)
176
+ use_default_objects_if_defined unless some_type_or_pc_option_given?
177
+ use_first_nonadvice_symbol_as_method(original_options) unless methods_given?
249
178
  calculate_excluded_types
250
179
  @advice = determine_advice block
251
- validate_specification
252
180
  end
253
-
181
+
254
182
  def calculate_excluded_types
255
183
  type_finder_options = {}
256
184
  %w[types types_and_ancestors types_and_descendents].each do |opt|
@@ -261,45 +189,32 @@ module Aquarium
261
189
  end
262
190
 
263
191
  def determine_advice block
264
- # There can be only one advice; take the last one...
265
- block || (@specification[:advice].kind_of?(Array) ? @specification[:advice].last : @specification[:advice])
192
+ # There can be only one advice; take any one in the set; options validation will raise if there is more than one.
193
+ block || (@specification[:advice].to_a.first)
266
194
  end
267
195
 
268
196
  def init_pointcuts
269
197
  pointcuts = []
270
198
  if pointcuts_given?
271
199
  pointcuts_given.each do |pointcut|
272
- if pointcut.kind_of?(Aquarium::Aspects::Pointcut)
200
+ if pointcut.kind_of? Pointcut
273
201
  pointcuts << pointcut
274
- elsif pointcut.kind_of?(Aquarium::Aspects::JoinPoint)
275
- pointcuts << Aquarium::Aspects::Pointcut.new(:join_point => pointcut)
202
+ elsif pointcut.kind_of? JoinPoint
203
+ pointcuts << Pointcut.new(:join_point => pointcut)
276
204
  else # a hash of Pointcut.new options?
277
- pointcuts << Aquarium::Aspects::Pointcut.new(pointcut)
205
+ pointcuts << Pointcut.new(pointcut)
278
206
  end
279
207
  end
280
208
  else
281
209
  pc_options = {}
282
- ALLOWED_OPTIONS_PLURAL.each do |option|
283
- next if pointcut_new_doesnt_accept? option
284
- self.instance_eval(<<-EOF, __FILE__, __LINE__)
285
- pc_options[:#{option}] = #{option}_given if #{option}_given?
286
- EOF
210
+ Pointcut::ALL_ALLOWED_OPTION_SYMBOLS.each do |pc_option|
211
+ pc_options[pc_option] = @specification[pc_option] unless @specification[pc_option].nil?
287
212
  end
288
- pointcuts << Aquarium::Aspects::Pointcut.new(pc_options)
213
+ pointcuts << Pointcut.new(pc_options)
289
214
  end
290
215
  @pointcuts = Set.new(remove_excluded_join_points_and_empty_pointcuts(pointcuts))
291
216
  end
292
217
 
293
- def pointcut_new_doesnt_accept? option
294
- case option
295
- when :advices: true
296
- when :pointcuts: true
297
- when :default_objects: true
298
- when :noops: true
299
- else false
300
- end
301
- end
302
-
303
218
  def remove_excluded_join_points_and_empty_pointcuts pointcuts
304
219
  pointcuts.reject do |pc|
305
220
  pc.join_points_matched.delete_if do |jp|
@@ -315,7 +230,7 @@ module Aquarium
315
230
  interesting_join_points(pointcut).each do |join_point|
316
231
  attr_name = Aspect.make_advice_chain_attr_sym(join_point)
317
232
  add_advice_framework(join_point) if need_advice_framework?(join_point)
318
- Aquarium::Aspects::Advice.sort_by_priority_order(specified_advice_kinds).reverse.each do |advice_kind|
233
+ Advice.sort_by_priority_order(specified_advice_kinds).reverse.each do |advice_kind|
319
234
  add_advice_to_chain join_point, advice_kind, advice
320
235
  end
321
236
  end
@@ -341,7 +256,7 @@ module Aquarium
341
256
  :next_node => start_of_advice_chain,
342
257
  :static_join_point => join_point})
343
258
  # New node is new start of chain.
344
- Aspect.set_advice_chain(join_point, Aquarium::Aspects::AdviceChainNodeFactory.make_node(options))
259
+ Aspect.set_advice_chain(join_point, AdviceChainNodeFactory.make_node(options))
345
260
  end
346
261
 
347
262
  def get_jps which_jps
@@ -370,7 +285,7 @@ module Aquarium
370
285
  type_to_advise = Aspect.type_to_advise_for join_point
371
286
  # Note: Must set advice chain, a class variable on the type we're advising, FIRST.
372
287
  # Otherwise the class_eval that follows will assume the @@ advice chain belongs to Aspect!
373
- Aspect.set_advice_chain join_point, Aquarium::Aspects::AdviceChainNodeFactory.make_node(
288
+ Aspect.set_advice_chain join_point, AdviceChainNodeFactory.make_node(
374
289
  :aspect => nil, # Belongs to all aspects that might advise this join point!
375
290
  :advice_kind => :none,
376
291
  :alias_method_name => alias_method_name,
@@ -529,7 +444,7 @@ module Aquarium
529
444
  end
530
445
 
531
446
  def some_type_or_pc_option_given?
532
- pointcuts_given? or some_type_option_given? or objects_given? #or default_objects_given?
447
+ pointcuts_given? or some_type_option_given? or objects_given?
533
448
  end
534
449
 
535
450
  def some_type_option_given?
@@ -545,42 +460,11 @@ module Aquarium
545
460
  end
546
461
 
547
462
  def specified_advice_kinds
548
- @specification.keys.select do |key|
549
- Aquarium::Aspects::Advice.kinds.include? key
550
- end
463
+ Advice.kinds & @specification.keys
551
464
  end
552
465
 
553
- def rationalize_parameters opts
554
- return opts unless opts.last.kind_of?(Hash)
555
- hash = opts.pop.dup
556
- opts.push hash
557
- ALLOWED_OPTIONS_SYNONYMS_MAP.each do |syn, actual|
558
- if hash.has_key? syn
559
- hash[actual] = make_array(hash[actual], hash[syn])
560
- hash.delete syn
561
- end
562
- end
563
- # Only one advice argument allowed.
564
- unless hash.has_key?(:advice)
565
- ADVICE_OPTIONS_SYNONYMS_MAP.each do |syn, actual|
566
- if hash.has_key? syn
567
- hash[actual] = hash[syn]
568
- hash.delete syn
569
- end
570
- end
571
- end
572
- ALLOWED_OPTIONS_PLURAL.each do |opt|
573
- case opt
574
- when :advices: next
575
- when :noops: next
576
- end
577
- hash[opt] = Set.new(make_array(hash[opt]))
578
- end
579
- opts
580
- end
581
-
582
466
  def validate_specification
583
- bad_options("One of #{Aquarium::Aspects::Advice.kinds.inspect} is required.") unless advice_kinds_given?
467
+ bad_options("One of #{Advice.kinds.inspect} is required.") unless advice_kinds_given?
584
468
  bad_options(":around can't be used with :before.") if around_given_with? :before
585
469
  bad_options(":around can't be used with :after.") if around_given_with? :after
586
470
  bad_options(":around can't be used with :after_returning.") if around_given_with? :after_returning
@@ -594,34 +478,20 @@ module Aquarium
594
478
  if pointcuts_given? and (some_type_option_given? or objects_given?)
595
479
  bad_options("Can't specify both :pointcut(s) and one or more of :type(s), and/or :object(s).")
596
480
  end
597
- @specification.each_key do |parameter|
598
- check_parameter parameter
599
- end
600
- if @advice.nil? && @specification[:noop].nil?
601
- bad_options "No advice block nor :advice argument was given."
602
- end
603
- if @advice.arity == -2
604
- bad_options "It appears that your advice parameter list is the obsolete format |jp, *args|. The correct format is |jp, object, *args|"
481
+ unless noop
482
+ if (not @specification[:advice].nil?) && @specification[:advice].size > 1
483
+ bad_options "You can only specify one advice object for the :advice option."
484
+ end
485
+ if @advice.nil?
486
+ bad_options "No advice block nor :advice option was given."
487
+ elsif @advice.arity == -2
488
+ bad_options "It appears that your advice parameter list is the obsolete format |jp, *args|. The correct format is |jp, object, *args|"
489
+ end
605
490
  end
606
491
  end
607
492
 
608
- def check_parameter parameter
609
- bad_options("Unrecognized parameter: :#{parameter}") unless is_valid_parameter(parameter)
610
- end
611
-
612
- def is_valid_parameter key
613
- ALLOWED_OPTIONS.include?(key) || ALLOWED_OPTIONS_SYNONYMS_MAP.keys.include?(key) ||
614
- ADVICE_OPTIONS_SYNONYMS_MAP.keys.include?(key) || KINDS_IN_PRIORITY_ORDER.include?(key) ||
615
- key == :exclude_types_calculated ||
616
- parameter_is_a_method_name?(key) # i.e., use_first_nonadvice_symbol_as_method
617
- end
618
-
619
- def parameter_is_a_method_name? name
620
- @specification[:methods].include? name
621
- end
622
-
623
493
  def advice_kinds_given
624
- Aquarium::Aspects::Advice.kinds.inject([]) {|ary, kind| ary << @specification[kind] if @specification[kind]; ary}
494
+ Advice.kinds.inject([]) {|ary, kind| ary << @specification[kind] if @specification[kind]; ary}
625
495
  end
626
496
 
627
497
  def advice_kinds_given?
@@ -636,29 +506,13 @@ module Aquarium
636
506
  EOF
637
507
  end
638
508
 
639
- ALLOWED_OPTIONS_PLURAL.each do |name|
640
- case name
641
- when :advices : next
642
- when :default_objects : next
643
- when :noops : next
644
- end
645
- class_eval(<<-EOF, __FILE__, __LINE__)
646
- def #{name}_given
647
- make_array(@specification[:#{name}])
648
- end
649
-
650
- def #{name}_given?
651
- not (#{name}_given.nil? or #{name}_given.empty?)
652
- end
653
- EOF
654
- end
655
-
656
509
  def use_first_nonadvice_symbol_as_method options
657
510
  2.times do |i|
658
511
  if options.size >= i+1
659
512
  sym = options[i]
660
- if sym.kind_of?(Symbol) && !Aquarium::Aspects::Advice::kinds.include?(sym)
513
+ if sym.kind_of?(Symbol) && !Advice::kinds.include?(sym)
661
514
  @specification[:methods] = Set.new([sym])
515
+ @first_option_that_was_method << sym
662
516
  return
663
517
  end
664
518
  end