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
data/CHANGES CHANGED
@@ -1,3 +1,38 @@
1
+ == Version 0.3.0
2
+
3
+ V0.3.0 adds numerous improvements to the DSL, making aspect specification more intuitive and
4
+ English-like. For example, where you previously wrote, e.g.,
5
+
6
+ around :methods => :all, :types => [Foo, Bar], :advice => advice_proc
7
+ after :attribute => name, :attribute_options => [:readers], :objects => [foo, bar] ...
8
+
9
+ Now you can write the same aspects as follows:
10
+
11
+ around :calls_to => :all_methods, :within_types => [Foo, Bar], :use_advice => advice_proc
12
+ after :reading => name, :on_objects => [foo, bar] ...
13
+
14
+ Other improvements include performance and robustness enhancements and miscellaneous internal
15
+ refactoring and DRY improvements.
16
+
17
+ Bug fixes:
18
+ 16267 gem not updating
19
+
20
+ Enhancements:
21
+ 17154 More intuitive synonyms for specifying types, methods and attributes
22
+
23
+ For #17154, the following changes were made:
24
+ Added :all_methods as a synonym for the :all special value.
25
+ Added :reading as a synonym for :attributes => ..., :attribute_options => [:readers]
26
+ Added :writing and :changing as synonyms for :attributes => ..., :attribute_options => [:writers]
27
+ Added :accessing as a synonym for :attributes => ...
28
+ Added :calls_to, :calling, :invoking, :sending_message_to as synonyms for :methods.
29
+ Added :on_types, :in_types, :within_types and :for_types as synonyms for :types. The same
30
+ set of prefixes is supported for :type, :objects, :object, and the various :exclude_*,
31
+ :*_and_ancestors, and :*_and_descendents.
32
+
33
+ The full list of possible synonyms are shown in the spec examples. In particular, see "pointcut_spec.rb".
34
+
35
+
1
36
  == Version 0.2.0
2
37
 
3
38
  V0.2.0 changes the parameter list used for advice blocks and adds numerous enhancements, robustness
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2007 The Aquarium Development Team
1
+ Copyright (c) 2007-2008 The Aquarium Development Team
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README CHANGED
@@ -56,12 +56,12 @@ Many of AspectJ's behaviors that aren't currently supported are planned for futu
56
56
 
57
57
  Several complete examples are provided in the "examples" directory.
58
58
 
59
- In most cases, you can either declare the appropriate classes or use the optional DSL, which adds convenience methods to classes, objects, or even Object itself.
59
+ In most cases, you can either declare the appropriate classes or use the optional DSL, which adds convenience methods to classes, objects, or even Object itself. The API also supports many synonyms for things like types, objects, and methods. The best place to see the full list of synonyms is the output of "pointcut_spec.rb".
60
60
 
61
61
  Here is an example that traces invocations of all public instance methods (included inherited ones) of the classes or modules Foo and Bar.
62
62
 
63
63
  require 'aquarium'
64
- Aspect.new :around, :types => [Foo, Bar], :methods => :all do |join_point, object, *args|
64
+ Aspect.new :around, :calls_to => :all_methods, :on_types => [Foo, Bar] do |join_point, object, *args|
65
65
  p "Entering: #{join_point.target_type.name}##{join_point.method_name} for object #{object}"
66
66
  result = join_point.proceed
67
67
  p "Leaving: #{join_point.target_type.name}##{join_point.method_name} for object #{object}"
@@ -71,7 +71,7 @@ Here is an example that traces invocations of all public instance methods (inclu
71
71
  The advice to execute at each join point is the block. The pointcut is the set of all public instance methods in Foo and Bar. (There are additional options available for specifying class methods, protected methods, excluding inherited (ancestor) methods, etc.) Here is the same example using the convenience DSL that adds aspect methods to Object (available only if you require aquarium/aspects/dsl/object_dsl', since other toolkits, like Rails, define similar methods on Object!).
72
72
 
73
73
  require 'aquarium/aspects/dsl/object_dsl'
74
- around :types => [Foo, Bar], :methods => :all do |join_point, object, *args|
74
+ around :calls_to => :all_methods, :on_types => [Foo, Bar] do |join_point, object, *args|
75
75
  p "Entering: #{join_point.target_type.name}##{join_point.method_name} for object #{object}"
76
76
  result = join_point.proceed
77
77
  p "Leaving: #{join_point.target_type.name}##{join_point.method_name} for object #{object}"
@@ -118,11 +118,11 @@ It is important to note that aspect "instances" usually behave like class (stati
118
118
 
119
119
  A common mistake is to create an aspect in an initialize method and assign it to an attribute. This usually means that you are creating long-lived, redundant aspects every time an instance of your class is created. The aspect modifications remain in effect even when the instances themselves are garbage collected!
120
120
 
121
- Here are some more succinct examples, illustrating the API (using the DSL methods).
121
+ Here are some more succinct examples, illustrating the API (using the DSL methods) and some of the various synonyms for methods, types, etc.
122
122
 
123
123
  You can pass in pointcuts defined elsewhere:
124
124
 
125
- my_pointcut = Pointcut.new :types => /Foo::Bar::/, :methods => /^do_/
125
+ my_pointcut = Pointcut.new :invocations_of => /^do_/, :within_types => /Foo::Bar::/
126
126
  around :pointcuts => my_pointcut do |jp, obj, *args| ... # Pass in a pointcut
127
127
  around :pointcuts => [my_pointcut, ...] do |jp, obj, *args| ... # Pass in a pointcut array
128
128
 
@@ -133,7 +133,7 @@ my_join_point2 = JoinPoint.new :type => Foo::Bar, :method => do_that
133
133
  around :pointcuts => my_join_point1 do |jp, obj, *args| ...
134
134
  around :pointcuts => [my_join_point1, my_join_point2, ...] do |jp, obj, *args| ...
135
135
 
136
- You can specify a single type, a type name, a type regular expression, or an array of the same. Note that :type and :types are synonymous "sugar".
136
+ You can specify a single type, a type name, a type regular expression, or an array of the same. Note that :type and :types are synonymous. Use the singular form for better readability when you are specifying just one type. Other synonyms include :on_types, :within_types, and :in_types, plus the singular forms.
137
137
 
138
138
  around :type = A, ...
139
139
  around :type = "A", ...
@@ -141,22 +141,41 @@ You can specify a single type, a type name, a type regular expression, or an arr
141
141
  around :types => %w[A, B, ...], ...
142
142
  around :types => /A::.*Helper$/, ...
143
143
  around :types => [/A::.*Helper$/, /B::Foo.*/], ...
144
-
145
- You can specify types and their descendents (subclasses or included modules) or ancestors.
144
+
145
+ Using the plural versions of the synonyms, with method specifications so they read better:
146
+
147
+ around :calls_to => :all_methods, :on_types => [A, B, ...], ...
148
+ around :calls_to => :all_methods, :in_types => [A, B, ...], ...
149
+ around :calls_to => :all_methods, :within_types => [A, B, ...], ...
150
+
151
+ You can specify types and their descendents (subclasses or included modules) or ancestors. The same synonym prefixes for :types and :type also apply.
146
152
 
147
153
  around :type_and_ancestors = A, ...
148
154
  around :types_and_ancestors = A, ...
149
155
  around :type_and_descendents = A, ...
150
156
  around :types_and_descendents = A, ...
157
+
158
+ Some of the synonyms:
159
+
160
+ around :calls_to => :all_methods, :on_types_and_ancestors = A, ...
161
+ around :calls_to => :all_methods, :in_types_and_ancestors = A, ...
162
+ around :calls_to => :all_methods, :within_types_and_ancestors = A, ...
163
+ and similarly for descendents
151
164
 
152
- You can specify a single object or an array of objects. Note that :object and :objects are synonymous.
165
+ You can specify a single object or an array of objects. As for :types, you can use :object, :objects, :on_objects, :within_object, :in_objects, and the singular forms synonymously.
153
166
 
154
167
  a1 = A.new
155
168
  a2 = A.new
156
169
  around :object = a1, ...
157
170
  around :objects => [a1, a2], ...
158
171
 
159
- If no types or objects are specified, the object defaults to "self". However, this default is only supported when using the DSL to create an aspect!
172
+ Some of the synonyms:
173
+
174
+ around :calls_to => :all_methods, :on_objects = [a1, a2], ...
175
+ around :calls_to => :all_methods, :in_objects = [a1, a2], ...
176
+ around :calls_to => :all_methods, :within_objects = [a1, a2], ...
177
+
178
+ If no types or objects are specified, the object defaults to "self". However, this default is only supported when using the DSL to create an aspect, e.g.,
160
179
 
161
180
  class MyClass
162
181
  include Aquarium::Aspects::DSL::AspectDSL
@@ -165,15 +184,23 @@ If no types or objects are specified, the object defaults to "self". However, th
165
184
  around :method => doit, ... # Implicit :object => self, i.e., MyClass
166
185
  end
167
186
 
168
- You can specify a single method symbol (name), a regular expression, or an array of the same. Note that :method and :methods are synonymous. The special keyword :all means match all methods, subject to the :method_options discussed next.
187
+ You can specify a single method symbol (name), a regular expression, or an array of the same. The synonyms for :methods include :method, :calls_to, :invoking, :invocations_of, and :sending_messages_to. The special keywords :all and :all_methods mean match all methods, subject to the :method_options discussed next.
169
188
 
170
- around :method = :all, ...
189
+ around :method = :all_methods, ...
171
190
  around :method = :foo, ...
172
191
  around :methods = [:foo, :bar, :baz], ...
173
192
  around :methods = /^foo/, ...
174
193
  around :methods = [/^foo/, /bar$/], ...
175
194
 
176
- You can specify method options. By default, public instance methods only are matched. Note that :methods => :all with no method options matches all public instance methods, including ancestor (inherited and included module) methods.
195
+ Using the synonyms:
196
+
197
+ around :calls_to = :all_methods, ...
198
+ after :invoking = :all_methods, ...
199
+ after :invocations_of = :all_methods, ...
200
+ after :sending_messages_to = :all_methods, ...
201
+ after :within_methods = :all_methods, ...
202
+
203
+ You can specify method options. By default, public instance methods only are matched. Note that :methods => :all or :all_methods with no method options matches all public instance methods, including ancestor (inherited and included module) methods. For all the method options (except for :exclude_ancestor_methods), you can append the suffix "_methods". You can also use the :restrict_methods_to synonym for :method_options.
177
204
 
178
205
  around :methods = /foo/, :method_options => [:instance], ... # match instance methods (default)
179
206
  around :methods = /foo/, :method_options => [:class], ... # match class methods
@@ -183,12 +210,23 @@ You can specify method options. By default, public instance methods only are mat
183
210
  around :methods = /foo/, :method_options => [:exclude_ancestor_methods], ...
184
211
  # ignore methods defined in ancestors, inherited classes and included modules
185
212
 
186
- You can specify attributes, which are actually convenience methods for the attribute accessors. They work
187
- very much like the :method options. Note that :all is NOT supported in this case and :attribute and :attributes are synonymous.
213
+ With synonyms:
214
+
215
+ around :calls_to = /foo/, :restricting_methods_to => [:singleton_methods], ...
216
+
217
+ You can specify attributes, which are actually convenience methods for the attribute accessors. They work very much like the :method options. Note that :all is NOT supported in this case. The available synonyms are slightly more complicated, as shown in these examples.
218
+
219
+ around :attribute = :foo, ... # defaults to methods #foo and #foo=
220
+ around :attributes = :foo, ... # the same
221
+ around :accessing = :foo, ... # the same
188
222
 
189
- around :attribute = :foo, ... # defaults to methods #foo and #foo=
190
223
  around :attribute = :foo, :attribute_options => [:readers]... # only matches #foo
224
+ around :reading = :foo # the same
225
+
226
+
191
227
  around :attribute = :foo, :attribute_options => [:writers]... # only matches #foo=
228
+ around :writing = :foo # the same
229
+
192
230
  around :attributes = [:foo, :bar, :baz], ...
193
231
  around :attributes = /^foo/, ...
194
232
  around :attributes = [/^foo/, /bar$/], ...
@@ -201,9 +239,14 @@ You can specify a "Pointcut" that encapsulates one or more pre-defined Pointcuts
201
239
  around :pointcuts = [jp, ...], ... # for pre-defined join point list
202
240
  around :pointcut = {:type => T, :method => :m}, ... # same as around :type => T, :method => :m, ..
203
241
 
204
- With release V0.1.8, you can specifically exclude particular pointcuts, join points, types, objects, methods, or attributes. This is useful when you specify a list or regular expression of "items" to match and you want to exclude some of the items.
205
- Note that there is an open bug (#15202) that appears to affect advising types, unadvising the types, then advising objects
206
- of the same types. (This is not likely to happen a lot in real applications, but it shows up when running specs.)
242
+ Using the plural versions of the synonyms, with method specifications so they read better:
243
+
244
+ around :on_pointcuts => [pc1, pc2, ...], ...
245
+ around :in_pointcuts => [pc1, pc2, ...], ...
246
+ around :within_pointcuts => [pc1, pc2, ...], ...
247
+
248
+ You can specifically exclude particular pointcuts, join points, types, objects, methods, or attributes. This is useful when you specify a list or regular expression of "items" to match and you want to exclude some of the items.
249
+ Note that there is an open bug (#15202) that appears to affect advising types, unadvising the types, then advising objects of the same types. (This is not likely to happen a lot in real applications, but it shows up when running Aquarium's specs.)
207
250
 
208
251
  around ..., :exclude_pointcut = pc, ...
209
252
  around ..., :exclude_pointcuts = [pc, ...]
@@ -222,6 +265,8 @@ of the same types. (This is not likely to happen a lot in real applications, but
222
265
  around ..., :exclude_attribute = a, ...
223
266
  around ..., :exclude_attributes = [a, ...]
224
267
 
268
+ All the same synonyms for :types, :objects, and :methods apply here as well (after the "exclude_" prefix).
269
+
225
270
  You can advice methods before execution:
226
271
 
227
272
  before :types => ...
@@ -258,7 +303,7 @@ If you pass a block to Aspect.new, it will be the advice. When invoked, the advi
258
303
  1) the JoinPoint, which will contain a JoinPoint::Context object with useful context information,
259
304
  2) the object being sent the current message, and
260
305
  3) the parameters passed with the original message.
261
- Recall that Proc don't check the number of arguments (while lambdas do), so if you don't care about any trailing parameters, you can leave them out of the parameter list. Recall that the other difference between the two is that a return statement in a Proc returns from the method that contains it. As rule, do NOT use return statements in advices!
306
+ Recall that a Proc doesn't check the number of arguments (while lambdas do), so if you don't care about any of the trailing parameters, you can leave them out of the parameter list. Recall that the other difference between the two is that a return statement in a Proc returns from the method that contains it. As rule, do NOT use return statements in advices!
262
307
 
263
308
  around :type => [...], :methods => :all do |join_point, object, *args|
264
309
  advice_to_execute_before_the_jp
@@ -279,6 +324,7 @@ Rather than passing a block as the advice, you can pass a previously-created Pro
279
324
  around :type => [...], :methods => :all, :call => advice # synonym for advice.
280
325
  around :type => [...], :methods => :all, :invoke => advice # synonym for advice.
281
326
 
327
+
282
328
  === Packages
283
329
 
284
330
  Aquarium::Aspects contains the Aspect class and supporting classes Pointcut, JoinPoint, etc.
data/Rakefile CHANGED
@@ -87,7 +87,7 @@ aquarium = Gem::Specification.new do |s|
87
87
  s.bindir = 'bin'
88
88
  s.executables = []
89
89
  s.default_executable = ''
90
- s.author = ["Aquarium Development Team"]
90
+ s.authors = ["Aquarium Development Team"]
91
91
  s.email = "aquarium-devel@rubyforge.org"
92
92
  s.homepage = "http://aquarium.rubyforge.org"
93
93
  s.rubyforge_project = "aquarium"
data/UPGRADE CHANGED
@@ -1,3 +1,8 @@
1
+ == Upgrading to Aquarium-0.3.0
2
+
3
+ There are no known upgrade issues with this release. Although many new synonyms were added for API method
4
+ parameters, all changes are backwards compatible.
5
+
1
6
  == Upgrading to Aquarium-0.2.0
2
7
 
3
8
  This release changes the expected advice parameter list from |join_point, *method_args| to
@@ -19,14 +19,15 @@ module Aquarium
19
19
  end
20
20
  attr_accessor :state
21
21
 
22
- # A simpler version of the following pointcut would be
22
+ # Two alternative versions of the following pointcut would be
23
23
  # STATE_CHANGE = pointcut :method => :state=
24
- # Note that the :attribute_options => :writer option is important, especially
24
+ # STATE_CHANGE = pointcut :attribute => :state, :attribute_options => [:writers]
25
+ # Note that only matching on the attribute writers is important, especially
25
26
  # given the advice block below, because if the reader is allowed to be advised,
26
27
  # we get an infinite recursion of advice invocation! The correct solution is
27
28
  # the planned extension of the pointcut language to support condition tests for
28
- # context. I.e., we don't want the advice applied when it's already inside advice!
29
- STATE_CHANGE = pointcut :attribute => :state, :attribute_options => :writer
29
+ # context. I.e., we don't want the advice applied when it's already inside advice.
30
+ STATE_CHANGE = pointcut :writing => :state
30
31
  end
31
32
  end
32
33
 
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../spec/aquarium/spec_helper.rb'
1
+ require File.dirname(__FILE__) + '/../spec/aquarium/spec_helper'
2
2
  require 'aquarium'
3
3
 
4
4
  # Example demonstrating emerging ideas about good aspect-oriented design. Specifically, this
@@ -17,14 +17,15 @@ module Aquarium
17
17
  end
18
18
  attr_accessor :state
19
19
 
20
- # A simpler version of the following pointcut would be
20
+ # Two alternative versions of the following pointcut would be
21
21
  # STATE_CHANGE = pointcut :method => :state=
22
- # Note that the :attribute_options => :writer option is important, especially
22
+ # STATE_CHANGE = pointcut :attribute => :state, :attribute_options => [:writers]
23
+ # Note that only matching on the attribute writers is important, especially
23
24
  # given the advice block below, because if the reader is allowed to be advised,
24
25
  # we get an infinite recursion of advice invocation! The correct solution is
25
26
  # the planned extension of the pointcut language to support condition tests for
26
- # context. I.e., we don't want the advice applied when it's already inside advice!
27
- STATE_CHANGE = pointcut :attribute => :state, :attribute_options => :writer
27
+ # context. I.e., we don't want the advice applied when it's already inside advice.
28
+ STATE_CHANGE = pointcut :writing => :state
28
29
  end
29
30
  end
30
31
 
@@ -15,7 +15,7 @@ module Aquarium
15
15
  p "inside :action"
16
16
  end
17
17
 
18
- precondition :method => :action, :message => "Must pass more than one argument." do |jp, obj, *args|
18
+ precondition :calls_to => :action, :message => "Must pass more than one argument." do |jp, obj, *args|
19
19
  args.size > 0
20
20
  end
21
21
  end
@@ -36,7 +36,7 @@ module Aquarium
36
36
  p "inside :action"
37
37
  end
38
38
 
39
- postcondition :method => :action,
39
+ postcondition :calls_to => :action,
40
40
  :message => "Must pass more than one argument and first argument must be non-empty." do |jp, obj, *args|
41
41
  args.size > 0 && ! args[0].empty?
42
42
  end
@@ -71,7 +71,7 @@ module Aquarium
71
71
  @invar = 1
72
72
  end
73
73
 
74
- invariant :methods => /action$/, :message => "Must not change the @invar value." do |jp, obj, *args|
74
+ invariant :calls_to => /action$/, :message => "Must not change the @invar value." do |jp, obj, *args|
75
75
  obj.invar == 0
76
76
  end
77
77
  end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../spec/aquarium/spec_helper.rb'
1
+ require File.dirname(__FILE__) + '/../spec/aquarium/spec_helper'
2
2
  require 'aquarium'
3
3
  require 'aquarium/extras/design_by_contract'
4
4
 
@@ -16,7 +16,7 @@ module Aquarium
16
16
  end
17
17
  attr_reader :state
18
18
 
19
- precondition :method => :action, :message => "Must pass more than one argument." do |jp, obj, *args|
19
+ precondition :calls_to => :action, :message => "Must pass more than one argument." do |jp, obj, *args|
20
20
  args.size > 0
21
21
  end
22
22
  end
@@ -41,7 +41,7 @@ module Aquarium
41
41
  end
42
42
  attr_reader :state
43
43
 
44
- postcondition :method => :action,
44
+ postcondition :calls_to => :action,
45
45
  :message => "Must pass more than one argument and first argument must be non-empty." do |jp, obj, *args|
46
46
  args.size > 0 && ! args[0].empty?
47
47
  end
@@ -73,7 +73,7 @@ module Aquarium
73
73
  @invar = 1
74
74
  end
75
75
 
76
- invariant :methods => /action$/, :message => "Must not change the @invar value." do |jp, obj, *args|
76
+ invariant :calls_to => /action$/, :message => "Must not change the @invar value." do |jp, obj, *args|
77
77
  obj.invar == 0
78
78
  end
79
79
  end
@@ -31,7 +31,7 @@ echo1.say "hello", "world!"
31
31
  echo1.log "something", "interesting..."
32
32
  echo1.shout "theater", "in", "a", "crowded", "firehouse!"
33
33
 
34
- Aquarium::Aspects::Aspect.new :around, :type => Aquarium::Echo, :method => :method_missing do |join_point, obj, sym, *args|
34
+ Aquarium::Aspects::Aspect.new :around, :calls_to => :method_missing, :for_type => Aquarium::Echo, do |join_point, obj, sym, *args|
35
35
  if sym == :log
36
36
  p "--- Sending to log: #{args.join(" ")}"
37
37
  else
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../spec/aquarium/spec_helper.rb'
1
+ require File.dirname(__FILE__) + '/../spec/aquarium/spec_helper'
2
2
  require 'aquarium'
3
3
 
4
4
  # Example demonstrating "around" advice for method_missing. This is a technique for
@@ -42,7 +42,7 @@ end
42
42
  describe "An example of a class' method_missing with around advice" do
43
43
  it "should only handle invocations not processed by the around advice." do
44
44
  @intercepted_message = nil
45
- aspect = Aquarium::Aspects::Aspect.new :around, :type => Aquarium::Echo, :method => :method_missing do |join_point, obj, sym, *args|
45
+ aspect = Aquarium::Aspects::Aspect.new :around, :calls_to => :method_missing, :for_type => Aquarium::Echo do |join_point, obj, sym, *args|
46
46
  if sym == :log
47
47
  @intercepted_message = "log: #{args.join(" ")}"
48
48
  else
@@ -38,7 +38,7 @@ bar1.do_something_else :b3, :b4
38
38
 
39
39
  include Aquarium::Aspects
40
40
 
41
- Aspect.new :around, :types => [Aquarium::Foo, Aquarium::Bar], :methods => :all,
41
+ Aspect.new :around, :calls_to => :all_methods, :for_types => [Aquarium::Foo, Aquarium::Bar],
42
42
  :method_options => :exclude_ancestor_methods do |execution_point, obj, *args|
43
43
  begin
44
44
  p "Entering: #{execution_point.target_type.name}##{execution_point.method_name}: args = #{args.inspect}"
@@ -57,8 +57,8 @@ bar1.do_something_else :b7, :b8
57
57
 
58
58
  # The "begin/ensure/end" idiom shown causes the advice to return the correct value; the result
59
59
  # of the "proceed", rather than the value returned by "p"!
60
- Aspect.new :around, :types => [Aquarium::Foo, Aquarium::Bar], :methods => :initialize,
61
- :method_options => :private do |execution_point, obj, *args|
60
+ Aspect.new :around, :invocations_of => :initialize, :for_types => [Aquarium::Foo, Aquarium::Bar],
61
+ :restricting_methods_to => :private_methods do |execution_point, obj, *args|
62
62
  begin
63
63
  p "Entering: #{execution_point.target_type.name}##{execution_point.method_name}: args = #{args.inspect}"
64
64
  execution_point.proceed
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../spec/aquarium/spec_helper.rb'
1
+ require File.dirname(__FILE__) + '/../spec/aquarium/spec_helper'
2
2
  require 'aquarium'
3
3
 
4
4
  # Example demonstrating "around" advice that traces calls to all methods in
@@ -57,7 +57,7 @@ describe "An example with advice on the public instance methods (excluding ances
57
57
  # The "begin/ensure/end" idiom shown causes the advice to return the correct value; the result
58
58
  # of the "proceed", rather than the value returned by "p"!
59
59
  aspect = Aquarium::Aspects::Aspect.new :around,
60
- :type => Aquarium::Foo, :methods => :all, :method_options => :exclude_ancestor_methods do |execution_point, obj, *args|
60
+ :invocations_of => :all_methods, :for_type => Aquarium::Foo, :restricting_methods_to => :exclude_ancestor_methods do |execution_point, obj, *args|
61
61
  begin
62
62
  obj.log "Entering: #{execution_point.target_type.name}##{execution_point.method_name}: args = #{args.inspect}"
63
63
  execution_point.proceed
@@ -80,7 +80,7 @@ end
80
80
  describe "An example with advice on the public instance methods (excluding ancestor methods) of Bar" do
81
81
  it "should not trace any calls to the public methods defined by the included BarModule" do
82
82
  aspect = Aquarium::Aspects::Aspect.new :around,
83
- :type => Aquarium::Bar, :methods => :all, :method_options => :exclude_ancestor_methods do |execution_point, obj, *args|
83
+ :invocations_of => :all_methods, :for_type => Aquarium::Bar, :restricting_methods_to => :exclude_ancestor_methods do |execution_point, obj, *args|
84
84
  begin
85
85
  obj.log "Entering: #{execution_point.target_type.name}##{execution_point.method_name}: args = #{args.inspect}"
86
86
  execution_point.proceed
@@ -99,7 +99,7 @@ end
99
99
  describe "An example with advice on the public instance methods (including ancestor methods) of Bar" do
100
100
  it "should trace all calls to the public methods defined by the included BarModule" do
101
101
  aspect = Aquarium::Aspects::Aspect.new :around,
102
- :type => Aquarium::Bar, :methods => /^do_/ do |execution_point, obj, *args|
102
+ :calls_to_methods_matching => /^do_/, :for_type => Aquarium::Bar do |execution_point, obj, *args|
103
103
  begin
104
104
  obj.log "Entering: #{execution_point.target_type.name}##{execution_point.method_name}: args = #{args.inspect}"
105
105
  execution_point.proceed
@@ -123,8 +123,8 @@ end
123
123
  describe "An example with advice on the private initialize method of Foo and Bar" do
124
124
  it "should trace all calls to initialize" do
125
125
  before_methods = Aquarium::Foo.private_instance_methods.sort #- Object.private_methods.sort
126
- aspect = Aquarium::Aspects::Aspect.new :around,
127
- :types => [Aquarium::Foo, Aquarium::Bar], :methods => :initialize, :method_options => :private do |execution_point, obj, *args|
126
+ aspect = Aquarium::Aspects::Aspect.new :around, :calls_to => :initialize, :for_types => [Aquarium::Foo, Aquarium::Bar],
127
+ :restricting_methods_to => :private_methods do |execution_point, obj, *args|
128
128
  begin
129
129
  obj.log "Entering: #{execution_point.target_type.name}##{execution_point.method_name}: args = #{args.inspect}"
130
130
  execution_point.proceed