unroller 0.0.21 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/Readme +18 -4
  2. data/lib/unroller.rb +82 -35
  3. metadata +11 -2
data/Readme CHANGED
@@ -54,13 +54,21 @@ Say I have an ActiveRecord model and want to know exactly what actually goes on
54
54
 
55
55
  Screenshot[link:include/screenshot1.png]
56
56
 
57
- This is much more efficient and reliable than manually tracing through the execution yourself! (Trying to guess which file the <tt>save!</tt> method would be defined in, searching for the file in the depths of <tt>/usr/lib/ruby/gems</tt>, scrolling down to the right line number, and repeating a zillion times...)
57
+ (The above shows <tt>:display_style => :concise</tt>.)
58
+
59
+ This is much more efficient and reliable than manually tracing through the execution yourself! (Which would involve trying to guess which file the <tt>save!</tt> method would be defined in, searching for the file in the depths of <tt>/usr/lib/ruby/gems</tt>, scrolling down to the right line number, and repeating a zillion times...)
60
+
61
+ Here's an example of the interactive debugger mode:
62
+
63
+ Screenshot[link:include/screenshot_interactive.png]
64
+
65
+ (The above shows <tt>:display_style => :show_entire_method_body</tt>.)
58
66
 
59
67
  ===Inspecting variables
60
68
 
61
- If you'd like to see the values of all arguments/parameters that were passed into the method for each method call, just pass in the :show_args => true option.
69
+ If you'd like to see the values of all arguments/parameters that were passed into the method for each method call, just pass in the <tt>:show_args => true</tt> option.
62
70
 
63
- If you'd like to see the values of all local variables as they exist right before executing the current line, just pass in the :show_locals => true option.
71
+ If you'd like to see the values of all local variables as they exist right before executing the current line, just pass in the <tt>:show_locals => true</tt> option.
64
72
 
65
73
  Note: You might like to know that the state of those variables is _after_ executing that line, too, but currently that's not possible.
66
74
 
@@ -166,6 +174,12 @@ Here's one way you could try to answer that question...
166
174
 
167
175
  ===Usage in Rails
168
176
 
177
+ Unroller can be useful for debugging in development mode as well as in tests. Keep in mind that it requires a terminal onto which to output, so it will work if you've started your server with <tt>./script/server</tt>, but not if the server is detached from the terminal with <tt>./script/server -d</tt> or if it's being executed via FastCGI...
178
+
179
+ Rails has a lot of levels of abstractions, so even a seemingly simple call can generate many, many method calls. You may want to try using some of the filtering options, such as <tt>:exclude_classes</tt>, to reduce the verbosity of the output.
180
+
181
+ <b>Unrolling an action in your controller:</b>
182
+
169
183
  If you want to see all code that gets executed within a certain action in your controller, you can just add this snippet to your controller, request the page, and watch the console where you have Webrick running as pages and pages of ActionController/ActionRecord code go flying by...
170
184
 
171
185
  around_filter do |controller, action|
@@ -184,7 +198,7 @@ The dependencies include: facets, qualitysmith_extensions, colored, and extensio
184
198
 
185
199
  It's pretty much fully functional, but may still have a couple rough edges.
186
200
 
187
- Occasionally it has caused some segmentation faults and other weirdness for me while using it, but maybe I was just doing something stupid. Generally it behaves quite reliably and stably.
201
+ Generally it behaves quite reliably and stably.
188
202
 
189
203
  (Don't even *think* about leaving this in your production code!)
190
204
 
data/lib/unroller.rb CHANGED
@@ -3,10 +3,11 @@ gem 'facets'
3
3
  require 'facets/core/module/namespace'
4
4
  require 'facets/core/kernel/with'
5
5
  require 'facets/core/kernel/set_with'
6
- require 'facets/core/string/bracket'
7
6
  require 'facets/core/kernel/singleton_class'
8
7
  require 'facets/core/symbol/to_proc'
8
+ require 'facets/core/string/bracket'
9
9
  require 'facets/core/string/index_all'
10
+ require 'facets/core/hash/reverse_merge'
10
11
  gem 'qualitysmith_extensions'
11
12
  require 'qualitysmith_extensions/object/send_if_not_nil'
12
13
  require 'qualitysmith_extensions/kernel/trap_chain'
@@ -21,6 +22,8 @@ require 'qualitysmith_extensions/enumerable/select_until'
21
22
  require 'qualitysmith_extensions/module/bool_attr_accessor'
22
23
  gem 'colored'
23
24
  require 'colored'
25
+ gem 'extensions'
26
+ require 'extensions/object'
24
27
 
25
28
  require 'English'
26
29
  require 'pp'
@@ -86,6 +89,13 @@ class Unroller
86
89
  "#{name} = #{value.inspect}"
87
90
  end.join('; ').bracket(' (', ')')
88
91
  end
92
+ def verbose_to_s
93
+ @variables.map do |variable|
94
+ name, value = *variable
95
+ "#{name} = " +
96
+ value.pp_s.gsub(/^/, ' ')
97
+ end.join("\n")
98
+ end
89
99
  def any?
90
100
  !@variables.empty?
91
101
  end
@@ -114,8 +124,12 @@ class Unroller
114
124
 
115
125
 
116
126
 
127
+ def self.debug(options = {}, &block)
128
+ options.reverse_merge! :interactive => true, :display_style => :show_entire_method_body
129
+ self.trace options, &block
130
+ end
131
+
117
132
  def self.trace(options = {}, &block)
118
- #puts 'called self.trace'
119
133
  if @@instance and @@instance.tracing
120
134
  # In case they try to turn tracing on when it's already on... Assume it was an accident and don't do anything.
121
135
  #puts "@@instance.tracing=#{@@instance.tracing}"
@@ -332,23 +346,27 @@ class Unroller
332
346
  #zzz
333
347
  when 'call'
334
348
  unless skip_line?
335
- column sprintf(' ' + '\\'.cyan + ' calling'.cyan + ' ' + '%s'.underline.cyan, fully_qualified_method), @column_widths[0]
349
+ depth_debug = '' #" (internal_depth about to be #{@internal_depth+1})"
350
+ column sprintf(' ' + '\\'.cyan + ' calling'.cyan + ' ' + '%s'.underline.cyan + depth_debug,
351
+ fully_qualified_method), @column_widths[0]
336
352
  newline
337
353
 
338
- puts
339
- header_before_code_for_entire_method(file, line_num)
340
- do_show_locals if show_args
341
- ret = code_for_entire_method(file, line, klass, id, line, 0)
342
- puts ret unless ret.nil?
343
- puts
354
+ #puts
355
+ #header_before_code_for_entire_method(file, line_num)
356
+ #do_show_locals if show_args
357
+ #ret = code_for_entire_method(file, line, klass, id, line, 0)
358
+ #puts ret unless ret.nil?
359
+ #puts
344
360
 
345
361
  @lines_output += 1
346
362
 
347
363
 
348
364
  @depth += 1
349
365
  end
350
- @call_stack.push current_call
366
+
367
+ @call_stack.push current_call
351
368
  @internal_depth += 1
369
+ #puts "(@internal_depth+=1 ... #{@internal_depth})"
352
370
 
353
371
 
354
372
  when 'class'
@@ -363,7 +381,7 @@ class Unroller
363
381
  unless @last_call == current_call # Without this, I was seeing two consecutive events for the exact same line. This seems to be necessary because 'if foo()' is treated as two 'line' events: one for 'foo()' and one for 'if' (?)...
364
382
  puts
365
383
  header_before_code_for_entire_method(file, line_num)
366
- do_show_locals if show_locals
384
+ do_show_locals if true #show_locals
367
385
  ret = code_for_entire_method(inside_of.file, inside_of.line_num, @klass, @id, line, -1)
368
386
  puts ret unless ret.nil?
369
387
  puts
@@ -383,15 +401,16 @@ class Unroller
383
401
  print "Debugger (" +
384
402
  "Step out".menu_item(:red, 'u') + ' | ' +
385
403
  "Step over (or Enter key)".menu_item(:cyan, 'v') + ' | ' +
386
- "Step into (Space or any key)".menu_item(:green, 'i') + ' | ' +
404
+ "Step into (Space)".menu_item(:green, 'i') + ' | ' +
387
405
  "show Locals".menu_item(:yellow, 'l') + ' | ' +
388
406
  "Run".menu_item(:blue) +
389
407
  ') > '
390
408
  response = $stdin.getc.chr.downcase
409
+ puts unless response == "\n"
391
410
 
392
411
  case response
393
412
  when 'l'
394
- do_show_locals if show_locals
413
+ do_show_locals_verbosely
395
414
  response = nil
396
415
  end
397
416
  end
@@ -402,6 +421,7 @@ class Unroller
402
421
  @interactive = false
403
422
  when 'u' # Step out
404
423
  @silent_until_return_to_this_depth = @internal_depth - 1
424
+ #puts "Setting @silent_until_return_to_this_depth = #{@silent_until_return_to_this_depth}"
405
425
  when 'v', "\n" # Step over = Ignore anything with a greater depth.
406
426
  @only_makes_sense_if_next_event_is_call = true
407
427
  @silent_until_return_to_this_depth = @internal_depth
@@ -418,29 +438,33 @@ class Unroller
418
438
  when 'return'
419
439
 
420
440
  @internal_depth -= 1
441
+ #puts "(@internal_depth-=1 ... #{@internal_depth})"
442
+
443
+ # Did we just get out of an uninteresting call?? Are we back in interesting land again??
444
+ if @silent_until_return_to_this_depth and
445
+ @silent_until_return_to_this_depth == @internal_depth
446
+ #puts "Yay, we're back in interesting land! (@internal_depth = #{@internal_depth})"
447
+ @silent_until_return_to_this_depth = nil
448
+ end
449
+
450
+
421
451
  unless skip_line?
422
452
  puts "Warning: @depth < 0. You may wish to call trace with a :depth => depth value greater than #{@initial_depth}" if @depth-1 < 0
423
453
  @depth -= 1 unless @depth == 0
424
454
  #puts "-- Decreased depth to #{depth}"
425
455
  returning_from = @call_stack.last
426
456
 
427
- column sprintf(' ' + '/'.cyan + ' returning from'.cyan + ' ' + '%s'.cyan, returning_from && returning_from.full_name), @column_widths[0]
457
+ depth_debug = '' #" (internal_depth was #{@internal_depth+1})"
458
+ column sprintf(' ' + '/'.cyan + ' returning from'.cyan + ' ' + '%s'.cyan + depth_debug,
459
+ returning_from && returning_from.full_name), @column_widths[0]
428
460
  newline
429
461
 
430
462
  @lines_output += 1
431
463
  end
432
464
 
433
- # Did we just get out of an uninteresting call?? Are we back in interesting land again??
434
- if @silent_until_return_to_this_depth and
435
- @silent_until_return_to_this_depth == @internal_depth
436
- puts "Yay, we're back in interesting land!"
437
- @silent_until_return_to_this_depth = nil
438
- end
439
-
440
465
  @call_stack.pop
441
466
 
442
467
 
443
-
444
468
  when 'raise'
445
469
  if !skip_line? or @always_show_raise_events
446
470
  # We probably always want to see these (?)... Never skip displaying them, even if we are "too deep".
@@ -850,6 +874,15 @@ protected
850
874
  def header_before_code_for_entire_method(file, line_num)
851
875
  puts '' + "#{fully_qualified_method} (#{file}:#{line_num}) (#{@event}):".magenta if show_filename_and_line_numbers
852
876
  end
877
+
878
+ def do_show_locals_verbosely
879
+ variables = Variables.new(:local, @binding)
880
+ if variables.any?
881
+ puts variables.verbose_to_s.yellow
882
+ end
883
+ end
884
+
885
+
853
886
  end # class Unroller
854
887
 
855
888
 
@@ -1138,7 +1171,7 @@ if $0 == __FILE__
1138
1171
  herald '-----------------------------------------------------------'
1139
1172
  herald 'Test @exclude_methods'
1140
1173
  herald 'Should only see calls to green, strong'
1141
- class Wasabi
1174
+ class Wasabi #:nodoc:
1142
1175
  def green
1143
1176
  '...'
1144
1177
  end
@@ -1170,7 +1203,7 @@ if $0 == __FILE__
1170
1203
  herald '-----------------------------------------------------------'
1171
1204
  herald 'Test @exclude_classes'
1172
1205
  herald 'Should only see calls to Interesting::...'
1173
- class Interesting
1206
+ class Interesting #:nodoc:
1174
1207
  def self.method
1175
1208
  '...'
1176
1209
  end
@@ -1179,9 +1212,9 @@ if $0 == __FILE__
1179
1212
  end
1180
1213
 
1181
1214
  end
1182
- module Uninteresting
1215
+ module Uninteresting #:nodoc:
1183
1216
 
1184
- class ClassThatCluttersUpOnesTraces
1217
+ class ClassThatCluttersUpOnesTraces #:nodoc:
1185
1218
  ('a'..last='h').each do |method_name|
1186
1219
  next_method_name = method_name.next unless method_name == last
1187
1220
  eval <<-End, binding, __FILE__, __LINE__ + 1
@@ -1251,7 +1284,7 @@ if $0 == __FILE__
1251
1284
  herald '-----------------------------------------------------------'
1252
1285
  herald 'Test class definition'
1253
1286
  Unroller::trace do
1254
- class NewClass
1287
+ class NewClass #:nodoc:
1255
1288
  def hi
1256
1289
  'hi'
1257
1290
  end
@@ -1283,12 +1316,12 @@ if $0 == __FILE__
1283
1316
 
1284
1317
  herald '-----------------------------------------------------------'
1285
1318
  herald 'Testing the :rails "preset"'
1286
- module ActiveSupport
1319
+ module ActiveSupport #:nodoc:
1287
1320
  def self.whatever
1288
1321
  'whatever'
1289
1322
  end
1290
1323
  end
1291
- module ActiveMongoose
1324
+ module ActiveMongoose #:nodoc:
1292
1325
  def self.whatever
1293
1326
  'whatever'
1294
1327
  end
@@ -1301,14 +1334,14 @@ if $0 == __FILE__
1301
1334
 
1302
1335
  herald '-----------------------------------------------------------'
1303
1336
  herald 'Testing the :dependencies "preset"'
1304
- module ActiveSupport
1305
- module Dependencies
1337
+ module ActiveSupport #:nodoc:
1338
+ module Dependencies #:nodoc:
1306
1339
  def self.whatever
1307
1340
  'whatever'
1308
1341
  end
1309
1342
  end
1310
1343
  end
1311
- module Gem
1344
+ module Gem #:nodoc:
1312
1345
  def self.whatever
1313
1346
  'whatever'
1314
1347
  end
@@ -1334,11 +1367,11 @@ if $0 == __FILE__
1334
1367
 
1335
1368
  herald '-----------------------------------------------------------'
1336
1369
  herald 'Testing watch_for_added_methods'
1337
- class Foo
1370
+ class Foo #:nodoc:
1338
1371
  def existing_method; end
1339
1372
  end
1340
1373
  Unroller::watch_for_added_methods(Foo, /interesting/) do
1341
- class Foo
1374
+ class Foo #:nodoc:
1342
1375
  def foo; end
1343
1376
  def an_interesting_method; end
1344
1377
  end
@@ -1371,6 +1404,19 @@ if $0 == __FILE__
1371
1404
  big_ol_gaggle
1372
1405
  end
1373
1406
 
1407
+ herald '-----------------------------------------------------------'
1408
+ herald 'Testing :interactive => true / interactive debugger'
1409
+ def factorial(x)
1410
+ if x == 1
1411
+ x
1412
+ else
1413
+ x * factorial(x - 1)
1414
+ end
1415
+ end
1416
+ Unroller::debug do
1417
+ factorial(4)
1418
+ end
1419
+
1374
1420
  herald '-----------------------------------------------------------'
1375
1421
  herald 'Testing :interactive => true / interactive debugger'
1376
1422
  def subway
@@ -1396,7 +1442,8 @@ if $0 == __FILE__
1396
1442
  _do = nil
1397
1443
  _do = nil
1398
1444
  end
1399
- Unroller::trace :display_style => :show_entire_method_body, :interactive => true do
1445
+ #Unroller::trace :display_style => :show_entire_method_body, :interactive => true do
1446
+ Unroller::debug do
1400
1447
  subway
1401
1448
  end
1402
1449
 
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: unroller
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.0.21
7
- date: 2007-06-06 00:00:00 -07:00
6
+ version: 0.0.22
7
+ date: 2007-06-18 00:00:00 -07:00
8
8
  summary: "Ruby Code Unroller: A tool for generating human-readable \"execution traces\""
9
9
  require_paths:
10
10
  - lib
@@ -84,3 +84,12 @@ dependencies:
84
84
  - !ruby/object:Gem::Version
85
85
  version: 0.0.0
86
86
  version:
87
+ - !ruby/object:Gem::Dependency
88
+ name: extensions
89
+ version_requirement:
90
+ version_requirements: !ruby/object:Gem::Version::Requirement
91
+ requirements:
92
+ - - ">"
93
+ - !ruby/object:Gem::Version
94
+ version: 0.0.0
95
+ version: