kefka 0.0.2 → 0.0.3
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 +1 -1
- data/app.rb +18 -3
- data/kefka.gemspec +2 -2
- data/lib/kefka.rb +29 -13
- data/public/javascripts/app.js +16 -10
- data/views/index.erb +12 -1
- metadata +21 -21
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
data/app.rb
CHANGED
@@ -12,21 +12,36 @@ end
|
|
12
12
|
get '/callgraph' do
|
13
13
|
content_type :json
|
14
14
|
|
15
|
-
path = "examples/sample_a.rb"
|
15
|
+
path = "#{File.expand_path(File.dirname(__FILE__))}/examples/sample_a.rb"
|
16
16
|
file = File.open(path)
|
17
17
|
|
18
18
|
@tracer = Kefka::Tracer.new
|
19
19
|
@tracer.trace(file, :callgraph_handler)
|
20
20
|
|
21
|
+
# input code
|
22
|
+
code = CodeRay.scan(@tracer.code, :ruby).div(:line_numbers => :table)
|
23
|
+
|
21
24
|
graph = @tracer.method_graph
|
25
|
+
|
26
|
+
# output call graph using dot if graphviz is installed
|
27
|
+
if graphviz_installed = system("which dot")
|
28
|
+
graph.write_to_graphic_file("png", "#{File.expand_path(File.dirname(__FILE__))}/public/graph")
|
29
|
+
end
|
30
|
+
|
31
|
+
# html code graph
|
22
32
|
graph.vertices.each { |method| method.format = :html }
|
23
|
-
|
33
|
+
|
34
|
+
{
|
35
|
+
:code => code,
|
36
|
+
:graphviz_installed => graphviz_installed,
|
37
|
+
:graph => graph
|
38
|
+
}.to_json
|
24
39
|
end
|
25
40
|
|
26
41
|
get '/locals' do
|
27
42
|
content_type :json
|
28
43
|
|
29
|
-
path = "examples/sample_a.rb"
|
44
|
+
path = "#{File.expand_path(File.dirname(__FILE__))}/examples/sample_a.rb"
|
30
45
|
file = File.open(path)
|
31
46
|
|
32
47
|
tracer = Kefka::Tracer.new
|
data/kefka.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "kefka"
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Reginald Tan"]
|
12
|
-
s.date = "2012-
|
12
|
+
s.date = "2012-08-12"
|
13
13
|
s.description = " It traces the execution path of a program and displays the source code of each method call in the callgraph "
|
14
14
|
s.email = "redge.tan@gmail.com"
|
15
15
|
s.executables = ["kefka"]
|
data/lib/kefka.rb
CHANGED
@@ -22,12 +22,10 @@ class Kefka
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def source_location
|
25
|
-
return nil unless @file && @line
|
26
25
|
[@file,@line]
|
27
26
|
end
|
28
27
|
|
29
28
|
def end_line
|
30
|
-
return nil unless @line && source
|
31
29
|
@line + source.lines.count - 1
|
32
30
|
end
|
33
31
|
|
@@ -61,6 +59,14 @@ class Kefka
|
|
61
59
|
"#{classname} #{id}"
|
62
60
|
end
|
63
61
|
|
62
|
+
def eql?(other)
|
63
|
+
self.key == other.key
|
64
|
+
end
|
65
|
+
|
66
|
+
def hash
|
67
|
+
[@file,@line].hash
|
68
|
+
end
|
69
|
+
|
64
70
|
def to_json(*a)
|
65
71
|
{
|
66
72
|
:classname => @classname,
|
@@ -97,7 +103,8 @@ class Kefka
|
|
97
103
|
|
98
104
|
class Tracer
|
99
105
|
|
100
|
-
attr_reader :
|
106
|
+
attr_reader :local_values, :logger, :callstack, :method_graph,
|
107
|
+
:code
|
101
108
|
|
102
109
|
def initialize(log_level = Logger::INFO)
|
103
110
|
@method_graph = MethodGraph.new
|
@@ -108,17 +115,21 @@ class Kefka
|
|
108
115
|
@logger.level = log_level
|
109
116
|
end
|
110
117
|
|
118
|
+
def get_locals(target)
|
119
|
+
target.eval("local_variables")
|
120
|
+
end
|
121
|
+
|
122
|
+
def deep_copy(val)
|
123
|
+
Marshal.load(Marshal.dump(val))
|
124
|
+
rescue TypeError
|
125
|
+
"_unknown_"
|
126
|
+
end
|
127
|
+
|
111
128
|
def get_values_of_locals_from_binding(target)
|
112
|
-
locals = target
|
129
|
+
locals = get_locals(target)
|
113
130
|
locals.inject({}) do |result,l|
|
114
131
|
val = target.eval(l.to_s)
|
115
|
-
val =
|
116
|
-
# deep copy
|
117
|
-
Marshal.load(Marshal.dump(val)) if val
|
118
|
-
rescue TypeError
|
119
|
-
"_unknown_"
|
120
|
-
end
|
121
|
-
|
132
|
+
val = deep_copy(val)
|
122
133
|
result.merge!({ l => val })
|
123
134
|
result
|
124
135
|
end
|
@@ -193,12 +204,17 @@ class Kefka
|
|
193
204
|
end
|
194
205
|
end
|
195
206
|
|
207
|
+
def print_callgraph
|
208
|
+
public_dir = "#{File.expand_path(File.dirname(__FILE__))}/../public"
|
209
|
+
@method_graph.write_to_graphic_file("png", "#{public_dir}/graph")
|
210
|
+
end
|
211
|
+
|
196
212
|
def trace(file_path, handler = :callgraph_handler)
|
197
213
|
file = File.open(file_path)
|
198
214
|
|
199
215
|
thread = Thread.new {
|
200
|
-
code = file.read
|
201
|
-
eval(code, TOPLEVEL_BINDING, file.path, 1)
|
216
|
+
@code = file.read
|
217
|
+
eval(@code, TOPLEVEL_BINDING, file.path, 1)
|
202
218
|
}
|
203
219
|
|
204
220
|
thread.set_trace_func method(handler).to_proc
|
data/public/javascripts/app.js
CHANGED
@@ -5,22 +5,31 @@ var jqSelectorEscape = function(text) {
|
|
5
5
|
var createCodeBubbles = function(data) {
|
6
6
|
console.log(data);
|
7
7
|
|
8
|
-
var
|
8
|
+
var input = data.code;
|
9
|
+
|
10
|
+
$("div#input").last().append(input);
|
11
|
+
|
12
|
+
if (data.graphviz_installed == true) {
|
13
|
+
$("div#callGraph").last().append("<img src='graph.png'/>");
|
14
|
+
} else {
|
15
|
+
$("div#callGraph").last().append("Graphviz visualization not Available. Install Graphviz to enable it.");
|
16
|
+
}
|
17
|
+
|
18
|
+
var codeGraph = data.graph;
|
9
19
|
|
10
20
|
var xPos = 0;
|
11
|
-
var yPos = 0;
|
12
21
|
var bubbleDiv, $bubble, $code,
|
13
22
|
key, header,
|
14
23
|
lineCount, column;
|
15
24
|
|
16
|
-
var methods =
|
25
|
+
var methods = codeGraph.vertices;
|
17
26
|
|
18
27
|
for (var i = 0; i < methods.length; i++ )
|
19
28
|
{
|
20
29
|
bubbleDiv = "<div class='bubble'></div>";
|
21
|
-
$(bubbleDiv).appendTo("#
|
30
|
+
$(bubbleDiv).appendTo("#codeGraph");
|
22
31
|
|
23
|
-
$bubble = $("#
|
32
|
+
$bubble = $("#codeGraph .bubble").last();
|
24
33
|
$bubble.append(methods[i].source);
|
25
34
|
|
26
35
|
// set id for bubble table
|
@@ -36,11 +45,8 @@ var createCodeBubbles = function(data) {
|
|
36
45
|
//xPos = $callerBubble.position().left + 200;
|
37
46
|
|
38
47
|
// position bubble table
|
39
|
-
$bubble.css("position", "
|
40
|
-
.css("left", xPos)
|
41
|
-
.css("top", yPos);
|
42
|
-
|
43
|
-
yPos += $bubble.height();
|
48
|
+
$bubble.css("position", "relative")
|
49
|
+
.css("left", xPos);
|
44
50
|
|
45
51
|
// add column for displaying local values
|
46
52
|
lineCount = $bubble.find("td.line-numbers a").length;
|
data/views/index.erb
CHANGED
@@ -11,7 +11,18 @@ Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
11
11
|
</head>
|
12
12
|
|
13
13
|
<body>
|
14
|
-
<
|
14
|
+
<h1 id="input_header">Input</h1>
|
15
|
+
<div id="input">
|
16
|
+
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<h1 id="codegraph_header">Graphviz CallGraph</h1>
|
20
|
+
<div id="callGraph">
|
21
|
+
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<h1 id="codegraph_header">CodeGraph</h1>
|
25
|
+
<div id="codeGraph">
|
15
26
|
|
16
27
|
</div>
|
17
28
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kefka
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: yajl-ruby
|
16
|
-
requirement: &
|
16
|
+
requirement: &70273937010140 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70273937010140
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: coderay
|
27
|
-
requirement: &
|
27
|
+
requirement: &70273937009600 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70273937009600
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: sinatra
|
38
|
-
requirement: &
|
38
|
+
requirement: &70273937008940 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70273937008940
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: method_source
|
49
|
-
requirement: &
|
49
|
+
requirement: &70273936990620 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70273936990620
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: rgl
|
60
|
-
requirement: &
|
60
|
+
requirement: &70273936989280 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70273936989280
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: pry
|
71
|
-
requirement: &
|
71
|
+
requirement: &70273936987380 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70273936987380
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: pry-doc
|
82
|
-
requirement: &
|
82
|
+
requirement: &70273936986160 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70273936986160
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: rspec
|
93
|
-
requirement: &
|
93
|
+
requirement: &70273936984420 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70273936984420
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: jeweler
|
104
|
-
requirement: &
|
104
|
+
requirement: &70273936983420 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70273936983420
|
113
113
|
description: ! ' It traces the execution path of a program and displays the source
|
114
114
|
code of each method call in the callgraph '
|
115
115
|
email: redge.tan@gmail.com
|
@@ -155,7 +155,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
155
155
|
version: '0'
|
156
156
|
segments:
|
157
157
|
- 0
|
158
|
-
hash:
|
158
|
+
hash: -1427345181685482934
|
159
159
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
160
|
none: false
|
161
161
|
requirements:
|