aquarium 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Aquarium.ipr +253 -0
- data/Aquarium.iws +629 -0
- data/CHANGES +43 -0
- data/UPGRADE +13 -7
- data/examples/method_tracing_example_spec.rb +4 -1
- data/lib/aquarium/aspects/aspect.rb +28 -11
- data/lib/aquarium/aspects/exclusion_handler.rb +1 -1
- data/lib/aquarium/aspects/join_point.rb +58 -14
- data/lib/aquarium/aspects/pointcut.rb +5 -6
- data/lib/aquarium/extras/design_by_contract.rb +1 -1
- data/lib/aquarium/finders/method_finder.rb +1 -4
- data/lib/aquarium/finders/type_finder.rb +8 -1
- data/lib/aquarium/utils.rb +1 -0
- data/lib/aquarium/utils/default_logger.rb +20 -0
- data/lib/aquarium/utils/options_utils.rb +74 -12
- data/lib/aquarium/utils/type_utils.rb +1 -7
- 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 +1531 -1465
- data/spec/aquarium/aspects/aspect_spec.rb +22 -27
- 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/dsl/aspect_dsl_spec.rb +434 -424
- data/spec/aquarium/aspects/join_point_spec.rb +27 -4
- data/spec/aquarium/aspects/pointcut_and_composition_spec.rb +98 -102
- data/spec/aquarium/aspects/pointcut_or_composition_spec.rb +95 -107
- data/spec/aquarium/aspects/pointcut_spec.rb +1365 -1382
- data/spec/aquarium/extensions/hash_spec.rb +1 -1
- data/spec/aquarium/extensions/set_spec.rb +1 -1
- data/spec/aquarium/finders/finder_result_spec.rb +1 -1
- data/spec/aquarium/finders/method_finder_spec.rb +1 -1
- data/spec/aquarium/finders/type_finder_with_descendents_and_ancestors_spec.rb +63 -145
- data/spec/aquarium/{spec_example_classes.rb → spec_example_types.rb} +35 -0
- data/spec/aquarium/utils/default_logger_spec.rb +28 -0
- data/spec/aquarium/utils/hash_utils_spec.rb +1 -1
- data/spec/aquarium/utils/logic_error_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/options_utils_spec.rb +122 -0
- data/spec/aquarium/utils/set_utils_spec.rb +1 -1
- metadata +9 -4
data/CHANGES
CHANGED
@@ -1,3 +1,46 @@
|
|
1
|
+
== Version 0.3.1
|
2
|
+
|
3
|
+
V0.3.1 adds numerous performance improvements, especially in the RSpec suite, and some minor API additions.
|
4
|
+
|
5
|
+
Bug fixes:
|
6
|
+
N.A.
|
7
|
+
|
8
|
+
Enhancements:
|
9
|
+
14447 Unify internal handling of reporting errors to the user
|
10
|
+
17514 Provide an Aquarium library-wide logger with configuration parameters and instance overrides
|
11
|
+
17515 Add an optional warning if an aspect doesn't match any join points
|
12
|
+
17516 Remove unnecessary examples that use :types_and_descendents to shorten time to run the RSpec suite
|
13
|
+
17565 JoinPoint.new should convert a type name, symbol, or regex to the type and only allow one type
|
14
|
+
|
15
|
+
These first two enhancements are related. There is a now an Aquarium::Utils::DefaultLogger
|
16
|
+
module with static accessors for getting and setting the "system-wide" logger.
|
17
|
+
|
18
|
+
When instance-level overrides are necessary, the Aquarium::Utils::OptionsUtils provides
|
19
|
+
"universal" options (but currently used only by Aspect and Pointcut) for specifying a logger
|
20
|
+
(with the new :logger parameter), or alternatively, specifying just the output stream
|
21
|
+
(:logger_stream) and/or the severity (:severity, one of the standard library's
|
22
|
+
Logger::Severity-defined constants). If either of the latter two options is specified, a
|
23
|
+
separate logger instance is created, rather than changing parameters for the global logger.
|
24
|
+
|
25
|
+
OptionsUtils also supports a :noop parameter, which classes interpret to mean do none (or
|
26
|
+
perhaps only some) of the processing. Useful for debugging.
|
27
|
+
|
28
|
+
#17515 adds a helpful warning to the system (or aspect-instance's) logger if an aspect
|
29
|
+
matches no join points. This warning will be suppressed if (i) the severity level for the
|
30
|
+
logger is above WARN or (ii) the aspect was created with the option
|
31
|
+
:ignore_no_matching_join_points => true.
|
32
|
+
|
33
|
+
#17516 fixes halved the long execution times for the whole RSpec suite by refactoring some examples
|
34
|
+
that used type finders with the :types_and_descendents option unnecessarily. It is a very intensive
|
35
|
+
computation! Note that I stubbed out these calls using an aspect with around advise, a useful
|
36
|
+
"development-time" aspect. See Aquarium::TypeUtilsStub (in spec_example_types.rb) and how it's used
|
37
|
+
in pointcut_spec.rb. Using this technique and other optimizations, the time to run the suite was
|
38
|
+
reduced from ~5 minutes to about 1 minute.
|
39
|
+
|
40
|
+
#17565 fixes a "hole" in JoinPoint, where it doesn't confirm that a specified type string, symbol
|
41
|
+
or regex matches a class that exists and only one class. Now it does and it stores the type, rather
|
42
|
+
than the original "specification" for it.
|
43
|
+
|
1
44
|
== Version 0.3.0
|
2
45
|
|
3
46
|
V0.3.0 adds numerous improvements to the DSL, making aspect specification more intuitive and
|
data/UPGRADE
CHANGED
@@ -1,9 +1,15 @@
|
|
1
|
-
==
|
1
|
+
== Updating to Aquarium-0.3.1
|
2
|
+
|
3
|
+
There should be no upgrade issues with this release. However, the enhancement #17565 now ensures that a
|
4
|
+
JoinPoint is only specified with one type and a type that actually exists, when a string, symbol, or
|
5
|
+
regex is used to specify the type.
|
6
|
+
|
7
|
+
== Updating to Aquarium-0.3.0
|
2
8
|
|
3
9
|
There are no known upgrade issues with this release. Although many new synonyms were added for API method
|
4
10
|
parameters, all changes are backwards compatible.
|
5
11
|
|
6
|
-
==
|
12
|
+
== Updating to Aquarium-0.2.0
|
7
13
|
|
8
14
|
This release changes the expected advice parameter list from |join_point, *method_args| to
|
9
15
|
|join_point, object, *method_args|, where "object" is the current object receiving the message
|
@@ -14,22 +20,22 @@ Aquarium will raise an exception if the advice block or proc has this obsolete s
|
|
14
20
|
|
15
21
|
Note that "JoinPoint#Context.advised_object" is still supported, even if it is now less useful.
|
16
22
|
|
17
|
-
==
|
23
|
+
== Updating to Aquarium-0.1.8
|
18
24
|
|
19
25
|
V0.1.7 did not successfully "register" at rubyforge. This releases fixes that problem and also adds
|
20
26
|
several feature enhancements and refactorings. There are no known upgrade issues.
|
21
27
|
|
22
|
-
==
|
28
|
+
== Updating to Aquarium-0.1.7
|
23
29
|
|
24
30
|
This is primarily a bug-fix release, so there should be no upgrading or incompatibility issues.
|
25
31
|
|
26
|
-
==
|
32
|
+
== Updating to Aquarium-0.1.6
|
27
33
|
|
28
34
|
As described in the CHANGES, the JoinPoint#type, JoinPoint#type=, JoinPoint#object, and JoinPoint#object=
|
29
35
|
are now deprecated. Client code that uses these methods will still work, but warning messages will be
|
30
36
|
written to STDOUT. See CHANGES for more details.
|
31
37
|
|
32
|
-
==
|
38
|
+
== Updating to Aquarium-0.1.5
|
33
39
|
|
34
40
|
This is mostly a bug-fix release, but it did have to introduce one API change, as described in the
|
35
41
|
CHANGES. In particular, the aspect "DSL" methods are no longer automatically to Object, as some of
|
@@ -69,6 +75,6 @@ object.extend(Aquarium::Aspects::DSL::AspectDSL)
|
|
69
75
|
|
70
76
|
See the CHANGES for more details.
|
71
77
|
|
72
|
-
==
|
78
|
+
== Updating existing code to Aquarium-0.1.0
|
73
79
|
|
74
80
|
This is the first release of Aquarium.
|
@@ -79,8 +79,11 @@ end
|
|
79
79
|
|
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
|
+
# Suppress warnings about no join points matched with :ignore_no_matching_join_points => true
|
82
83
|
aspect = Aquarium::Aspects::Aspect.new :around,
|
83
|
-
:invocations_of => :all_methods, :for_type => Aquarium::Bar,
|
84
|
+
:invocations_of => :all_methods, :for_type => Aquarium::Bar,
|
85
|
+
:restricting_methods_to => :exclude_ancestor_methods,
|
86
|
+
:ignore_no_matching_join_points => true do |execution_point, obj, *args|
|
84
87
|
begin
|
85
88
|
obj.log "Entering: #{execution_point.target_type.name}##{execution_point.method_name}: args = #{args.inspect}"
|
86
89
|
execution_point.proceed
|
@@ -35,7 +35,8 @@ module Aquarium
|
|
35
35
|
CANONICAL_OPTIONS = Pointcut::CANONICAL_OPTIONS.merge({
|
36
36
|
"advice" => %w[action do_action use_advice advise_with invoke call],
|
37
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]
|
38
|
+
"exclude_pointcuts" => %w[exclude_pointcut exclude_on_pointcut exclude_on_pointcuts exclude_within_pointcut exclude_within_pointcuts],
|
39
|
+
"ignore_no_matching_join_points" => %[ignore_no_jps]
|
39
40
|
})
|
40
41
|
|
41
42
|
ALL_ALLOWED_OPTIONS = CANONICAL_OPTIONS.keys.inject([]) {|ary,i| ary << i << CANONICAL_OPTIONS[i]}.flatten +
|
@@ -103,15 +104,18 @@ module Aquarium
|
|
103
104
|
# One or an array of Pointcut or JoinPoint objects. Mutually-exclusive with the :types, :objects,
|
104
105
|
# :methods, :attributes, :method_options, and :attribute_options parameters.
|
105
106
|
#
|
106
|
-
# <tt>:
|
107
|
-
#
|
107
|
+
# <tt>:ignore_no_matching_join_points => true | false</tt>
|
108
|
+
# <tt>ignore_no_jps => true | false</tt>::
|
109
|
+
# Do not issue a warning if no join points are actually matched by the aspect. By default, the value
|
110
|
+
# is false, meaning that a WARN-level message will be written to the log. It is usually very helpful
|
111
|
+
# to be warned when no matches occurred, for diagnostic purposes!
|
108
112
|
#
|
109
|
-
#
|
110
|
-
# :methods, etc.
|
113
|
+
# Aspect.new also accepts all the same options that Pointcut accepts, including the synonyms for :types,
|
114
|
+
# :methods, etc. It also accepts the "universal" options documented in OptionsUtils.
|
111
115
|
def initialize *options, &block
|
112
116
|
@first_option_that_was_method = []
|
113
117
|
opts = rationalize options
|
114
|
-
init_specification opts,
|
118
|
+
init_specification opts, CANONICAL_OPTIONS, &block
|
115
119
|
init_pointcuts
|
116
120
|
validate_specification
|
117
121
|
return if noop
|
@@ -126,9 +130,6 @@ module Aquarium
|
|
126
130
|
get_jps :join_points_not_matched
|
127
131
|
end
|
128
132
|
|
129
|
-
def canonical_options
|
130
|
-
CANONICAL_OPTIONS
|
131
|
-
end
|
132
133
|
def all_allowed_option_symbols
|
133
134
|
ALL_ALLOWED_OPTION_SYMBOLS + @first_option_that_was_method
|
134
135
|
end
|
@@ -213,8 +214,25 @@ module Aquarium
|
|
213
214
|
pointcuts << Pointcut.new(pc_options)
|
214
215
|
end
|
215
216
|
@pointcuts = Set.new(remove_excluded_join_points_and_empty_pointcuts(pointcuts))
|
217
|
+
warn_if_no_join_points_matched
|
216
218
|
end
|
217
219
|
|
220
|
+
def warn_if_no_join_points_matched
|
221
|
+
return unless should_warn_if_no_matching_join_points
|
222
|
+
@pointcuts.each do |pc|
|
223
|
+
if pc.join_points_matched.size > 0
|
224
|
+
return
|
225
|
+
end
|
226
|
+
end
|
227
|
+
logger.warn "Warning: No join points were matched. The options specified were #{@original_options.inspect}"
|
228
|
+
end
|
229
|
+
|
230
|
+
def should_warn_if_no_matching_join_points
|
231
|
+
@specification[:ignore_no_matching_join_points].nil? or
|
232
|
+
@specification[:ignore_no_matching_join_points].empty? or
|
233
|
+
@specification[:ignore_no_matching_join_points].to_a.first == false
|
234
|
+
end
|
235
|
+
|
218
236
|
def remove_excluded_join_points_and_empty_pointcuts pointcuts
|
219
237
|
pointcuts.reject do |pc|
|
220
238
|
pc.join_points_matched.delete_if do |jp|
|
@@ -328,7 +346,6 @@ module Aquarium
|
|
328
346
|
Aspect.is_type_join_point?(join_point) ? "" : "remove_method :#{join_point.method_name}"
|
329
347
|
end
|
330
348
|
|
331
|
-
# TODO Move to JoinPoint
|
332
349
|
def self.is_type_join_point? join_point
|
333
350
|
Aquarium::Utils::TypeUtils.is_type? join_point.type_or_object
|
334
351
|
end
|
@@ -473,7 +490,7 @@ module Aquarium
|
|
473
490
|
bad_options(":after can't be used with :after_raising.") if after_given_with? :after_raising
|
474
491
|
bad_options(":after_returning can't be used with :after_raising.") if after_returning_given_with? :after_raising
|
475
492
|
unless some_type_or_pc_option_given?
|
476
|
-
bad_options("At least one of :pointcut(s), :type(s), :type(s)
|
493
|
+
bad_options("At least one of :pointcut(s), :type(s), :type(s)_and_ancestors, :type(s)_and_descendents, :object(s) is required.")
|
477
494
|
end
|
478
495
|
if pointcuts_given? and (some_type_option_given? or objects_given?)
|
479
496
|
bad_options("Can't specify both :pointcut(s) and one or more of :type(s), and/or :object(s).")
|
@@ -18,7 +18,7 @@ module Aquarium
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
# Using @specification[:exclude_join_points].include?(jp) doesn't always work correctly (it probably uses equal())!
|
21
|
+
# Using @specification[:exclude_join_points].include?(jp) doesn't always work correctly (it probably uses equal?())!
|
22
22
|
def is_excluded_join_point? jp
|
23
23
|
return false if @specification[:exclude_join_points].nil?
|
24
24
|
@specification[:exclude_join_points].find {|jp2| jp2 == jp || jp2.eql?(jp)}
|
@@ -17,6 +17,20 @@ module Aquarium
|
|
17
17
|
alias :target_object :advised_object
|
18
18
|
alias :target_object= :advised_object=
|
19
19
|
|
20
|
+
# Create a join point object. It must have one and only type _or_ object and one method or the special keywords <tt>:all</tt>.
|
21
|
+
# Usage:
|
22
|
+
# join_point = JoinPoint.new.find :type => ..., :method_name => ... [, (:class_method | :instance_method) => (true | false) ]
|
23
|
+
# where
|
24
|
+
# <tt>:type => type_or_type_name_or_regexp</tt>::
|
25
|
+
# A single type, type name or regular expression matching only one type. One and only one
|
26
|
+
# type _or_ object is required. An error is raised otherwise.
|
27
|
+
#
|
28
|
+
# <tt>:method_name => method_name_or_sym</tt>::
|
29
|
+
# <tt>:method => method_name_or_sym</tt>::
|
30
|
+
# A single method name or symbol. Only one is allowed, although the special flag <tt>:all</tt> is allowed.
|
31
|
+
#
|
32
|
+
# <tt>(:class_method | :instance_method) => (true | false)</tt>::
|
33
|
+
# Is the method a class or instance method? Defaults to <tt>:instance_method => true</tt>.
|
20
34
|
def initialize options
|
21
35
|
update options
|
22
36
|
assert_valid options
|
@@ -91,7 +105,7 @@ module Aquarium
|
|
91
105
|
end
|
92
106
|
|
93
107
|
def initialize options = {}
|
94
|
-
@target_type = options
|
108
|
+
@target_type = resolve_type options
|
95
109
|
@target_object = options[:object]
|
96
110
|
@method_name = options[:method_name] || options[:method]
|
97
111
|
class_method = options[:class_method].nil? ? false : options[:class_method]
|
@@ -143,24 +157,26 @@ module Aquarium
|
|
143
157
|
new_jp
|
144
158
|
end
|
145
159
|
|
160
|
+
# Needed for comparing this field in #compare_field
|
161
|
+
def instance_method
|
162
|
+
@instance_method
|
163
|
+
end
|
164
|
+
|
146
165
|
# We require the same object id, not just equal objects.
|
147
166
|
def <=> other
|
148
167
|
return 0 if object_id == other.object_id
|
149
168
|
return 1 if other.nil?
|
150
|
-
result = self.class <=> other.class
|
151
|
-
return result unless result == 0
|
152
|
-
result = (self.target_type.nil? and other.target_type.nil?) ? 0 : self.target_type.to_s <=> other.target_type.to_s
|
169
|
+
result = self.class <=> other.class
|
153
170
|
return result unless result == 0
|
154
|
-
result = (
|
171
|
+
result = compare_field(:target_object, other) {|f1,f2| f1.object_id <=> f2.object_id}
|
155
172
|
return result unless result == 0
|
156
|
-
result = (
|
173
|
+
result = compare_field(:instance_method, other) {|f1,f2| boolean_compare(f1,f2)}
|
157
174
|
return result unless result == 0
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
return self.context <=> other.context
|
175
|
+
[:target_type, :method_name, :context].each do |field|
|
176
|
+
result = compare_field field, other
|
177
|
+
return result unless result == 0
|
178
|
+
end
|
179
|
+
0
|
164
180
|
end
|
165
181
|
|
166
182
|
def eql? other
|
@@ -179,9 +195,37 @@ module Aquarium
|
|
179
195
|
|
180
196
|
protected
|
181
197
|
|
198
|
+
def compare_field field_reader, other
|
199
|
+
field1 = self.method(field_reader).call
|
200
|
+
field2 = other.method(field_reader).call
|
201
|
+
if field1.nil?
|
202
|
+
return field2.nil? ? 0 : -1
|
203
|
+
else
|
204
|
+
return 1 if field2.nil?
|
205
|
+
end
|
206
|
+
block_given? ? (yield field1, field2) : (field1 <=> field2)
|
207
|
+
end
|
208
|
+
|
209
|
+
def boolean_compare b1, b2
|
210
|
+
return 0 if b1 == b2
|
211
|
+
return b1 == true ? 1 : -1
|
212
|
+
end
|
213
|
+
|
214
|
+
def resolve_type options
|
215
|
+
type = options[:type]
|
216
|
+
return type if type.nil? # okay, if they specified an object!
|
217
|
+
return type if type.kind_of? Module
|
218
|
+
found = Aquarium::Finders::TypeFinder.new.find :type => type
|
219
|
+
if found.matched.empty?
|
220
|
+
bad_attributes("No type matched the string or regular expression: #{type}", options)
|
221
|
+
elsif found.matched.size > 1
|
222
|
+
bad_attributes("More than one type matched the string or regular expression: #{type}", options)
|
223
|
+
end
|
224
|
+
found.matched.keys.first
|
225
|
+
end
|
226
|
+
|
182
227
|
# Since JoinPoints can be declared for non-existent methods, tolerate "nil" for the visibility.
|
183
|
-
def assert_valid options
|
184
|
-
error_message = ""
|
228
|
+
def assert_valid options, error_message = ""
|
185
229
|
error_message << "Must specify a :method_name. " unless method_name
|
186
230
|
error_message << "Must specify either a :type or :object. " unless (target_type or target_object)
|
187
231
|
error_message << "Can't specify both a :type or :object. " if (target_type and target_object)
|
@@ -158,8 +158,10 @@ module Aquarium
|
|
158
158
|
# Exclude the specified types and their descendents, ancestors.
|
159
159
|
# If you want to exclude both the descendents _and_ ancestors, use both options.
|
160
160
|
#
|
161
|
+
# Pointcut.new also accepts all the "universal" options documented in OptionsUtils.
|
161
162
|
def initialize options = {}
|
162
|
-
init_specification options,
|
163
|
+
init_specification options, CANONICAL_OPTIONS
|
164
|
+
return if noop
|
163
165
|
init_candidate_types
|
164
166
|
init_candidate_objects
|
165
167
|
init_candidate_join_points
|
@@ -177,8 +179,8 @@ module Aquarium
|
|
177
179
|
candidate_types == other.candidate_types &&
|
178
180
|
candidate_types_excluded == other.candidate_types_excluded &&
|
179
181
|
candidate_objects == other.candidate_objects &&
|
180
|
-
|
181
|
-
|
182
|
+
join_points_not_matched == other.join_points_not_matched &&
|
183
|
+
join_points_matched == other.join_points_matched) # not_matched is probably smaller, so do first.
|
182
184
|
end
|
183
185
|
|
184
186
|
alias :== :eql?
|
@@ -220,9 +222,6 @@ module Aquarium
|
|
220
222
|
|
221
223
|
ALL_ALLOWED_OPTION_SYMBOLS = ALL_ALLOWED_OPTIONS.map {|o| o.intern}
|
222
224
|
|
223
|
-
def canonical_options
|
224
|
-
CANONICAL_OPTIONS
|
225
|
-
end
|
226
225
|
def all_allowed_option_symbols
|
227
226
|
ALL_ALLOWED_OPTION_SYMBOLS
|
228
227
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# A simple Design by Contract module. Adds advice to test that the contract, which is specified with
|
2
2
|
# a block passes. Note that it doesn't attempt to handle the correct behavior under contract
|
3
|
-
# inheritance
|
3
|
+
# inheritance.
|
4
4
|
# Warning: This module automatically includes Aquarium::Aspects::DSL::AspectDSL into the class with
|
5
5
|
# the contract and it adds the :precondition, :postcondition, and the :invariant methods to Object!
|
6
6
|
require 'aquarium'
|
@@ -90,7 +90,7 @@ module Aquarium
|
|
90
90
|
# +Derived+ class that is defined in the +Base+ class, you won't find it!
|
91
91
|
#
|
92
92
|
def find options = {}
|
93
|
-
init_specification options,
|
93
|
+
init_specification options, CANONICAL_OPTIONS
|
94
94
|
return Aquarium::Finders::FinderResult.new if nothing_to_find?
|
95
95
|
types_and_objects = input_types + input_objects
|
96
96
|
method_names_or_regexps = input_methods
|
@@ -126,9 +126,6 @@ module Aquarium
|
|
126
126
|
|
127
127
|
ALL_ALLOWED_OPTION_SYMBOLS = ALL_ALLOWED_OPTIONS.map {|o| o.intern}
|
128
128
|
|
129
|
-
def canonical_options
|
130
|
-
CANONICAL_OPTIONS
|
131
|
-
end
|
132
129
|
def all_allowed_option_symbols
|
133
130
|
ALL_ALLOWED_OPTION_SYMBOLS
|
134
131
|
end
|
@@ -14,6 +14,8 @@ module Aquarium
|
|
14
14
|
include Aquarium::Utils::ArrayUtils
|
15
15
|
include Aquarium::Utils::TypeUtils
|
16
16
|
|
17
|
+
TYPES_SYNONYMS = %w[name names type types]
|
18
|
+
|
17
19
|
# Usage:
|
18
20
|
# finder_result = TypeFinder.new.find [options => [...] ]
|
19
21
|
# where
|
@@ -88,11 +90,13 @@ module Aquarium
|
|
88
90
|
# Note: a common idiom in aspects is to include descendents of a type, but not the type
|
89
91
|
# itself. You can do as in the following example:
|
90
92
|
# <tt>... :type_and_descendents => "Foo", :exclude_type => "Foo"
|
93
|
+
# TODO: Use the new OptionsUtils.
|
91
94
|
def find options = {}
|
92
95
|
result = Aquarium::Finders::FinderResult.new
|
93
96
|
excluded = Aquarium::Finders::FinderResult.new
|
94
97
|
unknown_options = []
|
95
98
|
input_type_nil = false
|
99
|
+
noop = false
|
96
100
|
options.each do |option, value|
|
97
101
|
unless TypeFinder.is_recognized_option option
|
98
102
|
unknown_options << option
|
@@ -102,6 +106,8 @@ module Aquarium
|
|
102
106
|
input_type_nil = true
|
103
107
|
next
|
104
108
|
end
|
109
|
+
noop = value if option == :noop
|
110
|
+
next if noop
|
105
111
|
if option.to_s =~ /^exclude_/
|
106
112
|
excluded << find_matching(value, option)
|
107
113
|
else
|
@@ -122,11 +128,12 @@ module Aquarium
|
|
122
128
|
end
|
123
129
|
|
124
130
|
def self.is_recognized_option option_or_symbol
|
125
|
-
|
131
|
+
TYPES_SYNONYMS.each do |t|
|
126
132
|
['', "exclude_"].each do |excl|
|
127
133
|
return true if ["#{excl}#{t}", "#{excl}#{t}_and_descendents", "#{excl}#{t}_and_ancestors"].include?(option_or_symbol.to_s)
|
128
134
|
end
|
129
135
|
end
|
136
|
+
return true if option_or_symbol.to_s.eql?("noop")
|
130
137
|
false
|
131
138
|
end
|
132
139
|
|
data/lib/aquarium/utils.rb
CHANGED
@@ -6,6 +6,7 @@ require 'aquarium/utils/method_utils'
|
|
6
6
|
require 'aquarium/utils/name_utils'
|
7
7
|
require 'aquarium/utils/options_utils'
|
8
8
|
|
9
|
+
require 'aquarium/utils/default_logger'
|
9
10
|
require 'aquarium/utils/html_escaper'
|
10
11
|
require 'aquarium/utils/invalid_options'
|
11
12
|
require 'aquarium/utils/logic_error'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Aquarium
|
4
|
+
module Utils
|
5
|
+
# DefaultLogger holds the Aquarium-wide "default" Ruby standard library logger.
|
6
|
+
# Individual objects may chose to create their own loggers.
|
7
|
+
module DefaultLogger
|
8
|
+
|
9
|
+
@@default_logger = Logger.new STDERR
|
10
|
+
|
11
|
+
def self.logger
|
12
|
+
@@default_logger
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.logger= logger
|
16
|
+
@@default_logger = logger
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|