debugger-xml 0.3.3 → 0.4.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.
- 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
|