aspector 0.10.1 → 0.11.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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.10.1
1
+ 0.11.0
data/aspector.gemspec CHANGED
@@ -4,14 +4,14 @@
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = "aspector"
8
- s.version = "0.10.1"
7
+ s.name = %q{aspector}
8
+ s.version = "0.11.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Guoliang Cao"]
12
- s.date = "2012-03-20"
13
- s.description = ""
14
- s.email = "gcao99@gmail.com"
12
+ s.date = %q{2012-04-15}
13
+ s.description = %q{}
14
+ s.email = %q{gcao99@gmail.com}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE.txt",
17
17
  "README.rdoc"
@@ -46,6 +46,7 @@ Gem::Specification.new do |s|
46
46
  "lib/aspector/base_class_methods.rb",
47
47
  "lib/aspector/deferred_logic.rb",
48
48
  "lib/aspector/deferred_option.rb",
49
+ "lib/aspector/logger.rb",
49
50
  "lib/aspector/method_matcher.rb",
50
51
  "lib/aspector/module_extension.rb",
51
52
  "lib/aspector/object_extension.rb",
@@ -55,6 +56,7 @@ Gem::Specification.new do |s|
55
56
  "performance-tests/before_test.rb",
56
57
  "performance-tests/combined_test.rb",
57
58
  "performance-tests/method_invocation_test.rb",
59
+ "performance-tests/raw_test.rb",
58
60
  "performance-tests/test_helper.rb",
59
61
  "spec/functional/advices_on_private_methods_spec.rb",
60
62
  "spec/functional/aspect_on_eigen_class_spec.rb",
@@ -70,13 +72,14 @@ Gem::Specification.new do |s|
70
72
  "spec/unit/base_spec.rb",
71
73
  "spec/unit/before_spec.rb",
72
74
  "spec/unit/deferred_logic_spec.rb",
73
- "spec/unit/method_matcher_spec.rb"
75
+ "spec/unit/method_matcher_spec.rb",
76
+ "spec/unit/raw_spec.rb"
74
77
  ]
75
- s.homepage = "http://github.com/gcao/aspector"
78
+ s.homepage = %q{http://github.com/gcao/aspector}
76
79
  s.licenses = ["MIT"]
77
80
  s.require_paths = ["lib"]
78
- s.rubygems_version = "1.8.18"
79
- s.summary = "Aspect Oriented Ruby Programming"
81
+ s.rubygems_version = %q{1.6.2}
82
+ s.summary = %q{Aspect Oriented Ruby Programming}
80
83
 
81
84
  if s.respond_to? :specification_version then
82
85
  s.specification_version = 3
@@ -13,16 +13,16 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13
13
  require 'aspector'
14
14
 
15
15
  class ActiveRecordHooks < Aspector::Base
16
- aspect = self
16
+ logger.level = Aspector::Logger::TRACE
17
17
 
18
18
  default :private_methods => true
19
19
 
20
20
  before :initialize do
21
- puts "#{aspect}: before creating #{self.class.name} instance"
21
+ puts "Before creating #{self.class.name} instance"
22
22
  end
23
23
 
24
24
  before :save do
25
- puts "#{aspect}: before saving"
25
+ puts "Before saving #{self.class.name} instance"
26
26
  end
27
27
  end
28
28
 
@@ -32,4 +32,3 @@ ActiveRecordHooks.apply(A)
32
32
 
33
33
  a = A.new
34
34
  a.save
35
-
@@ -46,7 +46,7 @@ require 'aspector'
46
46
  class CacheAspect < Aspector::Base
47
47
  default :ttl => 60
48
48
 
49
- around options[:method], :aspect_arg => true, :method_arg => true do |aspect, method, proxy, &block|
49
+ around :aspect_arg => true, :method_arg => true do |aspect, method, proxy, &block|
50
50
  key = method
51
51
  ttl = aspect.options[:ttl]
52
52
 
@@ -59,8 +59,8 @@ end
59
59
 
60
60
  ##############################
61
61
 
62
- CacheAspect.apply A, :method => :test, :ttl => 2 # 2 seconds
63
- CacheAspect.apply A, :method => :test2
62
+ CacheAspect.apply "A#test", :ttl => 2 # 2 seconds
63
+ CacheAspect.apply "A#test2"
64
64
 
65
65
  a = A.new
66
66
 
@@ -22,13 +22,13 @@ class ExceptionHandler < Aspector::Base
22
22
  end
23
23
  end
24
24
 
25
- around options[:method], :handle_exception
25
+ around :handle_exception
26
26
 
27
27
  end
28
28
 
29
29
  ##############################
30
30
 
31
- ExceptionHandler.apply(A, :method => :test)
31
+ ExceptionHandler.apply "A#test"
32
32
 
33
33
  a = A.new
34
34
  a.test 'good'
@@ -28,13 +28,13 @@ class RetryAspect < Aspector::Base
28
28
  end
29
29
  end
30
30
 
31
- around options[:method], :retry_this
31
+ around :retry_this
32
32
 
33
33
  end
34
34
 
35
35
  ##############################
36
36
 
37
- RetryAspect.apply(A, :method => :test)
37
+ RetryAspect.apply "A#test"
38
38
 
39
39
  a = A.new
40
40
  a.test
@@ -4,8 +4,10 @@ module Aspector
4
4
  BEFORE = 1
5
5
  AFTER = 2
6
6
  AROUND = 3
7
+ RAW = 4
7
8
 
8
9
  attr_reader :type, :method_matcher, :options, :advice_block
10
+ attr_accessor :index
9
11
 
10
12
  def initialize parent, type, method_matcher, with_method, options = {}, &block
11
13
  @parent = parent
@@ -31,6 +33,10 @@ module Aspector
31
33
  not @except.match?(method)
32
34
  end
33
35
 
36
+ def raw?
37
+ type == RAW
38
+ end
39
+
34
40
  def before?
35
41
  type == BEFORE
36
42
  end
@@ -52,19 +58,21 @@ module Aspector
52
58
  when BEFORE then @options[:skip_if_false] ? "BEFORE_FILTER" : "BEFORE"
53
59
  when AFTER then "AFTER"
54
60
  when AROUND then "AROUND"
61
+ when RAW then "RAW"
55
62
  else "UNKNOWN?!"
56
63
  end
57
64
  end
58
65
 
59
66
  def to_s
60
- s = type_name
67
+ s = "<advice " << index.to_s << ">: "
68
+ s << type_name
61
69
  s << " [" << @method_matcher.to_s << "] DO "
62
- s << @with_method.to_s
63
- s << " WITH OPTIONS "
64
- @options.each do |key, value|
65
- next if key == :skip_if_false
66
- s << key.to_s << ":" << value.to_s << " "
70
+ if @with_method
71
+ s << @with_method.to_s
72
+ else
73
+ s << "stuff in block"
67
74
  end
75
+ s << " WITH OPTIONS " << @options.inspect
68
76
  s
69
77
  end
70
78
 
@@ -12,6 +12,7 @@ module Aspector
12
12
  BEFORE_FILTER = new Aspector::Advice::BEFORE, nil, :skip_if_false => true
13
13
  AFTER = new Aspector::Advice::AFTER, { :result_arg => true }, nil
14
14
  AROUND = new Aspector::Advice::AROUND, nil, nil
15
+ RAW = new Aspector::Advice::RAW, nil, nil
15
16
  end
16
17
  end
17
18
 
data/lib/aspector/base.rb CHANGED
@@ -4,7 +4,10 @@ module Aspector
4
4
  class Base
5
5
 
6
6
  attr :aop_options
7
- alias :options :aop_options
7
+ alias options aop_options
8
+
9
+ attr :aop_target
10
+ alias target aop_target
8
11
 
9
12
  attr :aop_wrapped_methods
10
13
 
@@ -51,7 +54,7 @@ module Aspector
51
54
 
52
55
  aop_disabled?
53
56
  end
54
- alias reset_disabled :aop_reset_disabled
57
+ alias reset_disabled aop_reset_disabled
55
58
 
56
59
  def aop_disabled?
57
60
  end
@@ -60,10 +63,15 @@ module Aspector
60
63
  aop_disabled?
61
64
  end
62
65
 
66
+ def aop_logger
67
+ @aop_logger ||= Logger.new(self, self.class.logger.level)
68
+ end
69
+ alias logger aop_logger
70
+
63
71
  def aop_advices
64
72
  self.class.aop_advices
65
73
  end
66
- alias :advices :aop_advices
74
+ alias advices aop_advices
67
75
 
68
76
  def aop_apply
69
77
  before_apply
@@ -74,7 +82,7 @@ module Aspector
74
82
  aop_add_method_hooks unless @aop_options[:old_methods_only]
75
83
  after_apply
76
84
  end
77
- alias :apply :aop_apply
85
+ alias apply aop_apply
78
86
 
79
87
  def aop_apply_to_methods
80
88
  advices = aop_advices
@@ -112,6 +120,7 @@ module Aspector
112
120
  advices = aop_filter_advices advices, method
113
121
  return if advices.empty?
114
122
 
123
+ aop_logger.log Logger::APPLY_TO_METHOD, method
115
124
  before_apply_to_method method, advices
116
125
 
117
126
  scope ||=
@@ -173,6 +182,7 @@ module Aspector
173
182
 
174
183
  def aop_define_methods_for_advice_blocks
175
184
  aop_advices.each do |advice|
185
+ next if advice.raw?
176
186
  next unless advice.advice_block
177
187
  @aop_context.send :define_method, advice.with_method, advice.advice_block
178
188
  @aop_context.send :private, advice.with_method
@@ -224,9 +234,24 @@ module Aspector
224
234
  end
225
235
 
226
236
  def aop_recreate_method method, advices, scope
227
- @aop_wrapped_methods[method] = @aop_context.instance_method(method)
228
237
  @aop_context.instance_variable_set(:@aop_creating_method, true)
229
238
 
239
+ raw_advices = advices.select {|advice| advice.raw? }
240
+
241
+ if raw_advices.size > 0
242
+ raw_advices.each do |advice|
243
+ if @aop_target.is_a? Module and not @aop_options[:class_methods]
244
+ @aop_target.class_exec method, self, &advice.advice_block
245
+ else
246
+ @aop_target.instance_exec method, self, &advice.advice_block
247
+ end
248
+ end
249
+
250
+ return if raw_advices.size == advices.size
251
+ end
252
+
253
+ @aop_wrapped_methods[method] = @aop_context.instance_method(method)
254
+
230
255
  before_advices = advices.select {|advice| advice.before? }
231
256
  after_advices = advices.select {|advice| advice.after? }
232
257
  around_advices = advices.select {|advice| advice.around? }
@@ -240,79 +265,137 @@ module Aspector
240
265
 
241
266
  @aop_context.send scope, method if scope != :public
242
267
  ensure
243
- @aop_context.instance_variable_set(:@aop_creating_method, nil)
268
+ @aop_context.send :remove_instance_variable, :@aop_creating_method
244
269
  end
245
270
 
246
271
  def aop_recreate_method_with_advices method, before_advices, after_advices, around_advice, is_outermost = false
247
272
  aspect = self
248
273
 
249
274
  code = METHOD_TEMPLATE.result(binding)
250
- #puts code
275
+ aspect.aop_logger.log Logger::GENERATE_CODE, method, code
251
276
  @aop_context.class_eval code, __FILE__, __LINE__ + 4
252
277
  end
253
278
 
254
- METHOD_TEMPLATE = ERB.new <<-CODE
255
- orig_method = aspect.aop_wrapped_methods['<%= method %>']
279
+ METHOD_TEMPLATE = ERB.new <<-CODE, nil, "%<>"
256
280
 
257
- <% if around_advice %>
281
+ orig_method = aspect.aop_wrapped_methods['<%= method %>']
282
+ % if around_advice
258
283
  wrapped_method = instance_method(:<%= method %>)
259
- <% end %>
284
+ % end
260
285
 
261
286
  define_method :<%= method %> do |*args, &block|
262
- return orig_method.bind(self).call(*args, &block) if aspect.aop_disabled?
287
+ % if aop_logger.visible?(Logger::TRACE)
288
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::ENTER_GENERATED_METHOD
289
+ % end
290
+
291
+ if aspect.aop_disabled?
292
+ % if aop_logger.visible?(Logger::TRACE)
293
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::EXIT_BECAUSE_DISABLED
294
+ % end
295
+ return orig_method.bind(self).call(*args, &block)
296
+ end
263
297
 
264
- <% if is_outermost %>
265
- catch(:aop_returns) do
266
- <% end %>
298
+ % if is_outermost
299
+ result = catch(:aop_returns) do
300
+ % end
267
301
 
302
+ % unless before_advices.empty?
268
303
  # Before advices
269
- <% before_advices.each do |advice| %>
304
+ % end
305
+ % before_advices.each do |advice|
306
+ % if aop_logger.visible?(Logger::TRACE)
307
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::BEFORE_INVOKE_ADVICE, '<advice <%= advice.index %>>'
308
+ % end
270
309
  result = <%= advice.with_method %> <%
271
310
  if advice.options[:aspect_arg] %>aspect, <% end %><%
272
311
  if advice.options[:method_arg] %>'<%= method %>', <% end
273
312
  %>*args
313
+ % if aop_logger.visible?(Logger::TRACE)
314
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::AFTER_INVOKE_ADVICE, '<advice <%= advice.index %>>'
315
+ % end
316
+ % if advice.options[:skip_if_false]
317
+ unless result
318
+ % if aop_logger.visible?(Logger::TRACE)
319
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::EXIT_FROM_BEFORE_FILTER, '<advice <%= advice.index %>>'
320
+ % end
321
+ return
322
+ end
323
+ % end
324
+ % end
274
325
 
275
- <% if advice.options[:skip_if_false] %>
276
- return unless result
277
- <% end
278
- end
279
- %>
280
-
281
- <% if around_advice %>
326
+ % if around_advice
282
327
  # Around advice
328
+ % if aop_logger.visible?(Logger::TRACE)
329
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::BEFORE_INVOKE_ADVICE, '<advice <%= around_advice.index %>>'
330
+ % end
331
+ % if aop_logger.visible?(Logger::TRACE)
332
+ proxy = lambda do |*args, &block|
333
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::BEFORE_INVOKE_PROXY
334
+ res = wrapped_method.bind(self).call *args, &block
335
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::AFTER_INVOKE_PROXY
336
+ res
337
+ end
338
+ result = <%= around_advice.with_method %> <%
339
+ if around_advice.options[:aspect_arg] %>aspect, <% end %><%
340
+ if around_advice.options[:method_arg] %>'<%= method %>', <% end
341
+ %>proxy, *args, &block
342
+ % else
283
343
  result = <%= around_advice.with_method %> <%
284
344
  if around_advice.options[:aspect_arg] %>aspect, <% end %><%
285
345
  if around_advice.options[:method_arg] %>'<%= method %>', <% end
286
346
  %>wrapped_method.bind(self), *args, &block
287
- <% else %>
347
+ % end
348
+ % if aop_logger.visible?(Logger::TRACE)
349
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::AFTER_INVOKE_ADVICE, '<advice <%= around_advice.index %>>'
350
+ % end
351
+
352
+ % else
353
+
288
354
  # Invoke original method
355
+ % if aop_logger.visible?(Logger::TRACE)
356
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::BEFORE_WRAPPED_METHOD
357
+ % end
289
358
  result = orig_method.bind(self).call *args, &block
290
- <% end %>
359
+ % if aop_logger.visible?(Logger::TRACE)
360
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::AFTER_WRAPPED_METHOD
361
+ % end
291
362
 
363
+ % end
364
+
365
+ % unless after_advices.empty?
292
366
  # After advices
293
- <% unless after_advices.empty?
294
- after_advices.each do |advice|
295
- if advice.options[:result_arg]
296
- %>
367
+ % after_advices.each do |advice|
368
+ % if aop_logger.visible?(Logger::TRACE)
369
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::BEFORE_INVOKE_ADVICE, '<advice <%= advice.index %>>'
370
+ % end
371
+ % if advice.options[:result_arg]
297
372
  result = <%= advice.with_method %> <%
298
373
  if advice.options[:aspect_arg] %>aspect, <% end %><%
299
374
  if advice.options[:method_arg] %>'<%= method %>', <% end %><%
300
375
  if advice.options[:result_arg] %>result, <% end
301
376
  %>*args
302
- <% else %>
377
+ % else
303
378
  <%= advice.with_method %> <%
304
379
  if advice.options[:aspect_arg] %>aspect, <% end %><%
305
380
  if advice.options[:method_arg] %>'<%= method %>', <% end
306
381
  %>*args
307
- <% end
308
- end
309
- %>
382
+ % end
383
+ % if aop_logger.visible?(Logger::TRACE)
384
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::AFTER_INVOKE_ADVICE, '<advice <%= advice.index %>>'
385
+ % end
386
+ % end
387
+ % end
388
+
389
+ % if is_outermost
310
390
  result
311
- <% end %>
312
391
 
313
- <% if is_outermost %>
314
- end
315
- <% end %>
392
+ end # end of catch
393
+ % end
394
+
395
+ % if aop_logger.visible?(Logger::TRACE)
396
+ aspect.aop_logger.log_method_call '<%= method %>', Aspector::Logger::EXIT_GENERATED_METHOD
397
+ % end
398
+ result
316
399
  end
317
400
  CODE
318
401
 
@@ -4,33 +4,41 @@ module Aspector
4
4
  ::Aspector::Base.extend(self)
5
5
 
6
6
  def aop_enable
7
+ aop_logger.log Logger::ENABLE_ASPECT
7
8
  send :define_method, :aop_disabled? do
8
9
  end
9
10
 
10
11
  nil
11
12
  end
12
- alias :enable :aop_enable
13
+ alias enable aop_enable
13
14
 
14
15
  def aop_disable
16
+ aop_logger.log Logger::DISABLE_ASPECT
15
17
  send :define_method, :aop_disabled? do
16
18
  true
17
19
  end
18
20
 
19
21
  nil
20
22
  end
21
- alias :disable :aop_disable
23
+ alias disable aop_disable
24
+
25
+ def aop_logger
26
+ @aop_logger ||= Logger.new(self)
27
+ end
28
+ alias logger aop_logger
22
29
 
23
30
  def aop_advices
24
31
  @aop_advices ||= []
25
32
  end
26
- alias :advices :aop_advices
33
+ alias advices aop_advices
27
34
 
28
35
  def aop_default_options
29
36
  @aop_default_options ||= {}
30
37
  end
31
- alias :default_options :aop_default_options
38
+ alias default_options aop_default_options
32
39
 
33
40
  def aop_apply target, options = {}
41
+ aop_logger.log Logger::APPLY, target, options.inspect
34
42
  # Handle 'Klass#method' and 'Klass.method' shortcut
35
43
  if target.is_a? String
36
44
  if target.index('.')
@@ -48,7 +56,7 @@ module Aspector
48
56
  aspect_instance.send :aop_apply
49
57
  aspect_instance
50
58
  end
51
- alias :apply :aop_apply
59
+ alias apply aop_apply
52
60
 
53
61
  def aop_default options
54
62
  if @aop_default_options
@@ -57,27 +65,47 @@ module Aspector
57
65
  @aop_default_options = options
58
66
  end
59
67
  end
60
- alias :default :aop_default
68
+ alias default aop_default
61
69
 
62
70
  def aop_before *methods, &block
63
- aop_advices << aop_create_advice(Aspector::AdviceMetadata::BEFORE, self, methods, &block)
71
+ aop_advices << advice = aop_create_advice(Aspector::AdviceMetadata::BEFORE, self, methods, &block)
72
+ advice.index = aop_advices.size
73
+ aop_logger.log Logger::DEFINE_ADVICE, advice
74
+ advice
64
75
  end
65
- alias :before :aop_before
76
+ alias before aop_before
66
77
 
67
78
  def aop_before_filter *methods, &block
68
- aop_advices << aop_create_advice(Aspector::AdviceMetadata::BEFORE_FILTER, self, methods, &block)
79
+ aop_advices << advice = aop_create_advice(Aspector::AdviceMetadata::BEFORE_FILTER, self, methods, &block)
80
+ advice.index = aop_advices.size
81
+ aop_logger.log Logger::DEFINE_ADVICE, advice
82
+ advice
69
83
  end
70
- alias :before_filter :aop_before_filter
84
+ alias before_filter aop_before_filter
71
85
 
72
86
  def aop_after *methods, &block
73
- aop_advices << aop_create_advice(Aspector::AdviceMetadata::AFTER, self, methods, &block)
87
+ aop_advices << advice = aop_create_advice(Aspector::AdviceMetadata::AFTER, self, methods, &block)
88
+ advice.index = aop_advices.size
89
+ aop_logger.log Logger::DEFINE_ADVICE, advice
90
+ advice
74
91
  end
75
- alias :after :aop_after
92
+ alias after aop_after
76
93
 
77
94
  def aop_around *methods, &block
78
- aop_advices << aop_create_advice(Aspector::AdviceMetadata::AROUND, self, methods, &block)
95
+ aop_advices << advice = aop_create_advice(Aspector::AdviceMetadata::AROUND, self, methods, &block)
96
+ advice.index = aop_advices.size
97
+ aop_logger.log Logger::DEFINE_ADVICE, advice
98
+ advice
99
+ end
100
+ alias around aop_around
101
+
102
+ def aop_raw *methods, &block
103
+ aop_advices << advice = aop_create_advice(Aspector::AdviceMetadata::RAW, self, methods, &block)
104
+ advice.index = aop_advices.size
105
+ aop_logger.log Logger::DEFINE_ADVICE, advice
106
+ advice
79
107
  end
80
- alias :around :aop_around
108
+ alias raw aop_raw
81
109
 
82
110
  def aop_target code = nil, &block
83
111
  return unless code or block_given?
@@ -86,12 +114,12 @@ module Aspector
86
114
  aop_deferred_logics << logic
87
115
  logic
88
116
  end
89
- alias :target :aop_target
117
+ alias target aop_target
90
118
 
91
119
  def aop_options
92
120
  DeferredOption.new
93
121
  end
94
- alias :options :aop_options
122
+ alias options aop_options
95
123
 
96
124
  private
97
125
 
@@ -111,7 +139,12 @@ module Aspector
111
139
  methods[i] = methods[i].to_s if methods[i].is_a? Symbol
112
140
  end
113
141
 
114
- with_method = methods.pop unless block_given?
142
+ if meta_data.advice_type == Aspector::Advice::RAW
143
+ raise "Bad raw advice - code block is required" unless block_given?
144
+ with_method = nil
145
+ else
146
+ with_method = methods.pop unless block_given?
147
+ end
115
148
 
116
149
  methods << aop_options[:method] << aop_options[:methods] if methods.empty?
117
150
 
@@ -8,5 +8,9 @@ module Aspector
8
8
  self
9
9
  end
10
10
 
11
+ def inspect
12
+ "options[:#{key}]"
13
+ end
11
14
  end
12
15
  end
16
+
@@ -0,0 +1,110 @@
1
+ module Aspector
2
+ class Logger
3
+ # Log levels
4
+ ERROR = 50
5
+ WARN = 40
6
+ INFO = 30
7
+ DEBUG = 20
8
+ TRACE = 10
9
+
10
+ DEFAULT_VISIBLE_LEVEL = INFO
11
+
12
+ # Actions
13
+ DEFINE_ADVICE = %W"define-advice"
14
+ APPLY = %W"apply"
15
+ APPLY_TO_METHOD = %W"apply-to-method #{DEBUG}"
16
+ ENABLE_ASPECT = %W"enable-aspect"
17
+ DISABLE_ASPECT = %W"disable-aspect"
18
+
19
+ GENERATE_CODE = %W"generate-code #{DEBUG}"
20
+
21
+ ENTER_GENERATED_METHOD = %W"enter-generated-method #{TRACE}"
22
+ EXIT_GENERATED_METHOD = %W"exit--generated-method #{TRACE}"
23
+ EXIT_BECAUSE_DISABLED = %W"exit--because-disabled #{TRACE}"
24
+ BEFORE_INVOKE_ADVICE = %W"before-invoke-advice #{TRACE}"
25
+ AFTER_INVOKE_ADVICE = %W"after--invoke-advice #{TRACE}"
26
+ BEFORE_WRAPPED_METHOD = %W"before-wrapped-method #{TRACE}"
27
+ AFTER_WRAPPED_METHOD = %W"after--wrapped-method #{TRACE}"
28
+ BEFORE_INVOKE_PROXY = %W"before-invoke-proxy #{TRACE}"
29
+ AFTER_INVOKE_PROXY = %W"after--invoke-proxy #{TRACE}"
30
+
31
+ attr_reader :context
32
+ attr_writer :level
33
+
34
+ def initialize context, level = nil
35
+ @context = context
36
+ @level = level
37
+ end
38
+
39
+ def level
40
+ return @level if @level
41
+
42
+ if (level_string = ENV['ASPECTOR_LOG_LEVEL'])
43
+ @level = string_to_level(level_string)
44
+ else
45
+ @level = DEFAULT_VISIBLE_LEVEL
46
+ end
47
+ end
48
+
49
+ def log action_level, *args
50
+ action, level = parse_action_level(action_level)
51
+
52
+ return if self.level > level
53
+
54
+ puts log_prefix(level) << action << " | " << args.join(" | ")
55
+ end
56
+
57
+ def log_method_call method, action_level, *args
58
+ action, level = parse_action_level(action_level)
59
+
60
+ return if self.level > level
61
+
62
+ puts log_prefix(level) << method << " | " << action << " | " << args.join(" | ")
63
+ end
64
+
65
+ def visible? level
66
+ self.level <= level
67
+ end
68
+
69
+ private
70
+
71
+ def parse_action_level action_level
72
+ action = action_level[0]
73
+ level = (action_level[1] || INFO).to_i
74
+ return action, level
75
+ end
76
+
77
+ def log_prefix level
78
+ s = "Aspector | " << level_to_string(level) << " | "
79
+ if context.is_a? Aspector::Base
80
+ s << context.class.to_s << " | " << context.aop_target.to_s << " | "
81
+ else
82
+ s << context.to_s << " | "
83
+ end
84
+ end
85
+
86
+ def level_to_string level
87
+ case level
88
+ when ERROR then "ERROR"
89
+ when WARN then "WARN "
90
+ when INFO then "INFO "
91
+ when DEBUG then "DEBUG"
92
+ when TRACE then "TRACE"
93
+ else level.to_s
94
+ end
95
+ end
96
+
97
+ def string_to_level level_string
98
+ return if level_string.nil? or level_string.strip == ''
99
+
100
+ case level_string.downcase
101
+ when 'error' then ERROR
102
+ when 'warn' then WARN
103
+ when 'info' then INFO
104
+ when 'debug' then DEBUG
105
+ when 'trace' then TRACE
106
+ end
107
+ end
108
+ end
109
+ end
110
+
@@ -19,7 +19,7 @@ module Aspector
19
19
 
20
20
  yield if block_given?
21
21
  ensure
22
- instance_variable_set(aop_applied_flag, nil)
22
+ remove_instance_variable aop_applied_flag
23
23
  end
24
24
  end
25
25
 
@@ -42,7 +42,7 @@ module Aspector
42
42
 
43
43
  yield if block_given?
44
44
  ensure
45
- eigen_class.instance_variable_set(aop_applied_flag, nil)
45
+ eigen_class.send :remove_instance_variable, aop_applied_flag
46
46
  end
47
47
  end
48
48
 
data/lib/aspector.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'aspector/logger'
2
+
1
3
  require 'aspector/object_extension'
2
4
  require 'aspector/module_extension'
3
5
 
@@ -26,14 +26,15 @@ class AroundAspect < Aspector::Base
26
26
  end
27
27
 
28
28
  class RawAspect < Aspector::Base
29
- target do
30
- wrapped_method = instance_method(:test)
31
- define_method :test do |*args, &block|
32
- begin
33
- wrapped_method.bind(self).call *args, &block
34
- rescue => e
35
- end
29
+ raw :test do |method,|
30
+ eval <<-CODE
31
+ alias #{method}_without_aspect #{method}
32
+
33
+ def #{method} *args, &block
34
+ #{method}_without_aspect *args, &block
35
+ rescue => e
36
36
  end
37
+ CODE
37
38
  end
38
39
  end
39
40
 
@@ -0,0 +1,37 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ class RawTest < Test::Unit::TestCase
4
+ include RubyProf::Test
5
+
6
+ class Klass
7
+
8
+ aspector do
9
+
10
+ raw :test do |method, aspect|
11
+ eval <<-CODE
12
+ alias #{method}_without_aspect #{method}
13
+
14
+ define_method :#{method} do
15
+ return #{method}_without_aspect if aspect.disabled?
16
+ before_#{method}
17
+ #{method}_without_aspect
18
+ end
19
+ CODE
20
+ end
21
+
22
+ end
23
+
24
+ def test_no_aspect; end
25
+
26
+ def test; end
27
+
28
+ def before_test; end
29
+ end
30
+
31
+ def test_raw
32
+ o = Klass.new
33
+ o.test_no_aspect
34
+ o.test
35
+ end
36
+ end
37
+
@@ -5,5 +5,5 @@ require 'test/unit'
5
5
  require 'ruby-prof/test'
6
6
  require 'aspector'
7
7
 
8
- RubyProf::Test::PROFILE_OPTIONS[:count ] = 10000
8
+ RubyProf::Test::PROFILE_OPTIONS[:count ] = 200000
9
9
  RubyProf::Test::PROFILE_OPTIONS[:output_dir] = File.dirname(__FILE__) + "/output"
@@ -0,0 +1,53 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Raw advices" do
4
+ it "should work" do
5
+ klass = create_test_class
6
+
7
+ aspector(klass) do
8
+ raw :test do
9
+ alias test_without_aspect test
10
+ def test
11
+ value << "raw_before"
12
+ test_without_aspect
13
+ end
14
+ end
15
+ end
16
+
17
+ obj = klass.new
18
+ obj.test
19
+ obj.value.should == %w"raw_before test"
20
+ end
21
+
22
+ it "new methods should work" do
23
+ klass = Class.new do
24
+ aspector do
25
+ raw :test do
26
+ alias test_without_aspect test
27
+ def test
28
+ do_this
29
+ test_without_aspect
30
+ end
31
+ end
32
+ end
33
+
34
+ def value
35
+ @value ||= []
36
+ end
37
+
38
+ def test
39
+ value << "test"
40
+ end
41
+
42
+ def do_this
43
+ value << "do_this"
44
+ end
45
+ end
46
+
47
+ obj = klass.new
48
+ obj.test
49
+ obj.value.should == %w"do_this test"
50
+ end
51
+
52
+ end
53
+
metadata CHANGED
@@ -1,200 +1,202 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: aspector
3
- version: !ruby/object:Gem::Version
4
- version: 0.10.1
3
+ version: !ruby/object:Gem::Version
4
+ hash: 51
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 11
9
+ - 0
10
+ version: 0.11.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Guoliang Cao
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2012-03-20 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: rspec
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :development
17
+
18
+ date: 2012-04-15 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
23
22
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
23
+ type: :development
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
30
- - !ruby/object:Gem::Dependency
31
- name: jeweler
32
- requirement: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ name: rspec
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ prerelease: false
37
+ type: :development
38
+ requirement: &id002 !ruby/object:Gem::Requirement
33
39
  none: false
34
- requirements:
40
+ requirements:
35
41
  - - ~>
36
- - !ruby/object:Gem::Version
42
+ - !ruby/object:Gem::Version
43
+ hash: 7
44
+ segments:
45
+ - 1
46
+ - 6
47
+ - 4
37
48
  version: 1.6.4
38
- type: :development
49
+ name: jeweler
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
39
52
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
53
+ type: :development
54
+ requirement: &id003 !ruby/object:Gem::Requirement
41
55
  none: false
42
- requirements:
43
- - - ~>
44
- - !ruby/object:Gem::Version
45
- version: 1.6.4
46
- - !ruby/object:Gem::Dependency
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
47
63
  name: ruby-prof
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - ! '>='
52
- - !ruby/object:Gem::Version
53
- version: '0'
54
- type: :development
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
55
66
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- - !ruby/object:Gem::Dependency
63
- name: guard
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ~>
68
- - !ruby/object:Gem::Version
69
- version: 0.8.4
70
67
  type: :development
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
68
+ requirement: &id004 !ruby/object:Gem::Requirement
73
69
  none: false
74
- requirements:
70
+ requirements:
75
71
  - - ~>
76
- - !ruby/object:Gem::Version
72
+ - !ruby/object:Gem::Version
73
+ hash: 55
74
+ segments:
75
+ - 0
76
+ - 8
77
+ - 4
77
78
  version: 0.8.4
78
- - !ruby/object:Gem::Dependency
79
- name: guard-bundler
80
- requirement: !ruby/object:Gem::Requirement
81
- none: false
82
- requirements:
83
- - - ~>
84
- - !ruby/object:Gem::Version
85
- version: 0.1.3
86
- type: :development
79
+ name: guard
80
+ version_requirements: *id004
81
+ - !ruby/object:Gem::Dependency
87
82
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
83
+ type: :development
84
+ requirement: &id005 !ruby/object:Gem::Requirement
89
85
  none: false
90
- requirements:
86
+ requirements:
91
87
  - - ~>
92
- - !ruby/object:Gem::Version
88
+ - !ruby/object:Gem::Version
89
+ hash: 29
90
+ segments:
91
+ - 0
92
+ - 1
93
+ - 3
93
94
  version: 0.1.3
94
- - !ruby/object:Gem::Dependency
95
- name: guard-rspec
96
- requirement: !ruby/object:Gem::Requirement
97
- none: false
98
- requirements:
99
- - - ~>
100
- - !ruby/object:Gem::Version
101
- version: 0.5.2
102
- type: :development
95
+ name: guard-bundler
96
+ version_requirements: *id005
97
+ - !ruby/object:Gem::Dependency
103
98
  prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
99
+ type: :development
100
+ requirement: &id006 !ruby/object:Gem::Requirement
105
101
  none: false
106
- requirements:
102
+ requirements:
107
103
  - - ~>
108
- - !ruby/object:Gem::Version
104
+ - !ruby/object:Gem::Version
105
+ hash: 15
106
+ segments:
107
+ - 0
108
+ - 5
109
+ - 2
109
110
  version: 0.5.2
110
- - !ruby/object:Gem::Dependency
111
- name: guard-shell
112
- requirement: !ruby/object:Gem::Requirement
113
- none: false
114
- requirements:
115
- - - ~>
116
- - !ruby/object:Gem::Version
117
- version: 0.1.1
118
- type: :development
111
+ name: guard-rspec
112
+ version_requirements: *id006
113
+ - !ruby/object:Gem::Dependency
119
114
  prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
115
+ type: :development
116
+ requirement: &id007 !ruby/object:Gem::Requirement
121
117
  none: false
122
- requirements:
118
+ requirements:
123
119
  - - ~>
124
- - !ruby/object:Gem::Version
120
+ - !ruby/object:Gem::Version
121
+ hash: 25
122
+ segments:
123
+ - 0
124
+ - 1
125
+ - 1
125
126
  version: 0.1.1
126
- - !ruby/object:Gem::Dependency
127
- name: rb-fsevent
128
- requirement: !ruby/object:Gem::Requirement
129
- none: false
130
- requirements:
131
- - - ~>
132
- - !ruby/object:Gem::Version
133
- version: 0.4.3.1
134
- type: :development
127
+ name: guard-shell
128
+ version_requirements: *id007
129
+ - !ruby/object:Gem::Dependency
135
130
  prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
131
+ type: :development
132
+ requirement: &id008 !ruby/object:Gem::Requirement
137
133
  none: false
138
- requirements:
134
+ requirements:
139
135
  - - ~>
140
- - !ruby/object:Gem::Version
136
+ - !ruby/object:Gem::Version
137
+ hash: 97
138
+ segments:
139
+ - 0
140
+ - 4
141
+ - 3
142
+ - 1
141
143
  version: 0.4.3.1
142
- - !ruby/object:Gem::Dependency
143
- name: growl
144
- requirement: !ruby/object:Gem::Requirement
144
+ name: rb-fsevent
145
+ version_requirements: *id008
146
+ - !ruby/object:Gem::Dependency
147
+ prerelease: false
148
+ type: :development
149
+ requirement: &id009 !ruby/object:Gem::Requirement
145
150
  none: false
146
- requirements:
151
+ requirements:
147
152
  - - ~>
148
- - !ruby/object:Gem::Version
153
+ - !ruby/object:Gem::Version
154
+ hash: 17
155
+ segments:
156
+ - 1
157
+ - 0
158
+ - 3
149
159
  version: 1.0.3
150
- type: :development
160
+ name: growl
161
+ version_requirements: *id009
162
+ - !ruby/object:Gem::Dependency
151
163
  prerelease: false
152
- version_requirements: !ruby/object:Gem::Requirement
164
+ type: :development
165
+ requirement: &id010 !ruby/object:Gem::Requirement
153
166
  none: false
154
- requirements:
155
- - - ~>
156
- - !ruby/object:Gem::Version
157
- version: 1.0.3
158
- - !ruby/object:Gem::Dependency
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ hash: 3
171
+ segments:
172
+ - 0
173
+ version: "0"
159
174
  name: awesome_print
160
- requirement: !ruby/object:Gem::Requirement
161
- none: false
162
- requirements:
163
- - - ! '>='
164
- - !ruby/object:Gem::Version
165
- version: '0'
166
- type: :development
175
+ version_requirements: *id010
176
+ - !ruby/object:Gem::Dependency
167
177
  prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
169
- none: false
170
- requirements:
171
- - - ! '>='
172
- - !ruby/object:Gem::Version
173
- version: '0'
174
- - !ruby/object:Gem::Dependency
175
- name: pry
176
- requirement: !ruby/object:Gem::Requirement
177
- none: false
178
- requirements:
179
- - - ! '>='
180
- - !ruby/object:Gem::Version
181
- version: '0'
182
178
  type: :development
183
- prerelease: false
184
- version_requirements: !ruby/object:Gem::Requirement
179
+ requirement: &id011 !ruby/object:Gem::Requirement
185
180
  none: false
186
- requirements:
187
- - - ! '>='
188
- - !ruby/object:Gem::Version
189
- version: '0'
190
- description: ''
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ hash: 3
185
+ segments:
186
+ - 0
187
+ version: "0"
188
+ name: pry
189
+ version_requirements: *id011
190
+ description: ""
191
191
  email: gcao99@gmail.com
192
192
  executables: []
193
+
193
194
  extensions: []
194
- extra_rdoc_files:
195
+
196
+ extra_rdoc_files:
195
197
  - LICENSE.txt
196
198
  - README.rdoc
197
- files:
199
+ files:
198
200
  - .document
199
201
  - .irbrc
200
202
  - .rspec
@@ -224,6 +226,7 @@ files:
224
226
  - lib/aspector/base_class_methods.rb
225
227
  - lib/aspector/deferred_logic.rb
226
228
  - lib/aspector/deferred_option.rb
229
+ - lib/aspector/logger.rb
227
230
  - lib/aspector/method_matcher.rb
228
231
  - lib/aspector/module_extension.rb
229
232
  - lib/aspector/object_extension.rb
@@ -233,6 +236,7 @@ files:
233
236
  - performance-tests/before_test.rb
234
237
  - performance-tests/combined_test.rb
235
238
  - performance-tests/method_invocation_test.rb
239
+ - performance-tests/raw_test.rb
236
240
  - performance-tests/test_helper.rb
237
241
  - spec/functional/advices_on_private_methods_spec.rb
238
242
  - spec/functional/aspect_on_eigen_class_spec.rb
@@ -249,32 +253,40 @@ files:
249
253
  - spec/unit/before_spec.rb
250
254
  - spec/unit/deferred_logic_spec.rb
251
255
  - spec/unit/method_matcher_spec.rb
256
+ - spec/unit/raw_spec.rb
257
+ has_rdoc: true
252
258
  homepage: http://github.com/gcao/aspector
253
- licenses:
259
+ licenses:
254
260
  - MIT
255
261
  post_install_message:
256
262
  rdoc_options: []
257
- require_paths:
263
+
264
+ require_paths:
258
265
  - lib
259
- required_ruby_version: !ruby/object:Gem::Requirement
266
+ required_ruby_version: !ruby/object:Gem::Requirement
260
267
  none: false
261
- requirements:
262
- - - ! '>='
263
- - !ruby/object:Gem::Version
264
- version: '0'
265
- segments:
268
+ requirements:
269
+ - - ">="
270
+ - !ruby/object:Gem::Version
271
+ hash: 3
272
+ segments:
266
273
  - 0
267
- hash: 3014402332352836990
268
- required_rubygems_version: !ruby/object:Gem::Requirement
274
+ version: "0"
275
+ required_rubygems_version: !ruby/object:Gem::Requirement
269
276
  none: false
270
- requirements:
271
- - - ! '>='
272
- - !ruby/object:Gem::Version
273
- version: '0'
277
+ requirements:
278
+ - - ">="
279
+ - !ruby/object:Gem::Version
280
+ hash: 3
281
+ segments:
282
+ - 0
283
+ version: "0"
274
284
  requirements: []
285
+
275
286
  rubyforge_project:
276
- rubygems_version: 1.8.18
287
+ rubygems_version: 1.6.2
277
288
  signing_key:
278
289
  specification_version: 3
279
290
  summary: Aspect Oriented Ruby Programming
280
291
  test_files: []
292
+