debugger-xml 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/bin/rdebug-ide +12 -9
- data/bin/rdebug-vim +30 -13
- data/debugger-xml.gemspec +7 -3
- data/lib/byebug/commands/frame.rb +16 -0
- data/lib/byebug/commands/help.rb +13 -0
- data/lib/byebug/commands/info.rb +13 -0
- data/lib/byebug/commands/inspect.rb +30 -0
- data/lib/byebug/commands/kill.rb +13 -0
- data/lib/byebug/commands/start.rb +25 -0
- data/lib/byebug/commands/threads.rb +10 -0
- data/lib/byebug/commands/trace.rb +13 -0
- data/lib/byebug/commands/variables.rb +54 -0
- data/lib/byebug/context_xml.rb +29 -0
- data/lib/byebug/printers/texts/xml.yml +122 -0
- data/lib/byebug/printers/xml.rb +197 -0
- data/lib/debugger/{xml/extensions/processor.rb → command_processor.rb} +0 -0
- data/lib/debugger/{xml/extensions/commands → commands}/edit.rb +0 -0
- data/lib/debugger/{xml/extensions/commands → commands}/frame.rb +0 -1
- data/lib/debugger/{xml/extensions/commands → commands}/help.rb +0 -0
- data/lib/debugger/{xml/extensions/commands → commands}/info.rb +0 -0
- data/lib/debugger/{xml/extensions/commands → commands}/inspect.rb +0 -0
- data/lib/debugger/{xml/extensions/commands → commands}/irb.rb +0 -0
- data/lib/debugger/{xml/extensions/commands → commands}/kill.rb +0 -0
- data/lib/debugger/commands/start.rb +25 -0
- data/lib/debugger/{xml/extensions/commands → commands}/threads.rb +0 -0
- data/lib/debugger/{xml/extensions/commands → commands}/tmate.rb +0 -0
- data/lib/debugger/{xml/extensions/commands → commands}/trace.rb +0 -0
- data/lib/debugger/{xml/extensions/commands → commands}/variables.rb +14 -0
- data/lib/debugger_xml.rb +91 -0
- data/lib/debugger_xml/byebug_proxy.rb +108 -0
- data/lib/debugger_xml/debugger_proxy.rb +115 -0
- data/lib/debugger_xml/fake_logger.rb +9 -0
- data/lib/debugger_xml/ide/control_command_processor.rb +69 -0
- data/lib/debugger_xml/ide/interface.rb +74 -0
- data/lib/debugger_xml/ide/logger.rb +9 -0
- data/lib/debugger_xml/ide/processor.rb +118 -0
- data/lib/debugger_xml/multiprocess/monkey.rb +47 -0
- data/lib/debugger_xml/multiprocess/pre_child.rb +79 -0
- data/lib/{debugger/xml → debugger_xml}/multiprocess/starter.rb +2 -2
- data/lib/debugger_xml/version.rb +3 -0
- data/lib/debugger_xml/vim/control_command_processor.rb +23 -0
- data/lib/debugger_xml/vim/interface.rb +46 -0
- data/lib/debugger_xml/vim/logger.rb +16 -0
- data/lib/debugger_xml/vim/notification.rb +35 -0
- data/lib/debugger_xml/vim/processor.rb +20 -0
- data/test/breakpoints_test.rb +0 -1
- data/test/ide/control_command_processor_test.rb +18 -13
- data/test/ide/processor_test.rb +11 -25
- data/test/printers/xml_test.rb +1 -0
- data/test/test_helper.rb +12 -3
- data/test/variables_test.rb +0 -1
- data/test/vim/control_command_processor_test.rb +4 -5
- data/test/vim/interface_test.rb +6 -6
- data/test/vim/notification_test.rb +3 -3
- data/test/vim/processor_test.rb +8 -8
- metadata +61 -48
- data/lib/debugger/xml.rb +0 -11
- data/lib/debugger/xml/extensions/ide_server.rb +0 -33
- data/lib/debugger/xml/extensions/vim_server.rb +0 -56
- data/lib/debugger/xml/fake_logger.rb +0 -11
- data/lib/debugger/xml/ide/control_command_processor.rb +0 -81
- data/lib/debugger/xml/ide/interface.rb +0 -72
- data/lib/debugger/xml/ide/logger.rb +0 -11
- data/lib/debugger/xml/ide/processor.rb +0 -94
- data/lib/debugger/xml/multiprocess/monkey.rb +0 -49
- data/lib/debugger/xml/multiprocess/pre_child.rb +0 -81
- data/lib/debugger/xml/version.rb +0 -5
- data/lib/debugger/xml/vim/control_command_processor.rb +0 -19
- data/lib/debugger/xml/vim/interface.rb +0 -42
- data/lib/debugger/xml/vim/logger.rb +0 -18
- data/lib/debugger/xml/vim/notification.rb +0 -37
- data/lib/debugger/xml/vim/processor.rb +0 -22
@@ -0,0 +1,115 @@
|
|
1
|
+
module DebuggerXml
|
2
|
+
class DebuggerProxy
|
3
|
+
def start
|
4
|
+
::Debugger.start
|
5
|
+
end
|
6
|
+
|
7
|
+
def handler
|
8
|
+
::Debugger.handler
|
9
|
+
end
|
10
|
+
|
11
|
+
def handler=(value)
|
12
|
+
::Debugger.handler = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def control_commands(interface)
|
16
|
+
control_command_classes = commands.select(&:allow_in_control)
|
17
|
+
state = ::Debugger::ControlCommandProcessor::State.new(interface, control_command_classes)
|
18
|
+
control_command_classes.map { |cmd| cmd.new(state) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def build_command_processor_state(interface)
|
22
|
+
::Debugger::CommandProcessor::State.new do |s|
|
23
|
+
s.context = handler.context
|
24
|
+
s.file = handler.file
|
25
|
+
s.line = handler.line
|
26
|
+
s.binding = handler.context.frame_binding(0)
|
27
|
+
s.interface = interface
|
28
|
+
s.commands = event_command_classes
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def commands
|
33
|
+
::Debugger::Command.commands
|
34
|
+
end
|
35
|
+
|
36
|
+
def event_commands(state)
|
37
|
+
event_command_classes.map { |cls| cls.new(state) }
|
38
|
+
end
|
39
|
+
|
40
|
+
def print(*args)
|
41
|
+
printer.print(*args)
|
42
|
+
end
|
43
|
+
|
44
|
+
def canonic_file(file)
|
45
|
+
::Debugger::CommandProcessor.canonic_file(file)
|
46
|
+
end
|
47
|
+
|
48
|
+
def line_at(file, line)
|
49
|
+
::Debugger.line_at(file, line)
|
50
|
+
end
|
51
|
+
|
52
|
+
def breakpoints
|
53
|
+
::Debugger.breakpoints
|
54
|
+
end
|
55
|
+
|
56
|
+
def debug_thread?(context)
|
57
|
+
context && context.thread.is_a?(debug_thread_class)
|
58
|
+
end
|
59
|
+
|
60
|
+
def debug_thread_class
|
61
|
+
::Debugger::DebugThread
|
62
|
+
end
|
63
|
+
|
64
|
+
def current_context
|
65
|
+
::Debugger.current_context
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_rdebug_script(file)
|
69
|
+
::Debugger.const_set("RDEBUG_SCRIPT", file)
|
70
|
+
end
|
71
|
+
|
72
|
+
def set_prog_script(file)
|
73
|
+
::Debugger.const_set("PROG_SCRIPT", file)
|
74
|
+
end
|
75
|
+
|
76
|
+
def set_argv(argv)
|
77
|
+
::Debugger.const_set("ARGV", argv)
|
78
|
+
end
|
79
|
+
|
80
|
+
def interrupt_last
|
81
|
+
::Debugger.interrupt_last
|
82
|
+
end
|
83
|
+
|
84
|
+
def tracing=(value)
|
85
|
+
::Debugger.tracing = value
|
86
|
+
end
|
87
|
+
|
88
|
+
def wait_connection=(value)
|
89
|
+
::Debugger.wait_connection = value
|
90
|
+
end
|
91
|
+
|
92
|
+
def printer=(value)
|
93
|
+
::Debugger.printer = value
|
94
|
+
end
|
95
|
+
|
96
|
+
def debug_load
|
97
|
+
::Debugger.debug_load(::Debugger::PROG_SCRIPT, false, false)
|
98
|
+
end
|
99
|
+
|
100
|
+
def inspect_command_class
|
101
|
+
::Debugger::InspectCommand
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def event_command_classes
|
107
|
+
commands.select(&:event)
|
108
|
+
end
|
109
|
+
|
110
|
+
def printer
|
111
|
+
::Debugger.printer
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module DebuggerXml
|
2
|
+
module Ide
|
3
|
+
class ControlCommandProcessor
|
4
|
+
|
5
|
+
def initialize(interface, proxy)
|
6
|
+
@interface = interface
|
7
|
+
@proxy = proxy
|
8
|
+
end
|
9
|
+
|
10
|
+
def process_commands
|
11
|
+
while input = @interface.read_command
|
12
|
+
process_input(input)
|
13
|
+
end
|
14
|
+
rescue IOError, Errno::EPIPE
|
15
|
+
rescue Exception
|
16
|
+
@interface.print("INTERNAL ERROR!!! #{$!}\n") rescue nil
|
17
|
+
@interface.print($!.backtrace.map { |l| "\t#{l}" }.join("\n")) rescue nil
|
18
|
+
ensure
|
19
|
+
@interface.close
|
20
|
+
end
|
21
|
+
|
22
|
+
def process_command(cmd)
|
23
|
+
catch(:debug_error) do
|
24
|
+
if matched_cmd = @proxy.control_commands(@interface).find { |c| c.match(cmd) }
|
25
|
+
matched_cmd.execute
|
26
|
+
else
|
27
|
+
process_context_commands(cmd)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def process_input(input)
|
35
|
+
split_commands(input).each do |cmd|
|
36
|
+
process_command(cmd)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def process_context_commands(input)
|
41
|
+
unless @proxy.handler.at_line?
|
42
|
+
@interface.errmsg(@proxy.print("base.errors.no_suspended_thread", input: input))
|
43
|
+
return
|
44
|
+
end
|
45
|
+
state = @proxy.build_command_processor_state(@interface)
|
46
|
+
event_commands = @proxy.event_commands(state)
|
47
|
+
catch(:debug_error) do
|
48
|
+
if cmd = event_commands.find { |c| c.match(input) }
|
49
|
+
if state.context.dead? && cmd.class.need_context
|
50
|
+
@interface.print(@proxy.print("base.errors.command_unavailable"))
|
51
|
+
else
|
52
|
+
cmd.execute
|
53
|
+
end
|
54
|
+
else
|
55
|
+
@interface.print(@proxy.print("base.errors.unknown_command", input: input))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
state.context.thread.run if state.proceed?
|
59
|
+
end
|
60
|
+
|
61
|
+
# Split commands like this:
|
62
|
+
# split_commands("abc;def\\;ghi;jkl") => ["abc", "def;ghi", "jkl"]
|
63
|
+
def split_commands(input)
|
64
|
+
input.split(/(?<!\\);/).map { |e| e.gsub("\\;", ";") }
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module DebuggerXml
|
2
|
+
module Ide
|
3
|
+
class Interface
|
4
|
+
attr_accessor :command_queue
|
5
|
+
attr_accessor :histfile
|
6
|
+
attr_accessor :history_save
|
7
|
+
attr_accessor :history_length
|
8
|
+
attr_accessor :restart_file
|
9
|
+
|
10
|
+
def initialize(socket)
|
11
|
+
@command_queue = []
|
12
|
+
@socket = socket
|
13
|
+
@history_save = false
|
14
|
+
@history_length = 256
|
15
|
+
@histfile = ''
|
16
|
+
@restart_file = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def close
|
20
|
+
@socket.close
|
21
|
+
rescue Exception
|
22
|
+
end
|
23
|
+
|
24
|
+
def print_debug(msg)
|
25
|
+
STDOUT.puts(msg)
|
26
|
+
end
|
27
|
+
|
28
|
+
def errmsg(*args)
|
29
|
+
print(*args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def confirm(prompt)
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def finalize
|
37
|
+
close
|
38
|
+
end
|
39
|
+
|
40
|
+
# Workaround for JRuby issue http://jira.codehaus.org/browse/JRUBY-2063
|
41
|
+
def non_blocking_gets
|
42
|
+
loop do
|
43
|
+
result, _, _ = IO.select([@socket], nil, nil, 0.2)
|
44
|
+
next unless result
|
45
|
+
return result[0].gets
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def read_command(*args)
|
50
|
+
result = non_blocking_gets
|
51
|
+
raise IOError unless result
|
52
|
+
result.chomp.tap do |r|
|
53
|
+
DebuggerXml.logger.puts("Read command: #{r}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def readline_support?
|
58
|
+
false
|
59
|
+
end
|
60
|
+
|
61
|
+
def print(*args)
|
62
|
+
escaped_args = escape_input(args)
|
63
|
+
value = escaped_args.first % escaped_args[1..-1]
|
64
|
+
DebuggerXml.logger.puts("Going to print: #{value}")
|
65
|
+
@socket.print(value)
|
66
|
+
end
|
67
|
+
|
68
|
+
def puts(*args)
|
69
|
+
print(*args)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module DebuggerXml
|
2
|
+
module Ide
|
3
|
+
class Processor
|
4
|
+
class << self
|
5
|
+
private
|
6
|
+
|
7
|
+
# Copied from debugger gem.
|
8
|
+
def protect(mname)
|
9
|
+
alias_method "__#{mname}", mname
|
10
|
+
module_eval %{
|
11
|
+
def #{mname}(*args)
|
12
|
+
@mutex.synchronize do
|
13
|
+
return unless @interface
|
14
|
+
__#{mname}(*args)
|
15
|
+
end
|
16
|
+
rescue IOError, Errno::EPIPE
|
17
|
+
self.interface = nil
|
18
|
+
rescue SignalException
|
19
|
+
raise
|
20
|
+
rescue Exception
|
21
|
+
@interface.print "INTERNAL ERROR!!! #\{$!\}\n" rescue nil
|
22
|
+
@interface.print $!.backtrace.map{|l| "\t#\{l\}"}.join("\n") rescue nil
|
23
|
+
end
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :context, :file, :line, :display
|
29
|
+
attr_accessor :interface
|
30
|
+
|
31
|
+
def initialize(interface, proxy)
|
32
|
+
@mutex = Mutex.new
|
33
|
+
@interface = interface
|
34
|
+
@proxy = proxy
|
35
|
+
@display = []
|
36
|
+
end
|
37
|
+
|
38
|
+
def at_breakpoint(context, breakpoint)
|
39
|
+
raise "@last_breakpoint supposed to be nil. is #{@last_breakpoint}" if @last_breakpoint
|
40
|
+
# at_breakpoint is immediately followed by #at_line event. So postpone breakpoint printing until #at_line.
|
41
|
+
@last_breakpoint = breakpoint
|
42
|
+
end
|
43
|
+
protect :at_breakpoint
|
44
|
+
|
45
|
+
# TODO: Catching exceptions doesn't work so far, need to fix
|
46
|
+
def at_catchpoint(context, excpt)
|
47
|
+
end
|
48
|
+
|
49
|
+
# We don't have tracing for IDE
|
50
|
+
def at_tracing(*args)
|
51
|
+
end
|
52
|
+
|
53
|
+
def at_line(context, file, line)
|
54
|
+
if context.nil? || context.stop_reason == :step
|
55
|
+
print_file_line(context, file, line)
|
56
|
+
end
|
57
|
+
line_event(context, file, line)
|
58
|
+
end
|
59
|
+
protect :at_line
|
60
|
+
|
61
|
+
def at_return(context, file, line)
|
62
|
+
print_file_line(context, file, line)
|
63
|
+
context.stop_frame = -1
|
64
|
+
line_event(context, file, line)
|
65
|
+
end
|
66
|
+
|
67
|
+
def at_line?
|
68
|
+
!!@line
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def print_file_line(context, file, line)
|
74
|
+
@interface.print(
|
75
|
+
@proxy.print(
|
76
|
+
"stop.suspend",
|
77
|
+
file: @proxy.canonic_file(file),
|
78
|
+
line_number: line,
|
79
|
+
line: @proxy.line_at(file, line),
|
80
|
+
thnum: context && context.thnum,
|
81
|
+
frames: context && context.stack_size
|
82
|
+
)
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
def line_event(context, file, line)
|
87
|
+
@line = line
|
88
|
+
@file = file
|
89
|
+
@context = context
|
90
|
+
if @last_breakpoint
|
91
|
+
# followed after #at_breakpoint in the same thread. Print breakpoint
|
92
|
+
# now when @line, @file and @context are correctly set to prevent race
|
93
|
+
# condition with `control thread'.
|
94
|
+
n = @proxy.breakpoints.index(@last_breakpoint) + 1
|
95
|
+
@interface.print(@proxy.print("breakpoints.stop_at_breakpoint",
|
96
|
+
id: n, file: @file, line: @line, thread_id: @proxy.current_context.thnum
|
97
|
+
))
|
98
|
+
end
|
99
|
+
if @proxy.debug_thread?(@context)
|
100
|
+
raise @proxy.print("thread.errors.debug_trace", thread: @context.thread)
|
101
|
+
end
|
102
|
+
# will be resumed by commands like `step', `next', `continue', `finish'
|
103
|
+
# from `control thread'
|
104
|
+
stop_thread
|
105
|
+
ensure
|
106
|
+
@line = nil
|
107
|
+
@file = nil
|
108
|
+
@context = nil
|
109
|
+
@last_breakpoint = nil
|
110
|
+
@proxy.inspect_command_class.clear_references
|
111
|
+
end
|
112
|
+
|
113
|
+
def stop_thread
|
114
|
+
Thread.stop
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module DebuggerXml
|
2
|
+
module MultiProcess
|
3
|
+
def self.create_mp_fork(private=false)
|
4
|
+
%Q{
|
5
|
+
alias pre_debugger_fork fork
|
6
|
+
|
7
|
+
#{private ? "private" : ""}
|
8
|
+
def fork(*args)
|
9
|
+
if block_given?
|
10
|
+
return pre_debugger_fork{DebuggerXml::MultiProcess::pre_child; yield}
|
11
|
+
end
|
12
|
+
result = pre_debugger_fork
|
13
|
+
DebuggerXml::MultiProcess::pre_child unless result
|
14
|
+
result
|
15
|
+
end
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.create_mp_exec(private=false)
|
20
|
+
%Q{
|
21
|
+
alias pre_debugger_exec exec
|
22
|
+
|
23
|
+
#{private ? "private" : ""}
|
24
|
+
def exec(*args)
|
25
|
+
Debugger.handler.interface.close
|
26
|
+
pre_debugger_exec(*args)
|
27
|
+
end
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module Kernel
|
34
|
+
class << self
|
35
|
+
module_eval DebuggerXml::MultiProcess.create_mp_fork
|
36
|
+
module_eval DebuggerXml::MultiProcess.create_mp_exec
|
37
|
+
end
|
38
|
+
module_eval DebuggerXml::MultiProcess.create_mp_fork(true)
|
39
|
+
module_eval DebuggerXml::MultiProcess.create_mp_exec(true)
|
40
|
+
end
|
41
|
+
|
42
|
+
module Process
|
43
|
+
class << self
|
44
|
+
module_eval DebuggerXml::MultiProcess.create_mp_fork
|
45
|
+
module_eval DebuggerXml::MultiProcess.create_mp_exec
|
46
|
+
end
|
47
|
+
end
|