readapt 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.travis.yml +13 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +29 -0
- data/Rakefile +25 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/readapt +5 -0
- data/ext/readapt/extconf.rb +3 -0
- data/ext/readapt/monitor.c +332 -0
- data/ext/readapt/monitor.h +1 -0
- data/ext/readapt/readapt.c +12 -0
- data/ext/readapt/threads.c +101 -0
- data/ext/readapt/threads.h +18 -0
- data/lib/readapt.rb +34 -0
- data/lib/readapt/adapter.rb +138 -0
- data/lib/readapt/breakpoint.rb +16 -0
- data/lib/readapt/breakpoints.rb +58 -0
- data/lib/readapt/debugger.rb +173 -0
- data/lib/readapt/finder.rb +20 -0
- data/lib/readapt/frame.rb +68 -0
- data/lib/readapt/location.rb +25 -0
- data/lib/readapt/message.rb +57 -0
- data/lib/readapt/message/attach.rb +11 -0
- data/lib/readapt/message/base.rb +32 -0
- data/lib/readapt/message/configuration_done.rb +11 -0
- data/lib/readapt/message/continue.rb +15 -0
- data/lib/readapt/message/disconnect.rb +14 -0
- data/lib/readapt/message/initialize.rb +13 -0
- data/lib/readapt/message/launch.rb +11 -0
- data/lib/readapt/message/next.rb +12 -0
- data/lib/readapt/message/pause.rb +11 -0
- data/lib/readapt/message/scopes.rb +25 -0
- data/lib/readapt/message/set_breakpoints.rb +26 -0
- data/lib/readapt/message/set_exception_breakpoints.rb +8 -0
- data/lib/readapt/message/stack_trace.rb +26 -0
- data/lib/readapt/message/step_in.rb +11 -0
- data/lib/readapt/message/step_out.rb +11 -0
- data/lib/readapt/message/threads.rb +18 -0
- data/lib/readapt/message/variables.rb +57 -0
- data/lib/readapt/monitor.rb +31 -0
- data/lib/readapt/shell.rb +48 -0
- data/lib/readapt/snapshot.rb +50 -0
- data/lib/readapt/thread.rb +39 -0
- data/lib/readapt/variable.rb +70 -0
- data/lib/readapt/version.rb +3 -0
- data/readapt.gemspec +39 -0
- metadata +184 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Readapt
|
4
|
+
module Finder
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def find program
|
8
|
+
return program if File.exist?(program)
|
9
|
+
which(program) || raise(LoadError, "#{program} is not a valid Ruby file or program")
|
10
|
+
end
|
11
|
+
|
12
|
+
def which program
|
13
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
14
|
+
exe = File.join(path, program)
|
15
|
+
return exe if File.file?(exe)
|
16
|
+
end
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Readapt
|
4
|
+
class Frame
|
5
|
+
attr_reader :location
|
6
|
+
|
7
|
+
def initialize location, binding_id
|
8
|
+
@location = location
|
9
|
+
@binding = ObjectSpace._id2ref(binding_id)
|
10
|
+
end
|
11
|
+
|
12
|
+
def local_id
|
13
|
+
@binding.object_id
|
14
|
+
end
|
15
|
+
|
16
|
+
def locals
|
17
|
+
return [] if @binding.nil?
|
18
|
+
result = []
|
19
|
+
@binding.local_variables.each do |sym|
|
20
|
+
var = @binding.local_variable_get(sym)
|
21
|
+
result.push Variable.new(sym, var)
|
22
|
+
end
|
23
|
+
if @binding.receiver != TOPLEVEL_BINDING.receiver
|
24
|
+
result.push Variable.new(:self, @binding.receiver)
|
25
|
+
end
|
26
|
+
result
|
27
|
+
end
|
28
|
+
|
29
|
+
def variables
|
30
|
+
return [] if @binding.nil?
|
31
|
+
result = []
|
32
|
+
@binding.local_variables.each do |sym|
|
33
|
+
var = @binding.local_variable_get(sym)
|
34
|
+
result.push Variable.new(sym, var)
|
35
|
+
end
|
36
|
+
if @binding.receiver != TOPLEVEL_BINDING.receiver
|
37
|
+
@binding.instance_variables.each do |sym|
|
38
|
+
var = @binding.receiver.instance_variable_get(sym)
|
39
|
+
result.push Variable.new(sym, var)
|
40
|
+
end
|
41
|
+
@binding.class.class_variables.each do |sym|
|
42
|
+
var = @binding.receiver.class.class_variable_get(sym)
|
43
|
+
result.push Variable.new(sym, var)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
def local sym
|
50
|
+
return @binding.receiver if sym == :self
|
51
|
+
@binding.local_variable_get sym
|
52
|
+
end
|
53
|
+
|
54
|
+
def globals
|
55
|
+
global_variables
|
56
|
+
end
|
57
|
+
|
58
|
+
def global sym
|
59
|
+
global sym
|
60
|
+
end
|
61
|
+
|
62
|
+
def evaluate code
|
63
|
+
@binding.eval code
|
64
|
+
end
|
65
|
+
|
66
|
+
NULL_FRAME = Frame.new(nil, nil.object_id)
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Readapt
|
4
|
+
# A simple file/line reference.
|
5
|
+
#
|
6
|
+
class Location
|
7
|
+
# @return [String]
|
8
|
+
attr_reader :file
|
9
|
+
|
10
|
+
# @return [Integer]
|
11
|
+
attr_reader :line
|
12
|
+
|
13
|
+
# @param file [String]
|
14
|
+
# @param line [Integer]
|
15
|
+
def initialize file, line
|
16
|
+
@file = file
|
17
|
+
@line = line
|
18
|
+
end
|
19
|
+
|
20
|
+
def match? other
|
21
|
+
return false unless other.is_a?(Location)
|
22
|
+
file == other.file && line == other.line
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'readapt/message/base'
|
4
|
+
require 'readapt/message/initialize'
|
5
|
+
require 'readapt/message/launch'
|
6
|
+
require 'readapt/message/set_breakpoints'
|
7
|
+
require 'readapt/message/set_exception_breakpoints'
|
8
|
+
require 'readapt/message/configuration_done'
|
9
|
+
require 'readapt/message/threads'
|
10
|
+
require 'readapt/message/stack_trace'
|
11
|
+
require 'readapt/message/scopes'
|
12
|
+
require 'readapt/message/continue'
|
13
|
+
require 'readapt/message/variables'
|
14
|
+
require 'readapt/message/next'
|
15
|
+
require 'readapt/message/step_in'
|
16
|
+
require 'readapt/message/step_out'
|
17
|
+
require 'readapt/message/disconnect'
|
18
|
+
require 'readapt/message/attach'
|
19
|
+
require 'readapt/message/pause'
|
20
|
+
|
21
|
+
module Readapt
|
22
|
+
module Message
|
23
|
+
@@messages = {}
|
24
|
+
@@seq = 0
|
25
|
+
|
26
|
+
def self.register name, klass
|
27
|
+
@@messages[name] = klass
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.process arguments, debugger
|
31
|
+
message = @@messages[arguments['command']].new(arguments['arguments'], debugger)
|
32
|
+
message.run
|
33
|
+
message
|
34
|
+
rescue Exception => e
|
35
|
+
STDERR.puts "Skipping error: #{e.message}"
|
36
|
+
STDERR.puts "Received: #{arguments}"
|
37
|
+
STDERR.puts e.backtrace
|
38
|
+
end
|
39
|
+
|
40
|
+
register 'initialize', Message::Initialize
|
41
|
+
register 'attach', Message::Attach
|
42
|
+
register 'launch', Message::Launch
|
43
|
+
register 'setBreakpoints', Message::SetBreakpoints
|
44
|
+
register 'setExceptionBreakpoints', Message::SetExceptionBreakpoints
|
45
|
+
register 'configurationDone', Message::ConfigurationDone
|
46
|
+
register 'threads', Message::Threads
|
47
|
+
register 'stackTrace', Message::StackTrace
|
48
|
+
register 'scopes', Message::Scopes
|
49
|
+
register 'continue', Message::Continue
|
50
|
+
register 'variables', Message::Variables
|
51
|
+
register 'next', Message::Next
|
52
|
+
register 'stepIn', Message::StepIn
|
53
|
+
register 'stepOut', Message::StepOut
|
54
|
+
register 'disconnect', Message::Disconnect
|
55
|
+
register 'pause', Message::Pause
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Readapt
|
4
|
+
module Message
|
5
|
+
class Base
|
6
|
+
# @return [Hash]
|
7
|
+
attr_reader :arguments
|
8
|
+
|
9
|
+
# @return [Debugger]
|
10
|
+
attr_reader :debugger
|
11
|
+
|
12
|
+
def initialize arguments, debugger
|
13
|
+
@arguments = arguments
|
14
|
+
@debugger = debugger
|
15
|
+
end
|
16
|
+
|
17
|
+
def run; end
|
18
|
+
|
19
|
+
def body
|
20
|
+
@body ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def set_body hash
|
24
|
+
@body = hash
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.run arguments, debugger
|
28
|
+
new(arguments, debugger).run
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Readapt
|
4
|
+
module Message
|
5
|
+
class Continue < Base
|
6
|
+
def run
|
7
|
+
thread = debugger.thread(arguments['threadId'])
|
8
|
+
thread.control = :continue
|
9
|
+
set_body({
|
10
|
+
allThreadsContinued: false
|
11
|
+
})
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Readapt
|
4
|
+
module Message
|
5
|
+
class Scopes < Base
|
6
|
+
def run
|
7
|
+
frame = debugger.frame(arguments['frameId'])
|
8
|
+
set_body({
|
9
|
+
scopes: [
|
10
|
+
{
|
11
|
+
name: 'Local',
|
12
|
+
variablesReference: frame.local_id,
|
13
|
+
expensive: false
|
14
|
+
},
|
15
|
+
{
|
16
|
+
name: 'Global',
|
17
|
+
variablesReference: TOPLEVEL_BINDING.receiver.object_id,
|
18
|
+
expensive: true
|
19
|
+
}
|
20
|
+
]
|
21
|
+
})
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Readapt
|
4
|
+
module Message
|
5
|
+
class SetBreakpoints < Base
|
6
|
+
def run
|
7
|
+
path = Readapt.normalize_path(arguments['source']['path'])
|
8
|
+
Monitor.breakpoints.clear path
|
9
|
+
result = arguments['lines'].map do |l|
|
10
|
+
# @todo Assuming breakpoints are verified
|
11
|
+
Breakpoint.new(path, l, true)
|
12
|
+
end
|
13
|
+
Monitor.breakpoints.concat result
|
14
|
+
set_body({
|
15
|
+
breakpoints: result.map { |bp|
|
16
|
+
{
|
17
|
+
verified: bp.verified,
|
18
|
+
source: arguments['source'],
|
19
|
+
line: bp.line
|
20
|
+
}
|
21
|
+
}
|
22
|
+
})
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Readapt
|
4
|
+
module Message
|
5
|
+
class StackTrace < Base
|
6
|
+
def run
|
7
|
+
frames = debugger.thread(arguments['threadId']).frames
|
8
|
+
set_body({
|
9
|
+
stackFrames: frames.map do |frm|
|
10
|
+
{
|
11
|
+
name: "#{File.basename(frm.location.file)}:#{frm.location.line}",
|
12
|
+
source: {
|
13
|
+
name: File.basename(frm.location.file),
|
14
|
+
path: frm.location.file
|
15
|
+
},
|
16
|
+
id: frm.local_id,
|
17
|
+
line: frm.location.line,
|
18
|
+
column: 0
|
19
|
+
}
|
20
|
+
end,
|
21
|
+
totalFrames: frames.length
|
22
|
+
})
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|