Skip to content

Commit 3024cb5

Browse files
committed
Add location slice to deconstruct_keys
It is nice to be able to slice out a location in pattern matching without having to explicitly get the location object and call slice manually. Also, construct the response for deconstruct_keys lazily in order to avoid reifying location objects if we don't have to.
1 parent ab9412c commit 3024cb5

2 files changed

Lines changed: 32 additions & 1 deletion

File tree

templates/lib/prism/node.rb.erb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,16 @@ module Prism
551551

552552
#: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
553553
def deconstruct_keys(keys) # :nodoc:
554-
{ <%= (["node_id: node_id", "location: location"] + node.fields.map { |field| "#{field.name}: #{field.name}" }).join(", ") %> }
554+
<%- deconstruct = [:node_id, :location, *node.fields.map { |field| field.name.to_sym }, *node.fields.select { |field| field.is_a?(Prism::Template::LocationField) || field.is_a?(Prism::Template::OptionalLocationField) }.map { |field| field.name.delete_suffix("_loc").to_sym }].uniq -%>
555+
(keys || %i[<%= deconstruct.join(" ") %>]).each_with_object(
556+
{} #: Hash[Symbol, untyped]
557+
) do |key, deconstructed|
558+
case key
559+
<%- deconstruct.each do |key| -%>
560+
when <%= "%-24s then" % [key.inspect] %> deconstructed[<%= key.inspect %>] = self.<%= key %>
561+
<%- end -%>
562+
end
563+
end
555564
end
556565

557566
# See `Node#type`.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "../test_helper"
4+
5+
module Prism
6+
class DeconstructKeysTest < TestCase
7+
def test_deconstruct_keys
8+
node = Prism.parse_statement("1.to_s")
9+
10+
deconstruct_all = node.deconstruct_keys(nil)
11+
assert_equal deconstruct_all[:node_id], node.node_id
12+
assert_equal deconstruct_all[:message], "to_s"
13+
14+
deconstruct_receiver = node.deconstruct_keys([:receiver])
15+
assert_equal 1, deconstruct_receiver[:receiver].value
16+
refute_includes deconstruct_receiver.keys, :message
17+
18+
deconstruct_invalid = node.deconstruct_keys([:invalid])
19+
refute_includes deconstruct_invalid.keys, :invalid
20+
end
21+
end
22+
end

0 commit comments

Comments
 (0)