Skip to content

Commit 11c2a89

Browse files
committed
Omit "#class" for simple values
1 parent ee133fd commit 11c2a89

File tree

2 files changed

+40
-12
lines changed

2 files changed

+40
-12
lines changed

Diff for: lib/debug/variable_inspector.rb

+13-1
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,25 @@ def named_members_of(obj)
4343
Variable.new(name: iv, value: M_INSTANCE_VARIABLE_GET.bind_call(obj, iv))
4444
end
4545

46-
members.unshift Variable.internal(name: '#class', value: M_CLASS.bind_call(obj))
4746
members.concat(ivars_members)
4847

48+
unless simple_value?(obj)
49+
members.unshift Variable.internal(name: '#class', value: M_CLASS.bind_call(obj))
50+
end
51+
4952
members
5053
end
5154

5255
private
5356

57+
SIMPLE_VALUE_TYPES = [NilClass, FalseClass, TrueClass, Symbol, String, Integer, Float, Class, Module, Array, Hash]
58+
59+
# A "simple" value is one that does not need its `#class` to be shown.
60+
def simple_value?(o)
61+
# Check `#instance_of?` instead of `#is_a?` so subclasses objects show their `#class` for added clarity.
62+
SIMPLE_VALUE_TYPES.any? { |t| M_INSTANCE_OF.bind_call(o, t) }
63+
end
64+
5465
def value_inspect(obj, short: true)
5566
self.class.value_inspect(obj, short: short)
5667
end
@@ -70,6 +81,7 @@ def self.value_inspect(obj, short: true)
7081

7182
# TODO: Replace with Reflection helpers once they are merged
7283
# https://github.com/ruby/debug/pull/1002
84+
M_INSTANCE_OF = method(:instance_of?).unbind
7385
M_INSTANCE_VARIABLES = method(:instance_variables).unbind
7486
M_INSTANCE_VARIABLE_GET = method(:instance_variable_get).unbind
7587
M_CLASS = method(:class).unbind

Diff for: test/debug/variable_inspector_test.rb

+27-11
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ def test_named_members_of_hash
4747
)
4848

4949
expected = [
50-
Variable.internal(name: '#class', value: Hash),
5150
Variable.new(name: ':sym', value: "has Symbol key"),
5251
Variable.new(name: '"str"', value: "has String key"),
5352
Variable.new(name: '1', value: "has Integer key"),
@@ -73,7 +72,6 @@ def test_named_members_of_struct
7372

7473
def test_named_members_of_string
7574
expected = [
76-
Variable.internal(name: '#class', value: String),
7775
Variable.internal(name: '#length', value: 5),
7876
Variable.internal(name: '#encoding', value: Encoding::UTF_8),
7977
# skip #dump member for short strings
@@ -85,7 +83,6 @@ def test_named_members_of_string
8583
long_string = "A long string " + ('*' * 1000)
8684

8785
expected = [
88-
Variable.internal(name: '#class', value: String),
8986
Variable.internal(name: '#length', value: long_string.length),
9087
Variable.internal(name: '#encoding', value: Encoding::UTF_8),
9188
Variable.internal(name: '#dump', value: VariableInspector::NaiveString.new(long_string)),
@@ -95,10 +92,7 @@ def test_named_members_of_string
9592
end
9693

9794
def test_named_members_of_class
98-
expected = [
99-
Variable.internal(name: '#class', value: Class),
100-
Variable.internal(name: '%ancestors', value: PointStruct.ancestors.drop(1)),
101-
]
95+
expected = [Variable.internal(name: '%ancestors', value: PointStruct.ancestors.drop(1)),]
10296

10397
assert_equal expected, @inspector.named_members_of(PointStruct)
10498
end
@@ -109,10 +103,7 @@ def test_named_members_of_module
109103
include *ancestors
110104
end
111105

112-
expected = [
113-
Variable.internal(name: '#class', value: Module),
114-
Variable.internal(name: '%ancestors', value: ancestors),
115-
]
106+
expected = [Variable.internal(name: '%ancestors', value: ancestors)]
116107

117108
assert_equal expected, @inspector.named_members_of(mod)
118109
end
@@ -196,6 +187,31 @@ def test_named_members_of_other_objects
196187
assert_equal expected, @inspector.named_members_of(point)
197188
end
198189

190+
def test_hide_class_of_simple_values
191+
assert_not_includes @inspector.named_members_of(nil).map(&:name), "#class"
192+
assert_not_includes @inspector.named_members_of(true), "#class"
193+
assert_not_includes @inspector.named_members_of(false), "#class"
194+
assert_not_includes @inspector.named_members_of(:symbol), "#class"
195+
assert_not_includes @inspector.named_members_of("string"), "#class"
196+
assert_not_includes @inspector.named_members_of(123), "#class"
197+
assert_not_includes @inspector.named_members_of(123.4), "#class"
198+
assert_not_includes @inspector.named_members_of(Class.new), "#class"
199+
assert_not_includes @inspector.named_members_of(Module.new), "#class"
200+
assert_not_includes @inspector.named_members_of(Array.new), "#class"
201+
assert_not_includes @inspector.named_members_of(Hash.new), "#class"
202+
end
203+
204+
def test_show_class_of_subclasses_of_simple_types
205+
# Skipping these classes, which can't be subclassed meaningfully (or at all):
206+
# NilClass, TrueClass, FalseClass, Symbol, Integer, Float, Class, Module
207+
string_subclass = Class.new(String)
208+
array_subclass = Class.new(Array)
209+
hash_subclass = Class.new(Hash) # E.g. HashWithIndifferentAccess would behave this way
210+
assert_includes @inspector.named_members_of(string_subclass.new), Variable.internal(name: "#class", value: string_subclass)
211+
assert_includes @inspector.named_members_of(array_subclass.new), Variable.internal(name: "#class", value: array_subclass)
212+
assert_includes @inspector.named_members_of(hash_subclass.new), Variable.internal(name: "#class", value: hash_subclass)
213+
end
214+
199215
private
200216

201217
class PointStruct < Struct.new(:x, :y, keyword_init: true)

0 commit comments

Comments
 (0)