aquarium 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|