SuperCaller 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/Manifest.txt +6 -0
- data/README.txt +55 -0
- data/Rakefile +20 -0
- data/lib/super_caller.rb +113 -0
- data/lib/super_caller/exception.rb +31 -0
- metadata +86 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
= SuperCaller
|
2
|
+
|
3
|
+
A Kernel#caller enhancement
|
4
|
+
|
5
|
+
Documentation:
|
6
|
+
|
7
|
+
http://seattlerb.org/SuperCaller
|
8
|
+
|
9
|
+
File Bugs:
|
10
|
+
|
11
|
+
http://rubyforge.org/tracker/?func=add&group_id=1513&atid=5921
|
12
|
+
|
13
|
+
== DESCRIPTION:
|
14
|
+
|
15
|
+
SuperCaller adds a beefed-up version of Kernel#caller and a beefed up
|
16
|
+
version of Exception#backtrace.
|
17
|
+
|
18
|
+
== FEATURES/PROBLEMS:
|
19
|
+
|
20
|
+
* Can cause Ruby to crash when an Exception with SuperCaller's
|
21
|
+
backtrace reaches the top level.
|
22
|
+
|
23
|
+
== SYNOPSIS:
|
24
|
+
|
25
|
+
Regular old Kernel#super_caller:
|
26
|
+
|
27
|
+
require 'super_caller'
|
28
|
+
|
29
|
+
def something() super_caller end
|
30
|
+
stack = something
|
31
|
+
p stack.first.file # => "-"
|
32
|
+
p stack.first.line # => 4
|
33
|
+
p stack.first.method_name # => nil
|
34
|
+
p stack.first.self # => main
|
35
|
+
p stack.first.sexp # => [:vcall, :super_caller]
|
36
|
+
p stack.first.source # => "def something\n super_caller\nend"
|
37
|
+
|
38
|
+
Fancy Exception#backtrace:
|
39
|
+
|
40
|
+
require 'super_caller/exception'
|
41
|
+
|
42
|
+
def raiser() raise end
|
43
|
+
|
44
|
+
def raisee
|
45
|
+
raiser
|
46
|
+
rescue => e
|
47
|
+
p e.backtrace.first.sexp
|
48
|
+
end
|
49
|
+
|
50
|
+
raiser # => [:vcall, :raise]
|
51
|
+
|
52
|
+
== INSTALL:
|
53
|
+
|
54
|
+
sudo gem install SuperCaller
|
55
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/super_caller.rb'
|
6
|
+
|
7
|
+
Hoe.new('SuperCaller', SuperCaller::VERSION) do |p|
|
8
|
+
p.rubyforge_name = 'seattlerb'
|
9
|
+
p.author = 'Eric Hodel'
|
10
|
+
p.email = 'drbrain@segment7.net'
|
11
|
+
p.summary = p.paragraphs_of('README.txt', 1).first
|
12
|
+
p.description = p.paragraphs_of('README.txt', 7).first
|
13
|
+
p.url = p.paragraphs_of('README.txt', 3).first
|
14
|
+
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
15
|
+
|
16
|
+
p.extra_deps << ['ParseTree', '~> 2.0']
|
17
|
+
p.extra_deps << ['ruby2ruby', '~> 1.1']
|
18
|
+
end
|
19
|
+
|
20
|
+
# vim: syntax=Ruby
|
data/lib/super_caller.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'inline'
|
3
|
+
require 'parse_tree'
|
4
|
+
require 'ruby2ruby'
|
5
|
+
|
6
|
+
module SuperCaller
|
7
|
+
|
8
|
+
VERSION = '1.0.0'
|
9
|
+
|
10
|
+
Frame = Struct.new :file, :line, :method_name, :self, :sexp
|
11
|
+
|
12
|
+
class Frame
|
13
|
+
def to_s
|
14
|
+
if method_name then
|
15
|
+
"%s:%d:in `%s'" % [file, line, method_name]
|
16
|
+
else
|
17
|
+
"%s:%d" % [file, line]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
alias to_str to_s
|
22
|
+
|
23
|
+
def split(*args)
|
24
|
+
to_s.split(*args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def source
|
28
|
+
return unless method_name
|
29
|
+
sexp = Sexp.for self.self.class, method_name, true
|
30
|
+
return if s(nil) == sexp
|
31
|
+
RubyToRuby.new.process sexp rescue nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
inline :C do |builder|
|
36
|
+
builder.include '"ruby.h"'
|
37
|
+
builder.include '"node.h"'
|
38
|
+
builder.include '"env.h"'
|
39
|
+
|
40
|
+
builder.prefix <<-'EOF'
|
41
|
+
static VALUE rb_mSuperCaller = Qnil;
|
42
|
+
static VALUE rb_cSuperCaller_Frame = Qnil;
|
43
|
+
|
44
|
+
void add_to_parse_tree(VALUE ary,
|
45
|
+
NODE * n,
|
46
|
+
VALUE newlines,
|
47
|
+
ID * locals);
|
48
|
+
|
49
|
+
static VALUE node_to_sexp(NODE * node) {
|
50
|
+
VALUE sexp = rb_ary_new();
|
51
|
+
|
52
|
+
add_to_parse_tree(sexp, node, Qfalse, NULL);
|
53
|
+
|
54
|
+
if (RARRAY(sexp)->len == 0) {
|
55
|
+
return Qnil;
|
56
|
+
} else {
|
57
|
+
return RARRAY(sexp)->ptr[0];
|
58
|
+
}
|
59
|
+
}
|
60
|
+
EOF
|
61
|
+
|
62
|
+
builder.c <<-'EOF'
|
63
|
+
static VALUE
|
64
|
+
super_caller() {
|
65
|
+
struct FRAME * c_frame = ruby_frame;
|
66
|
+
VALUE r_frame, stack, method_name;
|
67
|
+
NODE * n;
|
68
|
+
|
69
|
+
if (NIL_P(rb_cSuperCaller_Frame)) {
|
70
|
+
rb_mSuperCaller =
|
71
|
+
rb_const_get(rb_cObject, rb_intern("SuperCaller"));
|
72
|
+
rb_cSuperCaller_Frame =
|
73
|
+
rb_const_get(rb_mSuperCaller, rb_intern("Frame"));
|
74
|
+
}
|
75
|
+
|
76
|
+
stack = rb_ary_new();
|
77
|
+
|
78
|
+
if (c_frame->last_func == ID_ALLOCATOR)
|
79
|
+
c_frame = c_frame->prev;
|
80
|
+
|
81
|
+
for (; c_frame && (n = c_frame->node); c_frame = c_frame->prev) {
|
82
|
+
if (c_frame->prev && c_frame->prev->last_func) {
|
83
|
+
if (c_frame->prev->node == n) {
|
84
|
+
if (c_frame->prev->last_func == c_frame->last_func)
|
85
|
+
continue;
|
86
|
+
}
|
87
|
+
|
88
|
+
method_name = ID2SYM(c_frame->prev->last_func);
|
89
|
+
} else {
|
90
|
+
method_name = Qnil;
|
91
|
+
}
|
92
|
+
|
93
|
+
r_frame = rb_funcall(rb_cSuperCaller_Frame, rb_intern("new"), 5,
|
94
|
+
rb_str_new2(n->nd_file),
|
95
|
+
INT2FIX(nd_line(n)),
|
96
|
+
method_name,
|
97
|
+
c_frame->self,
|
98
|
+
node_to_sexp(n));
|
99
|
+
|
100
|
+
rb_ary_push(stack, r_frame);
|
101
|
+
}
|
102
|
+
|
103
|
+
return stack;
|
104
|
+
}
|
105
|
+
EOF
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
class Object
|
111
|
+
include SuperCaller
|
112
|
+
end
|
113
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'super_caller'
|
2
|
+
|
3
|
+
module Kernel
|
4
|
+
|
5
|
+
alias old_raise raise
|
6
|
+
|
7
|
+
def raise(*args)
|
8
|
+
old_raise(*args)
|
9
|
+
rescue Exception => e
|
10
|
+
e.backtrace = super_caller[1..-1]
|
11
|
+
old_raise e
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
class Exception
|
17
|
+
|
18
|
+
alias old_backtrace backtrace
|
19
|
+
|
20
|
+
attr_reader :backtrace
|
21
|
+
|
22
|
+
alias old_set_backtrace set_backtrace
|
23
|
+
|
24
|
+
def backtrace=(backtrace)
|
25
|
+
old_set_backtrace backtrace.map { |frame| frame.to_s }
|
26
|
+
@backtrace = backtrace
|
27
|
+
end
|
28
|
+
|
29
|
+
alias set_backtrace backtrace=
|
30
|
+
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4.3
|
3
|
+
specification_version: 1
|
4
|
+
name: SuperCaller
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2007-08-04 00:00:00 -07:00
|
8
|
+
summary: A Kernel#caller enhancement
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: drbrain@segment7.net
|
12
|
+
homepage: http://seattlerb.org/SuperCaller
|
13
|
+
rubyforge_project: seattlerb
|
14
|
+
description: SuperCaller adds a beefed-up version of Kernel#caller and a beefed up version of Exception#backtrace.
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.0.0
|
30
|
+
version:
|
31
|
+
platform: ruby
|
32
|
+
signing_key:
|
33
|
+
cert_chain:
|
34
|
+
post_install_message:
|
35
|
+
authors:
|
36
|
+
- Eric Hodel
|
37
|
+
files:
|
38
|
+
- History.txt
|
39
|
+
- Manifest.txt
|
40
|
+
- README.txt
|
41
|
+
- Rakefile
|
42
|
+
- lib/super_caller.rb
|
43
|
+
- lib/super_caller/exception.rb
|
44
|
+
test_files: []
|
45
|
+
|
46
|
+
rdoc_options:
|
47
|
+
- --main
|
48
|
+
- README.txt
|
49
|
+
extra_rdoc_files:
|
50
|
+
- History.txt
|
51
|
+
- Manifest.txt
|
52
|
+
- README.txt
|
53
|
+
executables: []
|
54
|
+
|
55
|
+
extensions: []
|
56
|
+
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
dependencies:
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: ParseTree
|
62
|
+
version_requirement:
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ~>
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "2.0"
|
68
|
+
version:
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: ruby2ruby
|
71
|
+
version_requirement:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: "1.1"
|
77
|
+
version:
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: hoe
|
80
|
+
version_requirement:
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 1.2.2
|
86
|
+
version:
|