Skip to content

Expose method signature to Ruby#686

Open
soutaro wants to merge 8 commits intomainfrom
soutaro-signature_ruby_api
Open

Expose method signature to Ruby#686
soutaro wants to merge 8 commits intomainfrom
soutaro-signature_ruby_api

Conversation

@soutaro
Copy link
Copy Markdown
Contributor

@soutaro soutaro commented Mar 24, 2026

Towards #668

  • RBS untyped method (?) -> returns empty parameters, which should be fixed later.
  • Method aliases to inherited methods doesn't work. It stops and returns empty signatures.

soutaro and others added 2 commits March 24, 2026 17:54
Align RBS keyword parameter offsets with Ruby indexer behavior.
The RBS indexer now includes the trailing colon in the offset for
required and optional keyword parameters (e.g. `name:` instead of `name`).

Adds `Offset::extend_end` helper to adjust byte ranges.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Expose method signature information through the Ruby C extension.
Each signature contains parameters as [kind, name, location] tuples,
following the same format as Method#parameters with an additional
location element.

- 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 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 24, 2026 08:58
@soutaro soutaro added the enhancement New feature or request label Mar 24, 2026
Add signatures method to method declarations (Rubydex::Method) that
aggregates signatures from all definitions, resolving method aliases
to the original method's signatures.

- Add query::method_definitions() in Rust for alias-aware lookup
- Add rdx_declaration_method_signatures C API function
- Register Method#signatures in the C extension

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@soutaro soutaro force-pushed the soutaro-signature_ruby_api branch from 8a49bfb to d1f4139 Compare March 24, 2026 09:02
/// - the declaration is not a method declaration
/// - any definition or owner declaration referenced by the method is missing from the graph
#[must_use]
pub fn method_definitions(graph: &Graph, declaration_id: DeclarationId) -> Vec<(DefinitionId, &MethodDefinition)> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The name may be confusing, what do you think of something like dealias_method_declaration_to_definitions

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.

Agree that method_definitions is too ambiguous. I feel dealias_ is a bit too implementation-specific though — the intent is "get the underlying MethodDefinitions from a declaration", not specifically about alias resolution.

How about resolve_method_declaration_to_definitions, or without the resolve_ prefix?

Copy link
Copy Markdown
Contributor

@Morriar Morriar Mar 25, 2026

Choose a reason for hiding this comment

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

I like resolve_method_declaration_to_definitions

Actually, we generally use resolve to go from a name to a declaration, it may be confusing to "resolve a declaration".

Let's go with method_declaration_to_definitions

Copy link
Copy Markdown
Member

@vinistock vinistock left a comment

Choose a reason for hiding this comment

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

This PR will likely be quicker to ship if we split it into smaller steps.

For example, the creation of the Signature class and all parameters can probably be shipped on its own

}

// Method#signatures -> [Rubydex::Signature]
static VALUE rdxr_method_declaration_signatures(VALUE self) {
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 to expose Declaration#signature? Signatures are associated to the specific Definition that creates them, so I'd expect us to access it like this:

method_decl = graph["Foo#bar()"]
signatures = method_decl.definitions.map(&:signature)

I think we can remove this one.

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.

I'd like to keep #signatures as a utility API. #definitions can contain method aliases, so definitions.flat_map(&:signatures) wouldn't work transparently — users would need to handle alias resolution themselves.

We could add a separate API for alias normalization, but if we're adding an API anyway, I think #signatures that does it all in one shot is the better choice.

Comment on lines +10 to +23
# Each parameter is a 3-element array of `[kind, name, location]`,
# following the same format as `Method#parameters` with an additional location element.
#
# The kind symbol is one of:
# - `:req` — required positional parameter (`a`) or post-rest positional parameter (`d` in `def foo(*c, d)`)
# - `:opt` — optional positional parameter (`b = 1`)
# - `:rest` — rest positional parameter (`*c`)
# - `:keyreq` — required keyword parameter (`e:`)
# - `:key` — optional keyword parameter (`f: 1`)
# - `:keyrest` — rest keyword parameter (`**g`)
# - `:block` — block parameter (`&h`)
# - `:forward` — forward parameter (`...`), Rubydex-specific (Ruby expands this to `:rest`, `:keyrest`, `:block`)
#
#: Array[[Symbol, Symbol, Location]]
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 please create Ruby objects to represent each parameter type instead of using symbols.

I suspect you only need a parent class and then a bunch of empty definitions:

class Parameter
  def initialize(name, location)
    # ...
  end
end

class PositionalParameter < Parameter; end
class OptionalPositionalParameter < Parameter; end
class KeywordParameter < Parameter; end
class OptionalKeywordParameter < Parameter; end
# ...

@soutaro
Copy link
Copy Markdown
Contributor Author

soutaro commented Mar 26, 2026

@vinistock Yeah, splitting sounds good to me. (Once I started working on this, everything came together as a single PR.)

I'll extract theMethodDefinition#signatures to Ruby API part into its own PR.

@soutaro
Copy link
Copy Markdown
Contributor Author

soutaro commented Mar 26, 2026

Opened two PRs (#697 and #694) so that we can move forward quickly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants