From bc4254004065aecaa57b7293de7672a037331854 Mon Sep 17 00:00:00 2001 From: Alexander Momchilov Date: Wed, 3 Jan 2024 22:57:48 -0500 Subject: [PATCH 1/8] Improve existing tests --- lib/debug/server_dap.rb | 1 + test/protocol/hover_raw_dap_test.rb | 41 +++++++++++++++-------------- test/protocol/variables_test.rb | 2 +- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/lib/debug/server_dap.rb b/lib/debug/server_dap.rb index 87c22ca45..f6fca9a46 100644 --- a/lib/debug/server_dap.rb +++ b/lib/debug/server_dap.rb @@ -880,6 +880,7 @@ def process_dap args case req.dig('arguments', 'filter') when 'indexed' start = req.dig('arguments', 'start') || 0 + # FIXME: `req.dig('arguments', 'count')` needs to be capped to be `<= obj.size`. count = req.dig('arguments', 'count') || obj.size vars = (start ... (start + count)).map{|i| variable(i.to_s, obj[i]) diff --git a/test/protocol/hover_raw_dap_test.rb b/test/protocol/hover_raw_dap_test.rb index b4b617ed9..f052b431b 100644 --- a/test/protocol/hover_raw_dap_test.rb +++ b/test/protocol/hover_raw_dap_test.rb @@ -578,80 +578,81 @@ def test_hover_works_correctly variables: [ { name: "0", - value: /.*/, - type: /.*/, + value: "JSON::Ext::Generator::GeneratorMethods::Integer", + type: "Module", variablesReference: 22, indexedVariables: 0, namedVariables: /\d+/ }, { name: "1", - value: /.*/, - type: /.*/, + value: "Numeric", + type: "Class", variablesReference: 23, indexedVariables: 0, namedVariables: /\d+/ }, { name: "2", - value: /.*/, - type: /.*/, + value: "Comparable", + type: "Module", variablesReference: 24, indexedVariables: 0, namedVariables: /\d+/ }, { name: "3", - value: /.*/, - type: /.*/, + value: "Object", + type: "Class", variablesReference: 25, indexedVariables: 0, namedVariables: /\d+/ }, { name: "4", - value: /.*/, - type: /.*/, + value: "JSON::Ext::Generator::GeneratorMethods::Object", + type: "Module", variablesReference: 26, indexedVariables: 0, namedVariables: /\d+/ }, { name: "5", - value: /.*/, - type: /.*/, + value: "PP::ObjectMixin", + type: "Module", variablesReference: 27, indexedVariables: 0, namedVariables: /\d+/ }, { name: "6", - value: /.*/, - type: /.*/, + value: "DEBUGGER__::TrapInterceptor", + type: "Module", variablesReference: 28, indexedVariables: 0, namedVariables: /\d+/ }, { name: "7", - value: /.*/, - type: /.*/, + value: "Kernel", + type: "Module", variablesReference: 29, indexedVariables: 0, namedVariables: /\d+/ }, { name: "8", - value: /.*/, - type: /.*/, + value: "BasicObject", + type: "Class", variablesReference: 30, indexedVariables: 0, namedVariables: /\d+/ }, { + # This is an extra entry caused by an out-of-bounds index access in server_dap.rb name: "9", - value: /.*/, - type: /.*/, + value: nil, + type: NilClass, variablesReference: 31, indexedVariables: 0, namedVariables: /\d+/ diff --git a/test/protocol/variables_test.rb b/test/protocol/variables_test.rb index 9b82419e8..2bc880ed8 100644 --- a/test/protocol/variables_test.rb +++ b/test/protocol/variables_test.rb @@ -76,7 +76,7 @@ def test_ordering_instance_variables res = send_dap_request 'variables', variablesReference: variables_reference instance_vars = res.dig(:body, :variables) - assert_equal instance_vars.map { |var| var[:name] }, ["#class", "@a", "@b", "@c"] + assert_equal ["#class", "@a", "@b", "@c"], instance_vars.map { |var| var[:name] } req_terminate_debuggee end From 0e8d46a0ad5442d2cfbc90fc6e4c0eccecedc50c Mon Sep 17 00:00:00 2001 From: Alexander Momchilov Date: Wed, 3 Jan 2024 23:16:44 -0500 Subject: [PATCH 2/8] Share variable inspection logic between CDP and DAP --- lib/debug/limited_pp.rb | 52 +++++++ lib/debug/server_cdp.rb | 55 +++---- lib/debug/server_dap.rb | 138 ++++++----------- lib/debug/session.rb | 50 +----- lib/debug/variable.rb | 56 +++++++ lib/debug/variable_inspector.rb | 86 +++++++++++ test/debug/variable_inspector_test.rb | 215 ++++++++++++++++++++++++++ 7 files changed, 481 insertions(+), 171 deletions(-) create mode 100644 lib/debug/limited_pp.rb create mode 100644 lib/debug/variable.rb create mode 100644 lib/debug/variable_inspector.rb create mode 100644 test/debug/variable_inspector_test.rb diff --git a/lib/debug/limited_pp.rb b/lib/debug/limited_pp.rb new file mode 100644 index 000000000..b2359e40a --- /dev/null +++ b/lib/debug/limited_pp.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require "pp" + +module DEBUGGER__ + class LimitedPP + SHORT_INSPECT_LENGTH = 40 + + def self.pp(obj, max = 80) + out = self.new(max) + catch out do + ::PP.singleline_pp(obj, out) + end + out.buf + end + + attr_reader :buf + + def initialize max + @max = max + @cnt = 0 + @buf = String.new + end + + def <<(other) + @buf << other + + if @buf.size >= @max + @buf = @buf[0..@max] + '...' + throw self + end + end + + def self.safe_inspect obj, max_length: SHORT_INSPECT_LENGTH, short: false + if short + LimitedPP.pp(obj, max_length) + else + obj.inspect + end + rescue NoMethodError => e + klass, oid = M_CLASS.bind_call(obj), M_OBJECT_ID.bind_call(obj) + if obj == (r = e.receiver) + "<\##{klass.name}#{oid} does not have \#inspect>" + else + rklass, roid = M_CLASS.bind_call(r), M_OBJECT_ID.bind_call(r) + "<\##{klass.name}:#{roid} contains <\##{rklass}:#{roid} and it does not have #inspect>" + end + rescue Exception => e + "<#inspect raises #{e.inspect}>" + end + end +end diff --git a/lib/debug/server_cdp.rb b/lib/debug/server_cdp.rb index 3826f1242..56a9bee8e 100644 --- a/lib/debug/server_cdp.rb +++ b/lib/debug/server_cdp.rb @@ -8,6 +8,8 @@ require 'tmpdir' require 'tempfile' require 'timeout' +require_relative 'variable' +require_relative 'variable_inspector' module DEBUGGER__ module UI_CDP @@ -1111,46 +1113,29 @@ def process_cdp args event! :protocol_result, :scope, req, vars when :properties oid = args.shift - result = [] - prop = [] if obj = @obj_map[oid] - case obj - when Array - result = obj.map.with_index{|o, i| - variable i.to_s, o - } - when Hash - result = obj.map{|k, v| - variable(k, v) - } - when Struct - result = obj.members.map{|m| - variable(m, obj[m]) - } - when String - prop = [ - internalProperty('#length', obj.length), - internalProperty('#encoding', obj.encoding) - ] - when Class, Module - result = obj.instance_variables.map{|iv| - variable(iv, obj.instance_variable_get(iv)) - } - prop = [internalProperty('%ancestors', obj.ancestors[1..])] - when Range - prop = [ - internalProperty('#begin', obj.begin), - internalProperty('#end', obj.end), - ] + members = if Array === obj + VariableInspector.new.indexed_members_of(obj, start: 0, count: obj.size) + else + VariableInspector.new.named_members_of(obj) end - result += M_INSTANCE_VARIABLES.bind_call(obj).map{|iv| - variable(iv, M_INSTANCE_VARIABLE_GET.bind_call(obj, iv)) - } - prop += [internalProperty('#class', M_CLASS.bind_call(obj))] + result = members.filter_map do |member| + next if member.internal? + variable(member.name, member.value) + end + + internal_properties = members.filter_map do |member| + next unless member.internal? + internalProperty(member.name, member.value) + end + else + result = [] + internal_properties = [] end - event! :protocol_result, :properties, req, result: result, internalProperties: prop + + event! :protocol_result, :properties, req, result: result, internalProperties: internal_properties when :exception oid = args.shift exc = nil diff --git a/lib/debug/server_dap.rb b/lib/debug/server_dap.rb index f6fca9a46..899c0bdf7 100644 --- a/lib/debug/server_dap.rb +++ b/lib/debug/server_dap.rb @@ -4,6 +4,8 @@ require 'irb/completion' require 'tmpdir' require 'fileutils' +require_relative 'variable' +require_relative 'variable_inspector' module DEBUGGER__ module UI_DAP @@ -765,18 +767,11 @@ def register_vars vars, tid end end - class NaiveString - attr_reader :str - def initialize str - @str = str - end - end - class ThreadClient MAX_LENGTH = 180 def value_inspect obj, short: true - # TODO: max length should be configuarable? + # TODO: max length should be configurable? str = DEBUGGER__.safe_inspect obj, short: short, max_length: MAX_LENGTH if str.encoding == Encoding::UTF_8 @@ -869,7 +864,7 @@ def process_dap args fid = args.shift frame = get_frame(fid) vars = collect_locals(frame).map do |var, val| - variable(var, val) + render_variable Variable.new(name: var, value: val) end event! :protocol_result, :scope, req, variables: vars, tid: self.id @@ -877,49 +872,18 @@ def process_dap args vid = args.shift obj = @var_map[vid] if obj - case req.dig('arguments', 'filter') + members = case req.dig('arguments', 'filter') when 'indexed' - start = req.dig('arguments', 'start') || 0 - # FIXME: `req.dig('arguments', 'count')` needs to be capped to be `<= obj.size`. - count = req.dig('arguments', 'count') || obj.size - vars = (start ... (start + count)).map{|i| - variable(i.to_s, obj[i]) - } + VariableInspector.new.indexed_members_of( + obj, + start: req.dig('arguments', 'start') || 0, + count: req.dig('arguments', 'count') || obj.size, + ) else - vars = [] - - case obj - when Hash - vars = obj.map{|k, v| - variable(value_inspect(k), v,) - } - when Struct - vars = obj.members.map{|m| - variable(m, obj[m]) - } - when String - vars = [ - variable('#length', obj.length), - variable('#encoding', obj.encoding), - ] - printed_str = value_inspect(obj) - vars << variable('#dump', NaiveString.new(obj)) if printed_str.end_with?('...') - when Class, Module - vars << variable('%ancestors', obj.ancestors[1..]) - when Range - vars = [ - variable('#begin', obj.begin), - variable('#end', obj.end), - ] - end - - unless NaiveString === obj - vars += M_INSTANCE_VARIABLES.bind_call(obj).sort.map{|iv| - variable(iv, M_INSTANCE_VARIABLE_GET.bind_call(obj, iv)) - } - vars.unshift variable('#class', M_CLASS.bind_call(obj)) - end + VariableInspector.new.named_members_of(obj) end + + vars = members.map { |member| render_variable member } end event! :protocol_result, :variable, req, variables: (vars || []), tid: self.id @@ -976,7 +940,13 @@ def process_dap args result = 'Error: Can not evaluate on this frame' end - event! :protocol_result, :evaluate, req, message: message, tid: self.id, **evaluate_result(result) + result_variable = Variable.new(name: nil, value: result) + + event! :protocol_result, :evaluate, req, + message: message, + tid: self.id, + result: result_variable.inspect_value, + **render_variable(result_variable) when :completions fid, text = args @@ -1052,58 +1022,48 @@ def type_name obj end end - def variable_ name, obj, indexedVariables: 0, namedVariables: 0 - if indexedVariables > 0 || namedVariables > 0 - vid = @var_map.size + 1 - @var_map[vid] = obj + # Renders the given Member into a DAP Variable + # https://microsoft.github.io/debug-adapter-protocol/specification#variable + def render_variable member + indexedVariables, namedVariables = if Array === member.value + [member.value.size, 0] else - vid = 0 + [0, VariableInspector.new.named_members_of(member.value).count] end - namedVariables += M_INSTANCE_VARIABLES.bind_call(obj).size - - if NaiveString === obj - str = obj.str.dump - vid = indexedVariables = namedVariables = 0 + # > If `variablesReference` is > 0, the variable is structured and its children + # > can be retrieved by passing `variablesReference` to the `variables` request + # > as long as execution remains suspended. + if indexedVariables > 0 || namedVariables > 0 + # This object has children that we might need to query, so we need to remember it by its vid + vid = @var_map.size + 1 + @var_map[vid] = member.value else - str = value_inspect(obj) + # This object has no children, so we don't need to remember it in the `@var_map` + vid = 0 end - if name - { name: name, - value: str, - type: type_name(obj), + variable = if member.name + # These two hashes are repeated so the "name" can come always come first, when available, + # which improves the readability of protocol responses. + { + name: member.name, + value: member.inspect_value, + type: member.value_type_name, variablesReference: vid, - indexedVariables: indexedVariables, - namedVariables: namedVariables, } else - { result: str, - type: type_name(obj), + { + value: member.inspect_value, + type: member.value_type_name, variablesReference: vid, - indexedVariables: indexedVariables, - namedVariables: namedVariables, } end - end - def variable name, obj - case obj - when Array - variable_ name, obj, indexedVariables: obj.size - when Hash - variable_ name, obj, namedVariables: obj.size - when String - variable_ name, obj, namedVariables: 3 # #length, #encoding, #to_str - when Struct - variable_ name, obj, namedVariables: obj.size - when Class, Module - variable_ name, obj, namedVariables: 1 # %ancestors (#ancestors without self) - when Range - variable_ name, obj, namedVariables: 2 # #begin, #end - else - variable_ name, obj, namedVariables: 1 # #class - end + variable[:indexedVariables] = indexedVariables unless indexedVariables == 0 + variable[:namedVariables] = namedVariables unless namedVariables == 0 + + variable end end end diff --git a/lib/debug/session.rb b/lib/debug/session.rb index 05dc7f508..de9313955 100644 --- a/lib/debug/session.rb +++ b/lib/debug/session.rb @@ -34,6 +34,7 @@ require_relative 'source_repository' require_relative 'breakpoint' require_relative 'tracer' +require_relative 'limited_pp' # To prevent loading old lib/debug.rb in Ruby 2.6 to 3.0 $LOADED_FEATURES << 'debug.rb' @@ -2327,53 +2328,8 @@ def self.load_rc end end - # Inspector - - SHORT_INSPECT_LENGTH = 40 - - class LimitedPP - def self.pp(obj, max=80) - out = self.new(max) - catch out do - PP.singleline_pp(obj, out) - end - out.buf - end - - attr_reader :buf - - def initialize max - @max = max - @cnt = 0 - @buf = String.new - end - - def <<(other) - @buf << other - - if @buf.size >= @max - @buf = @buf[0..@max] + '...' - throw self - end - end - end - - def self.safe_inspect obj, max_length: SHORT_INSPECT_LENGTH, short: false - if short - LimitedPP.pp(obj, max_length) - else - obj.inspect - end - rescue NoMethodError => e - klass, oid = M_CLASS.bind_call(obj), M_OBJECT_ID.bind_call(obj) - if obj == (r = e.receiver) - "<\##{klass.name}#{oid} does not have \#inspect>" - else - rklass, roid = M_CLASS.bind_call(r), M_OBJECT_ID.bind_call(r) - "<\##{klass.name}:#{roid} contains <\##{rklass}:#{roid} and it does not have #inspect>" - end - rescue Exception => e - "<#inspect raises #{e.inspect}>" + def self.safe_inspect obj, max_length: LimitedPP::SHORT_INSPECT_LENGTH, short: false + LimitedPP.safe_inspect(obj, max_length: max_length, short: short) end def self.warn msg diff --git a/lib/debug/variable.rb b/lib/debug/variable.rb new file mode 100644 index 000000000..2f78e69dd --- /dev/null +++ b/lib/debug/variable.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require_relative 'variable_inspector' + +module DEBUGGER__ + class Variable + attr_reader :name, :value + + def initialize(name:, value:, internal: false) + @name = name + @value = value + @is_internal = internal + end + + def internal? + @is_internal + end + + def self.internal name:, value: + new(name: name, value: value, internal: true) + end + + def inspect_value + @inspect_value ||= if VariableInspector::NaiveString === @value + @value.str.dump + else + VariableInspector.value_inspect(@value) + end + end + + def value_type_name + klass = M_CLASS.bind_call(@value) + + begin + M_NAME.bind_call(klass) || klass.to_s + rescue Exception => e + "" + end + end + + def ==(other) + other.instance_of?(self.class) && + @name == other.name && + @value == other.value && + @is_internal == other.internal? + end + + def inspect + "#" + end + + # TODO: Replace with Reflection helpers once they are merged + # https://github.com/ruby/debug/pull/1002 + M_CLASS = method(:class).unbind + end +end diff --git a/lib/debug/variable_inspector.rb b/lib/debug/variable_inspector.rb new file mode 100644 index 000000000..72dd01377 --- /dev/null +++ b/lib/debug/variable_inspector.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +require_relative 'variable' +require_relative 'limited_pp' + +module DEBUGGER__ + class VariableInspector + def indexed_members_of(obj, start:, count:) + return [] if start > (obj.length - 1) + + (start...(start + count)).map do |i| + Variable.new(name: i.to_s, value: obj[i]) + end + end + + def named_members_of(obj) + return [] if NaiveString === obj + + members = case obj + when Hash then obj.map { |k, v| Variable.new(name: value_inspect(k), value: v) } + when Struct then obj.members.map { |name| Variable.new(name: name, value: obj[name]) } + when String + members = [ + Variable.internal(name: '#length', value: obj.length), + Variable.internal(name: '#encoding', value: obj.encoding), + ] + + printed_str = value_inspect(obj) + members << Variable.internal(name: "#dump", value: NaiveString.new(obj)) if printed_str.end_with?('...') + + members + when Class, Module then [Variable.internal(name: "%ancestors", value: obj.ancestors[1..])] + when Range then [ + Variable.internal(name: "#begin", value: obj.begin), + Variable.internal(name: "#end", value: obj.end), + ] + else [] + end + + ivars_members = M_INSTANCE_VARIABLES.bind_call(obj).sort.map do |iv| + Variable.new(name: iv, value: M_INSTANCE_VARIABLE_GET.bind_call(obj, iv)) + end + + members.unshift Variable.internal(name: '#class', value: M_CLASS.bind_call(obj)) + members.concat(ivars_members) + + members + end + + private + + def value_inspect(obj, short: true) + self.class.value_inspect(obj, short: short) + end + + def self.value_inspect(obj, short: true) + # TODO: max length should be configurable? + str = LimitedPP.safe_inspect obj, short: short, max_length: MAX_LENGTH + + if str.encoding == Encoding::UTF_8 + str.scrub + else + str.encode(Encoding::UTF_8, invalid: :replace, undef: :replace) + end + end + + MAX_LENGTH = 180 + + # TODO: Replace with Reflection helpers once they are merged + # https://github.com/ruby/debug/pull/1002 + M_INSTANCE_VARIABLES = method(:instance_variables).unbind + M_INSTANCE_VARIABLE_GET = method(:instance_variable_get).unbind + M_CLASS = method(:class).unbind + + class NaiveString + attr_reader :str + def initialize str + @str = str + end + + def == other + other.instance_of?(self.class) && @str == other.str + end + end + end +end diff --git a/test/debug/variable_inspector_test.rb b/test/debug/variable_inspector_test.rb new file mode 100644 index 000000000..33c833685 --- /dev/null +++ b/test/debug/variable_inspector_test.rb @@ -0,0 +1,215 @@ +# frozen_string_literal: true + +require 'test/unit' +require_relative '../../lib/debug/variable_inspector' + +module DEBUGGER__ + class VariableInspectorTest < Test::Unit::TestCase + def setup + @inspector = VariableInspector.new + end + + def test_array_indexed_members + a = ['a', 'b', 'c'] + + # Test correct truncation + assert_equal [], @inspector.indexed_members_of(a, start: 0, count: 0).map(&:value) + assert_equal ['a'], @inspector.indexed_members_of(a, start: 0, count: 1).map(&:value) + assert_equal ['a', 'b'], @inspector.indexed_members_of(a, start: 0, count: 2).map(&:value) + assert_equal ['a', 'b', 'c'], @inspector.indexed_members_of(a, start: 0, count: 3).map(&:value) + assert_equal ['a', 'b', 'c'], @inspector.indexed_members_of(a, start: 0, count: 4).map(&:value) + assert_equal ['b'], @inspector.indexed_members_of(a, start: 1, count: 1).map(&:value) + assert_equal ['b', 'c'], @inspector.indexed_members_of(a, start: 1, count: 2).map(&:value) + assert_equal ['b', 'c'], @inspector.indexed_members_of(a, start: 1, count: 3).map(&:value) + assert_equal ['b', 'c'], @inspector.indexed_members_of(a, start: 1, count: 4).map(&:value) + + # Test starting off the end + assert_equal [], @inspector.indexed_members_of(a, start: 999, count: 1).map(&:value) + + assert_equal [], @inspector.indexed_members_of([], start: 0, count: 999) + assert_equal [Variable.new(name: '0', value: 'a')], @inspector.indexed_members_of(['a'], start: 0, count: 999) + + expected = [ + Variable.new(name: '5', value: 'f'), + Variable.new(name: '6', value: 'g'), + Variable.new(name: '7', value: 'h'), + ] + assert_equal expected, @inspector.indexed_members_of(Array('a'...'z'), start: 5, count: 3) + end + + def test_named_members_of_hash + actual = @inspector.named_members_of( + { + sym: 'has Symbol key', + "str" => 'has String key', + 1 => 'has Integer key', + } + ) + + expected = [ + Variable.internal(name: '#class', value: Hash), + Variable.new(name: ':sym', value: "has Symbol key"), + Variable.new(name: '"str"', value: "has String key"), + Variable.new(name: '1', value: "has Integer key"), + ] + + assert_equal expected, actual + end + + def test_named_members_of_struct + expected = [ + Variable.internal(name: '#class', value: PointStruct), + # Struct members are stored separately from ivars + Variable.new(name: :x, value: 1), + Variable.new(name: :y, value: 2), + # If there are any other other ivars, they should also be included + Variable.new(name: :@ivar, value: "some other ivar"), + ] + + point = PointStruct.new(x: 1, y: 2) + + assert_equal expected, @inspector.named_members_of(point) + end + + def test_named_members_of_string + expected = [ + Variable.internal(name: '#class', value: String), + Variable.internal(name: '#length', value: 5), + Variable.internal(name: '#encoding', value: Encoding::UTF_8), + # skip #dump member for short strings + ] + + assert_equal expected, @inspector.named_members_of("hello") + + + long_string = "A long string " + ('*' * 1000) + + expected = [ + Variable.internal(name: '#class', value: String), + Variable.internal(name: '#length', value: long_string.length), + Variable.internal(name: '#encoding', value: Encoding::UTF_8), + Variable.internal(name: '#dump', value: VariableInspector::NaiveString.new(long_string)), + ] + + assert_equal expected, @inspector.named_members_of(long_string) + end + + def test_named_members_of_class + expected = [ + Variable.internal(name: '#class', value: Class), + Variable.internal(name: '%ancestors', value: PointStruct.ancestors.drop(1)), + ] + + assert_equal expected, @inspector.named_members_of(PointStruct) + end + + def test_named_members_of_module + ancestors = [Module.new, Module.new, Module.new] + mod = Module.new do + include *ancestors + end + + expected = [ + Variable.internal(name: '#class', value: Module), + Variable.internal(name: '%ancestors', value: ancestors), + ] + + assert_equal expected, @inspector.named_members_of(mod) + end + + def test_named_members_of_range + # Ranges that include end + assert_equal( + [ + Variable.internal(name: "#class", value: Range), + Variable.internal(name: "#begin", value: 1), + Variable.internal(name: "#end", value: 2), + ], + @inspector.named_members_of(1..2) + ) + assert_equal( + [ + Variable.internal(name: "#class", value: Range), + Variable.internal(name: "#begin", value: 1), + Variable.internal(name: "#end", value: nil), + ], + @inspector.named_members_of(1..) + ) + assert_equal( + [ + Variable.internal(name: "#class", value: Range), + Variable.internal(name: "#begin", value: nil), + Variable.internal(name: "#end", value: 2), + ], + @inspector.named_members_of(..2) + ) + + # Ranges that exclude end + assert_equal( + [ + Variable.internal(name: "#class", value: Range), + Variable.internal(name: "#begin", value: 1), + Variable.internal(name: "#end", value: 2), + ], + @inspector.named_members_of(1...2) + ) + assert_equal( + [ + Variable.internal(name: "#class", value: Range), + Variable.internal(name: "#begin", value: 1), + Variable.internal(name: "#end", value: nil), + ], + @inspector.named_members_of(1...) + ) + assert_equal( + [ + Variable.internal(name: "#class", value: Range), + Variable.internal(name: "#begin", value: nil), + Variable.internal(name: "#end", value: 2) + ], + @inspector.named_members_of(...2) + ) + + # Range with nil bounds + assert_equal( + [ + Variable.internal(name: "#class", value: Range), + Variable.internal(name: "#begin", value: nil), + Variable.internal(name: "#end", value: nil), + ], + @inspector.named_members_of(Range.new(nil, nil)) + ) + end + + def test_named_members_of_other_objects + assert_equal [Variable.internal(name: '#class', value: Object)], @inspector.named_members_of(Object.new) + + expected = [ + Variable.internal(name: '#class', value: Point), + # Struct members are stored separately from ivars + Variable.new(name: :@x, value: 1), + Variable.new(name: :@y, value: 2), + ] + + point = Point.new(x: 1, y: 2) + + assert_equal expected, @inspector.named_members_of(point) + end + + private + + class PointStruct < Struct.new(:x, :y, keyword_init: true) + def initialize(x:, y:) + super + @ivar = "some other ivar" + end + end + + class Point # A "plain ol' Ruby object" + def initialize(x:, y:) + @x = x + @y = y + end + end + end +end From 6ac6e109349379c689a43d65bbe5cfbd6f834e14 Mon Sep 17 00:00:00 2001 From: Alexander Momchilov Date: Tue, 26 Sep 2023 18:16:13 -0400 Subject: [PATCH 3/8] Inline `variable.rb` --- lib/debug/server_cdp.rb | 1 - lib/debug/server_dap.rb | 1 - lib/debug/variable.rb | 56 --------------------------------- lib/debug/variable_inspector.rb | 52 +++++++++++++++++++++++++++++- 4 files changed, 51 insertions(+), 59 deletions(-) delete mode 100644 lib/debug/variable.rb diff --git a/lib/debug/server_cdp.rb b/lib/debug/server_cdp.rb index 56a9bee8e..531d41155 100644 --- a/lib/debug/server_cdp.rb +++ b/lib/debug/server_cdp.rb @@ -8,7 +8,6 @@ require 'tmpdir' require 'tempfile' require 'timeout' -require_relative 'variable' require_relative 'variable_inspector' module DEBUGGER__ diff --git a/lib/debug/server_dap.rb b/lib/debug/server_dap.rb index 899c0bdf7..f0a6117d3 100644 --- a/lib/debug/server_dap.rb +++ b/lib/debug/server_dap.rb @@ -4,7 +4,6 @@ require 'irb/completion' require 'tmpdir' require 'fileutils' -require_relative 'variable' require_relative 'variable_inspector' module DEBUGGER__ diff --git a/lib/debug/variable.rb b/lib/debug/variable.rb deleted file mode 100644 index 2f78e69dd..000000000 --- a/lib/debug/variable.rb +++ /dev/null @@ -1,56 +0,0 @@ -# frozen_string_literal: true - -require_relative 'variable_inspector' - -module DEBUGGER__ - class Variable - attr_reader :name, :value - - def initialize(name:, value:, internal: false) - @name = name - @value = value - @is_internal = internal - end - - def internal? - @is_internal - end - - def self.internal name:, value: - new(name: name, value: value, internal: true) - end - - def inspect_value - @inspect_value ||= if VariableInspector::NaiveString === @value - @value.str.dump - else - VariableInspector.value_inspect(@value) - end - end - - def value_type_name - klass = M_CLASS.bind_call(@value) - - begin - M_NAME.bind_call(klass) || klass.to_s - rescue Exception => e - "" - end - end - - def ==(other) - other.instance_of?(self.class) && - @name == other.name && - @value == other.value && - @is_internal == other.internal? - end - - def inspect - "#" - end - - # TODO: Replace with Reflection helpers once they are merged - # https://github.com/ruby/debug/pull/1002 - M_CLASS = method(:class).unbind - end -end diff --git a/lib/debug/variable_inspector.rb b/lib/debug/variable_inspector.rb index 72dd01377..15c255013 100644 --- a/lib/debug/variable_inspector.rb +++ b/lib/debug/variable_inspector.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require_relative 'variable' require_relative 'limited_pp' module DEBUGGER__ @@ -83,4 +82,55 @@ def == other end end end + + class Variable + attr_reader :name, :value + + def initialize(name:, value:, internal: false) + @name = name + @value = value + @is_internal = internal + end + + def internal? + @is_internal + end + + def self.internal name:, value: + new(name: name, value: value, internal: true) + end + + def inspect_value + @inspect_value ||= if VariableInspector::NaiveString === @value + @value.str.dump + else + VariableInspector.value_inspect(@value) + end + end + + def value_type_name + klass = M_CLASS.bind_call(@value) + + begin + M_NAME.bind_call(klass) || klass.to_s + rescue Exception => e + "" + end + end + + def ==(other) + other.instance_of?(self.class) && + @name == other.name && + @value == other.value && + @is_internal == other.internal? + end + + def inspect + "#" + end + + # TODO: Replace with Reflection helpers once they are merged + # https://github.com/ruby/debug/pull/1002 + M_CLASS = method(:class).unbind + end end From ccdce55ba49478aa3b46a6a40bc6476347fa5715 Mon Sep 17 00:00:00 2001 From: Alexander Momchilov Date: Wed, 3 Jan 2024 21:09:54 -0500 Subject: [PATCH 4/8] Fix edge case for falsy values --- lib/debug/server_cdp.rb | 4 +++- lib/debug/server_dap.rb | 6 ++++-- test/protocol/step_back_raw_dap_test.rb | 6 +++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/debug/server_cdp.rb b/lib/debug/server_cdp.rb index 531d41155..e3532f7fd 100644 --- a/lib/debug/server_cdp.rb +++ b/lib/debug/server_cdp.rb @@ -1113,7 +1113,9 @@ def process_cdp args when :properties oid = args.shift - if obj = @obj_map[oid] + if @obj_map.key?(oid) + obj = @obj_map[oid] + members = if Array === obj VariableInspector.new.indexed_members_of(obj, start: 0, count: obj.size) else diff --git a/lib/debug/server_dap.rb b/lib/debug/server_dap.rb index f0a6117d3..6edde3746 100644 --- a/lib/debug/server_dap.rb +++ b/lib/debug/server_dap.rb @@ -869,8 +869,10 @@ def process_dap args event! :protocol_result, :scope, req, variables: vars, tid: self.id when :variable vid = args.shift - obj = @var_map[vid] - if obj + + if @var_map.key?(vid) + obj = @var_map[vid] + members = case req.dig('arguments', 'filter') when 'indexed' VariableInspector.new.indexed_members_of( diff --git a/test/protocol/step_back_raw_dap_test.rb b/test/protocol/step_back_raw_dap_test.rb index eee84d8e2..413a6cda6 100644 --- a/test/protocol/step_back_raw_dap_test.rb +++ b/test/protocol/step_back_raw_dap_test.rb @@ -883,7 +883,7 @@ def test_step_back_works_correctly namedVariables: /\d+/, indexedVariables: 0, expensive: false, - variablesReference: 11 + variablesReference: 12 }, { name: "Global variables", @@ -917,7 +917,7 @@ def test_step_back_works_correctly name: "%self", value: "Foo", type: "Module", - variablesReference: 12, + variablesReference: 13, indexedVariables: 0, namedVariables: /\d+/ }, @@ -925,7 +925,7 @@ def test_step_back_works_correctly name: "bar", value: "nil", type: "NilClass", - variablesReference: 13, + variablesReference: 14, indexedVariables: 0, namedVariables: /\d+/ } From ff9816c19845a88c62c19f65d234d970df4e68f9 Mon Sep 17 00:00:00 2001 From: Alexander Momchilov Date: Wed, 3 Jan 2024 21:13:45 -0500 Subject: [PATCH 5/8] Skip unnecessary values when 0 These values are assumed to be 0 if they're missing. --- lib/debug/server_dap.rb | 9 ++-- test/protocol/boot_config_raw_dap_test.rb | 3 -- test/protocol/break_raw_dap_test.rb | 21 -------- test/protocol/call_stack_raw_dap_test.rb | 13 ----- test/protocol/catch_raw_dap_test.rb | 14 ----- test/protocol/eval_raw_dap_test.rb | 48 ----------------- test/protocol/finish_raw_dap_test.rb | 10 ---- test/protocol/hover_raw_dap_test.rb | 65 ----------------------- test/protocol/next_raw_dap_test.rb | 7 --- test/protocol/step_back_raw_dap_test.rb | 17 ------ test/protocol/step_raw_dap_test.rb | 11 ---- test/protocol/watch_raw_dap_test.rb | 55 ------------------- 12 files changed, 4 insertions(+), 269 deletions(-) diff --git a/lib/debug/server_dap.rb b/lib/debug/server_dap.rb index 6edde3746..a218e85a7 100644 --- a/lib/debug/server_dap.rb +++ b/lib/debug/server_dap.rb @@ -849,14 +849,12 @@ def process_dap args presentationHint: 'locals', # variablesReference: N, # filled by SESSION namedVariables: lnum, - indexedVariables: 0, expensive: false, }, { name: 'Global variables', presentationHint: 'globals', variablesReference: 1, # GLOBAL namedVariables: safe_global_variables.size, - indexedVariables: 0, expensive: false, }] when :scope @@ -1052,18 +1050,19 @@ def render_variable member value: member.inspect_value, type: member.value_type_name, variablesReference: vid, + indexedVariables: indexedVariables, + namedVariables: namedVariables, } else { value: member.inspect_value, type: member.value_type_name, variablesReference: vid, + indexedVariables: indexedVariables, + namedVariables: namedVariables, } end - variable[:indexedVariables] = indexedVariables unless indexedVariables == 0 - variable[:namedVariables] = namedVariables unless namedVariables == 0 - variable end end diff --git a/test/protocol/boot_config_raw_dap_test.rb b/test/protocol/boot_config_raw_dap_test.rb index 677becd63..d182cf6ad 100644 --- a/test/protocol/boot_config_raw_dap_test.rb +++ b/test/protocol/boot_config_raw_dap_test.rb @@ -200,7 +200,6 @@ def test_boot_configuration_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -209,7 +208,6 @@ def test_boot_configuration_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -237,7 +235,6 @@ def test_boot_configuration_works_correctly value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ } ] diff --git a/test/protocol/break_raw_dap_test.rb b/test/protocol/break_raw_dap_test.rb index 5427959d3..f551ad3e8 100644 --- a/test/protocol/break_raw_dap_test.rb +++ b/test/protocol/break_raw_dap_test.rb @@ -127,7 +127,6 @@ def test_break_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -136,7 +135,6 @@ def test_break_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -164,7 +162,6 @@ def test_break_works_correctly value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -416,7 +413,6 @@ def test_break_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 4 }, @@ -425,7 +421,6 @@ def test_break_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -453,7 +448,6 @@ def test_break_works_correctly value: "Foo", type: "Module", variablesReference: 5, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -461,7 +455,6 @@ def test_break_works_correctly value: "nil", type: "NilClass", variablesReference: 6, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -595,7 +588,6 @@ def test_break_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 7 }, @@ -604,7 +596,6 @@ def test_break_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -632,7 +623,6 @@ def test_break_works_correctly value: "Foo::Bar", type: "Class", variablesReference: 8, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -755,7 +745,6 @@ def test_break_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 9 }, @@ -764,7 +753,6 @@ def test_break_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -792,7 +780,6 @@ def test_break_works_correctly value: "Foo", type: "Module", variablesReference: 10, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -800,7 +787,6 @@ def test_break_works_correctly value: "nil", type: "NilClass", variablesReference: 11, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -953,7 +939,6 @@ def test_check_run_to_line_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -962,7 +947,6 @@ def test_check_run_to_line_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -990,7 +974,6 @@ def test_check_run_to_line_works_correctly value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -1149,7 +1132,6 @@ def test_check_run_to_line_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 4 }, @@ -1158,7 +1140,6 @@ def test_check_run_to_line_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -1186,7 +1167,6 @@ def test_check_run_to_line_works_correctly value: "Foo", type: "Module", variablesReference: 5, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1194,7 +1174,6 @@ def test_check_run_to_line_works_correctly value: "nil", type: "NilClass", variablesReference: 6, - indexedVariables: 0, namedVariables: /\d+/ } ] diff --git a/test/protocol/call_stack_raw_dap_test.rb b/test/protocol/call_stack_raw_dap_test.rb index db47ecf62..272a4a0d5 100644 --- a/test/protocol/call_stack_raw_dap_test.rb +++ b/test/protocol/call_stack_raw_dap_test.rb @@ -127,7 +127,6 @@ def test_call_stack_works_correctly_1643805481 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -136,7 +135,6 @@ def test_call_stack_works_correctly_1643805481 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -164,7 +162,6 @@ def test_call_stack_works_correctly_1643805481 value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -334,7 +331,6 @@ def test_call_stack_works_correctly_1643805481 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 4 }, @@ -343,7 +339,6 @@ def test_call_stack_works_correctly_1643805481 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -371,7 +366,6 @@ def test_call_stack_works_correctly_1643805481 value: "Foo::Bar", type: "Class", variablesReference: 5, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -398,7 +392,6 @@ def test_call_stack_works_correctly_1643805481 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 6 }, @@ -407,7 +400,6 @@ def test_call_stack_works_correctly_1643805481 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -435,7 +427,6 @@ def test_call_stack_works_correctly_1643805481 value: "Foo", type: "Module", variablesReference: 7, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -443,7 +434,6 @@ def test_call_stack_works_correctly_1643805481 value: "nil", type: "NilClass", variablesReference: 8, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -470,7 +460,6 @@ def test_call_stack_works_correctly_1643805481 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 9 }, @@ -479,7 +468,6 @@ def test_call_stack_works_correctly_1643805481 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -507,7 +495,6 @@ def test_call_stack_works_correctly_1643805481 value: "main", type: "Object", variablesReference: 10, - indexedVariables: 0, namedVariables: /\d+/ } ] diff --git a/test/protocol/catch_raw_dap_test.rb b/test/protocol/catch_raw_dap_test.rb index 273c3dd10..73bd020fb 100644 --- a/test/protocol/catch_raw_dap_test.rb +++ b/test/protocol/catch_raw_dap_test.rb @@ -126,7 +126,6 @@ def test_catching_runtime_error_works_correctly_1643891417 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -135,7 +134,6 @@ def test_catching_runtime_error_works_correctly_1643891417 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -163,7 +161,6 @@ def test_catching_runtime_error_works_correctly_1643891417 value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -297,7 +294,6 @@ def test_catching_runtime_error_works_correctly_1643891417 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 4 }, @@ -306,7 +302,6 @@ def test_catching_runtime_error_works_correctly_1643891417 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -334,7 +329,6 @@ def test_catching_runtime_error_works_correctly_1643891417 value: "Foo::Bar", type: "Class", variablesReference: 5, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -342,7 +336,6 @@ def test_catching_runtime_error_works_correctly_1643891417 value: "#", type: "RuntimeError", variablesReference: 6, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -495,7 +488,6 @@ def test_catching_any_exception_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -504,7 +496,6 @@ def test_catching_any_exception_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -532,7 +523,6 @@ def test_catching_any_exception_works_correctly value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -715,7 +705,6 @@ def test_catching_any_exception_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 4 }, @@ -724,7 +713,6 @@ def test_catching_any_exception_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -752,7 +740,6 @@ def test_catching_any_exception_works_correctly value: "1", type: "Integer", variablesReference: 5, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -760,7 +747,6 @@ def test_catching_any_exception_works_correctly value: "#", type: "ZeroDivisionError", variablesReference: 6, - indexedVariables: 0, namedVariables: /\d+/ } ] diff --git a/test/protocol/eval_raw_dap_test.rb b/test/protocol/eval_raw_dap_test.rb index 7f01a48e6..a8b2bf4d9 100644 --- a/test/protocol/eval_raw_dap_test.rb +++ b/test/protocol/eval_raw_dap_test.rb @@ -124,7 +124,6 @@ def test_eval_works_correctly_1643807667 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -133,7 +132,6 @@ def test_eval_works_correctly_1643807667 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -161,7 +159,6 @@ def test_eval_works_correctly_1643807667 value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -169,7 +166,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 4, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -177,7 +173,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 5, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -185,7 +180,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 6, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -193,7 +187,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 7, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -201,7 +194,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 8, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -209,7 +201,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 9, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -357,7 +348,6 @@ def test_eval_works_correctly_1643807667 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 10 }, @@ -366,7 +356,6 @@ def test_eval_works_correctly_1643807667 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -394,7 +383,6 @@ def test_eval_works_correctly_1643807667 value: "main", type: "Object", variablesReference: 11, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -402,7 +390,6 @@ def test_eval_works_correctly_1643807667 value: "2", type: "Integer", variablesReference: 12, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -410,7 +397,6 @@ def test_eval_works_correctly_1643807667 value: "3", type: "Integer", variablesReference: 13, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -418,7 +404,6 @@ def test_eval_works_correctly_1643807667 value: "1", type: "Integer", variablesReference: 14, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -426,7 +411,6 @@ def test_eval_works_correctly_1643807667 value: "4", type: "Integer", variablesReference: 15, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -434,7 +418,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 16, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -442,7 +425,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 17, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -519,7 +501,6 @@ def test_eval_works_correctly_1643807667 body: { type: "Integer", variablesReference: 18, - indexedVariables: 0, namedVariables: /\d+/, result: "2" } @@ -545,7 +526,6 @@ def test_eval_works_correctly_1643807667 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 19 }, @@ -554,7 +534,6 @@ def test_eval_works_correctly_1643807667 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -582,7 +561,6 @@ def test_eval_works_correctly_1643807667 value: "main", type: "Object", variablesReference: 20, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -590,7 +568,6 @@ def test_eval_works_correctly_1643807667 value: "2", type: "Integer", variablesReference: 21, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -598,7 +575,6 @@ def test_eval_works_correctly_1643807667 value: "3", type: "Integer", variablesReference: 22, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -606,7 +582,6 @@ def test_eval_works_correctly_1643807667 value: "1", type: "Integer", variablesReference: 23, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -614,7 +589,6 @@ def test_eval_works_correctly_1643807667 value: "4", type: "Integer", variablesReference: 24, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -622,7 +596,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 25, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -630,7 +603,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 26, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -715,7 +687,6 @@ def test_eval_works_correctly_1643807667 body: { type: "Integer", variablesReference: 27, - indexedVariables: 0, namedVariables: /\d+/, result: "4" } @@ -741,7 +712,6 @@ def test_eval_works_correctly_1643807667 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 28 }, @@ -750,7 +720,6 @@ def test_eval_works_correctly_1643807667 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -778,7 +747,6 @@ def test_eval_works_correctly_1643807667 value: "main", type: "Object", variablesReference: 29, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -786,7 +754,6 @@ def test_eval_works_correctly_1643807667 value: "2", type: "Integer", variablesReference: 30, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -794,7 +761,6 @@ def test_eval_works_correctly_1643807667 value: "3", type: "Integer", variablesReference: 31, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -802,7 +768,6 @@ def test_eval_works_correctly_1643807667 value: "1", type: "Integer", variablesReference: 32, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -810,7 +775,6 @@ def test_eval_works_correctly_1643807667 value: "4", type: "Integer", variablesReference: 33, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -818,7 +782,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 34, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -826,7 +789,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 35, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -852,7 +814,6 @@ def test_eval_works_correctly_1643807667 body: { type: "Integer", variablesReference: 36, - indexedVariables: 0, namedVariables: /\d+/, result: "3" } @@ -878,7 +839,6 @@ def test_eval_works_correctly_1643807667 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 37 }, @@ -887,7 +847,6 @@ def test_eval_works_correctly_1643807667 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -915,7 +874,6 @@ def test_eval_works_correctly_1643807667 value: "main", type: "Object", variablesReference: 38, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -923,7 +881,6 @@ def test_eval_works_correctly_1643807667 value: "2", type: "Integer", variablesReference: 39, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -931,7 +888,6 @@ def test_eval_works_correctly_1643807667 value: "3", type: "Integer", variablesReference: 40, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -939,7 +895,6 @@ def test_eval_works_correctly_1643807667 value: "1", type: "Integer", variablesReference: 41, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -947,7 +902,6 @@ def test_eval_works_correctly_1643807667 value: "4", type: "Integer", variablesReference: 42, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -955,7 +909,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 43, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -963,7 +916,6 @@ def test_eval_works_correctly_1643807667 value: "nil", type: "NilClass", variablesReference: 44, - indexedVariables: 0, namedVariables: /\d+/ } ] diff --git a/test/protocol/finish_raw_dap_test.rb b/test/protocol/finish_raw_dap_test.rb index 150cfb4b2..c64def7e1 100644 --- a/test/protocol/finish_raw_dap_test.rb +++ b/test/protocol/finish_raw_dap_test.rb @@ -127,7 +127,6 @@ def test_finish_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -136,7 +135,6 @@ def test_finish_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -164,7 +162,6 @@ def test_finish_works_correctly value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -334,7 +331,6 @@ def test_finish_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 4 }, @@ -343,7 +339,6 @@ def test_finish_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -371,7 +366,6 @@ def test_finish_works_correctly value: "Foo::Bar", type: "Class", variablesReference: 5, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -500,7 +494,6 @@ def test_finish_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 6 }, @@ -509,7 +502,6 @@ def test_finish_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -537,7 +529,6 @@ def test_finish_works_correctly value: "Foo::Bar", type: "Class", variablesReference: 7, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -545,7 +536,6 @@ def test_finish_works_correctly value: "\"hello\"", type: "String", variablesReference: 8, - indexedVariables: 0, namedVariables: /\d+/ } ] diff --git a/test/protocol/hover_raw_dap_test.rb b/test/protocol/hover_raw_dap_test.rb index f052b431b..47c02405b 100644 --- a/test/protocol/hover_raw_dap_test.rb +++ b/test/protocol/hover_raw_dap_test.rb @@ -123,7 +123,6 @@ def test_hover_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -132,7 +131,6 @@ def test_hover_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -160,7 +158,6 @@ def test_hover_works_correctly value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -168,7 +165,6 @@ def test_hover_works_correctly value: "nil", type: "NilClass", variablesReference: 4, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -176,7 +172,6 @@ def test_hover_works_correctly value: "nil", type: "NilClass", variablesReference: 5, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -184,7 +179,6 @@ def test_hover_works_correctly value: "nil", type: "NilClass", variablesReference: 6, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -192,7 +186,6 @@ def test_hover_works_correctly value: "nil", type: "NilClass", variablesReference: 7, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -200,7 +193,6 @@ def test_hover_works_correctly value: "nil", type: "NilClass", variablesReference: 8, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -348,7 +340,6 @@ def test_hover_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 9 }, @@ -357,7 +348,6 @@ def test_hover_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -385,7 +375,6 @@ def test_hover_works_correctly value: "main", type: "Object", variablesReference: 10, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -393,7 +382,6 @@ def test_hover_works_correctly value: "1", type: "Integer", variablesReference: 11, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -401,7 +389,6 @@ def test_hover_works_correctly value: "2", type: "Integer", variablesReference: 12, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -409,7 +396,6 @@ def test_hover_works_correctly value: "3", type: "Integer", variablesReference: 13, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -417,7 +403,6 @@ def test_hover_works_correctly value: "nil", type: "NilClass", variablesReference: 14, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -425,7 +410,6 @@ def test_hover_works_correctly value: "nil", type: "NilClass", variablesReference: 15, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -451,7 +435,6 @@ def test_hover_works_correctly body: { type: "Integer", variablesReference: 16, - indexedVariables: 0, namedVariables: /\d+/, result: "2" } @@ -478,7 +461,6 @@ def test_hover_works_correctly value: "Integer", type: "Class", variablesReference: 17, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -506,7 +488,6 @@ def test_hover_works_correctly value: "Class", type: "Class", variablesReference: 18, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -542,7 +523,6 @@ def test_hover_works_correctly value: "Class", type: "Class", variablesReference: 20, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -581,7 +561,6 @@ def test_hover_works_correctly value: "JSON::Ext::Generator::GeneratorMethods::Integer", type: "Module", variablesReference: 22, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -589,7 +568,6 @@ def test_hover_works_correctly value: "Numeric", type: "Class", variablesReference: 23, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -597,7 +575,6 @@ def test_hover_works_correctly value: "Comparable", type: "Module", variablesReference: 24, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -605,7 +582,6 @@ def test_hover_works_correctly value: "Object", type: "Class", variablesReference: 25, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -613,7 +589,6 @@ def test_hover_works_correctly value: "JSON::Ext::Generator::GeneratorMethods::Object", type: "Module", variablesReference: 26, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -621,7 +596,6 @@ def test_hover_works_correctly value: "PP::ObjectMixin", type: "Module", variablesReference: 27, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -629,7 +603,6 @@ def test_hover_works_correctly value: "DEBUGGER__::TrapInterceptor", type: "Module", variablesReference: 28, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -637,7 +610,6 @@ def test_hover_works_correctly value: "Kernel", type: "Module", variablesReference: 29, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -645,7 +617,6 @@ def test_hover_works_correctly value: "BasicObject", type: "Class", variablesReference: 30, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -654,7 +625,6 @@ def test_hover_works_correctly value: nil, type: NilClass, variablesReference: 31, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -680,7 +650,6 @@ def test_hover_works_correctly body: { type: "Integer", variablesReference: 32, - indexedVariables: 0, namedVariables: /\d+/, result: "3" } @@ -707,7 +676,6 @@ def test_hover_works_correctly value: "Integer", type: "Class", variablesReference: 33, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -733,7 +701,6 @@ def test_hover_works_correctly body: { type: "Integer", variablesReference: 34, - indexedVariables: 0, namedVariables: /\d+/, result: "2" } @@ -760,7 +727,6 @@ def test_hover_works_correctly value: "Integer", type: "Class", variablesReference: 35, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -786,7 +752,6 @@ def test_hover_works_correctly body: { type: "Integer", variablesReference: 36, - indexedVariables: 0, namedVariables: /\d+/, result: "1" } @@ -813,7 +778,6 @@ def test_hover_works_correctly value: "Integer", type: "Class", variablesReference: 37, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -988,7 +952,6 @@ def test_1641198331 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -997,7 +960,6 @@ def test_1641198331 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -1025,7 +987,6 @@ def test_1641198331 value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1033,7 +994,6 @@ def test_1641198331 value: "nil", type: "NilClass", variablesReference: 4, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -1181,7 +1141,6 @@ def test_1641198331 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 5 }, @@ -1190,7 +1149,6 @@ def test_1641198331 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -1218,7 +1176,6 @@ def test_1641198331 value: "main", type: "Object", variablesReference: 6, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1226,7 +1183,6 @@ def test_1641198331 value: "nil", type: "NilClass", variablesReference: 7, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -1252,7 +1208,6 @@ def test_1641198331 body: { type: "Module", variablesReference: 8, - indexedVariables: 0, namedVariables: /\d+/, result: "Abc" } @@ -1279,7 +1234,6 @@ def test_1641198331 value: "Module", type: "Class", variablesReference: 9, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1287,7 +1241,6 @@ def test_1641198331 value: "[]", type: "Array", variablesReference: 0, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -1313,7 +1266,6 @@ def test_1641198331 body: { type: "Class", variablesReference: 10, - indexedVariables: 0, namedVariables: /\d+/, result: "Abc::Def123" } @@ -1340,7 +1292,6 @@ def test_1641198331 value: "Class", type: "Class", variablesReference: 11, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1374,7 +1325,6 @@ def test_1641198331 body: { type: "Module", variablesReference: 13, - indexedVariables: 0, namedVariables: /\d+/, result: "Abc" } @@ -1401,7 +1351,6 @@ def test_1641198331 value: "Module", type: "Class", variablesReference: 14, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1409,7 +1358,6 @@ def test_1641198331 value: "[]", type: "Array", variablesReference: 0, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -1435,7 +1383,6 @@ def test_1641198331 body: { type: "Class", variablesReference: 15, - indexedVariables: 0, namedVariables: /\d+/, result: "Abc::Def123" } @@ -1462,7 +1409,6 @@ def test_1641198331 value: "Class", type: "Class", variablesReference: 16, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1496,7 +1442,6 @@ def test_1641198331 body: { type: "Class", variablesReference: 18, - indexedVariables: 0, namedVariables: /\d+/, result: "Abc::Def123::Ghi" } @@ -1523,7 +1468,6 @@ def test_1641198331 value: "Class", type: "Class", variablesReference: 19, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1557,7 +1501,6 @@ def test_1641198331 body: { type: "Class", variablesReference: 21, - indexedVariables: 0, namedVariables: /\d+/, result: "Abc::Def123::Ghi" } @@ -1584,7 +1527,6 @@ def test_1641198331 value: "Class", type: "Class", variablesReference: 22, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1618,7 +1560,6 @@ def test_1641198331 body: { type: "Module", variablesReference: 24, - indexedVariables: 0, namedVariables: /\d+/, result: "Abc" } @@ -1645,7 +1586,6 @@ def test_1641198331 value: "Module", type: "Class", variablesReference: 25, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1653,7 +1593,6 @@ def test_1641198331 value: "[]", type: "Array", variablesReference: 0, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -1679,7 +1618,6 @@ def test_1641198331 body: { type: "Class", variablesReference: 26, - indexedVariables: 0, namedVariables: /\d+/, result: "Abc::Def123" } @@ -1706,7 +1644,6 @@ def test_1641198331 value: "Class", type: "Class", variablesReference: 27, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1740,7 +1677,6 @@ def test_1641198331 body: { type: "Class", variablesReference: 29, - indexedVariables: 0, namedVariables: /\d+/, result: "Abc::Def123" } @@ -1767,7 +1703,6 @@ def test_1641198331 value: "Class", type: "Class", variablesReference: 30, - indexedVariables: 0, namedVariables: /\d+/ }, { diff --git a/test/protocol/next_raw_dap_test.rb b/test/protocol/next_raw_dap_test.rb index 9eef94f21..b857d2411 100644 --- a/test/protocol/next_raw_dap_test.rb +++ b/test/protocol/next_raw_dap_test.rb @@ -127,7 +127,6 @@ def test_next_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -136,7 +135,6 @@ def test_next_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -164,7 +162,6 @@ def test_next_works_correctly value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -566,7 +563,6 @@ def test_next_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 4 }, @@ -575,7 +571,6 @@ def test_next_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -603,7 +598,6 @@ def test_next_works_correctly value: "Foo", type: "Module", variablesReference: 5, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -611,7 +605,6 @@ def test_next_works_correctly value: "nil", type: "NilClass", variablesReference: 6, - indexedVariables: 0, namedVariables: /\d+/ } ] diff --git a/test/protocol/step_back_raw_dap_test.rb b/test/protocol/step_back_raw_dap_test.rb index 413a6cda6..7afc29883 100644 --- a/test/protocol/step_back_raw_dap_test.rb +++ b/test/protocol/step_back_raw_dap_test.rb @@ -129,7 +129,6 @@ def test_step_back_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -138,7 +137,6 @@ def test_step_back_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -166,7 +164,6 @@ def test_step_back_works_correctly value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -420,7 +417,6 @@ def test_step_back_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 4 }, @@ -429,7 +425,6 @@ def test_step_back_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -457,7 +452,6 @@ def test_step_back_works_correctly value: "Foo", type: "Module", variablesReference: 5, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -465,7 +459,6 @@ def test_step_back_works_correctly value: "nil", type: "NilClass", variablesReference: 6, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -575,7 +568,6 @@ def test_step_back_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 7 }, @@ -584,7 +576,6 @@ def test_step_back_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -612,7 +603,6 @@ def test_step_back_works_correctly value: "Foo", type: "Module", variablesReference: 8, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -620,7 +610,6 @@ def test_step_back_works_correctly value: "nil", type: "NilClass", variablesReference: 9, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -741,7 +730,6 @@ def test_step_back_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 10 }, @@ -750,7 +738,6 @@ def test_step_back_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -881,7 +868,6 @@ def test_step_back_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 12 }, @@ -890,7 +876,6 @@ def test_step_back_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -918,7 +903,6 @@ def test_step_back_works_correctly value: "Foo", type: "Module", variablesReference: 13, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -926,7 +910,6 @@ def test_step_back_works_correctly value: "nil", type: "NilClass", variablesReference: 14, - indexedVariables: 0, namedVariables: /\d+/ } ] diff --git a/test/protocol/step_raw_dap_test.rb b/test/protocol/step_raw_dap_test.rb index 77560e82c..caaadc190 100644 --- a/test/protocol/step_raw_dap_test.rb +++ b/test/protocol/step_raw_dap_test.rb @@ -127,7 +127,6 @@ def test_step_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -136,7 +135,6 @@ def test_step_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -164,7 +162,6 @@ def test_step_works_correctly value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -705,7 +702,6 @@ def test_step_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 4 }, @@ -714,7 +710,6 @@ def test_step_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -763,7 +758,6 @@ def test_step_works_correctly value: "Foo", type: "Module", variablesReference: 5, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -771,7 +765,6 @@ def test_step_works_correctly value: "nil", type: "NilClass", variablesReference: 6, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -842,7 +835,6 @@ def test_step_works_correctly name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 7 }, @@ -851,7 +843,6 @@ def test_step_works_correctly presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -879,7 +870,6 @@ def test_step_works_correctly value: "Foo", type: "Module", variablesReference: 8, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -887,7 +877,6 @@ def test_step_works_correctly value: "nil", type: "NilClass", variablesReference: 9, - indexedVariables: 0, namedVariables: /\d+/ } ] diff --git a/test/protocol/watch_raw_dap_test.rb b/test/protocol/watch_raw_dap_test.rb index 3e6e8b2db..bd7a29635 100644 --- a/test/protocol/watch_raw_dap_test.rb +++ b/test/protocol/watch_raw_dap_test.rb @@ -125,7 +125,6 @@ def test_watch_works_correctly_1643810224 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 2 }, @@ -134,7 +133,6 @@ def test_watch_works_correctly_1643810224 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -162,7 +160,6 @@ def test_watch_works_correctly_1643810224 value: "main", type: "Object", variablesReference: 3, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -170,7 +167,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 4, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -178,7 +174,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 5, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -186,7 +181,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 6, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -194,7 +188,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 7, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -228,7 +221,6 @@ def test_watch_works_correctly_1643810224 body: { type: "NilClass", variablesReference: 8, - indexedVariables: 0, namedVariables: /\d+/, result: "nil" } @@ -246,7 +238,6 @@ def test_watch_works_correctly_1643810224 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 9 }, @@ -255,7 +246,6 @@ def test_watch_works_correctly_1643810224 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -283,7 +273,6 @@ def test_watch_works_correctly_1643810224 value: "main", type: "Object", variablesReference: 10, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -291,7 +280,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 11, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -299,7 +287,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 12, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -307,7 +294,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 13, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -315,7 +301,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 14, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -421,7 +406,6 @@ def test_watch_works_correctly_1643810224 body: { type: "Integer", variablesReference: 15, - indexedVariables: 0, namedVariables: /\d+/, result: "2" } @@ -447,7 +431,6 @@ def test_watch_works_correctly_1643810224 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 16 }, @@ -456,7 +439,6 @@ def test_watch_works_correctly_1643810224 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -484,7 +466,6 @@ def test_watch_works_correctly_1643810224 value: "main", type: "Object", variablesReference: 17, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -492,7 +473,6 @@ def test_watch_works_correctly_1643810224 value: "2", type: "Integer", variablesReference: 18, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -500,7 +480,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 19, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -508,7 +487,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 20, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -516,7 +494,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 21, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -622,7 +599,6 @@ def test_watch_works_correctly_1643810224 body: { type: "Integer", variablesReference: 22, - indexedVariables: 0, namedVariables: /\d+/, result: "3" } @@ -648,7 +624,6 @@ def test_watch_works_correctly_1643810224 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 23 }, @@ -657,7 +632,6 @@ def test_watch_works_correctly_1643810224 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -685,7 +659,6 @@ def test_watch_works_correctly_1643810224 value: "main", type: "Object", variablesReference: 24, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -693,7 +666,6 @@ def test_watch_works_correctly_1643810224 value: "3", type: "Integer", variablesReference: 25, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -701,7 +673,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 26, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -709,7 +680,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 27, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -717,7 +687,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 28, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -823,7 +792,6 @@ def test_watch_works_correctly_1643810224 body: { type: "Integer", variablesReference: 29, - indexedVariables: 0, namedVariables: /\d+/, result: "4" } @@ -849,7 +817,6 @@ def test_watch_works_correctly_1643810224 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 30 }, @@ -858,7 +825,6 @@ def test_watch_works_correctly_1643810224 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -886,7 +852,6 @@ def test_watch_works_correctly_1643810224 value: "main", type: "Object", variablesReference: 31, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -894,7 +859,6 @@ def test_watch_works_correctly_1643810224 value: "4", type: "Integer", variablesReference: 32, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -902,7 +866,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 33, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -910,7 +873,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 34, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -918,7 +880,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 35, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -1024,7 +985,6 @@ def test_watch_works_correctly_1643810224 body: { type: "Integer", variablesReference: 36, - indexedVariables: 0, namedVariables: /\d+/, result: "4" } @@ -1050,7 +1010,6 @@ def test_watch_works_correctly_1643810224 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 37 }, @@ -1059,7 +1018,6 @@ def test_watch_works_correctly_1643810224 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -1087,7 +1045,6 @@ def test_watch_works_correctly_1643810224 value: "main", type: "Object", variablesReference: 38, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1095,7 +1052,6 @@ def test_watch_works_correctly_1643810224 value: "4", type: "Integer", variablesReference: 39, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1103,7 +1059,6 @@ def test_watch_works_correctly_1643810224 value: "4", type: "Integer", variablesReference: 40, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1111,7 +1066,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 41, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1119,7 +1073,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 42, - indexedVariables: 0, namedVariables: /\d+/ } ] @@ -1225,7 +1178,6 @@ def test_watch_works_correctly_1643810224 body: { type: "Integer", variablesReference: 43, - indexedVariables: 0, namedVariables: /\d+/, result: "5" } @@ -1251,7 +1203,6 @@ def test_watch_works_correctly_1643810224 name: "Local variables", presentationHint: "locals", namedVariables: /\d+/, - indexedVariables: 0, expensive: false, variablesReference: 44 }, @@ -1260,7 +1211,6 @@ def test_watch_works_correctly_1643810224 presentationHint: "globals", variablesReference: 1, namedVariables: /\d+/, - indexedVariables: 0, expensive: false } ] @@ -1288,7 +1238,6 @@ def test_watch_works_correctly_1643810224 value: "main", type: "Object", variablesReference: 45, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1296,7 +1245,6 @@ def test_watch_works_correctly_1643810224 value: "5", type: "Integer", variablesReference: 46, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1304,7 +1252,6 @@ def test_watch_works_correctly_1643810224 value: "4", type: "Integer", variablesReference: 47, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1312,7 +1259,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 48, - indexedVariables: 0, namedVariables: /\d+/ }, { @@ -1320,7 +1266,6 @@ def test_watch_works_correctly_1643810224 value: "nil", type: "NilClass", variablesReference: 49, - indexedVariables: 0, namedVariables: /\d+/ } ] From 9c435ba1805b3bd4c5bb0c1066df4d9c4fe9105d Mon Sep 17 00:00:00 2001 From: Alexander Momchilov Date: Wed, 3 Jan 2024 23:13:27 -0500 Subject: [PATCH 6/8] Fix out-of-bound index access --- lib/debug/variable_inspector.rb | 4 +++- test/protocol/hover_raw_dap_test.rb | 26 +++++++++----------------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/lib/debug/variable_inspector.rb b/lib/debug/variable_inspector.rb index 15c255013..f74e170db 100644 --- a/lib/debug/variable_inspector.rb +++ b/lib/debug/variable_inspector.rb @@ -7,7 +7,9 @@ class VariableInspector def indexed_members_of(obj, start:, count:) return [] if start > (obj.length - 1) - (start...(start + count)).map do |i| + capped_count = [count, obj.length - start].min + + (start...(start + capped_count)).map do |i| Variable.new(name: i.to_s, value: obj[i]) end end diff --git a/test/protocol/hover_raw_dap_test.rb b/test/protocol/hover_raw_dap_test.rb index 47c02405b..35af47b22 100644 --- a/test/protocol/hover_raw_dap_test.rb +++ b/test/protocol/hover_raw_dap_test.rb @@ -619,14 +619,6 @@ def test_hover_works_correctly variablesReference: 30, namedVariables: /\d+/ }, - { - # This is an extra entry caused by an out-of-bounds index access in server_dap.rb - name: "9", - value: nil, - type: NilClass, - variablesReference: 31, - namedVariables: /\d+/ - } ] } }, @@ -649,7 +641,7 @@ def test_hover_works_correctly message: "Success", body: { type: "Integer", - variablesReference: 32, + variablesReference: 31, namedVariables: /\d+/, result: "3" } @@ -658,7 +650,7 @@ def test_hover_works_correctly seq: 23, command: "variables", arguments: { - variablesReference: 32 + variablesReference: 31 }, type: "request" }, @@ -675,7 +667,7 @@ def test_hover_works_correctly name: "#class", value: "Integer", type: "Class", - variablesReference: 33, + variablesReference: 32, namedVariables: /\d+/ } ] @@ -700,7 +692,7 @@ def test_hover_works_correctly message: "Success", body: { type: "Integer", - variablesReference: 34, + variablesReference: 33, namedVariables: /\d+/, result: "2" } @@ -709,7 +701,7 @@ def test_hover_works_correctly seq: 25, command: "variables", arguments: { - variablesReference: 34 + variablesReference: 33 }, type: "request" }, @@ -726,7 +718,7 @@ def test_hover_works_correctly name: "#class", value: "Integer", type: "Class", - variablesReference: 35, + variablesReference: 34, namedVariables: /\d+/ } ] @@ -751,7 +743,7 @@ def test_hover_works_correctly message: "Success", body: { type: "Integer", - variablesReference: 36, + variablesReference: 35, namedVariables: /\d+/, result: "1" } @@ -760,7 +752,7 @@ def test_hover_works_correctly seq: 27, command: "variables", arguments: { - variablesReference: 36 + variablesReference: 35 }, type: "request" }, @@ -777,7 +769,7 @@ def test_hover_works_correctly name: "#class", value: "Integer", type: "Class", - variablesReference: 37, + variablesReference: 36, namedVariables: /\d+/ } ] From 48d487d202c6bc5910cdfed18f4821b6a801a054 Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Sun, 7 Jan 2024 20:10:53 +0900 Subject: [PATCH 7/8] Test for #1001 --- test/protocol/hover_raw_dap_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/protocol/hover_raw_dap_test.rb b/test/protocol/hover_raw_dap_test.rb index 35af47b22..63441cec1 100644 --- a/test/protocol/hover_raw_dap_test.rb +++ b/test/protocol/hover_raw_dap_test.rb @@ -14,6 +14,7 @@ class HoverTest1638791703 < ProtocolTestCase RUBY def test_hover_works_correctly + omit "This test is designed for Ruby 3.1 and later versions because ancestor classes are changed" if RUBY_VERSION.to_f <= 3.0 run_dap_scenario PROGRAM do [ *INITIALIZE_DAP_MSGS, From 8a6053bad0df595a2f3d55ceac8513a06a6a85f4 Mon Sep 17 00:00:00 2001 From: Alexander Momchilov Date: Fri, 28 Jul 2023 10:30:05 -0400 Subject: [PATCH 8/8] Add hook for customizing the debug representation of objects --- lib/debug/variable_inspector.rb | 14 +++++++++++ test/debug/variable_inspector_test.rb | 35 +++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/lib/debug/variable_inspector.rb b/lib/debug/variable_inspector.rb index f74e170db..4d4db0b34 100644 --- a/lib/debug/variable_inspector.rb +++ b/lib/debug/variable_inspector.rb @@ -17,6 +17,19 @@ def indexed_members_of(obj, start:, count:) def named_members_of(obj) return [] if NaiveString === obj + if M_RESPOND_TO.bind_call(obj, :debug_representation) + debug_representation = obj.debug_representation + members = named_members_of(debug_representation) + + # Discard the "#class" member of the debug representation, if any. + members.delete_if { |m| m.name == '#class' } + + # Add the real "#class" of the object being inspected. + members.unshift Variable.internal(name: '#class', value: M_CLASS.bind_call(obj)) + + return members + end + members = case obj when Hash then obj.map { |k, v| Variable.new(name: value_inspect(k), value: v) } when Struct then obj.members.map { |name| Variable.new(name: name, value: obj[name]) } @@ -69,6 +82,7 @@ def self.value_inspect(obj, short: true) # TODO: Replace with Reflection helpers once they are merged # https://github.com/ruby/debug/pull/1002 + M_RESPOND_TO = method(:respond_to?).unbind M_INSTANCE_VARIABLES = method(:instance_variables).unbind M_INSTANCE_VARIABLE_GET = method(:instance_variable_get).unbind M_CLASS = method(:class).unbind diff --git a/test/debug/variable_inspector_test.rb b/test/debug/variable_inspector_test.rb index 33c833685..05f6c2b8a 100644 --- a/test/debug/variable_inspector_test.rb +++ b/test/debug/variable_inspector_test.rb @@ -196,6 +196,31 @@ def test_named_members_of_other_objects assert_equal expected, @inspector.named_members_of(point) end + def test_debug_representation_hook + object_with_simple_repr = ClassWithCustomDebugRepresentation.new({ a: 1, b: 2 }) + + expected = [ + # We should always show the `#class` when using this hook, even if the + # debug_representation is a simple value. + Variable.internal(name: '#class', value: ClassWithCustomDebugRepresentation), + Variable.new(name: ':a', value: 1), + Variable.new(name: ':b', value: 2), + ] + + assert_equal expected, @inspector.named_members_of(object_with_simple_repr) + + object_with_complex_repr = ClassWithCustomDebugRepresentation.new(Point.new(x: 1, y: 2)) + + expected = [ + # Make sure we don't add the '#class' twice for non-simple debug representations + Variable.internal(name: '#class', value: ClassWithCustomDebugRepresentation), + Variable.new(name: :@x, value: 1), + Variable.new(name: :@y, value: 2), + ] + + assert_equal expected, @inspector.named_members_of(object_with_complex_repr) + end + private class PointStruct < Struct.new(:x, :y, keyword_init: true) @@ -211,5 +236,15 @@ def initialize(x:, y:) @y = y end end + + class ClassWithCustomDebugRepresentation + def initialize(debug_representation) + @debug_representation = debug_representation + end + + def debug_representation + @debug_representation + end + end end end