Skip to content

Add MethodDefinition#signatures to Ruby API#697

Open
soutaro wants to merge 2 commits intomainfrom
soutaro-definition-signatures
Open

Add MethodDefinition#signatures to Ruby API#697
soutaro wants to merge 2 commits intomainfrom
soutaro-definition-signatures

Conversation

@soutaro
Copy link
Copy Markdown
Contributor

@soutaro soutaro commented Mar 26, 2026

Summary

  • Expose method signature information through MethodDefinition#signatures, returning an array of Rubydex::Signature objects
  • Each Signature holds an array of typed Parameter subclasses (PositionalParameter, KeywordParameter, etc.) with name and location attributes
  • Add Rust C API (ParameterKind, SignatureEntry, SignatureArray) and C extension glue for conversion

Extracted from #686.

Test plan

  • Tests cover all 8 parameter kinds (positional, optional, rest, keyword, optional keyword, rest keyword, block, forward)
  • Tests cover RBS-defined signatures, overloads, untyped parameters, and no-parameter methods

🤖 Generated with Claude Code

Expose method signature information through the Ruby C extension.
Each signature contains parameters as an array of Signature::Parameter
subclasses (PositionalParameter, KeywordParameter, etc.), each holding
a name and location.

- Add Parameter::inner() to access ParameterStruct from any variant
- Add Rust C API: ParameterKind, SignatureEntry, SignatureArray structs
  and rdx_definition_signatures/rdx_definition_signatures_free functions
- Add Rubydex::Signature Ruby class with #parameters and #method_definition
- Add Rubydex::Signature::Parameter base class and typed subclasses
- Add rdxi_signatures_to_ruby shared C helper for SignatureArray conversion
- Register MethodDefinition#signatures in the C extension

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@soutaro soutaro requested a review from a team as a code owner March 26, 2026 05:34
@soutaro soutaro self-assigned this Mar 26, 2026
Comment on lines +80 to +88
cParameter = rb_define_class_under(cSignature, "Parameter", rb_cObject);
cPositionalParameter = rb_define_class_under(cSignature, "PositionalParameter", cParameter);
cOptionalPositionalParameter = rb_define_class_under(cSignature, "OptionalPositionalParameter", cParameter);
cRestPositionalParameter = rb_define_class_under(cSignature, "RestPositionalParameter", cParameter);
cKeywordParameter = rb_define_class_under(cSignature, "KeywordParameter", cParameter);
cOptionalKeywordParameter = rb_define_class_under(cSignature, "OptionalKeywordParameter", cParameter);
cRestKeywordParameter = rb_define_class_under(cSignature, "RestKeywordParameter", cParameter);
cBlockParameter = rb_define_class_under(cSignature, "BlockParameter", cParameter);
cForwardParameter = rb_define_class_under(cSignature, "ForwardParameter", cParameter);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we define these in Ruby? It seems like we may not even need new C files. We could just put the rdxi_signatures_to_ruby helper in definition.c.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also for MethodDeclaration#signatures. That will be in declaration.c and then the rdxi_signatures_to_ruby will be used from two files.

Another question is if Rubydex::Signature is a good place to define the class. Does Rubydex::MethodDefinition::Signature make more sense?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So far, we haven't really nested any of the classes in sub-modules. I think Rubydex::Signature is fine for now.

}

/// Helper: build signature entries from a MethodDefinition and append them to the output vector.
pub(crate) fn collect_method_signatures(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be public? I think it's only used in this file.

#: (parameters: Array[Parameter], method_definition: MethodDefinition) -> void
def initialize(parameters:, method_definition:)
@parameters = parameters
@method_definition = method_definition
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this back link? Considering that consumers will interact with the API like this:

declaration.definitions.first.signatures

I think we can remove this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for MethodDeclaration#signatures. It will return an array of Signature, and then we should need the backlink to retrieve docs and something associated to the method definition.

We can drop the backlink and add a new class or use tuple for #signatures method though?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's discuss in the team sync, but I think exposing signatures at the declaration level has the potential to be a bit confusing.

Maybe we can handle the alias case in some other way.

- Rename ParameterKind variants to full names (e.g. Req -> RequiredPositional)
- Merge two let-else bindings into one in rdx_definition_signatures
- Make collect_method_signatures private
- Change Signature#initialize from keyword arguments to positional arguments

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants