-
Notifications
You must be signed in to change notification settings - Fork 128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Parse RBS overloads into signatures #2243
base: main
Are you sure you want to change the base?
Conversation
ea7c625
to
c9a3dca
Compare
2f4c24e
to
640f9fc
Compare
(have moved the Ruby LSP changes out to |
640f9fc
to
cd5f555
Compare
@soutaro this is still WIP, but thought you may be interested to see our approach. |
44ff15a
to
bfaca26
Compare
bfaca26
to
4a2b446
Compare
# There are no methods in Core that have required keyword arguments, | ||
# so we test against RBS directly | ||
|
||
# TODO: why does removing the block break this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to figure out why
def foo: (::Numeric a, ::Numeric b) -> self
is failing with:
Minitest::Assertion: Expected #<RubyIndexer::Entry::RequiredParameter:0x0000000129a54158 @name=:a>
to be a kind of RubyIndexer::Entry::KeywordParameter, not RubyIndexer::Entry::RequiredParameter.
4a2b446
to
4b683e4
Compare
assert_equal(1, entry.parameters.length) | ||
parameter = entry.parameters.first | ||
parameters = entry.signatures.first.parameters | ||
assert_equal(1, parameters.length) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These kind of length assertions were useful during development, but we could remove them to make the tests a little shorter.
|
||
first_signature = signatures.first | ||
|
||
# (::string salt_str) -> ::String |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied in the RBS definitions for easy reference, but we could remove them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like those, it's easier to understand 👍
end | ||
|
||
def test_rbs_method_with_optional_keywords | ||
entries = @index["step"] # https://www.rubydoc.info/stdlib/core/Numeric#step-instance_method |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
step
is an interesting one since it can called with either positional or keyword args.
There's one thing I need to fix but I'd like to start getting reviews on this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great
sig { params(source: T.untyped, pathname: Pathname, declarations: T::Array[RBS::AST::Declarations::Base]).void } | ||
sig do | ||
params( | ||
source: T.any(Symbol, String), # If source is from Ruby Core, it will be the symbol `:core` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't look like we're using source
. Should we remove it?
parameters += process_trailing_positionals(function) if function.trailing_positionals | ||
parameters += process_rest_positionals(function) if function.rest_positionals | ||
parameters += process_required_keywords(function) if function.required_keywords | ||
parameters += process_optional_keywords(function) if function.optional_keywords |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at our implementation for Ruby, are we missing keyword rest? (e.g.: **kwargs
)?
function.optional_positionals.map do |param| | ||
# Optional positionals may be unnamed, e.g. | ||
# def self.polar: (Numeric, ?Numeric) -> Complex | ||
name = param.name || :anon # TODO: what should we call this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't use anon
since you cannot actually have an anonymous optional parameter, they must always have some name.
My vote goes for simplicity with arg0
, arg1
, arg2
and so on using a map with index.
end | ||
|
||
sig { params(function: RBS::Types::Function).returns(T::Array[Entry::OptionalParameter]) } | ||
def process_trailing_positionals(function) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll defer to you if you prefer this style, but I'm not a fan of this tiny methods that just map through one parameter type. I would just inline them all.
@@ -74,5 +74,229 @@ def test_location_and_name_location_are_the_same | |||
|
|||
assert_same(entry.location, entry.name_location) | |||
end | |||
|
|||
def test_rbs_method_with_required_positionals | |||
entries = @index["crypt"] # https://www.rubydoc.info/stdlib/core/String#crypt-instance_method |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's either remove the link or point to the official docs.
|
||
first_signature = signatures.first | ||
|
||
# (::string salt_str) -> ::String |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like those, it's easier to understand 👍
assert_kind_of(Entry::KeywordParameter, parameters[1]) | ||
end | ||
|
||
def test_parse_simple_rbs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a test for keyword rest **kwargs
.
Motivation
In this PR we are beginning fuller indexing of RBS, by handline multiple signatures per method.
Implementation
Previously,
arguments
was a field ofEntry::Method
. Now anEntry::Method
has asignatures
field (of type array), and each signature has the array of arguments.Not covered yet:
Automated Tests
The tests are mostly using a selection of methods from Ruby core to verify the various forms of signatures in use.
Manual Tests
There is no integration with the LSP features yet so this cannot be easily manually tested.