Skip to content

Fix RBS signatures in send nodes like prepend#432

Open
allcre wants to merge 1 commit intomasterfrom
sigs-append
Open

Fix RBS signatures in send nodes like prepend#432
allcre wants to merge 1 commit intomasterfrom
sigs-append

Conversation

@allcre
Copy link
Copy Markdown

@allcre allcre commented May 14, 2025

Fix RBS signature recognition in send node contexts

Ticket: https://github.com/Shopify/team-ruby-dx/issues/1451

Solution

SigsRewriter changes:

  • Added logic to rewrite arguments in non-visibility send nodes
  • This enables the rewriter to traverse into send node arguments and process any method definitions found there
  • Specifically skip visibility modifier sends (like private def method_name) to prevent double-processing, since those method definitions are already handled directly by the main AST traversal

Example

# typed: strict

class A; end

A.prepend(Module.new do
  #: -> void
  def foo; end  # Now properly recognizes the RBS signature
end)

@allcre allcre force-pushed the sigs-append branch 5 times, most recently from 9347b86 to a1bcaff Compare May 22, 2025 19:28
Copy link
Copy Markdown
Author

allcre commented May 22, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

@allcre allcre requested review from KaanOzkan and st0012 May 22, 2025 19:44
Comment thread test/testdata/rbs/signatures_defs.rb
@allcre allcre marked this pull request as ready for review May 23, 2025 14:16
Comment thread rbs/SigsRewriter.cc
result = move(node);
},
[&](parser::Send *send) {
if (!parser::MK::isVisibilitySend(send)) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Why do we need this condition, can't we just visit them?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

From my understanding, a method like this:

#: (Integer) -> void
private def method1(x)
  T.reveal_type(x)
end

has a DefMethod node and a Send node from the private keyword.

First, signaturesTarget() finds the DefMethod → creates signature.
Then, rewriteNodes processes the Send arguments → finds same DefMethod → creates duplicate signature.

This results in "Unused type annotation" errors if we do not include this check.

Copy link
Copy Markdown

@Morriar Morriar Jun 5, 2025

Choose a reason for hiding this comment

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

I'm not sure I follow.

The comment should have been associated to the def:

associateSignatureCommentsToNode(send->args[0].get());

So this means we're visiting the same node twice?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ok, it seems we're visiting the send arg once through the body of the class, then a second type by visiting the send itself.

I wonder if we should instead attach the comment to the send in commentsAssociator so we don't have to check isVisibilitySend 3 times?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for the suggestion! I looked into this with @KaanOzkan, and if we associate comments with the Send node instead of the method def, the rewriter would need to extract the comment from the Send and apply it to the DefMethod in args[0]. This cross-node processing would add some complexity compared to the current approach. I can explore this if you think we should go with this route, or I can open the PR in Sorbet and see what they say.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I've prototyped it here: #436, let me know what you think!

Comment thread test/testdata/rbs/signatures_defs.rb
RBS signatures weren't being recognized when method definitions were
nested inside `send` node arguments (e.g., `A.prepend(Module.new do...`).

The SigsRewriter now traverses into non-visibility send node arguments
to process method definitions and convert their associated RBS comments
into signature nodes. Visibility modifier sends are skipped to prevent
double-processing.
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.

3 participants