aquarium 0.2.0 → 0.3.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.
- data/CHANGES +35 -0
- data/MIT-LICENSE +1 -1
- data/README +66 -20
- data/Rakefile +1 -1
- data/UPGRADE +5 -0
- data/examples/aspect_design_example.rb +5 -4
- data/examples/aspect_design_example_spec.rb +6 -5
- data/examples/design_by_contract_example.rb +3 -3
- data/examples/design_by_contract_example_spec.rb +4 -4
- data/examples/method_missing_example.rb +1 -1
- data/examples/method_missing_example_spec.rb +2 -2
- data/examples/method_tracing_example.rb +3 -3
- data/examples/method_tracing_example_spec.rb +6 -6
- data/lib/aquarium/aspects/advice.rb +2 -3
- data/lib/aquarium/aspects/aspect.rb +100 -246
- data/lib/aquarium/aspects/{default_object_handler.rb → default_objects_handler.rb} +7 -6
- data/lib/aquarium/aspects/dsl/aspect_dsl.rb +2 -2
- data/lib/aquarium/aspects/pointcut.rb +190 -107
- data/lib/aquarium/finders/method_finder.rb +120 -34
- data/lib/aquarium/finders/type_finder.rb +2 -5
- data/lib/aquarium/utils.rb +1 -0
- data/lib/aquarium/utils/array_utils.rb +11 -3
- data/lib/aquarium/utils/options_utils.rb +74 -0
- data/lib/aquarium/utils/type_utils.rb +25 -11
- data/lib/aquarium/version.rb +1 -1
- data/spec/aquarium/aspects/advice_chain_node_spec.rb +1 -1
- data/spec/aquarium/aspects/advice_spec.rb +1 -1
- data/spec/aquarium/aspects/aspect_invocation_spec.rb +179 -145
- data/spec/aquarium/aspects/aspect_spec.rb +1 -1
- data/spec/aquarium/aspects/aspect_with_nested_types_spec.rb +1 -1
- data/spec/aquarium/aspects/aspect_with_subtypes_spec.rb +1 -1
- data/spec/aquarium/aspects/concurrent_aspects_spec.rb +1 -1
- data/spec/aquarium/aspects/concurrent_aspects_with_objects_and_types_spec.rb +1 -1
- data/spec/aquarium/aspects/default_objects_handler_spec.rb +147 -0
- data/spec/aquarium/aspects/dsl/aspect_dsl_spec.rb +72 -121
- data/spec/aquarium/aspects/join_point_spec.rb +1 -1
- data/spec/aquarium/aspects/pointcut_and_composition_spec.rb +1 -1
- data/spec/aquarium/aspects/pointcut_or_composition_spec.rb +48 -47
- data/spec/aquarium/aspects/pointcut_spec.rb +727 -410
- data/spec/aquarium/extensions/hash_spec.rb +1 -1
- data/spec/aquarium/extensions/regex_spec.rb +1 -1
- data/spec/aquarium/extensions/set_spec.rb +1 -1
- data/spec/aquarium/extensions/string_spec.rb +1 -1
- data/spec/aquarium/extensions/symbol_spec.rb +1 -1
- data/spec/aquarium/extras/design_by_contract_spec.rb +1 -1
- data/spec/aquarium/finders/finder_result_spec.rb +1 -1
- data/spec/aquarium/finders/method_finder_spec.rb +49 -16
- data/spec/aquarium/finders/type_finder_spec.rb +1 -1
- data/spec/aquarium/finders/type_finder_with_descendents_and_ancestors_spec.rb +16 -1
- data/spec/aquarium/utils/array_utils_spec.rb +31 -6
- data/spec/aquarium/utils/hash_utils_spec.rb +1 -1
- data/spec/aquarium/utils/html_escaper_spec.rb +1 -1
- data/spec/aquarium/utils/logic_error_spec.rb +1 -1
- data/spec/aquarium/utils/method_utils_spec.rb +1 -1
- data/spec/aquarium/utils/name_utils_spec.rb +1 -1
- data/spec/aquarium/utils/nil_object_spec.rb +1 -1
- data/spec/aquarium/utils/set_utils_spec.rb +1 -1
- data/spec/aquarium/utils/type_utils_spec.rb +1 -1
- 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? }
|
76
|
-
# p "<br/><br/>returning last_node: #{last_node.inspect .gsub(/\</,"<").gsub(/\>/,">")}"
|
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 =
|
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/
|
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
|
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
|
-
|
35
|
-
|
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
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
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
|
76
|
+
# Invoke the specified advice before the join point.
|
95
77
|
#
|
96
78
|
# <tt>:after</tt>::
|
97
|
-
# Invoke the specified advice
|
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
|
83
|
+
# Invoke the specified advice after the join point returns successfully.
|
102
84
|
#
|
103
|
-
# <tt>:after_raising</tt>::
|
104
|
-
# Invoke the specified advice
|
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>:
|
114
|
-
#
|
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
|
-
#
|
155
|
-
#
|
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
|
-
|
112
|
+
@first_option_that_was_method = []
|
113
|
+
opts = rationalize options
|
114
|
+
init_specification opts, canonical_options, &block
|
195
115
|
init_pointcuts
|
196
|
-
|
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
|
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
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
end
|
242
|
-
|
243
|
-
def
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
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
|
265
|
-
block || (@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?
|
200
|
+
if pointcut.kind_of? Pointcut
|
273
201
|
pointcuts << pointcut
|
274
|
-
elsif pointcut.kind_of?
|
275
|
-
pointcuts <<
|
202
|
+
elsif pointcut.kind_of? JoinPoint
|
203
|
+
pointcuts << Pointcut.new(:join_point => pointcut)
|
276
204
|
else # a hash of Pointcut.new options?
|
277
|
-
pointcuts <<
|
205
|
+
pointcuts << Pointcut.new(pointcut)
|
278
206
|
end
|
279
207
|
end
|
280
208
|
else
|
281
209
|
pc_options = {}
|
282
|
-
|
283
|
-
|
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 <<
|
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
|
-
|
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,
|
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,
|
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?
|
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
|
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 #{
|
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
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
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
|
-
|
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) && !
|
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
|