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,197 @@
|
|
1
|
+
require 'byebug/printers/base'
|
2
|
+
require 'builder'
|
3
|
+
|
4
|
+
module Byebug
|
5
|
+
module Printers
|
6
|
+
class Xml < Byebug::Printers::Base
|
7
|
+
|
8
|
+
def print(path, args = {})
|
9
|
+
case parts(path)[1]
|
10
|
+
when "errors"
|
11
|
+
print_error(path, args)
|
12
|
+
when "confirmations"
|
13
|
+
print_confirmation(path, args)
|
14
|
+
when "debug"
|
15
|
+
print_debug(path, args)
|
16
|
+
when "messages"
|
17
|
+
print_message(path, args)
|
18
|
+
else
|
19
|
+
print_general(path, args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def print_collection(path, collection, &block)
|
24
|
+
settings = locate(path)
|
25
|
+
xml = ::Builder::XmlMarkup.new
|
26
|
+
tag = translate(settings["tag"])
|
27
|
+
xml.tag!("#{tag}s") do |xml|
|
28
|
+
array_of_args(collection, &block).each do |args|
|
29
|
+
xml.tag!(tag, translated_attributes(settings["attributes"], args))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def print_variables(variables, global_kind)
|
35
|
+
print_collection("variable.variable", variables) do |(key, value, kind), index|
|
36
|
+
Variable.new(key, value, kind || global_kind).to_hash
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def print_instance_variables(object)
|
41
|
+
variables = if object.is_a?(Array)
|
42
|
+
object.each.with_index.map { |item, index| ["[#{index}]", item, 'instance'] }
|
43
|
+
elsif object.is_a?(Hash)
|
44
|
+
object.map { |key, value| [key.is_a?(String) ? "'#{key}'" : key.to_s, value, 'instance'] }
|
45
|
+
else
|
46
|
+
AllVariables.new(object).variables
|
47
|
+
end
|
48
|
+
print_variables(variables, nil)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def print_general(path, args)
|
54
|
+
settings = locate(path)
|
55
|
+
xml = ::Builder::XmlMarkup.new
|
56
|
+
tag = translate(settings["tag"], args)
|
57
|
+
attributes = translated_attributes(settings["attributes"], args)
|
58
|
+
xml.tag!(tag, attributes)
|
59
|
+
end
|
60
|
+
|
61
|
+
def print_debug(path, args)
|
62
|
+
translate(locate(path), args)
|
63
|
+
end
|
64
|
+
|
65
|
+
def print_error(path, args)
|
66
|
+
xml = ::Builder::XmlMarkup.new
|
67
|
+
xml.error { print_content(xml, path, args) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def print_confirmation(path, args)
|
71
|
+
xml = ::Builder::XmlMarkup.new
|
72
|
+
xml.confirmation { print_content(xml, path, args) }
|
73
|
+
end
|
74
|
+
|
75
|
+
def print_message(path, args)
|
76
|
+
xml = ::Builder::XmlMarkup.new
|
77
|
+
xml.message { print_content(xml, path, args) }
|
78
|
+
end
|
79
|
+
|
80
|
+
def print_content(xml, path, args)
|
81
|
+
xml.text!(translate(locate(path), args))
|
82
|
+
end
|
83
|
+
|
84
|
+
def translated_attributes(attributes, args)
|
85
|
+
attributes.inject({}) do |hash, (key, value)|
|
86
|
+
hash[key] = translate(value, args)
|
87
|
+
hash
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def contents_files
|
92
|
+
[File.expand_path(File.join("..", "texts", "xml.yml"), __FILE__)] + super
|
93
|
+
end
|
94
|
+
|
95
|
+
class Variable
|
96
|
+
attr_reader :name, :kind
|
97
|
+
def initialize(name, value, kind = nil)
|
98
|
+
@name = name.to_s
|
99
|
+
@value = value
|
100
|
+
@kind = kind
|
101
|
+
end
|
102
|
+
|
103
|
+
def has_children?
|
104
|
+
if @value.is_a?(Array) || @value.is_a?(Hash)
|
105
|
+
!@value.empty?
|
106
|
+
else
|
107
|
+
!@value.instance_variables.empty? || !@value.class.class_variables.empty?
|
108
|
+
end
|
109
|
+
rescue
|
110
|
+
false
|
111
|
+
end
|
112
|
+
|
113
|
+
def value
|
114
|
+
if @value.is_a?(Array) || @value.is_a?(Hash)
|
115
|
+
if has_children?
|
116
|
+
"#{@value.class} (#{@value.size} element(s))"
|
117
|
+
else
|
118
|
+
"Empty #{@value.class}"
|
119
|
+
end
|
120
|
+
else
|
121
|
+
value_str = @value.nil? ? 'nil' : @value.to_s
|
122
|
+
if !value_str.is_a?(String)
|
123
|
+
"ERROR: #{@value.class}.to_s method returns #{value_str.class}. Should return String."
|
124
|
+
elsif binary_data?(value_str)
|
125
|
+
"[Binary Data]"
|
126
|
+
else
|
127
|
+
value_str.gsub(/^(")(.*)(")$/, '\2')
|
128
|
+
end
|
129
|
+
end
|
130
|
+
rescue => e
|
131
|
+
"<raised exception: #{e}>"
|
132
|
+
end
|
133
|
+
|
134
|
+
def id
|
135
|
+
@value.respond_to?(:object_id) ? "%#+x" % @value.object_id : nil
|
136
|
+
rescue
|
137
|
+
nil
|
138
|
+
end
|
139
|
+
|
140
|
+
def type
|
141
|
+
@value.class
|
142
|
+
rescue
|
143
|
+
"Undefined"
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_hash
|
147
|
+
{name: @name, kind: @kind, value: value, type: type, has_children: has_children?, id: id}
|
148
|
+
end
|
149
|
+
|
150
|
+
private
|
151
|
+
|
152
|
+
def binary_data?(string)
|
153
|
+
string.count("\x00-\x7F", "^ -~\t\r\n").fdiv(string.size) > 0.3 || string.index("\x00") unless string.empty?
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class AllVariables
|
158
|
+
def initialize(object)
|
159
|
+
@object = object
|
160
|
+
@instance_binding = object.instance_eval{binding()}
|
161
|
+
@class_binding = object.class.class_eval('binding()')
|
162
|
+
|
163
|
+
@instance_variable_names = object.instance_variables
|
164
|
+
@self_variable_name = @instance_variable_names.delete('self')
|
165
|
+
@class_variable_names = object.class.class_variables
|
166
|
+
end
|
167
|
+
|
168
|
+
def variables
|
169
|
+
self_variables + instance_variables + class_variables
|
170
|
+
end
|
171
|
+
|
172
|
+
private
|
173
|
+
|
174
|
+
def instance_variables
|
175
|
+
@instance_variable_names.map do |var|
|
176
|
+
[var.to_s, (eval(var.to_s, @instance_binding) rescue "<raised exception>"), 'instance']
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def self_variables
|
181
|
+
if @self_variable_name
|
182
|
+
[@self_variable_name, (eval(@self_variable_name, @instance_binding)), 'instance']
|
183
|
+
else
|
184
|
+
[]
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def class_variables
|
189
|
+
@class_variable_names.map do |var|
|
190
|
+
[var.to_s, (eval(var.to_s, @class_binding) rescue "<raised exception>"), 'class']
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Debugger
|
2
|
+
class StartCommand < Command # :nodoc:
|
3
|
+
self.allow_in_control = true
|
4
|
+
|
5
|
+
def regexp
|
6
|
+
/^\s*(start)\s*$/ix
|
7
|
+
end
|
8
|
+
|
9
|
+
def execute
|
10
|
+
DebuggerXml.proceed
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def help_command
|
15
|
+
'start'
|
16
|
+
end
|
17
|
+
|
18
|
+
def help(cmd)
|
19
|
+
%{
|
20
|
+
run prog script
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -20,4 +20,18 @@ module Debugger
|
|
20
20
|
alias_method :execute, :execute_with_xml
|
21
21
|
|
22
22
|
end
|
23
|
+
|
24
|
+
class VarIdeCommand < Command
|
25
|
+
def regexp
|
26
|
+
/^\s*v(?:ar)?\s+ide\s*$/
|
27
|
+
end
|
28
|
+
|
29
|
+
def execute
|
30
|
+
locals = []
|
31
|
+
_self = @state.context.frame_self(@state.frame_pos)
|
32
|
+
locals << ['self', _self] unless _self.to_s == "main"
|
33
|
+
locals += @state.context.frame_locals(@state.frame_pos).sort.map { |key, value| [key, value] }
|
34
|
+
print prv(locals, 'instance')
|
35
|
+
end
|
36
|
+
end
|
23
37
|
end
|
data/lib/debugger_xml.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
Dir.glob(File.expand_path("../debugger_xml/**/*.rb", __FILE__)).each { |f| require f }
|
2
|
+
if DEBUGGER_TYPE == :debugger
|
3
|
+
Dir.glob(File.expand_path("../debugger/**/*.rb", __FILE__)).each { |f| require f }
|
4
|
+
else
|
5
|
+
Dir.glob(File.expand_path("../byebug/**/*.rb", __FILE__)).each { |f| require f }
|
6
|
+
end
|
7
|
+
|
8
|
+
module DebuggerXml
|
9
|
+
class << self
|
10
|
+
attr_accessor :logger, :wait_for_start, :control_thread, :handler, :queue
|
11
|
+
|
12
|
+
def start_remote_ide(proxy, host, port)
|
13
|
+
return if @control_thread
|
14
|
+
@mutex = Mutex.new
|
15
|
+
@proceed = ConditionVariable.new
|
16
|
+
@queue = Queue.new
|
17
|
+
proxy.start
|
18
|
+
@control_thread = proxy.debug_thread_class.new do
|
19
|
+
server = TCPServer.new(host, port)
|
20
|
+
$stderr.printf "Fast Debugger (debugger-xml #{VERSION}) listens on #{host}:#{port}\n"
|
21
|
+
while (session = server.accept)
|
22
|
+
dispatcher = ENV['IDE_PROCESS_DISPATCHER']
|
23
|
+
if dispatcher && !dispatcher.include?(":")
|
24
|
+
ENV['IDE_PROCESS_DISPATCHER'] = "#{session.peeraddr[2]}:#{dispatcher}"
|
25
|
+
end
|
26
|
+
interface = DebuggerXml::Ide::Interface.new(session)
|
27
|
+
processor = DebuggerXml::Ide::ControlCommandProcessor.new(interface, proxy)
|
28
|
+
debugger_class.handler = DebuggerXml::Ide::Processor.new(interface, proxy)
|
29
|
+
processor.process_commands
|
30
|
+
end
|
31
|
+
end
|
32
|
+
@mutex.synchronize { @proceed.wait(@mutex) } if wait_for_start
|
33
|
+
end
|
34
|
+
|
35
|
+
def start_for_vim(proxy, options)
|
36
|
+
return if @control_thread
|
37
|
+
logger.puts("Going to daemonize")
|
38
|
+
daemonize!
|
39
|
+
logger.puts("Successfully daemonized")
|
40
|
+
$stdout.reopen(options.output_file, 'w')
|
41
|
+
$stdout.sync
|
42
|
+
$stderr.reopen($stdout)
|
43
|
+
logger.puts("Redirected stderr")
|
44
|
+
@mutex = Mutex.new
|
45
|
+
@proceed = ConditionVariable.new
|
46
|
+
@queue = Queue.new
|
47
|
+
proxy.start
|
48
|
+
logger.puts("Started debugger")
|
49
|
+
File.unlink(options.socket) if File.exist?(options.socket)
|
50
|
+
server = UNIXServer.new(options.socket)
|
51
|
+
Vim::Notification.new("establish_connection", options).send
|
52
|
+
logger.puts("Sent 'established_connection' command")
|
53
|
+
@control_thread = proxy.debug_thread_class.new do
|
54
|
+
begin
|
55
|
+
while (session = server.accept)
|
56
|
+
logger.puts("Accepted connection");
|
57
|
+
interface = Vim::Interface.new(session, options)
|
58
|
+
processor = Vim::ControlCommandProcessor.new(interface, proxy)
|
59
|
+
proxy.handler = Vim::Processor.new(processor, interface, proxy)
|
60
|
+
logger.puts("Going to process commands");
|
61
|
+
processor.process_commands
|
62
|
+
end
|
63
|
+
rescue Exception => e
|
64
|
+
logger.puts("INTERNAL ERROR!!! #{$!}") rescue nil
|
65
|
+
logger.puts($!.backtrace.map { |l| "\t#{l}" }.join("\n")) rescue nil
|
66
|
+
raise e
|
67
|
+
ensure
|
68
|
+
logger.puts("Closing server");
|
69
|
+
server.close
|
70
|
+
end
|
71
|
+
end
|
72
|
+
@mutex.synchronize { @proceed.wait(@mutex) } if wait_for_start
|
73
|
+
end
|
74
|
+
|
75
|
+
def proceed
|
76
|
+
return unless @mutex
|
77
|
+
@mutex.synchronize { @proceed.signal }
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def daemonize!
|
83
|
+
pid = Process.fork
|
84
|
+
if pid
|
85
|
+
print pid
|
86
|
+
exit
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module DebuggerXml
|
2
|
+
class ByebugProxy
|
3
|
+
def start
|
4
|
+
::Byebug.start
|
5
|
+
end
|
6
|
+
|
7
|
+
def handler
|
8
|
+
::Byebug.handler
|
9
|
+
end
|
10
|
+
|
11
|
+
def handler=(value)
|
12
|
+
::Byebug.handler = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def control_commands(interface)
|
16
|
+
control_command_classes = commands.select(&:allow_in_control)
|
17
|
+
state = ::Byebug::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
|
+
::Byebug::CommandProcessor::State.new(commands, handler.context, [], handler.file, interface, handler.line)
|
23
|
+
end
|
24
|
+
|
25
|
+
def commands
|
26
|
+
::Byebug::Command.commands
|
27
|
+
end
|
28
|
+
|
29
|
+
def event_commands(state)
|
30
|
+
event_command_classes.map { |cls| cls.new(state) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def print(*args)
|
34
|
+
printer.print(*args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def canonic_file(file)
|
38
|
+
::Byebug::CommandProcessor.canonic_file(file)
|
39
|
+
end
|
40
|
+
|
41
|
+
def line_at(file, line)
|
42
|
+
end
|
43
|
+
|
44
|
+
def breakpoints
|
45
|
+
::Byebug.breakpoints
|
46
|
+
end
|
47
|
+
|
48
|
+
def debug_thread?(context)
|
49
|
+
context && context.thread.is_a?(debug_thread_class)
|
50
|
+
end
|
51
|
+
|
52
|
+
def debug_thread_class
|
53
|
+
::Byebug::DebugThread
|
54
|
+
end
|
55
|
+
|
56
|
+
def current_context
|
57
|
+
::Byebug.current_context
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_rdebug_script(file)
|
61
|
+
::Byebug.const_set("RDEBUG_SCRIPT", file)
|
62
|
+
end
|
63
|
+
|
64
|
+
def set_prog_script(file)
|
65
|
+
::Byebug.const_set("PROG_SCRIPT", file)
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_argv(argv)
|
69
|
+
::Byebug.const_set("ARGV", argv)
|
70
|
+
end
|
71
|
+
|
72
|
+
def interrupt_last
|
73
|
+
::Byebug.interrupt_last
|
74
|
+
end
|
75
|
+
|
76
|
+
def tracing=(value)
|
77
|
+
::Byebug.tracing = value
|
78
|
+
end
|
79
|
+
|
80
|
+
def wait_connection=(value)
|
81
|
+
::Byebug.wait_connection = value
|
82
|
+
end
|
83
|
+
|
84
|
+
def printer=(value)
|
85
|
+
::Byebug.printer = value
|
86
|
+
end
|
87
|
+
|
88
|
+
def debug_load
|
89
|
+
::Byebug.debug_load(::Byebug::PROG_SCRIPT, false)
|
90
|
+
end
|
91
|
+
|
92
|
+
def inspect_command_class
|
93
|
+
::Byebug::InspectCommand
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def event_command_classes
|
99
|
+
commands
|
100
|
+
end
|
101
|
+
|
102
|
+
def printer
|
103
|
+
::Byebug.printer
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|