Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions lib/pp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ class << self
end
end

M_RESPOND_TO = Object.instance_method(:respond_to?)
private_constant :M_RESPOND_TO

module PPMethods

# Yields to a block
Expand Down Expand Up @@ -188,7 +191,7 @@ def pop_inspect_key(id)
def pp(obj)
# If obj is a Delegator then use the object being delegated to for cycle
# detection
obj = obj.__getobj__ if defined?(::Delegator) and obj.is_a?(::Delegator)
obj = obj.__getobj__ if defined?(::Delegator) and ::Delegator === obj

if check_inspect_key(obj)
group {obj.pretty_print_cycle self}
Expand All @@ -197,7 +200,12 @@ def pp(obj)

begin
push_inspect_key(obj)
group {obj.pretty_print self}

if M_RESPOND_TO.bind_call(obj, :pretty_print)
group { obj.pretty_print self }
else
group { Object.instance_method(:pretty_print).bind_call(obj, self) }
end
ensure
pop_inspect_key(obj) unless PP.sharing_detection
end
Expand Down Expand Up @@ -266,8 +274,15 @@ def seplist(list, sep=nil, iter_method=:each) # :yield: element

# A present standard failsafe for pretty printing any given Object
def pp_object(obj)
instance_variables =
if M_RESPOND_TO.bind_call(obj, :pretty_print_instance_variables)
obj.pretty_print_instance_variables
else
Object.instance_method(:pretty_print_instance_variables).bind_call(obj)
end

object_address_group(obj) {
seplist(obj.pretty_print_instance_variables, lambda { text ',' }) {|v|
seplist(instance_variables, lambda { text ',' }) {|v|
breakable
v = v.to_s if Symbol === v
text v
Expand Down Expand Up @@ -325,7 +340,7 @@ def pretty_print(q)
end
if inspect_method && inspect_method.owner != Kernel
q.text self.inspect
elsif !inspect_method && self.respond_to?(:inspect)
elsif !inspect_method && M_RESPOND_TO.bind_call(self, :inspect)
q.text self.inspect
else
q.pp_object(self)
Expand All @@ -346,7 +361,7 @@ def pretty_print_cycle(q)
# This method should return an array of names of instance variables as symbols or strings as:
# +[:@a, :@b]+.
def pretty_print_instance_variables
instance_variables.sort
Object.instance_method(:instance_variables).bind_call(self).sort
end

# Is #inspect implementation using #pretty_print.
Expand Down
11 changes: 11 additions & 0 deletions test/test_pp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ def test_list0123_11
assert_equal("[0,\n 1,\n 2,\n 3]\n", PP.pp([0,1,2,3], ''.dup, 11))
end

def test_basic_object
foo_class = Class.new(Object) do
def initialize
@obj = BasicObject.new
end
end
assert_match(/#<BasicObject:.*>/, PP.pp(BasicObject.new, ''.dup, 12))
assert_match(/\[0,\n 1,\n 2,\n #<BasicObject:.*>\]\n/, PP.pp([0,1,2, BasicObject.new], ''.dup, 12))
assert_match(/#<#<Class:.*>:.*\n @obj=\n #<BasicObject:.*>>/, PP.pp(foo_class.new, ''.dup, 12))
end

OverriddenStruct = Struct.new("OverriddenStruct", :members, :class)
def test_struct_override_members # [ruby-core:7865]
a = OverriddenStruct.new(1,2)
Expand Down