[ruby/yarp] Provide a better inspect

https://github.com/ruby/yarp/commit/ef14ae66e4
This commit is contained in:
Kevin Newton 2023-09-01 14:51:50 -04:00 committed by Takashi Kokubun
parent 00f263e6c4
commit e8ef5b1281
2 changed files with 110 additions and 1 deletions

View File

@ -141,6 +141,10 @@ module YARP
def deconstruct_keys(keys)
{ type: type, location: location }
end
def inspect
"#<YARP::Comment @type=#{@type.inspect} @location=#{@location.inspect}>"
end
end
# This represents an error that was encountered during parsing.
@ -155,6 +159,10 @@ module YARP
def deconstruct_keys(keys)
{ message: message, location: location }
end
def inspect
"#<YARP::ParseError @message=#{@message.inspect} @location=#{@location.inspect}>"
end
end
# This represents a warning that was encountered during parsing.
@ -169,6 +177,10 @@ module YARP
def deconstruct_keys(keys)
{ message: message, location: location }
end
def inspect
"#<YARP::ParseWarning @message=#{@message.inspect} @location=#{@location.inspect}>"
end
end
# A class that knows how to walk down the tree. None of the individual visit
@ -323,7 +335,6 @@ module YARP
q.nest(2) do
deconstructed = deconstruct_keys([])
deconstructed.delete(:location)
q.breakable("")
q.seplist(deconstructed, lambda { q.comma_breakable }, :each_value) { |value| q.pp(value) }
end
@ -333,6 +344,71 @@ module YARP
end
end
# This object is responsible for generating the output for the inspect method
# implementations of child nodes.
class NodeInspector
attr_reader :prefix, :output
def initialize(prefix = "")
@prefix = prefix
@output = +""
end
# Appends a line to the output with the current prefix.
def <<(line)
output << "#{prefix}#{line}"
end
# This generates a string that is used as the header of the inspect output
# for any given node.
def header(node)
output = +"@ #{node.class.name.split("::").last} ("
output << "location: (#{node.location.start_offset}...#{node.location.end_offset})"
output << ", newline: true" if node.newline?
output << ")\n"
output
end
# Generates a string that represents a list of nodes. It handles properly
# using the box drawing characters to make the output look nice.
def list(prefix, nodes)
output = +"(length: #{nodes.length})\n"
last_index = nodes.length - 1
nodes.each_with_index do |node, index|
pointer, preadd = (index == last_index) ? ["└── ", " "] : ["├── ", ""]
node_prefix = "#{prefix}#{preadd}"
output << node.inspect(NodeInspector.new(node_prefix)).sub(node_prefix, "#{prefix}#{pointer}")
end
output
end
# Generates a string that represents a location field on a node.
def location(value)
if value
"(#{value.start_offset}...#{value.end_offset}) = #{value.slice.inspect}"
else
""
end
end
# Generates a string that represents a child node.
def child_node(node, append)
node.inspect(child_inspector(append)).delete_prefix(prefix)
end
# Returns a new inspector that can be used to inspect a child node.
def child_inspector(append)
NodeInspector.new("#{prefix}#{append}")
end
# Returns the output as a string.
def to_str
output
end
end
class FloatNode < Node
def value
Float(slice)

View File

@ -92,6 +92,39 @@ module YARP
<%- end -%>
<%- end -%>
<%- end -%>
def inspect(inspector = NodeInspector.new)
inspector << inspector.header(self)
<%- node.fields.each_with_index do |field, index| -%>
<%- pointer, preadd = index == node.fields.length - 1 ? ["└── ", " "] : ["├── ", "│ "] -%>
<%- case field -%>
<%- when YARP::NodeListField -%>
inspector << "<%= pointer %><%= field.name %>: #{inspector.list("#{inspector.prefix}<%= preadd %>", <%= field.name %>)}"
<%- when YARP::LocationListField, YARP::ConstantListField -%>
inspector << "<%= pointer %><%= field.name %>: #{<%= field.name %>.inspect}\n"
<%- when YARP::NodeField -%>
inspector << "<%= pointer %><%= field.name %>:\n"
inspector << inspector.child_node(<%= field.name %>, "<%= preadd %>")
<%- when YARP::OptionalNodeField -%>
if (<%= field.name %> = self.<%= field.name %>).nil?
inspector << "<%= pointer %><%= field.name %>: ∅\n"
else
inspector << "<%= pointer %><%= field.name %>:\n"
inspector << <%= field.name %>.inspect(inspector.child_inspector("<%= preadd %>")).delete_prefix(inspector.prefix)
end
<%- when YARP::ConstantField, YARP::StringField, YARP::UInt32Field -%>
inspector << "<%= pointer %><%= field.name %>: #{<%= field.name %>.inspect}\n"
<%- when YARP::FlagsField -%>
<%- flag = flags.find { |flag| flag.name == field.kind }.tap { |flag| raise unless flag } -%>
inspector << "<%= pointer %><%= field.name %>: #{[<%= flag.values.map { |value| "(\"#{value.name.downcase}\" if #{value.name.downcase}?)" }.join(", ") %>].compact.join(", ")}\n"
<%- when YARP::LocationField, YARP::OptionalLocationField -%>
inspector << "<%= pointer %><%= field.name %>: #{inspector.location(<%= field.name %>)}\n"
<%- else -%>
<%- raise -%>
<%- end -%>
<%- end -%>
inspector.to_str
end
end
<%- end -%>