defly 0.1.0 → 0.2.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/Gemfile +2 -0
- data/Gemfile.lock +2 -0
- data/README.md +67 -17
- data/VERSION +1 -1
- data/defly.gemspec +7 -2
- data/lib/defly.rb +10 -1
- data/lib/inspectable.rb +26 -0
- data/lib/tracable.rb +18 -27
- data/lib/whinable.rb +19 -0
- metadata +24 -11
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -6,12 +6,19 @@ A ruby debugging tool. Easy way to trace function calls and variables.
|
|
6
6
|
|
7
7
|
Just `gem install defly`.
|
8
8
|
|
9
|
-
##
|
9
|
+
## Feature
|
10
|
+
* Trace method calls: including arguments and return values
|
11
|
+
* Trace variable changes
|
12
|
+
* Showing source code when NoMethodError is thrown
|
13
|
+
* Opening a shell when a particular error occurred
|
14
|
+
|
15
|
+
## Tracing method and instance variables
|
10
16
|
|
11
17
|
### Input
|
12
18
|
|
13
19
|
```ruby
|
14
20
|
require 'defly'
|
21
|
+
|
15
22
|
class Warrior
|
16
23
|
attr_accessor :hp, :mp
|
17
24
|
|
@@ -21,7 +28,8 @@ class Warrior
|
|
21
28
|
end
|
22
29
|
end
|
23
30
|
|
24
|
-
Warrior.
|
31
|
+
Warrior.debug!
|
32
|
+
Warrior.new.trace([:hp, :hp=, :mp, :mp=, :sleep], [:@hp, :@mp]) do |warrior|
|
25
33
|
warrior.hp = 10
|
26
34
|
warrior.mp = 20
|
27
35
|
warrior.sleep
|
@@ -30,30 +38,72 @@ end
|
|
30
38
|
|
31
39
|
### Output (Run on IRB)
|
32
40
|
|
33
|
-
Tracing hp, hp=, mp, mp
|
34
|
-
Tracing @hp, @mp
|
35
|
-
<<<<< Warrior#hp=(10) # (irb):
|
41
|
+
Tracing hp, hp=, mp, mp=, sleep on Warrior instance
|
42
|
+
Tracing @hp, @mp on Warrior instance
|
43
|
+
<<<<< Warrior#hp=(10) # (irb):14:in `block in irb_binding'
|
36
44
|
@hp = 10 # undefined
|
37
45
|
@mp = nil # undefined
|
38
46
|
>>>>> 10
|
39
|
-
<<<<< Warrior#mp=(20) # (irb):
|
47
|
+
<<<<< Warrior#mp=(20) # (irb):15:in `block in irb_binding'
|
40
48
|
@mp = 20 # undefined
|
41
49
|
>>>>> 20
|
42
|
-
<<<<< Warrior#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
50
|
+
<<<<< Warrior#sleep() # (irb):16:in `block in irb_binding'
|
51
|
+
<<<<< Warrior#hp() # (irb):7:in `sleep'
|
52
|
+
>>>>> 10
|
53
|
+
<<<<< Warrior#hp=(20) # (irb):7:in `sleep'
|
54
|
+
@hp = 20 # 10 -> 20
|
55
|
+
>>>>> 20
|
56
|
+
<<<<< Warrior#mp() # (irb):8:in `sleep'
|
57
|
+
>>>>> 20
|
58
|
+
<<<<< Warrior#mp=(22) # (irb):8:in `sleep'
|
59
|
+
@mp = 22 # 20 -> 22
|
60
|
+
>>>>> 22
|
51
61
|
>>>>> 22
|
52
|
-
=> #<Warrior:0x00000100987488 @defly_methods=[:hp, :hp=, :mp, :mp=], @defly_variables=[:@hp, :@mp], @__defly_level=0, @hp=20, @__defly={:@hp=>20, :@mp=>22}, @mp=22>
|
53
62
|
|
63
|
+
## Better Error Message
|
64
|
+
|
65
|
+
### NoMethodError
|
66
|
+
|
67
|
+
Showing the exact code and the position of the error.
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
irb(main):001:0> require 'defly'
|
71
|
+
=> true
|
72
|
+
irb(main):002:0> require 'bug'
|
73
|
+
NoMethodError: undefined method `is_annoying' for "debugging":String
|
74
|
+
bug.rb:1> "debugging".<<is_annoying>>
|
75
|
+
from /Users/eggegg/bug.rb:1:in `<top (required)>'
|
76
|
+
...
|
77
|
+
```
|
78
|
+
|
79
|
+
## Inspecting error
|
80
|
+
|
81
|
+
### Input
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
class Rocket
|
85
|
+
def launch
|
86
|
+
@reason = "Bugs invasion"
|
87
|
+
raise "Engine Fail"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
Rocket.debug!
|
92
|
+
rocket = Rocket.new
|
93
|
+
rocket.watch_error "Engine Fail"
|
94
|
+
rocket.launch
|
95
|
+
```
|
96
|
+
|
97
|
+
### Output
|
98
|
+
|
99
|
+
>>>>> Error received:
|
100
|
+
"Engine Fail"
|
101
|
+
>>>>>
|
102
|
+
#<Rocket:0(0)>> @reason
|
103
|
+
=> "Bugs invasion"
|
104
|
+
#<Rocket:0(0)>>
|
54
105
|
|
55
106
|
## Copyright
|
56
107
|
|
57
108
|
Copyright (c) 2011 Andrew Liu. See LICENSE.txt for
|
58
109
|
further details.
|
59
|
-
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/defly.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{defly}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Andrew Liu"]
|
12
|
-
s.date = %q{2011-08-
|
12
|
+
s.date = %q{2011-08-26}
|
13
13
|
s.description = %q{Trace methods and instance variables with ease!}
|
14
14
|
s.email = %q{andrewliu33@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -26,7 +26,9 @@ Gem::Specification.new do |s|
|
|
26
26
|
"VERSION",
|
27
27
|
"defly.gemspec",
|
28
28
|
"lib/defly.rb",
|
29
|
+
"lib/inspectable.rb",
|
29
30
|
"lib/tracable.rb",
|
31
|
+
"lib/whinable.rb",
|
30
32
|
"test/helper.rb",
|
31
33
|
"test/test_defly.rb"
|
32
34
|
]
|
@@ -40,17 +42,20 @@ Gem::Specification.new do |s|
|
|
40
42
|
s.specification_version = 3
|
41
43
|
|
42
44
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
45
|
+
s.add_runtime_dependency(%q<rib>, [">= 0"])
|
43
46
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
44
47
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
45
48
|
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
46
49
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
47
50
|
else
|
51
|
+
s.add_dependency(%q<rib>, [">= 0"])
|
48
52
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
49
53
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
50
54
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
51
55
|
s.add_dependency(%q<rcov>, [">= 0"])
|
52
56
|
end
|
53
57
|
else
|
58
|
+
s.add_dependency(%q<rib>, [">= 0"])
|
54
59
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
55
60
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
56
61
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
data/lib/defly.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
require 'tracable'
|
2
|
+
require 'whinable'
|
3
|
+
require 'inspectable'
|
2
4
|
|
3
5
|
module Defly
|
4
6
|
end
|
5
7
|
|
6
|
-
|
8
|
+
class Class
|
9
|
+
def debug!
|
10
|
+
self.send(:include, Defly::Inspectable)
|
11
|
+
self.send(:include, Defly::Tracable)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
NoMethodError.send(:include, Defly::Whinable)
|
data/lib/inspectable.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rib/core'
|
2
|
+
require 'rib/more'
|
3
|
+
|
4
|
+
module Defly
|
5
|
+
module Inspectable
|
6
|
+
def watch_error error
|
7
|
+
@__defly_watch ||= []
|
8
|
+
@__defly_watch << error
|
9
|
+
end
|
10
|
+
|
11
|
+
def raise error
|
12
|
+
@__defly_watch ||= []
|
13
|
+
|
14
|
+
if @__defly_watch.include? error.class or @__defly_watch.include? error
|
15
|
+
puts ">>>>> Error received:"
|
16
|
+
p error
|
17
|
+
puts ">>>>> "
|
18
|
+
|
19
|
+
Rib.enable_anchor do
|
20
|
+
Rib.anchor self
|
21
|
+
end
|
22
|
+
end
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/tracable.rb
CHANGED
@@ -10,12 +10,12 @@ module Defly
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def trace_method!(methods)
|
13
|
-
@
|
13
|
+
@__defly_methods ||= []
|
14
14
|
|
15
15
|
methods = public_methods(false) if methods.size == 0
|
16
16
|
methods.map! {|m| m.to_sym }
|
17
|
-
methods -= @
|
18
|
-
@
|
17
|
+
methods -= @__defly_methods
|
18
|
+
@__defly_methods |= methods
|
19
19
|
|
20
20
|
STDERR << "Tracing #{methods.join(', ')} on #{self.class} instance\n"
|
21
21
|
|
@@ -30,7 +30,7 @@ module Defly
|
|
30
30
|
@__defly_level += 1
|
31
31
|
result = super
|
32
32
|
@__defly_level -= 1
|
33
|
-
|
33
|
+
__defly_check_var(indent) if defined? __defly_check_var
|
34
34
|
STDERR << "\#{indent}>>>>> \#{result}\n"
|
35
35
|
result
|
36
36
|
rescue
|
@@ -43,37 +43,28 @@ module Defly
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def trace_variable!(variables)
|
46
|
-
@
|
46
|
+
@__defly_variables ||= []
|
47
47
|
|
48
48
|
variables = instance_variables if variables.size == 0
|
49
49
|
variables.map! {|v| v.to_sym }
|
50
|
-
variables -= @
|
51
|
-
@
|
50
|
+
variables -= @__defly_variables
|
51
|
+
@__defly_variables |= variables
|
52
52
|
|
53
|
-
STDERR << "Tracing #{variables.join(', ')}
|
53
|
+
STDERR << "Tracing #{variables.join(', ')} on #{self.class} instance\n"
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
eigenclass.class_eval <<-RUBY, __FILE__, __LINE__
|
58
|
-
def defly_check_var_list
|
59
|
-
[#{@defly_variables.map(&:inspect).join(', ')}]
|
60
|
-
end
|
61
|
-
RUBY
|
62
|
-
|
63
|
-
unless eigenclass.instance_methods.include? :defly_check_var
|
55
|
+
unless eigenclass.instance_methods.include? :__defly_check_var
|
64
56
|
eigenclass.class_eval <<-RUBY, __FILE__, __LINE__
|
65
|
-
def
|
66
|
-
@
|
57
|
+
def __defly_check_var(indent)
|
58
|
+
@__defly_varmap ||= {}
|
67
59
|
|
68
|
-
|
69
|
-
var_list.each do |v|
|
60
|
+
@__defly_variables.each do |v|
|
70
61
|
new_val = instance_variable_get(v)
|
71
|
-
if @
|
72
|
-
STDERR << " \#{indent}\#{v.to_s} = \#{new_val.inspect} # \#{@
|
62
|
+
if @__defly_varmap[v]
|
63
|
+
STDERR << " \#{indent}\#{v.to_s} = \#{new_val.inspect} # \#{@__defly_varmap[v].inspect} -> \#{new_val.inspect}\n" unless @__defly_varmap[v] == new_val
|
73
64
|
else
|
74
65
|
STDERR << " \#{indent}\#{v.to_s} = \#{new_val.inspect} # undefined\n"
|
75
66
|
end
|
76
|
-
@
|
67
|
+
@__defly_varmap[v] = new_val
|
77
68
|
end
|
78
69
|
end
|
79
70
|
RUBY
|
@@ -81,8 +72,8 @@ module Defly
|
|
81
72
|
end
|
82
73
|
|
83
74
|
def untrace!
|
84
|
-
[:
|
85
|
-
eigenclass.remove_method
|
75
|
+
[:__defly_check_var].concat(@__defly_methods).each do |m|
|
76
|
+
eigenclass.send(:remove_method, m) if eigenclass.instance_methods.include? m
|
86
77
|
end
|
87
78
|
end
|
88
79
|
|
@@ -90,4 +81,4 @@ module Defly
|
|
90
81
|
class << self; self; end
|
91
82
|
end
|
92
83
|
end
|
93
|
-
end
|
84
|
+
end
|
data/lib/whinable.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Defly
|
2
|
+
module Whinable
|
3
|
+
def to_s
|
4
|
+
orig_message = super
|
5
|
+
position = backtrace[0]
|
6
|
+
message = ""
|
7
|
+
missing_method = name.to_s
|
8
|
+
|
9
|
+
unless /^\(.*\):.*/ =~ position # skipping irb
|
10
|
+
file, line, other = position.split(':')
|
11
|
+
code = IO.readlines(file)[line.to_i - 1].chomp
|
12
|
+
code.gsub!(/(#{missing_method})/, '<<\1>>')
|
13
|
+
message = "#{file.split('/')[-1]}:#{line}> #{code}"
|
14
|
+
end
|
15
|
+
|
16
|
+
"#{orig_message}\n#{message}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: defly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,23 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-08-
|
12
|
+
date: 2011-08-26 00:00:00.000000000 +08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rib
|
17
|
+
requirement: &2153950820 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2153950820
|
15
26
|
- !ruby/object:Gem::Dependency
|
16
27
|
name: shoulda
|
17
|
-
requirement: &
|
28
|
+
requirement: &2153949880 !ruby/object:Gem::Requirement
|
18
29
|
none: false
|
19
30
|
requirements:
|
20
31
|
- - ! '>='
|
@@ -22,10 +33,10 @@ dependencies:
|
|
22
33
|
version: '0'
|
23
34
|
type: :development
|
24
35
|
prerelease: false
|
25
|
-
version_requirements: *
|
36
|
+
version_requirements: *2153949880
|
26
37
|
- !ruby/object:Gem::Dependency
|
27
38
|
name: bundler
|
28
|
-
requirement: &
|
39
|
+
requirement: &2153948960 !ruby/object:Gem::Requirement
|
29
40
|
none: false
|
30
41
|
requirements:
|
31
42
|
- - ~>
|
@@ -33,10 +44,10 @@ dependencies:
|
|
33
44
|
version: 1.0.0
|
34
45
|
type: :development
|
35
46
|
prerelease: false
|
36
|
-
version_requirements: *
|
47
|
+
version_requirements: *2153948960
|
37
48
|
- !ruby/object:Gem::Dependency
|
38
49
|
name: jeweler
|
39
|
-
requirement: &
|
50
|
+
requirement: &2153947960 !ruby/object:Gem::Requirement
|
40
51
|
none: false
|
41
52
|
requirements:
|
42
53
|
- - ~>
|
@@ -44,10 +55,10 @@ dependencies:
|
|
44
55
|
version: 1.6.4
|
45
56
|
type: :development
|
46
57
|
prerelease: false
|
47
|
-
version_requirements: *
|
58
|
+
version_requirements: *2153947960
|
48
59
|
- !ruby/object:Gem::Dependency
|
49
60
|
name: rcov
|
50
|
-
requirement: &
|
61
|
+
requirement: &2153946880 !ruby/object:Gem::Requirement
|
51
62
|
none: false
|
52
63
|
requirements:
|
53
64
|
- - ! '>='
|
@@ -55,7 +66,7 @@ dependencies:
|
|
55
66
|
version: '0'
|
56
67
|
type: :development
|
57
68
|
prerelease: false
|
58
|
-
version_requirements: *
|
69
|
+
version_requirements: *2153946880
|
59
70
|
description: Trace methods and instance variables with ease!
|
60
71
|
email: andrewliu33@gmail.com
|
61
72
|
executables: []
|
@@ -73,7 +84,9 @@ files:
|
|
73
84
|
- VERSION
|
74
85
|
- defly.gemspec
|
75
86
|
- lib/defly.rb
|
87
|
+
- lib/inspectable.rb
|
76
88
|
- lib/tracable.rb
|
89
|
+
- lib/whinable.rb
|
77
90
|
- test/helper.rb
|
78
91
|
- test/test_defly.rb
|
79
92
|
has_rdoc: true
|
@@ -92,7 +105,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
92
105
|
version: '0'
|
93
106
|
segments:
|
94
107
|
- 0
|
95
|
-
hash: -
|
108
|
+
hash: -1635137758272325934
|
96
109
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
110
|
none: false
|
98
111
|
requirements:
|