From 74b13807bd4edda3c394114a53a478ba5cbc04fb Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Mon, 4 Jun 2018 20:13:39 +0300 Subject: [PATCH] new hash item presentation, lets add objectId of a hash key to the xml so we can inspect it later --- bin/rdebug-ide | 7 +++- lib/ruby-debug-ide.rb | 1 + lib/ruby-debug-ide/xml_printer.rb | 32 +++++++++++--- test-base/test_base.rb | 8 ++-- test-base/variables_test.rb | 70 ++++++++++++++++++++++++------- test/rd_test_base.rb | 4 +- 6 files changed, 96 insertions(+), 26 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index a72dfd1..3054353 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -27,7 +27,8 @@ options = OpenStruct.new( 'catchpoint_deleted_event' => false, 'value_as_nested_element' => false, 'attach_mode' => false, - 'cli_debug' => false + 'cli_debug' => false, + 'key_value_mode' => false ) opts = OptionParser.new do |opts| @@ -80,6 +81,9 @@ EOB opts.on("--attach-mode", "Tells that rdebug-ide is working in attach mode") do options.attach_mode = true end + opts.on("--key-value", "Key/Value presentation of hash items") do + options.key_value_mode = true + end opts.on("--ignore-port", "Generate another port") do options.ignore_port = true end @@ -166,6 +170,7 @@ Debugger.debugger_memory_limit = options.debugger_memory_limit Debugger.inspect_time_limit = options.inspect_time_limit Debugger.catchpoint_deleted_event = options.catchpoint_deleted_event || options.rm_protocol_extensions Debugger.value_as_nested_element = options.value_as_nested_element || options.rm_protocol_extensions +Debugger.key_value_mode = options.key_value_mode if options.attach_mode if Debugger::FRONT_END == "debase" diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 7874134..e7b57d4 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -51,6 +51,7 @@ def cleanup_backtrace(backtrace) end attr_accessor :attached + attr_accessor :key_value_mode attr_accessor :cli_debug, :xml_debug, :evaluation_timeout attr_accessor :trace_to_s, :debugger_memory_limit, :inspect_time_limit attr_accessor :control_thread diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 916f33a..65b8dbf 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -144,19 +144,36 @@ def print_array(array) end end - def print_hash(hash) + def do_print_hash_key_value(hash) + print_element("variables", {:type => 'hashItem'}) do + hash.each {|(k, v)| + print_variable('key', k, 'instance') + print_variable('value', v, 'instance') + } + end + end + + def do_print_hash(hash) print_element("variables") do - hash.keys.each {|k| + hash.each {|(k, v)| if k.class.name == "String" name = '\'' + k + '\'' else name = exec_with_allocation_control(k, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) end - print_variable(name, hash[k], 'instance') + print_variable(name, v, 'instance') } end end + def print_hash(hash) + if Debugger.key_value_mode + do_print_hash_key_value(hash) + else + do_print_hash(hash) + end + end + def print_string(string) print_element("variables") do if string.respond_to?('bytes') @@ -243,6 +260,7 @@ def exec_with_allocation_control(value, exec_method, overflow_message_type) def print_variable(name, value, kind) name = name.to_s + if value.nil? print("", CGI.escapeHTML(name), kind) return @@ -280,6 +298,7 @@ def print_variable(name, value, kind) CGI.escapeHTML(name), build_compact_value_attr(value, value_str), kind, build_value_attr(escaped_value_str), value.class, has_children, value.object_id) + print("", escaped_value_str) if Debugger.value_as_nested_element print('') rescue StandardError => e @@ -439,8 +458,11 @@ def print_load_result(file, exception = nil) end end - def print_element(name) - print("<#{name}>") + def print_element(name, additional_tags = nil) + additional_tags_presentation = additional_tags.nil? ? '' + : additional_tags.map {|tag, value| " #{tag}=\"#{value}\""}.reduce(:+) + + print("<#{name}#{additional_tags_presentation}>") begin yield if block_given? ensure diff --git a/test-base/test_base.rb b/test-base/test_base.rb index 01bd85d..91cf22d 100644 --- a/test-base/test_base.rb +++ b/test-base/test_base.rb @@ -82,9 +82,9 @@ def debug_jruby? config_load('debug_jruby') end - def start_ruby_process(script) + def start_ruby_process(script, additional_opts = '') @port = TestBase.find_free_port - cmd = debug_command(script, @port) + cmd = debug_command(script, @port, additional_opts) debug "Starting: #{cmd}\n" Thread.new do @@ -147,10 +147,10 @@ def create_test2(lines) # Creates test.rb with the given lines, set up @test_name and @test_path # variables and then start the process. - def create_socket(lines) + def create_socket(lines, additional_opts = '') @test_name = "test.rb" @test_path = create_file(@test_name, lines) - start_ruby_process(@test_path) + start_ruby_process(@test_path, additional_opts) end def socket diff --git a/test-base/variables_test.rb b/test-base/variables_test.rb index 67f9b48..50c1b2d 100644 --- a/test-base/variables_test.rb +++ b/test-base/variables_test.rb @@ -199,22 +199,64 @@ def test_to_s_raises_exception send_cont end + def test_new_hash_presentation + create_socket ['class A', + ' def to_s', + ' "A instance"', + ' end', + 'end', + + 'class C', + ' def to_s', + ' "C instance"', + ' end', + 'end', + + 'b = Hash.new', + 'c = C.new', + 'a = A.new', + 'b[1] = a', + 'b[a] = "1"', + 'b[c] = a', + 'puts b #bp here'], '--key-value' + run_to_line(17) + send_ruby('v l') + assert_variables(read_variables, 3, + {:name => "a", :value => "A instance",:type => "A"}, + {:name => "b", :value => "Hash (3 elements)", :type => "Hash"}, + {:name => "c", :value => "C instance", :type => "C"}) + + send_ruby("v i b") + + assert_variables(read_variables, 6, + {:name => "key", :value => "1"}, + {:name => "value", :value => "A instance", :type => "A"}, + + {:name => "key", :value => "A instance", :type => "A"}, + {:name => "value", :value => "1", :type => "String"}, + + {:name => "key", :value => "C instance", :type => "C"}, + {:name => "value", :value => "A instance", :type => "A"}) + send_cont + end + def test_to_s_timelimit create_socket ['class A', - 'def to_s', - 'a = 1', - 'loop do', - 'a = a + 1', - 'sleep 1', - 'break if (a > 2)', - 'end', - 'a.to_s', - 'end', - 'end', - 'b = Hash.new', - 'b[A.new] = A.new', - 'b[1] = A.new', - 'puts b #bp here'] + 'def to_s', + 'a = 1', + 'loop do', + 'a = a + 1', + 'sleep 1', + 'break if (a > 2)', + 'end', + 'a.to_s', + 'end', + 'end', + + 'b = Hash.new', + 'b[A.new] = A.new', + 'b[1] = A.new', + 'puts b #bp here'], '--evaluation-control --time-limit 100 --memory-limit 0' run_to_line(15) send_ruby('v l') assert_variables(read_variables, 1, diff --git a/test/rd_test_base.rb b/test/rd_test_base.rb index 7d29edc..d5b7e4f 100644 --- a/test/rd_test_base.rb +++ b/test/rd_test_base.rb @@ -18,13 +18,13 @@ def setup end end - def debug_command(script, port) + def debug_command(script, port, additional_opts='') cmd = "#{interpreter}" cmd << " --debug" if jruby? cmd << " -J-Xdebug -J-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y" if jruby? and debug_jruby? cmd << " -I 'lib:#{File.dirname(script)}' #{@rdebug_ide}" + (@verbose_server ? " -d" : "") + - " -p #{port} --evaluation-control --time-limit 100 --memory-limit 0 -- '#{script}'" + " -p #{port} #{additional_opts} -- '#{script}'" end def start_debugger