зеркало из https://github.com/github/ruby.git
[ruby/prism] Provide Parameters#signature for mirroring Method#parameters
https://github.com/ruby/prism/commit/90b3245528
This commit is contained in:
Родитель
f9e34a1fd3
Коммит
201853f4e1
|
@ -61,7 +61,8 @@ module Prism
|
|||
end
|
||||
|
||||
class ConstantReadNode < Node
|
||||
# Returns the list of parts for the full name of this constant. For example: [:Foo]
|
||||
# Returns the list of parts for the full name of this constant.
|
||||
# For example: [:Foo]
|
||||
def full_name_parts
|
||||
[name]
|
||||
end
|
||||
|
@ -73,7 +74,8 @@ module Prism
|
|||
end
|
||||
|
||||
class ConstantPathNode < Node
|
||||
# Returns the list of parts for the full name of this constant path. For example: [:Foo, :Bar]
|
||||
# Returns the list of parts for the full name of this constant path.
|
||||
# For example: [:Foo, :Bar]
|
||||
def full_name_parts
|
||||
parts = [child.name]
|
||||
current = parent
|
||||
|
@ -93,7 +95,8 @@ module Prism
|
|||
end
|
||||
|
||||
class ConstantPathTargetNode < Node
|
||||
# Returns the list of parts for the full name of this constant path. For example: [:Foo, :Bar]
|
||||
# Returns the list of parts for the full name of this constant path.
|
||||
# For example: [:Foo, :Bar]
|
||||
def full_name_parts
|
||||
(parent&.full_name_parts || [:""]).push(child.name)
|
||||
end
|
||||
|
@ -103,4 +106,47 @@ module Prism
|
|||
full_name_parts.join("::")
|
||||
end
|
||||
end
|
||||
|
||||
class ParametersNode < Node
|
||||
# Mirrors the Method#parameters method.
|
||||
def signature
|
||||
names = []
|
||||
|
||||
requireds.each do |param|
|
||||
names << (param.is_a?(MultiTargetNode) ? [:req] : [:req, param.name])
|
||||
end
|
||||
|
||||
optionals.each { |param| names << [:opt, param.name] }
|
||||
names << [:rest, rest.name || :*] if rest
|
||||
|
||||
posts.each do |param|
|
||||
names << (param.is_a?(MultiTargetNode) ? [:req] : [:req, param.name])
|
||||
end
|
||||
|
||||
# Regardless of the order in which the keywords were defined, the required
|
||||
# keywords always come first followed by the optional keywords.
|
||||
keyopt = []
|
||||
keywords.each do |param|
|
||||
if param.is_a?(OptionalKeywordParameterNode)
|
||||
keyopt << param
|
||||
else
|
||||
names << [:keyreq, param.name]
|
||||
end
|
||||
end
|
||||
|
||||
keyopt.each { |param| names << [:key, param.name] }
|
||||
|
||||
case keyword_rest
|
||||
when ForwardingParameterNode
|
||||
names.concat([[:rest, :*], [:keyrest, :**], [:block, :&]])
|
||||
when KeywordRestParameterNode
|
||||
names << [:keyrest, keyword_rest.name || :**]
|
||||
when NoKeywordsParameterNode
|
||||
names << [:nokey]
|
||||
end
|
||||
|
||||
names << [:block, block.name || :&] if block
|
||||
names
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "test_helper"
|
||||
|
||||
return if RUBY_VERSION < "3.2" || RUBY_ENGINE == "truffleruby"
|
||||
|
||||
module Prism
|
||||
class ParametersSignatureTest < TestCase
|
||||
def test_req
|
||||
assert_parameters([[:req, :a]], "a")
|
||||
end
|
||||
|
||||
def test_req_destructure
|
||||
assert_parameters([[:req]], "(a, b)")
|
||||
end
|
||||
|
||||
def test_opt
|
||||
assert_parameters([[:opt, :a]], "a = 1")
|
||||
end
|
||||
|
||||
def test_rest
|
||||
assert_parameters([[:rest, :a]], "*a")
|
||||
end
|
||||
|
||||
def test_rest_anonymous
|
||||
assert_parameters([[:rest, :*]], "*")
|
||||
end
|
||||
|
||||
def test_post
|
||||
assert_parameters([[:rest, :a], [:req, :b]], "*a, b")
|
||||
end
|
||||
|
||||
def test_post_destructure
|
||||
assert_parameters([[:rest, :a], [:req]], "*a, (b, c)")
|
||||
end
|
||||
|
||||
def test_keyreq
|
||||
assert_parameters([[:keyreq, :a]], "a:")
|
||||
end
|
||||
|
||||
def test_key
|
||||
assert_parameters([[:key, :a]], "a: 1")
|
||||
end
|
||||
|
||||
def test_keyrest
|
||||
assert_parameters([[:keyrest, :a]], "**a")
|
||||
end
|
||||
|
||||
def test_nokey
|
||||
assert_parameters([[:nokey]], "**nil")
|
||||
end
|
||||
|
||||
def test_keyrest_anonymous
|
||||
assert_parameters([[:keyrest, :**]], "**")
|
||||
end
|
||||
|
||||
def test_key_ordering
|
||||
assert_parameters([[:keyreq, :a], [:keyreq, :b], [:key, :c], [:key, :d]], "a:, c: 1, b:, d: 2")
|
||||
end
|
||||
|
||||
def test_block
|
||||
assert_parameters([[:block, :a]], "&a")
|
||||
end
|
||||
|
||||
def test_block_anonymous
|
||||
assert_parameters([[:block, :&]], "&")
|
||||
end
|
||||
|
||||
def test_forwarding
|
||||
assert_parameters([[:rest, :*], [:keyrest, :**], [:block, :&]], "...")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def assert_parameters(expected, source)
|
||||
eval("def self.m(#{source}); end")
|
||||
|
||||
begin
|
||||
assert_equal(expected, method(:m).parameters)
|
||||
assert_equal(expected, signature(source))
|
||||
ensure
|
||||
singleton_class.undef_method(:m)
|
||||
end
|
||||
end
|
||||
|
||||
def signature(source)
|
||||
program = Prism.parse("def m(#{source}); end").value
|
||||
program.statements.body.first.parameters.signature
|
||||
end
|
||||
end
|
||||
end
|
Загрузка…
Ссылка в новой задаче